@memberjunction/ng-explorer-settings 5.11.0 → 5.13.0

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.
@@ -469,11 +469,11 @@ export class PermissionDialogComponent {
469
469
  i0.ɵɵconditionalCreate(0, PermissionDialogComponent_Conditional_0_Template, 101, 16, "div", 0);
470
470
  } if (rf & 2) {
471
471
  i0.ɵɵconditional(ctx.visible ? 0 : -1);
472
- } }, dependencies: [i1.ɵNgNoValidate, i1.CheckboxControlValueAccessor, i1.NgControlStatus, i1.NgControlStatusGroup, i1.NgModel, i1.FormGroupDirective, i2.DatePipe], styles: ["/* ==============================================\n Permission Dialog - MJ Design System\n Using MJ design tokens from _tokens.scss\n Pure Modal (No Kendo UI)\n ============================================== */\n\n/* Modal Backdrop */\n.modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n padding: 1rem;\n animation: fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* Modal Dialog Container */\n.modal-dialog {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n width: 900px;\n max-width: calc(100vw - 2rem);\n max-height: calc(100vh - 2rem);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: slideIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes slideIn {\n from {\n opacity: 0;\n transform: scale(0.95) translateY(20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n/* Modal Header - MJ Blue Background */\n.modal-header {\n background: var(--mj-brand-primary);\n padding: 24px 32px;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.dialog-header {\n flex: 1;\n color: var(--mj-brand-on-primary);\n}\n\n.dialog-header .dialog-title {\n font-size: 20px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 12px;\n margin: 0 0 4px 0;\n color: var(--mj-brand-on-primary);\n}\n\n.dialog-header .dialog-title i {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.15);\n border-radius: var(--mj-radius-md);\n font-size: 16px;\n}\n\n.dialog-header .dialog-subtitle {\n margin: 0;\n font-size: 13px;\n opacity: 0.9;\n font-weight: 400;\n color: var(--mj-brand-on-primary);\n}\n\n/* Modal Close Button */\n.modal-close {\n background: rgba(255, 255, 255, 0.1);\n border: 1px solid rgba(255, 255, 255, 0.2);\n color: var(--mj-brand-on-primary);\n border-radius: var(--mj-radius-md);\n width: 44px;\n height: 44px;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n flex-shrink: 0;\n}\n\n.modal-close:hover {\n background: rgba(255, 255, 255, 0.2);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.modal-close i {\n font-size: 16px;\n}\n\n/* Modal Body - Scrollable Content */\n.modal-body {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background: var(--mj-bg-surface);\n}\n\n/* Content Sections */\n.content-section {\n padding: 32px;\n}\n\n.content-section:not(:last-child) {\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n/* Form Sections */\n.form-section .section-header {\n margin-bottom: 24px;\n}\n\n.form-section .section-header .section-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.form-section .section-header .section-title i {\n color: var(--mj-brand-primary);\n font-size: 18px;\n}\n\n.form-section .section-header .section-description {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* Entity Info Card - Static Display (Non-interactive) */\n.entity-info-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n padding: 24px;\n cursor: default;\n}\n\n.entity-info-card .entity-meta {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n@media (max-width: 640px) {\n .entity-info-card .entity-meta {\n grid-template-columns: 1fr;\n }\n}\n\n.entity-info-card .entity-meta .meta-item {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.entity-info-card .entity-meta .meta-item i {\n color: var(--mj-brand-primary);\n width: 16px;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.entity-info-card .entity-meta .meta-item .meta-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n white-space: nowrap;\n}\n\n.entity-info-card .entity-meta .meta-item .meta-value {\n font-size: 12px;\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n/* Permissions Table */\n.permissions-table-container {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.permissions-table-container .permissions-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.permissions-table-container .permissions-table thead {\n background: var(--mj-bg-surface-card);\n}\n\n.permissions-table-container .permissions-table thead th {\n padding: 16px 24px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n white-space: nowrap;\n}\n\n.permissions-table-container .permissions-table thead th.role-column {\n width: 25%;\n min-width: 200px;\n}\n\n.permissions-table-container .permissions-table thead th.permission-column {\n width: 15%;\n text-align: center;\n}\n\n.permissions-table-container .permissions-table thead th.permission-column i {\n color: var(--mj-brand-primary);\n margin-right: 4px;\n}\n\n.permissions-table-container .permissions-table thead th.actions-column {\n width: 10%;\n text-align: center;\n}\n\n.permissions-table-container .permissions-table tbody tr {\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.permissions-table-container .permissions-table tbody tr:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.permissions-table-container .permissions-table tbody tr.has-changes {\n background: var(--mj-color-accent-300);\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.permissions-table-container .permissions-table tbody tr.is-new {\n background: var(--mj-color-success-100);\n border-left: 3px solid var(--mj-color-success-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td {\n padding: 16px 24px;\n border-bottom: 1px solid var(--mj-bg-surface-card);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-text-primary);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info i {\n color: var(--mj-brand-primary);\n width: 16px;\n flex-shrink: 0;\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .new-badge,\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .changed-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--mj-radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n margin-left: 8px;\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .new-badge {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-color-success-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .changed-badge {\n background: var(--mj-color-warning-100);\n color: var(--mj-color-warning-800);\n border: 1px solid var(--mj-color-warning-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td.permission-cell,\n.permissions-table-container .permissions-table tbody tr td.actions-cell {\n text-align: center;\n}\n\n/* Permission Toggle - Checkbox */\n.permission-toggle {\n display: flex;\n justify-content: center;\n}\n\n.permission-toggle .permission-checkbox {\n position: absolute;\n opacity: 0;\n cursor: pointer;\n}\n\n.permission-toggle .permission-checkbox:checked + .permission-label .checkbox-indicator {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.permission-toggle .permission-checkbox:checked + .permission-label .checkbox-indicator::after {\n opacity: 1;\n transform: rotate(45deg) scale(1);\n}\n\n.permission-toggle .permission-checkbox:focus + .permission-label .checkbox-indicator {\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.permission-toggle .permission-label {\n display: flex;\n align-items: center;\n cursor: pointer;\n margin: 0;\n min-width: 44px;\n min-height: 44px;\n justify-content: center;\n}\n\n.permission-toggle .checkbox-indicator {\n width: 20px;\n height: 20px;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n position: relative;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.permission-toggle .checkbox-indicator::after {\n content: '';\n position: absolute;\n left: 6px;\n top: 2px;\n width: 4px;\n height: 8px;\n border: solid var(--mj-brand-on-primary);\n border-width: 0 2px 2px 0;\n opacity: 0;\n transform: rotate(45deg) scale(0.8);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Action Buttons - Danger Icon Button */\n.btn-icon {\n width: 44px;\n height: 44px;\n min-width: 44px;\n min-height: 44px;\n border: none;\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n}\n\n.btn-icon.btn-danger {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n}\n\n.btn-icon.btn-danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 20%, transparent);\n transform: scale(1.05);\n}\n\n/* Empty Permissions */\n.empty-permissions {\n text-align: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n}\n\n.empty-permissions i {\n font-size: 2rem;\n color: var(--mj-border-default);\n margin-bottom: 16px;\n}\n\n.empty-permissions p {\n margin: 0 0 4px 0;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.empty-permissions .empty-subtext {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* Add Role Section */\n.add-role-section {\n margin-top: 32px;\n padding-top: 24px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.add-role-section .add-role-header {\n margin-bottom: 24px;\n}\n\n.add-role-section .add-role-header h4 {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.add-role-section .add-role-header p {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.add-role-section .available-roles {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.add-role-section .available-roles .role-chip {\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n align-items: center;\n gap: 4px;\n min-height: 44px;\n}\n\n.add-role-section .available-roles .role-chip i {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.add-role-section .available-roles .role-chip:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.add-role-section .available-roles .no-available-roles {\n color: var(--mj-text-secondary);\n font-style: italic;\n margin: 0;\n}\n\n/* Alert Messages */\n.alert {\n padding: 16px 24px;\n border-radius: var(--mj-radius-md);\n margin-bottom: 0;\n display: flex;\n align-items: flex-start;\n gap: 16px;\n}\n\n.alert i {\n font-size: 16px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.alert.alert-error {\n background: var(--mj-color-error-100);\n border: 1px solid var(--mj-status-error);\n color: var(--mj-color-error-700);\n}\n\n.alert.alert-error i {\n color: var(--mj-status-error);\n}\n\n/* Modal Footer */\n.modal-footer {\n padding: 24px 32px;\n background: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.modal-footer .footer-info {\n flex: 1;\n}\n\n.modal-footer .footer-info .changes-indicator {\n color: var(--mj-color-warning-500);\n font-size: 12px;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.modal-footer .footer-info .changes-indicator i {\n font-size: 14px;\n}\n\n.modal-footer .footer-actions {\n display: flex;\n gap: 16px;\n}\n\n/* Button Styles */\n.modal-footer .btn {\n padding: 0.75rem 1.5rem;\n border-radius: var(--mj-radius-full);\n font-size: 14px;\n font-weight: 600;\n border: 1px solid transparent;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: inline-flex;\n align-items: center;\n gap: 8px;\n min-height: 44px;\n}\n\n.modal-footer .btn:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.modal-footer .btn:disabled i.fa-spinner {\n animation: spin 1s linear infinite;\n}\n\n/* Secondary Button - Light, fills with primary on hover */\n.modal-footer .btn.btn-secondary {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border-color: var(--mj-border-strong);\n}\n\n.modal-footer .btn.btn-secondary:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.modal-footer .btn.btn-secondary:active:not(:disabled) {\n background: var(--mj-color-brand-700);\n border-color: var(--mj-color-brand-700);\n}\n\n/* Primary Button - Dark, lightens on hover */\n.modal-footer .btn.btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.modal-footer .btn.btn-primary:hover:not(:disabled) {\n background: var(--mj-color-brand-350);\n box-shadow: var(--mj-shadow-md);\n transform: translateY(-1px);\n}\n\n.modal-footer .btn.btn-primary:active:not(:disabled) {\n background: var(--mj-color-brand-300);\n transform: scale(0.98);\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Accessibility - Focus Indicators */\nbutton:focus-visible,\ninput:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Reduced Motion */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .modal-backdrop {\n padding: 0;\n align-items: flex-start;\n }\n\n .modal-dialog {\n width: 100vw;\n max-width: 100vw;\n max-height: 100vh;\n border-radius: 0;\n margin: 0;\n }\n\n .modal-header {\n padding: 16px 20px;\n }\n\n .dialog-header .dialog-title {\n font-size: 18px;\n }\n\n .content-section {\n padding: 24px 20px;\n }\n\n .modal-footer {\n padding: 16px 20px;\n flex-direction: column;\n align-items: stretch;\n }\n\n .modal-footer .footer-info,\n .modal-footer .footer-actions {\n width: 100%;\n }\n\n .modal-footer .footer-actions {\n display: flex;\n gap: 12px;\n }\n\n .modal-footer .footer-actions .btn {\n flex: 1;\n justify-content: center;\n }\n\n .permissions-table-container {\n overflow-x: auto;\n }\n\n .permissions-table-container .permissions-table {\n min-width: 600px;\n }\n\n .available-roles .role-chip {\n flex: 1;\n min-width: 120px;\n justify-content: center;\n }\n}\n\n@media (max-width: 640px) {\n .entity-info-card .entity-meta {\n grid-template-columns: 1fr;\n }\n}\n"], encapsulation: 2 });
472
+ } }, dependencies: [i1.ɵNgNoValidate, i1.CheckboxControlValueAccessor, i1.NgControlStatus, i1.NgControlStatusGroup, i1.NgModel, i1.FormGroupDirective, i2.DatePipe], styles: ["/* ==============================================\n Permission Dialog - MJ Design System\n Using MJ design tokens from _tokens.scss\n Pure Modal (No Kendo UI)\n ============================================== */\n\n/* Modal Backdrop */\n.modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n padding: 1rem;\n animation: fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* Modal Dialog Container */\n.modal-dialog {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n width: 900px;\n max-width: calc(100vw - 2rem);\n max-height: calc(100vh - 2rem);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: slideIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes slideIn {\n from {\n opacity: 0;\n transform: scale(0.95) translateY(20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n/* Modal Header - MJ Blue Background */\n.modal-header {\n background: var(--mj-brand-primary);\n padding: 24px 32px;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.dialog-header {\n flex: 1;\n color: var(--mj-brand-on-primary);\n}\n\n.dialog-header .dialog-title {\n font-size: 20px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 12px;\n margin: 0 0 4px 0;\n color: var(--mj-brand-on-primary);\n}\n\n.dialog-header .dialog-title i {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.15);\n border-radius: var(--mj-radius-md);\n font-size: 16px;\n}\n\n.dialog-header .dialog-subtitle {\n margin: 0;\n font-size: 13px;\n opacity: 0.9;\n font-weight: 400;\n color: var(--mj-brand-on-primary);\n}\n\n/* Modal Close Button */\n.modal-close {\n background: rgba(255, 255, 255, 0.1);\n border: 1px solid rgba(255, 255, 255, 0.2);\n color: var(--mj-brand-on-primary);\n border-radius: var(--mj-radius-md);\n width: 44px;\n height: 44px;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n flex-shrink: 0;\n}\n\n.modal-close:hover {\n background: rgba(255, 255, 255, 0.2);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.modal-close i {\n font-size: 16px;\n}\n\n/* Modal Body - Scrollable Content */\n.modal-body {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background: var(--mj-bg-surface);\n}\n\n/* Content Sections */\n.content-section {\n padding: 32px;\n}\n\n.content-section:not(:last-child) {\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n/* Form Sections */\n.form-section .section-header {\n margin-bottom: 24px;\n}\n\n.form-section .section-header .section-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.form-section .section-header .section-title i {\n color: var(--mj-brand-primary);\n font-size: 18px;\n}\n\n.form-section .section-header .section-description {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* Entity Info Card - Static Display (Non-interactive) */\n.entity-info-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n padding: 24px;\n cursor: default;\n}\n\n.entity-info-card .entity-meta {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n@media (max-width: 640px) {\n .entity-info-card .entity-meta {\n grid-template-columns: 1fr;\n }\n}\n\n.entity-info-card .entity-meta .meta-item {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.entity-info-card .entity-meta .meta-item i {\n color: var(--mj-brand-primary);\n width: 16px;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.entity-info-card .entity-meta .meta-item .meta-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n white-space: nowrap;\n}\n\n.entity-info-card .entity-meta .meta-item .meta-value {\n font-size: 12px;\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n/* Permissions Table */\n.permissions-table-container {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.permissions-table-container .permissions-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.permissions-table-container .permissions-table thead {\n background: var(--mj-bg-surface-card);\n}\n\n.permissions-table-container .permissions-table thead th {\n padding: 16px 24px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n white-space: nowrap;\n}\n\n.permissions-table-container .permissions-table thead th.role-column {\n width: 25%;\n min-width: 200px;\n}\n\n.permissions-table-container .permissions-table thead th.permission-column {\n width: 15%;\n text-align: center;\n}\n\n.permissions-table-container .permissions-table thead th.permission-column i {\n color: var(--mj-brand-primary);\n margin-right: 4px;\n}\n\n.permissions-table-container .permissions-table thead th.actions-column {\n width: 10%;\n text-align: center;\n}\n\n.permissions-table-container .permissions-table tbody tr {\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.permissions-table-container .permissions-table tbody tr:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.permissions-table-container .permissions-table tbody tr.has-changes {\n background: var(--mj-color-accent-300);\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.permissions-table-container .permissions-table tbody tr.is-new {\n background: var(--mj-color-success-100);\n border-left: 3px solid var(--mj-color-success-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td {\n padding: 16px 24px;\n border-bottom: 1px solid var(--mj-bg-surface-card);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-text-primary);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info i {\n color: var(--mj-brand-primary);\n width: 16px;\n flex-shrink: 0;\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .new-badge,\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .changed-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--mj-radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n margin-left: 8px;\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .new-badge {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-color-success-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .changed-badge {\n background: var(--mj-color-warning-100);\n color: var(--mj-color-warning-800);\n border: 1px solid var(--mj-color-warning-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td.permission-cell,\n.permissions-table-container .permissions-table tbody tr td.actions-cell {\n text-align: center;\n}\n\n/* Permission Toggle - Checkbox */\n.permission-toggle {\n display: flex;\n justify-content: center;\n}\n\n.permission-toggle .permission-checkbox {\n position: absolute;\n opacity: 0;\n cursor: pointer;\n}\n\n.permission-toggle .permission-checkbox:checked + .permission-label .checkbox-indicator {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.permission-toggle .permission-checkbox:checked + .permission-label .checkbox-indicator::after {\n opacity: 1;\n transform: rotate(45deg) scale(1);\n}\n\n.permission-toggle .permission-checkbox:focus + .permission-label .checkbox-indicator {\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.permission-toggle .permission-label {\n display: flex;\n align-items: center;\n cursor: pointer;\n margin: 0;\n min-width: 44px;\n min-height: 44px;\n justify-content: center;\n}\n\n.permission-toggle .checkbox-indicator {\n width: 20px;\n height: 20px;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n position: relative;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.permission-toggle .checkbox-indicator::after {\n content: '';\n position: absolute;\n left: 6px;\n top: 2px;\n width: 4px;\n height: 8px;\n border: solid var(--mj-brand-on-primary);\n border-width: 0 2px 2px 0;\n opacity: 0;\n transform: rotate(45deg) scale(0.8);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Action Buttons - Danger Icon Button */\n.btn-icon {\n width: 44px;\n height: 44px;\n min-width: 44px;\n min-height: 44px;\n border: none;\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n}\n\n.btn-icon.btn-danger {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n}\n\n.btn-icon.btn-danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 20%, transparent);\n transform: scale(1.05);\n}\n\n/* Empty Permissions */\n.empty-permissions {\n text-align: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n}\n\n.empty-permissions i {\n font-size: 2rem;\n color: var(--mj-border-default);\n margin-bottom: 16px;\n}\n\n.empty-permissions p {\n margin: 0 0 4px 0;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.empty-permissions .empty-subtext {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* Add Role Section */\n.add-role-section {\n margin-top: 32px;\n padding-top: 24px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.add-role-section .add-role-header {\n margin-bottom: 24px;\n}\n\n.add-role-section .add-role-header h4 {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.add-role-section .add-role-header p {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.add-role-section .available-roles {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.add-role-section .available-roles .role-chip {\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n align-items: center;\n gap: 4px;\n min-height: 44px;\n}\n\n.add-role-section .available-roles .role-chip i {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.add-role-section .available-roles .role-chip:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.add-role-section .available-roles .no-available-roles {\n color: var(--mj-text-secondary);\n font-style: italic;\n margin: 0;\n}\n\n/* Alert Messages */\n.alert {\n padding: 16px 24px;\n border-radius: var(--mj-radius-md);\n margin-bottom: 0;\n display: flex;\n align-items: flex-start;\n gap: 16px;\n}\n\n.alert i {\n font-size: 16px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.alert.alert-error {\n background: var(--mj-color-error-100);\n border: 1px solid var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n.alert.alert-error i {\n color: var(--mj-status-error);\n}\n\n/* Modal Footer */\n.modal-footer {\n padding: 24px 32px;\n background: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.modal-footer .footer-info {\n flex: 1;\n}\n\n.modal-footer .footer-info .changes-indicator {\n color: var(--mj-color-warning-500);\n font-size: 12px;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.modal-footer .footer-info .changes-indicator i {\n font-size: 14px;\n}\n\n.modal-footer .footer-actions {\n display: flex;\n gap: 16px;\n}\n\n/* Button Styles */\n.modal-footer .btn {\n padding: 0.75rem 1.5rem;\n border-radius: var(--mj-radius-full);\n font-size: 14px;\n font-weight: 600;\n border: 1px solid transparent;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: inline-flex;\n align-items: center;\n gap: 8px;\n min-height: 44px;\n}\n\n.modal-footer .btn:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.modal-footer .btn:disabled i.fa-spinner {\n animation: spin 1s linear infinite;\n}\n\n/* Secondary Button - Light, fills with primary on hover */\n.modal-footer .btn.btn-secondary {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border-color: var(--mj-border-strong);\n}\n\n.modal-footer .btn.btn-secondary:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.modal-footer .btn.btn-secondary:active:not(:disabled) {\n background: var(--mj-color-brand-700);\n border-color: var(--mj-color-brand-700);\n}\n\n/* Primary Button - Dark, lightens on hover */\n.modal-footer .btn.btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.modal-footer .btn.btn-primary:hover:not(:disabled) {\n background: var(--mj-color-brand-350);\n box-shadow: var(--mj-shadow-md);\n transform: translateY(-1px);\n}\n\n.modal-footer .btn.btn-primary:active:not(:disabled) {\n background: var(--mj-color-brand-300);\n transform: scale(0.98);\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Accessibility - Focus Indicators */\nbutton:focus-visible,\ninput:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Reduced Motion */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .modal-backdrop {\n padding: 0;\n align-items: flex-start;\n }\n\n .modal-dialog {\n width: 100vw;\n max-width: 100vw;\n max-height: 100vh;\n border-radius: 0;\n margin: 0;\n }\n\n .modal-header {\n padding: 16px 20px;\n }\n\n .dialog-header .dialog-title {\n font-size: 18px;\n }\n\n .content-section {\n padding: 24px 20px;\n }\n\n .modal-footer {\n padding: 16px 20px;\n flex-direction: column;\n align-items: stretch;\n }\n\n .modal-footer .footer-info,\n .modal-footer .footer-actions {\n width: 100%;\n }\n\n .modal-footer .footer-actions {\n display: flex;\n gap: 12px;\n }\n\n .modal-footer .footer-actions .btn {\n flex: 1;\n justify-content: center;\n }\n\n .permissions-table-container {\n overflow-x: auto;\n }\n\n .permissions-table-container .permissions-table {\n min-width: 600px;\n }\n\n .available-roles .role-chip {\n flex: 1;\n min-width: 120px;\n justify-content: center;\n }\n}\n\n@media (max-width: 640px) {\n .entity-info-card .entity-meta {\n grid-template-columns: 1fr;\n }\n}\n"], encapsulation: 2 });
473
473
  }
474
474
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PermissionDialogComponent, [{
475
475
  type: Component,
476
- args: [{ standalone: false, selector: 'mj-permission-dialog', encapsulation: ViewEncapsulation.None, template: "<!-- MD3 Modal Dialog -->\n@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <!-- Modal Header -->\n <div class=\"modal-header\">\n <div class=\"dialog-header\">\n <h2 class=\"dialog-title\">\n <i class=\"fa-solid fa-key\"></i>\n Edit Entity Permissions\n </h2>\n <p class=\"dialog-subtitle\">\n Configure role-based permissions for {{ data?.entity?.Name }}\n </p>\n </div>\n <button type=\"button\" class=\"modal-close\" (click)=\"onCancel()\" aria-label=\"Close dialog\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"permissionForm\" (ngSubmit)=\"onSubmit()\">\n @if (error) {\n <div class=\"content-section\">\n <div class=\"alert alert-error\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <div>{{ error }}</div>\n </div>\n </div>\n }\n <!-- Entity Information Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-database\"></i>\n Entity Information\n </h3>\n <p class=\"section-description\">{{ data?.entity?.Description || 'Entity permissions configuration' }}</p>\n </div>\n <div class=\"entity-info-card\">\n <div class=\"entity-meta\">\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-table\"></i>\n <span class=\"meta-label\">Entity:</span>\n <span class=\"meta-value\">{{ data?.entity?.Name }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span class=\"meta-label\">Schema Name:</span>\n <span class=\"meta-value\">{{ data?.entity?.SchemaName || 'N/A' }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-key\"></i>\n <span class=\"meta-label\">Total Permissions:</span>\n <span class=\"meta-value\">{{ rolePermissions.length }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-clock\"></i>\n <span class=\"meta-label\">Last Updated:</span>\n <span class=\"meta-value\">{{ data?.entity?.__mj_UpdatedAt | date:'medium' }}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n <!-- Permissions Configuration Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-users-cog\"></i>\n Role Permissions\n </h3>\n <p class=\"section-description\">Configure CRUD permissions for each role</p>\n </div>\n <div class=\"permissions-table-container\">\n <table class=\"permissions-table\">\n <thead>\n <tr>\n <th class=\"role-column\">Role</th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-plus\"></i>\n Create\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-eye\"></i>\n Read\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-edit\"></i>\n Update\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-trash\"></i>\n Delete\n </th>\n <th class=\"actions-column\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (rolePermission of rolePermissions; track rolePermission.roleId) {\n <tr class=\"permission-row\" [class.has-changes]=\"hasEntityChanges(rolePermission)\" [class.is-new]=\"rolePermission.isNew\">\n <td class=\"role-name\">\n <div class=\"role-info\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>{{ rolePermission.roleName }}</span>\n @if (rolePermission.isNew) {\n <span class=\"new-badge\">New</span>\n }\n @if (hasEntityChanges(rolePermission) && !rolePermission.isNew) {\n <span class=\"changed-badge\">Modified</span>\n }\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'create-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanCreate\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'create-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'read-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanRead\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'read-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'update-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanUpdate\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'update-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'delete-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanDelete\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'delete-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"actions-cell\">\n <button\n type=\"button\"\n class=\"btn-icon btn-danger\"\n (click)=\"removeRolePermission(rolePermission)\"\n title=\"Remove permissions for this role\"\n attr.aria-label=\"Remove permissions for {{ rolePermission.roleName }}\"\n >\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n @if (rolePermissions.length === 0) {\n <div class=\"empty-permissions\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <p>No role permissions configured</p>\n <p class=\"empty-subtext\">Add permissions for specific roles to control access to this entity</p>\n </div>\n }\n </div>\n <!-- Add Role Permissions -->\n <div class=\"add-role-section\">\n <div class=\"add-role-header\">\n <h4>Add Role Permissions</h4>\n <p>Select roles to configure permissions for this entity</p>\n </div>\n <div class=\"available-roles\">\n @for (role of availableRoles; track role.ID) {\n <button\n type=\"button\"\n class=\"role-chip\"\n (click)=\"addRolePermission(role)\"\n title=\"Add permissions for {{ role.Name }}\"\n attr.aria-label=\"Add permissions for {{ role.Name }}\"\n >\n <i class=\"fa-solid fa-plus\"></i>\n {{ role.Name }}\n </button>\n }\n @if (availableRoles.length === 0) {\n <p class=\"no-available-roles\">All roles have been configured</p>\n }\n </div>\n </div>\n </div>\n </div>\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n <div class=\"footer-info\">\n @if (hasChanges) {\n <span class=\"changes-indicator\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n You have unsaved changes\n </span>\n }\n </div>\n <div class=\"footer-actions\">\n <button\n type=\"submit\"\n class=\"btn btn-primary\"\n [disabled]=\"!hasChanges || isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n Save Permissions\n }\n </button>\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"onCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n Cancel\n </button>\n </div>\n </div>\n </form>\n </div>\n </div>\n </div>\n}\n", styles: ["/* ==============================================\n Permission Dialog - MJ Design System\n Using MJ design tokens from _tokens.scss\n Pure Modal (No Kendo UI)\n ============================================== */\n\n/* Modal Backdrop */\n.modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n padding: 1rem;\n animation: fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* Modal Dialog Container */\n.modal-dialog {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n width: 900px;\n max-width: calc(100vw - 2rem);\n max-height: calc(100vh - 2rem);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: slideIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes slideIn {\n from {\n opacity: 0;\n transform: scale(0.95) translateY(20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n/* Modal Header - MJ Blue Background */\n.modal-header {\n background: var(--mj-brand-primary);\n padding: 24px 32px;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.dialog-header {\n flex: 1;\n color: var(--mj-brand-on-primary);\n}\n\n.dialog-header .dialog-title {\n font-size: 20px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 12px;\n margin: 0 0 4px 0;\n color: var(--mj-brand-on-primary);\n}\n\n.dialog-header .dialog-title i {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.15);\n border-radius: var(--mj-radius-md);\n font-size: 16px;\n}\n\n.dialog-header .dialog-subtitle {\n margin: 0;\n font-size: 13px;\n opacity: 0.9;\n font-weight: 400;\n color: var(--mj-brand-on-primary);\n}\n\n/* Modal Close Button */\n.modal-close {\n background: rgba(255, 255, 255, 0.1);\n border: 1px solid rgba(255, 255, 255, 0.2);\n color: var(--mj-brand-on-primary);\n border-radius: var(--mj-radius-md);\n width: 44px;\n height: 44px;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n flex-shrink: 0;\n}\n\n.modal-close:hover {\n background: rgba(255, 255, 255, 0.2);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.modal-close i {\n font-size: 16px;\n}\n\n/* Modal Body - Scrollable Content */\n.modal-body {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background: var(--mj-bg-surface);\n}\n\n/* Content Sections */\n.content-section {\n padding: 32px;\n}\n\n.content-section:not(:last-child) {\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n/* Form Sections */\n.form-section .section-header {\n margin-bottom: 24px;\n}\n\n.form-section .section-header .section-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.form-section .section-header .section-title i {\n color: var(--mj-brand-primary);\n font-size: 18px;\n}\n\n.form-section .section-header .section-description {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* Entity Info Card - Static Display (Non-interactive) */\n.entity-info-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n padding: 24px;\n cursor: default;\n}\n\n.entity-info-card .entity-meta {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n@media (max-width: 640px) {\n .entity-info-card .entity-meta {\n grid-template-columns: 1fr;\n }\n}\n\n.entity-info-card .entity-meta .meta-item {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.entity-info-card .entity-meta .meta-item i {\n color: var(--mj-brand-primary);\n width: 16px;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.entity-info-card .entity-meta .meta-item .meta-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n white-space: nowrap;\n}\n\n.entity-info-card .entity-meta .meta-item .meta-value {\n font-size: 12px;\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n/* Permissions Table */\n.permissions-table-container {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.permissions-table-container .permissions-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.permissions-table-container .permissions-table thead {\n background: var(--mj-bg-surface-card);\n}\n\n.permissions-table-container .permissions-table thead th {\n padding: 16px 24px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n white-space: nowrap;\n}\n\n.permissions-table-container .permissions-table thead th.role-column {\n width: 25%;\n min-width: 200px;\n}\n\n.permissions-table-container .permissions-table thead th.permission-column {\n width: 15%;\n text-align: center;\n}\n\n.permissions-table-container .permissions-table thead th.permission-column i {\n color: var(--mj-brand-primary);\n margin-right: 4px;\n}\n\n.permissions-table-container .permissions-table thead th.actions-column {\n width: 10%;\n text-align: center;\n}\n\n.permissions-table-container .permissions-table tbody tr {\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.permissions-table-container .permissions-table tbody tr:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.permissions-table-container .permissions-table tbody tr.has-changes {\n background: var(--mj-color-accent-300);\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.permissions-table-container .permissions-table tbody tr.is-new {\n background: var(--mj-color-success-100);\n border-left: 3px solid var(--mj-color-success-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td {\n padding: 16px 24px;\n border-bottom: 1px solid var(--mj-bg-surface-card);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-text-primary);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info i {\n color: var(--mj-brand-primary);\n width: 16px;\n flex-shrink: 0;\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .new-badge,\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .changed-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--mj-radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n margin-left: 8px;\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .new-badge {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-color-success-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .changed-badge {\n background: var(--mj-color-warning-100);\n color: var(--mj-color-warning-800);\n border: 1px solid var(--mj-color-warning-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td.permission-cell,\n.permissions-table-container .permissions-table tbody tr td.actions-cell {\n text-align: center;\n}\n\n/* Permission Toggle - Checkbox */\n.permission-toggle {\n display: flex;\n justify-content: center;\n}\n\n.permission-toggle .permission-checkbox {\n position: absolute;\n opacity: 0;\n cursor: pointer;\n}\n\n.permission-toggle .permission-checkbox:checked + .permission-label .checkbox-indicator {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.permission-toggle .permission-checkbox:checked + .permission-label .checkbox-indicator::after {\n opacity: 1;\n transform: rotate(45deg) scale(1);\n}\n\n.permission-toggle .permission-checkbox:focus + .permission-label .checkbox-indicator {\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.permission-toggle .permission-label {\n display: flex;\n align-items: center;\n cursor: pointer;\n margin: 0;\n min-width: 44px;\n min-height: 44px;\n justify-content: center;\n}\n\n.permission-toggle .checkbox-indicator {\n width: 20px;\n height: 20px;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n position: relative;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.permission-toggle .checkbox-indicator::after {\n content: '';\n position: absolute;\n left: 6px;\n top: 2px;\n width: 4px;\n height: 8px;\n border: solid var(--mj-brand-on-primary);\n border-width: 0 2px 2px 0;\n opacity: 0;\n transform: rotate(45deg) scale(0.8);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Action Buttons - Danger Icon Button */\n.btn-icon {\n width: 44px;\n height: 44px;\n min-width: 44px;\n min-height: 44px;\n border: none;\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n}\n\n.btn-icon.btn-danger {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n}\n\n.btn-icon.btn-danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 20%, transparent);\n transform: scale(1.05);\n}\n\n/* Empty Permissions */\n.empty-permissions {\n text-align: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n}\n\n.empty-permissions i {\n font-size: 2rem;\n color: var(--mj-border-default);\n margin-bottom: 16px;\n}\n\n.empty-permissions p {\n margin: 0 0 4px 0;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.empty-permissions .empty-subtext {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* Add Role Section */\n.add-role-section {\n margin-top: 32px;\n padding-top: 24px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.add-role-section .add-role-header {\n margin-bottom: 24px;\n}\n\n.add-role-section .add-role-header h4 {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.add-role-section .add-role-header p {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.add-role-section .available-roles {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.add-role-section .available-roles .role-chip {\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n align-items: center;\n gap: 4px;\n min-height: 44px;\n}\n\n.add-role-section .available-roles .role-chip i {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.add-role-section .available-roles .role-chip:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.add-role-section .available-roles .no-available-roles {\n color: var(--mj-text-secondary);\n font-style: italic;\n margin: 0;\n}\n\n/* Alert Messages */\n.alert {\n padding: 16px 24px;\n border-radius: var(--mj-radius-md);\n margin-bottom: 0;\n display: flex;\n align-items: flex-start;\n gap: 16px;\n}\n\n.alert i {\n font-size: 16px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.alert.alert-error {\n background: var(--mj-color-error-100);\n border: 1px solid var(--mj-status-error);\n color: var(--mj-color-error-700);\n}\n\n.alert.alert-error i {\n color: var(--mj-status-error);\n}\n\n/* Modal Footer */\n.modal-footer {\n padding: 24px 32px;\n background: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.modal-footer .footer-info {\n flex: 1;\n}\n\n.modal-footer .footer-info .changes-indicator {\n color: var(--mj-color-warning-500);\n font-size: 12px;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.modal-footer .footer-info .changes-indicator i {\n font-size: 14px;\n}\n\n.modal-footer .footer-actions {\n display: flex;\n gap: 16px;\n}\n\n/* Button Styles */\n.modal-footer .btn {\n padding: 0.75rem 1.5rem;\n border-radius: var(--mj-radius-full);\n font-size: 14px;\n font-weight: 600;\n border: 1px solid transparent;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: inline-flex;\n align-items: center;\n gap: 8px;\n min-height: 44px;\n}\n\n.modal-footer .btn:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.modal-footer .btn:disabled i.fa-spinner {\n animation: spin 1s linear infinite;\n}\n\n/* Secondary Button - Light, fills with primary on hover */\n.modal-footer .btn.btn-secondary {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border-color: var(--mj-border-strong);\n}\n\n.modal-footer .btn.btn-secondary:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.modal-footer .btn.btn-secondary:active:not(:disabled) {\n background: var(--mj-color-brand-700);\n border-color: var(--mj-color-brand-700);\n}\n\n/* Primary Button - Dark, lightens on hover */\n.modal-footer .btn.btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.modal-footer .btn.btn-primary:hover:not(:disabled) {\n background: var(--mj-color-brand-350);\n box-shadow: var(--mj-shadow-md);\n transform: translateY(-1px);\n}\n\n.modal-footer .btn.btn-primary:active:not(:disabled) {\n background: var(--mj-color-brand-300);\n transform: scale(0.98);\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Accessibility - Focus Indicators */\nbutton:focus-visible,\ninput:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Reduced Motion */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .modal-backdrop {\n padding: 0;\n align-items: flex-start;\n }\n\n .modal-dialog {\n width: 100vw;\n max-width: 100vw;\n max-height: 100vh;\n border-radius: 0;\n margin: 0;\n }\n\n .modal-header {\n padding: 16px 20px;\n }\n\n .dialog-header .dialog-title {\n font-size: 18px;\n }\n\n .content-section {\n padding: 24px 20px;\n }\n\n .modal-footer {\n padding: 16px 20px;\n flex-direction: column;\n align-items: stretch;\n }\n\n .modal-footer .footer-info,\n .modal-footer .footer-actions {\n width: 100%;\n }\n\n .modal-footer .footer-actions {\n display: flex;\n gap: 12px;\n }\n\n .modal-footer .footer-actions .btn {\n flex: 1;\n justify-content: center;\n }\n\n .permissions-table-container {\n overflow-x: auto;\n }\n\n .permissions-table-container .permissions-table {\n min-width: 600px;\n }\n\n .available-roles .role-chip {\n flex: 1;\n min-width: 120px;\n justify-content: center;\n }\n}\n\n@media (max-width: 640px) {\n .entity-info-card .entity-meta {\n grid-template-columns: 1fr;\n }\n}\n"] }]
476
+ args: [{ standalone: false, selector: 'mj-permission-dialog', encapsulation: ViewEncapsulation.None, template: "<!-- MD3 Modal Dialog -->\n@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <!-- Modal Header -->\n <div class=\"modal-header\">\n <div class=\"dialog-header\">\n <h2 class=\"dialog-title\">\n <i class=\"fa-solid fa-key\"></i>\n Edit Entity Permissions\n </h2>\n <p class=\"dialog-subtitle\">\n Configure role-based permissions for {{ data?.entity?.Name }}\n </p>\n </div>\n <button type=\"button\" class=\"modal-close\" (click)=\"onCancel()\" aria-label=\"Close dialog\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"permissionForm\" (ngSubmit)=\"onSubmit()\">\n @if (error) {\n <div class=\"content-section\">\n <div class=\"alert alert-error\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <div>{{ error }}</div>\n </div>\n </div>\n }\n <!-- Entity Information Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-database\"></i>\n Entity Information\n </h3>\n <p class=\"section-description\">{{ data?.entity?.Description || 'Entity permissions configuration' }}</p>\n </div>\n <div class=\"entity-info-card\">\n <div class=\"entity-meta\">\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-table\"></i>\n <span class=\"meta-label\">Entity:</span>\n <span class=\"meta-value\">{{ data?.entity?.Name }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span class=\"meta-label\">Schema Name:</span>\n <span class=\"meta-value\">{{ data?.entity?.SchemaName || 'N/A' }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-key\"></i>\n <span class=\"meta-label\">Total Permissions:</span>\n <span class=\"meta-value\">{{ rolePermissions.length }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-clock\"></i>\n <span class=\"meta-label\">Last Updated:</span>\n <span class=\"meta-value\">{{ data?.entity?.__mj_UpdatedAt | date:'medium' }}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n <!-- Permissions Configuration Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-users-cog\"></i>\n Role Permissions\n </h3>\n <p class=\"section-description\">Configure CRUD permissions for each role</p>\n </div>\n <div class=\"permissions-table-container\">\n <table class=\"permissions-table\">\n <thead>\n <tr>\n <th class=\"role-column\">Role</th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-plus\"></i>\n Create\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-eye\"></i>\n Read\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-edit\"></i>\n Update\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-trash\"></i>\n Delete\n </th>\n <th class=\"actions-column\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (rolePermission of rolePermissions; track rolePermission.roleId) {\n <tr class=\"permission-row\" [class.has-changes]=\"hasEntityChanges(rolePermission)\" [class.is-new]=\"rolePermission.isNew\">\n <td class=\"role-name\">\n <div class=\"role-info\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>{{ rolePermission.roleName }}</span>\n @if (rolePermission.isNew) {\n <span class=\"new-badge\">New</span>\n }\n @if (hasEntityChanges(rolePermission) && !rolePermission.isNew) {\n <span class=\"changed-badge\">Modified</span>\n }\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'create-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanCreate\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'create-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'read-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanRead\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'read-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'update-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanUpdate\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'update-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'delete-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanDelete\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'delete-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"actions-cell\">\n <button\n type=\"button\"\n class=\"btn-icon btn-danger\"\n (click)=\"removeRolePermission(rolePermission)\"\n title=\"Remove permissions for this role\"\n attr.aria-label=\"Remove permissions for {{ rolePermission.roleName }}\"\n >\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n @if (rolePermissions.length === 0) {\n <div class=\"empty-permissions\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <p>No role permissions configured</p>\n <p class=\"empty-subtext\">Add permissions for specific roles to control access to this entity</p>\n </div>\n }\n </div>\n <!-- Add Role Permissions -->\n <div class=\"add-role-section\">\n <div class=\"add-role-header\">\n <h4>Add Role Permissions</h4>\n <p>Select roles to configure permissions for this entity</p>\n </div>\n <div class=\"available-roles\">\n @for (role of availableRoles; track role.ID) {\n <button\n type=\"button\"\n class=\"role-chip\"\n (click)=\"addRolePermission(role)\"\n title=\"Add permissions for {{ role.Name }}\"\n attr.aria-label=\"Add permissions for {{ role.Name }}\"\n >\n <i class=\"fa-solid fa-plus\"></i>\n {{ role.Name }}\n </button>\n }\n @if (availableRoles.length === 0) {\n <p class=\"no-available-roles\">All roles have been configured</p>\n }\n </div>\n </div>\n </div>\n </div>\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n <div class=\"footer-info\">\n @if (hasChanges) {\n <span class=\"changes-indicator\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n You have unsaved changes\n </span>\n }\n </div>\n <div class=\"footer-actions\">\n <button\n type=\"submit\"\n class=\"btn btn-primary\"\n [disabled]=\"!hasChanges || isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n Save Permissions\n }\n </button>\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"onCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n Cancel\n </button>\n </div>\n </div>\n </form>\n </div>\n </div>\n </div>\n}\n", styles: ["/* ==============================================\n Permission Dialog - MJ Design System\n Using MJ design tokens from _tokens.scss\n Pure Modal (No Kendo UI)\n ============================================== */\n\n/* Modal Backdrop */\n.modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n padding: 1rem;\n animation: fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* Modal Dialog Container */\n.modal-dialog {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n width: 900px;\n max-width: calc(100vw - 2rem);\n max-height: calc(100vh - 2rem);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: slideIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes slideIn {\n from {\n opacity: 0;\n transform: scale(0.95) translateY(20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n/* Modal Header - MJ Blue Background */\n.modal-header {\n background: var(--mj-brand-primary);\n padding: 24px 32px;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.dialog-header {\n flex: 1;\n color: var(--mj-brand-on-primary);\n}\n\n.dialog-header .dialog-title {\n font-size: 20px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 12px;\n margin: 0 0 4px 0;\n color: var(--mj-brand-on-primary);\n}\n\n.dialog-header .dialog-title i {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.15);\n border-radius: var(--mj-radius-md);\n font-size: 16px;\n}\n\n.dialog-header .dialog-subtitle {\n margin: 0;\n font-size: 13px;\n opacity: 0.9;\n font-weight: 400;\n color: var(--mj-brand-on-primary);\n}\n\n/* Modal Close Button */\n.modal-close {\n background: rgba(255, 255, 255, 0.1);\n border: 1px solid rgba(255, 255, 255, 0.2);\n color: var(--mj-brand-on-primary);\n border-radius: var(--mj-radius-md);\n width: 44px;\n height: 44px;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n flex-shrink: 0;\n}\n\n.modal-close:hover {\n background: rgba(255, 255, 255, 0.2);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.modal-close i {\n font-size: 16px;\n}\n\n/* Modal Body - Scrollable Content */\n.modal-body {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background: var(--mj-bg-surface);\n}\n\n/* Content Sections */\n.content-section {\n padding: 32px;\n}\n\n.content-section:not(:last-child) {\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n/* Form Sections */\n.form-section .section-header {\n margin-bottom: 24px;\n}\n\n.form-section .section-header .section-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.form-section .section-header .section-title i {\n color: var(--mj-brand-primary);\n font-size: 18px;\n}\n\n.form-section .section-header .section-description {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* Entity Info Card - Static Display (Non-interactive) */\n.entity-info-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n padding: 24px;\n cursor: default;\n}\n\n.entity-info-card .entity-meta {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n@media (max-width: 640px) {\n .entity-info-card .entity-meta {\n grid-template-columns: 1fr;\n }\n}\n\n.entity-info-card .entity-meta .meta-item {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.entity-info-card .entity-meta .meta-item i {\n color: var(--mj-brand-primary);\n width: 16px;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.entity-info-card .entity-meta .meta-item .meta-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n white-space: nowrap;\n}\n\n.entity-info-card .entity-meta .meta-item .meta-value {\n font-size: 12px;\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n/* Permissions Table */\n.permissions-table-container {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.permissions-table-container .permissions-table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.permissions-table-container .permissions-table thead {\n background: var(--mj-bg-surface-card);\n}\n\n.permissions-table-container .permissions-table thead th {\n padding: 16px 24px;\n text-align: left;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n white-space: nowrap;\n}\n\n.permissions-table-container .permissions-table thead th.role-column {\n width: 25%;\n min-width: 200px;\n}\n\n.permissions-table-container .permissions-table thead th.permission-column {\n width: 15%;\n text-align: center;\n}\n\n.permissions-table-container .permissions-table thead th.permission-column i {\n color: var(--mj-brand-primary);\n margin-right: 4px;\n}\n\n.permissions-table-container .permissions-table thead th.actions-column {\n width: 10%;\n text-align: center;\n}\n\n.permissions-table-container .permissions-table tbody tr {\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.permissions-table-container .permissions-table tbody tr:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.permissions-table-container .permissions-table tbody tr.has-changes {\n background: var(--mj-color-accent-300);\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.permissions-table-container .permissions-table tbody tr.is-new {\n background: var(--mj-color-success-100);\n border-left: 3px solid var(--mj-color-success-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td {\n padding: 16px 24px;\n border-bottom: 1px solid var(--mj-bg-surface-card);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-text-primary);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info i {\n color: var(--mj-brand-primary);\n width: 16px;\n flex-shrink: 0;\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .new-badge,\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .changed-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--mj-radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n margin-left: 8px;\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .new-badge {\n background: var(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-color-success-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td.role-name .role-info .changed-badge {\n background: var(--mj-color-warning-100);\n color: var(--mj-color-warning-800);\n border: 1px solid var(--mj-color-warning-500);\n}\n\n.permissions-table-container .permissions-table tbody tr td.permission-cell,\n.permissions-table-container .permissions-table tbody tr td.actions-cell {\n text-align: center;\n}\n\n/* Permission Toggle - Checkbox */\n.permission-toggle {\n display: flex;\n justify-content: center;\n}\n\n.permission-toggle .permission-checkbox {\n position: absolute;\n opacity: 0;\n cursor: pointer;\n}\n\n.permission-toggle .permission-checkbox:checked + .permission-label .checkbox-indicator {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.permission-toggle .permission-checkbox:checked + .permission-label .checkbox-indicator::after {\n opacity: 1;\n transform: rotate(45deg) scale(1);\n}\n\n.permission-toggle .permission-checkbox:focus + .permission-label .checkbox-indicator {\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.permission-toggle .permission-label {\n display: flex;\n align-items: center;\n cursor: pointer;\n margin: 0;\n min-width: 44px;\n min-height: 44px;\n justify-content: center;\n}\n\n.permission-toggle .checkbox-indicator {\n width: 20px;\n height: 20px;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n position: relative;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.permission-toggle .checkbox-indicator::after {\n content: '';\n position: absolute;\n left: 6px;\n top: 2px;\n width: 4px;\n height: 8px;\n border: solid var(--mj-brand-on-primary);\n border-width: 0 2px 2px 0;\n opacity: 0;\n transform: rotate(45deg) scale(0.8);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Action Buttons - Danger Icon Button */\n.btn-icon {\n width: 44px;\n height: 44px;\n min-width: 44px;\n min-height: 44px;\n border: none;\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n}\n\n.btn-icon.btn-danger {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n}\n\n.btn-icon.btn-danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 20%, transparent);\n transform: scale(1.05);\n}\n\n/* Empty Permissions */\n.empty-permissions {\n text-align: center;\n padding: 32px;\n color: var(--mj-text-secondary);\n}\n\n.empty-permissions i {\n font-size: 2rem;\n color: var(--mj-border-default);\n margin-bottom: 16px;\n}\n\n.empty-permissions p {\n margin: 0 0 4px 0;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.empty-permissions .empty-subtext {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* Add Role Section */\n.add-role-section {\n margin-top: 32px;\n padding-top: 24px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.add-role-section .add-role-header {\n margin-bottom: 24px;\n}\n\n.add-role-section .add-role-header h4 {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.add-role-section .add-role-header p {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.add-role-section .available-roles {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.add-role-section .available-roles .role-chip {\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n align-items: center;\n gap: 4px;\n min-height: 44px;\n}\n\n.add-role-section .available-roles .role-chip i {\n font-size: 12px;\n color: var(--mj-brand-primary);\n}\n\n.add-role-section .available-roles .role-chip:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.add-role-section .available-roles .no-available-roles {\n color: var(--mj-text-secondary);\n font-style: italic;\n margin: 0;\n}\n\n/* Alert Messages */\n.alert {\n padding: 16px 24px;\n border-radius: var(--mj-radius-md);\n margin-bottom: 0;\n display: flex;\n align-items: flex-start;\n gap: 16px;\n}\n\n.alert i {\n font-size: 16px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.alert.alert-error {\n background: var(--mj-color-error-100);\n border: 1px solid var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n.alert.alert-error i {\n color: var(--mj-status-error);\n}\n\n/* Modal Footer */\n.modal-footer {\n padding: 24px 32px;\n background: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.modal-footer .footer-info {\n flex: 1;\n}\n\n.modal-footer .footer-info .changes-indicator {\n color: var(--mj-color-warning-500);\n font-size: 12px;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.modal-footer .footer-info .changes-indicator i {\n font-size: 14px;\n}\n\n.modal-footer .footer-actions {\n display: flex;\n gap: 16px;\n}\n\n/* Button Styles */\n.modal-footer .btn {\n padding: 0.75rem 1.5rem;\n border-radius: var(--mj-radius-full);\n font-size: 14px;\n font-weight: 600;\n border: 1px solid transparent;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: inline-flex;\n align-items: center;\n gap: 8px;\n min-height: 44px;\n}\n\n.modal-footer .btn:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.modal-footer .btn:disabled i.fa-spinner {\n animation: spin 1s linear infinite;\n}\n\n/* Secondary Button - Light, fills with primary on hover */\n.modal-footer .btn.btn-secondary {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border-color: var(--mj-border-strong);\n}\n\n.modal-footer .btn.btn-secondary:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.modal-footer .btn.btn-secondary:active:not(:disabled) {\n background: var(--mj-color-brand-700);\n border-color: var(--mj-color-brand-700);\n}\n\n/* Primary Button - Dark, lightens on hover */\n.modal-footer .btn.btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.modal-footer .btn.btn-primary:hover:not(:disabled) {\n background: var(--mj-color-brand-350);\n box-shadow: var(--mj-shadow-md);\n transform: translateY(-1px);\n}\n\n.modal-footer .btn.btn-primary:active:not(:disabled) {\n background: var(--mj-color-brand-300);\n transform: scale(0.98);\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Accessibility - Focus Indicators */\nbutton:focus-visible,\ninput:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Reduced Motion */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .modal-backdrop {\n padding: 0;\n align-items: flex-start;\n }\n\n .modal-dialog {\n width: 100vw;\n max-width: 100vw;\n max-height: 100vh;\n border-radius: 0;\n margin: 0;\n }\n\n .modal-header {\n padding: 16px 20px;\n }\n\n .dialog-header .dialog-title {\n font-size: 18px;\n }\n\n .content-section {\n padding: 24px 20px;\n }\n\n .modal-footer {\n padding: 16px 20px;\n flex-direction: column;\n align-items: stretch;\n }\n\n .modal-footer .footer-info,\n .modal-footer .footer-actions {\n width: 100%;\n }\n\n .modal-footer .footer-actions {\n display: flex;\n gap: 12px;\n }\n\n .modal-footer .footer-actions .btn {\n flex: 1;\n justify-content: center;\n }\n\n .permissions-table-container {\n overflow-x: auto;\n }\n\n .permissions-table-container .permissions-table {\n min-width: 600px;\n }\n\n .available-roles .role-chip {\n flex: 1;\n min-width: 120px;\n justify-content: center;\n }\n}\n\n@media (max-width: 640px) {\n .entity-info-card .entity-meta {\n grid-template-columns: 1fr;\n }\n}\n"] }]
477
477
  }], () => [], { data: [{
478
478
  type: Input
479
479
  }], visible: [{
@@ -40,11 +40,11 @@ export class GeneralSettingsComponent {
40
40
  i0.ɵɵproperty("expanded", ctx.ProfileExpanded);
41
41
  i0.ɵɵadvance(3);
42
42
  i0.ɵɵproperty("expanded", ctx.AccountExpanded);
43
- } }, dependencies: [i1.SettingsCardComponent, i2.UserProfileSettingsComponent, i3.AccountInfoComponent], styles: [".general-settings[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.section-title[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n font-weight: 600;\n margin: 0 0 0.5rem 0;\n color: var(--mj-text-primary, #1a1a1a);\n}\n\n.section-description[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: var(--mj-text-secondary, #666);\n margin: 0 0 1.5rem 0;\n}\n\n.settings-grid[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.card-content[_ngcontent-%COMP%] {\n padding: 0.5rem 0;\n}"] });
43
+ } }, dependencies: [i1.SettingsCardComponent, i2.UserProfileSettingsComponent, i3.AccountInfoComponent], styles: [".general-settings[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.section-title[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n font-weight: 600;\n margin: 0 0 0.5rem 0;\n color: var(--mj-text-primary);\n}\n\n.section-description[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n margin: 0 0 1.5rem 0;\n}\n\n.settings-grid[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.card-content[_ngcontent-%COMP%] {\n padding: 0.5rem 0;\n}"] });
44
44
  }
45
45
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(GeneralSettingsComponent, [{
46
46
  type: Component,
47
- args: [{ standalone: false, selector: 'mj-general-settings', template: "<div class=\"general-settings\">\n <h2 class=\"section-title\">General Settings</h2>\n <p class=\"section-description\">Manage your profile and account information</p>\n\n <div class=\"settings-grid\">\n <!-- Profile Information Section -->\n <mj-settings-card\n title=\"Profile Information\"\n icon=\"fa-solid fa-user\"\n [expanded]=\"ProfileExpanded\"\n (toggle)=\"ToggleProfile()\"\n >\n <div class=\"card-content\">\n <mj-user-profile-settings></mj-user-profile-settings>\n </div>\n </mj-settings-card>\n\n <!-- Account Information Section -->\n <mj-settings-card\n title=\"Account Information\"\n icon=\"fa-solid fa-id-card\"\n [expanded]=\"AccountExpanded\"\n (toggle)=\"ToggleAccount()\"\n >\n <div class=\"card-content\">\n <mj-account-info></mj-account-info>\n </div>\n </mj-settings-card>\n </div>\n</div>\n", styles: [".general-settings {\n padding: 0;\n}\n\n.section-title {\n font-size: 1.5rem;\n font-weight: 600;\n margin: 0 0 0.5rem 0;\n color: var(--mj-text-primary, #1a1a1a);\n}\n\n.section-description {\n font-size: 0.875rem;\n color: var(--mj-text-secondary, #666);\n margin: 0 0 1.5rem 0;\n}\n\n.settings-grid {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.card-content {\n padding: 0.5rem 0;\n}\n"] }]
47
+ args: [{ standalone: false, selector: 'mj-general-settings', template: "<div class=\"general-settings\">\n <h2 class=\"section-title\">General Settings</h2>\n <p class=\"section-description\">Manage your profile and account information</p>\n\n <div class=\"settings-grid\">\n <!-- Profile Information Section -->\n <mj-settings-card\n title=\"Profile Information\"\n icon=\"fa-solid fa-user\"\n [expanded]=\"ProfileExpanded\"\n (toggle)=\"ToggleProfile()\"\n >\n <div class=\"card-content\">\n <mj-user-profile-settings></mj-user-profile-settings>\n </div>\n </mj-settings-card>\n\n <!-- Account Information Section -->\n <mj-settings-card\n title=\"Account Information\"\n icon=\"fa-solid fa-id-card\"\n [expanded]=\"AccountExpanded\"\n (toggle)=\"ToggleAccount()\"\n >\n <div class=\"card-content\">\n <mj-account-info></mj-account-info>\n </div>\n </mj-settings-card>\n </div>\n</div>\n", styles: [".general-settings {\n padding: 0;\n}\n\n.section-title {\n font-size: 1.5rem;\n font-weight: 600;\n margin: 0 0 0.5rem 0;\n color: var(--mj-text-primary);\n}\n\n.section-description {\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n margin: 0 0 1.5rem 0;\n}\n\n.settings-grid {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.card-content {\n padding: 0.5rem 0;\n}\n"] }]
48
48
  }], null, null); })();
49
49
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(GeneralSettingsComponent, { className: "GeneralSettingsComponent", filePath: "src/lib/general-settings/general-settings.component.ts", lineNumber: 13 }); })();
50
50
  //# sourceMappingURL=general-settings.component.js.map
@@ -374,11 +374,11 @@ export class NotificationPreferencesComponent {
374
374
  } if (rf & 2) {
375
375
  i0.ɵɵadvance();
376
376
  i0.ɵɵconditional(ctx.loading ? 1 : 2);
377
- } }, dependencies: [i2.CheckboxControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.LoadingComponent], styles: ["\n\n\n\n\n\n\n\n[_nghost-%COMP%] {\n \n\n --md-primary: #0076B6;\n --md-on-primary: #FFFFFF;\n --md-primary-container: #AAE7FD;\n --md-on-primary-container: #001F2A;\n\n \n\n --md-secondary: #F5A623;\n --md-on-secondary: #FFFFFF;\n --md-secondary-container: #FFECD6;\n --md-on-secondary-container: #2D1600;\n\n \n\n --md-tertiary: #4CAF50;\n --md-on-tertiary: #FFFFFF;\n --md-tertiary-container: #C8E6C9;\n --md-on-tertiary-container: #002204;\n\n \n\n --md-error: #D32F2F;\n --md-on-error: #FFFFFF;\n --md-error-container: #FFCDD2;\n --md-on-error-container: #410002;\n\n \n\n --md-warning: #FFC107;\n --md-on-warning: #2D1600;\n --md-warning-container: #FFF3CD;\n --md-on-warning-container: #856404;\n\n \n\n --md-surface: #FAFCFF;\n --md-surface-container-lowest: #FFFFFF;\n --md-surface-container-low: #F3F5F9;\n --md-surface-container: #EDF0F4;\n --md-surface-container-high: #E7EAEE;\n --md-surface-container-highest: #E1E3E8;\n --md-on-surface: #191C20;\n --md-on-surface-variant: #43474E;\n --md-outline: #74777F;\n --md-outline-variant: #C4C6D0;\n\n \n\n --md-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n --md-elevation-2: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n --md-elevation-3: 0 4px 8px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.08);\n --md-elevation-4: 0 6px 12px rgba(0, 0, 0, 0.1), 0 12px 24px rgba(0, 0, 0, 0.08);\n --md-elevation-5: 0 8px 16px rgba(0, 0, 0, 0.12), 0 16px 32px rgba(0, 0, 0, 0.1);\n\n \n\n --md-corner-extra-small: 4px;\n --md-corner-small: 8px;\n --md-corner-medium: 12px;\n --md-corner-large: 16px;\n --md-corner-extra-large: 28px;\n --md-corner-full: 9999px;\n\n \n\n display: block;\n width: 100%;\n}\n\n\n\n\n\n.notification-preferences-container[_ngcontent-%COMP%] {\n padding: 1.5rem;\n max-width: 1200px;\n margin: 0 auto;\n background: var(--md-surface);\n}\n\n\n\n\n\n.content[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 3rem 1.5rem;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 4rem;\n color: var(--md-outline-variant);\n margin-bottom: 1.5rem;\n display: block;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n font-weight: 500;\n color: var(--md-on-surface-variant);\n margin: 0;\n}\n\n\n\n\n\n.notification-types-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));\n gap: 1.25rem;\n margin-bottom: 1.5rem;\n}\n\n\n\n\n\n.notification-type-card[_ngcontent-%COMP%] {\n background: var(--md-surface-container-lowest);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n border-left: 4px solid var(--md-outline-variant);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--md-elevation-1);\n}\n\n.notification-type-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--md-elevation-2);\n border-color: var(--md-primary);\n}\n\n.notification-type-card.changed[_ngcontent-%COMP%] {\n border-left-color: var(--md-primary) !important;\n border-color: var(--md-primary);\n box-shadow: var(--md-elevation-3);\n background: var(--md-primary-container);\n}\n\n\n\n\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n gap: 1rem;\n padding: 1.25rem;\n border-bottom: 1px solid var(--md-outline-variant);\n align-items: flex-start;\n}\n\n.icon-wrapper[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: var(--md-corner-small);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: transform 0.2s;\n}\n\n.notification-type-card[_ngcontent-%COMP%]:hover .icon-wrapper[_ngcontent-%COMP%] {\n transform: scale(1.05);\n}\n\n.icon-wrapper[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n}\n\n.header-text[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.header-text[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 0.375rem 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--md-on-surface);\n}\n\n.type-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 0.875rem;\n color: var(--md-on-surface-variant);\n line-height: 1.4;\n}\n\n\n\n\n\n.card-body[_ngcontent-%COMP%] {\n padding: 1.25rem;\n}\n\n.preference-row[_ngcontent-%COMP%] {\n margin-bottom: 1rem;\n}\n\n.preference-row[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n.delivery-label[_ngcontent-%COMP%] {\n display: block;\n font-weight: 600;\n margin-bottom: 0.75rem;\n font-size: 0.875rem;\n color: var(--md-on-surface);\n letter-spacing: 0.01em;\n}\n\n\n\n\n\n.delivery-checkboxes[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.channel-checkbox[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 0.75rem 1rem;\n border: 2px solid var(--md-outline-variant);\n border-radius: var(--md-corner-small);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n user-select: none;\n background: var(--md-surface);\n min-height: 44px;\n}\n\n.channel-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--md-primary);\n margin: 0;\n}\n\n.channel-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%]:disabled {\n cursor: not-allowed;\n}\n\n.channel-checkbox[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--md-on-surface-variant);\n font-size: 1rem;\n transition: color 0.2s;\n}\n\n.channel-checkbox[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--md-on-surface);\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:hover:not(:has(input:disabled)) {\n border-color: var(--md-primary);\n background: var(--md-primary-container);\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:hover:not(:has(input:disabled)) i[_ngcontent-%COMP%] {\n color: var(--md-primary);\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:has(input:checked) {\n border-color: var(--md-primary);\n background: var(--md-primary-container);\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:has(input:checked) i[_ngcontent-%COMP%] {\n color: var(--md-primary);\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:has(input:disabled) {\n opacity: 0.5;\n cursor: not-allowed;\n background: var(--md-surface-container-low);\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:focus-within {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n\n\n\n\n.info-message[_ngcontent-%COMP%] {\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: var(--md-warning-container);\n border-left: 3px solid var(--md-warning);\n border-radius: var(--md-corner-small);\n font-size: 0.8125rem;\n display: flex;\n gap: 0.75rem;\n align-items: flex-start;\n line-height: 1.4;\n color: var(--md-on-warning-container);\n}\n\n.info-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--md-on-warning-container);\n font-size: 1rem;\n margin-top: 0.1rem;\n flex-shrink: 0;\n}\n\n\n\n\n\n.metadata-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.625rem;\n align-items: center;\n font-size: 0.8125rem;\n color: var(--md-on-surface-variant);\n padding-top: 0.75rem;\n margin-top: 0.75rem;\n border-top: 1px solid var(--md-outline-variant);\n}\n\n.metadata-row[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--md-on-surface-variant);\n font-size: 0.875rem;\n flex-shrink: 0;\n}\n\n.metadata-text[_ngcontent-%COMP%] {\n line-height: 1.4;\n}\n\n\n\n\n\n.actions[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-start;\n gap: 0.75rem;\n padding: 1.25rem;\n background: var(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n border: 1px solid var(--md-outline-variant);\n margin-top: 1.5rem;\n}\n\n\n\n\n\n.btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n border: none;\n border-radius: var(--md-corner-full);\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n min-height: 44px;\n}\n\n.btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1rem;\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: var(--md-surface);\n color: var(--md-primary);\n border: 1px solid var(--md-outline);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: #005A8C;\n border-color: #005A8C;\n transform: scale(0.98);\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #3395C8;\n box-shadow: var(--md-elevation-2);\n}\n\n.btn-primary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: #4BA5D4;\n transform: scale(0.98);\n}\n\n.btn-ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--md-on-surface-variant);\n border: none;\n}\n\n.btn-ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.btn-ghost[_ngcontent-%COMP%]:active:not(:disabled) {\n background: #005A8C;\n transform: scale(0.98);\n}\n\n.btn-danger[_ngcontent-%COMP%] {\n background: var(--md-error);\n color: var(--md-on-error);\n box-shadow: var(--md-elevation-1);\n}\n\n.btn-danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #E57373;\n box-shadow: var(--md-elevation-2);\n}\n\n.btn-danger[_ngcontent-%COMP%]:active:not(:disabled) {\n background: #EF9A9A;\n transform: scale(0.98);\n}\n\n.btn-sm[_ngcontent-%COMP%] {\n padding: 0.5rem 0.875rem;\n font-size: 0.8125rem;\n min-height: 36px;\n}\n\n\n\n\n\n.badge-system[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--md-corner-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n background: var(--md-secondary-container);\n color: #7A4D0C;\n border: 1px solid var(--md-secondary);\n}\n\n.badge-custom[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--md-corner-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n background: var(--md-tertiary-container);\n color: #1B5E20;\n border: 1px solid var(--md-tertiary);\n}\n\n\n\n\n\nbutton[_ngcontent-%COMP%]:focus-visible, \ninput[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n\n\n\n\n@media (prefers-reduced-motion: reduce) {\n *[_ngcontent-%COMP%], \n *[_ngcontent-%COMP%]::before, \n *[_ngcontent-%COMP%]::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n\n\n\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n\n\n@media (max-width: 639px) {\n .notification-preferences-container[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .notification-types-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 1rem;\n }\n\n .card-header[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .card-body[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .delivery-checkboxes[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .channel-checkbox[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .actions[_ngcontent-%COMP%] {\n flex-direction: column;\n padding: 1rem;\n }\n\n .actions[_ngcontent-%COMP%] .btn[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: center;\n }\n}\n\n@media (min-width: 640px) and (max-width: 767px) {\n .notification-types-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}\n\n@media (min-width: 768px) {\n .notification-preferences-container[_ngcontent-%COMP%] {\n padding: 2rem;\n }\n\n .notification-types-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));\n }\n}\n\n@media (min-width: 1024px) {\n .notification-types-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));\n gap: 1.5rem;\n }\n}"] });
377
+ } }, dependencies: [i2.CheckboxControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.LoadingComponent], styles: ["\n\n\n\n\n\n\n\n[_nghost-%COMP%] {\n display: block;\n width: 100%;\n}\n\n\n\n\n\n.notification-preferences-container[_ngcontent-%COMP%] {\n padding: 1.5rem;\n max-width: 1200px;\n margin: 0 auto;\n background: var(--mj-bg-page);\n}\n\n\n\n\n\n.content[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 3rem 1.5rem;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 4rem;\n color: var(--mj-border-strong);\n margin-bottom: 1.5rem;\n display: block;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n font-weight: 500;\n color: var(--mj-text-muted);\n margin: 0;\n}\n\n\n\n\n\n.notification-types-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));\n gap: 1.25rem;\n margin-bottom: 1.5rem;\n}\n\n\n\n\n\n.notification-type-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-radius: 12px;\n border-left: 4px solid var(--mj-border-strong);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.notification-type-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n border-color: var(--mj-brand-primary);\n}\n\n.notification-type-card.changed[_ngcontent-%COMP%] {\n border-left-color: var(--mj-brand-primary) !important;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.08);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n\n\n\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n gap: 1rem;\n padding: 1.25rem;\n border-bottom: 1px solid var(--mj-border-strong);\n align-items: flex-start;\n}\n\n.icon-wrapper[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: transform 0.2s;\n}\n\n.notification-type-card[_ngcontent-%COMP%]:hover .icon-wrapper[_ngcontent-%COMP%] {\n transform: scale(1.05);\n}\n\n.icon-wrapper[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n}\n\n.header-text[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.header-text[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 0.375rem 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.type-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mj-text-muted);\n line-height: 1.4;\n}\n\n\n\n\n\n.card-body[_ngcontent-%COMP%] {\n padding: 1.25rem;\n}\n\n.preference-row[_ngcontent-%COMP%] {\n margin-bottom: 1rem;\n}\n\n.preference-row[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n.delivery-label[_ngcontent-%COMP%] {\n display: block;\n font-weight: 600;\n margin-bottom: 0.75rem;\n font-size: 0.875rem;\n color: var(--mj-text-primary);\n letter-spacing: 0.01em;\n}\n\n\n\n\n\n.delivery-checkboxes[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.channel-checkbox[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 0.75rem 1rem;\n border: 2px solid var(--mj-border-strong);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n user-select: none;\n background: var(--mj-bg-page);\n min-height: 44px;\n}\n\n.channel-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n margin: 0;\n}\n\n.channel-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%]:disabled {\n cursor: not-allowed;\n}\n\n.channel-checkbox[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 1rem;\n transition: color 0.2s;\n}\n\n.channel-checkbox[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:hover:not(:has(input:disabled)) {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:hover:not(:has(input:disabled)) i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:has(input:checked) {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:has(input:checked) i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:has(input:disabled) {\n opacity: 0.5;\n cursor: not-allowed;\n background: var(--mj-bg-surface-sunken);\n}\n\n.channel-checkbox[_ngcontent-%COMP%]:focus-within {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n\n\n\n\n.info-message[_ngcontent-%COMP%] {\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-status-warning);\n border-radius: 8px;\n font-size: 0.8125rem;\n display: flex;\n gap: 0.75rem;\n align-items: flex-start;\n line-height: 1.4;\n color: var(--mj-text-primary);\n}\n\n.info-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 1rem;\n margin-top: 0.1rem;\n flex-shrink: 0;\n}\n\n\n\n\n\n.metadata-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.625rem;\n align-items: center;\n font-size: 0.8125rem;\n color: var(--mj-text-muted);\n padding-top: 0.75rem;\n margin-top: 0.75rem;\n border-top: 1px solid var(--mj-border-strong);\n}\n\n.metadata-row[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 0.875rem;\n flex-shrink: 0;\n}\n\n.metadata-text[_ngcontent-%COMP%] {\n line-height: 1.4;\n}\n\n\n\n\n\n.actions[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-start;\n gap: 0.75rem;\n padding: 1.25rem;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n border: 1px solid var(--mj-border-strong);\n margin-top: 1.5rem;\n}\n\n\n\n\n\n.btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n border: none;\n border-radius: 9999px;\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n min-height: 44px;\n}\n\n.btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1rem;\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-border-strong);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-bg-surface);\n border-color: var(--mj-brand-primary);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n transform: scale(0.98);\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-bg-surface);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n}\n\n.btn-primary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-brand-primary);\n transform: scale(0.98);\n}\n\n.btn-ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--mj-text-muted);\n border: none;\n}\n\n.btn-ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-bg-surface);\n}\n\n.btn-ghost[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-brand-primary);\n transform: scale(0.98);\n}\n\n.btn-danger[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-bg-surface);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.btn-danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-status-error);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n}\n\n.btn-danger[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-status-error);\n transform: scale(0.98);\n}\n\n.btn-sm[_ngcontent-%COMP%] {\n padding: 0.5rem 0.875rem;\n font-size: 0.8125rem;\n min-height: 36px;\n}\n\n\n\n\n\n.badge-system[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: 9999px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n border: 1px solid var(--mj-status-warning);\n}\n\n.badge-custom[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: 9999px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border: 1px solid var(--mj-status-success);\n}\n\n\n\n\n\nbutton[_ngcontent-%COMP%]:focus-visible, \ninput[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n\n\n\n\n@media (prefers-reduced-motion: reduce) {\n *[_ngcontent-%COMP%], \n *[_ngcontent-%COMP%]::before, \n *[_ngcontent-%COMP%]::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n\n\n\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n\n\n@media (max-width: 639px) {\n .notification-preferences-container[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .notification-types-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 1rem;\n }\n\n .card-header[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .card-body[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .delivery-checkboxes[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .channel-checkbox[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .actions[_ngcontent-%COMP%] {\n flex-direction: column;\n padding: 1rem;\n }\n\n .actions[_ngcontent-%COMP%] .btn[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: center;\n }\n}\n\n@media (min-width: 640px) and (max-width: 767px) {\n .notification-types-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}\n\n@media (min-width: 768px) {\n .notification-preferences-container[_ngcontent-%COMP%] {\n padding: 2rem;\n }\n\n .notification-types-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));\n }\n}\n\n@media (min-width: 1024px) {\n .notification-types-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));\n gap: 1.5rem;\n }\n}"] });
378
378
  }
379
379
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(NotificationPreferencesComponent, [{
380
380
  type: Component,
381
- args: [{ standalone: false, selector: 'mj-notification-preferences', template: "<div class=\"notification-preferences-container\">\n @if (loading) {\n <mj-loading text=\"Loading notification preferences...\"></mj-loading>\n } @else {\n <div class=\"content\">\n @if (viewModels.length === 0) {\n <!-- Empty state -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-bell-slash\"></i>\n <p>No notification types configured yet.</p>\n </div>\n } @else {\n <!-- Notification type cards -->\n <div class=\"notification-types-grid\">\n @for (vm of viewModels; track vm.type.ID) {\n <article class=\"notification-type-card\"\n [class.changed]=\"vm.changed\"\n role=\"region\"\n [attr.aria-label]=\"'Notification settings for ' + vm.type.Name\">\n\n <div class=\"card-header\" [style.border-left-color]=\"getTypeColor(vm.type)\">\n <div class=\"icon-wrapper\" [style.background-color]=\"getTypeColor(vm.type) + '20'\">\n <i [class]=\"'fa-solid ' + getTypeIcon(vm.type)\" [style.color]=\"getTypeColor(vm.type)\" [attr.aria-hidden]=\"true\"></i>\n </div>\n <div class=\"header-text\">\n <h4>{{ vm.type.Name }}</h4>\n <p class=\"type-description\">{{ vm.type.Description }}</p>\n </div>\n </div>\n\n <div class=\"card-body\">\n <!-- Delivery channel checkboxes -->\n <div class=\"preference-row\">\n <label class=\"delivery-label\" [attr.id]=\"'delivery-label-' + vm.type.ID\">Delivery Channels</label>\n\n <div class=\"delivery-checkboxes\" role=\"group\" [attr.aria-labelledby]=\"'delivery-label-' + vm.type.ID\">\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.inAppEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable in-app notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-bell\" aria-hidden=\"true\"></i>\n <span>In-App</span>\n </label>\n\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.emailEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable email notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span>Email</span>\n </label>\n\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.smsEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable SMS notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-mobile\" aria-hidden=\"true\"></i>\n <span>SMS</span>\n </label>\n </div>\n\n @if (!getAllowUserPreference(vm.type)) {\n <div class=\"info-message\" role=\"alert\" aria-live=\"polite\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n <span>This notification type's delivery channels cannot be customized.</span>\n </div>\n }\n </div>\n\n <!-- Auto-expire info -->\n @if (getTypeAutoExpireDays(vm.type)) {\n <div class=\"metadata-row\">\n <i class=\"fa-solid fa-clock\" aria-hidden=\"true\"></i>\n <span class=\"metadata-text\">\n Auto-marks as read after {{ getTypeAutoExpireDays(vm.type) }} day(s)\n </span>\n </div>\n }\n </div>\n </article>\n }\n </div>\n }\n\n <!-- Action buttons -->\n @if (hasChanges) {\n <div class=\"actions\" role=\"group\" aria-label=\"Save or cancel changes\">\n <button class=\"btn btn-secondary\"\n type=\"button\"\n (click)=\"cancel()\"\n [disabled]=\"saving\"\n [attr.aria-busy]=\"saving\">\n Cancel\n </button>\n <button class=\"btn btn-primary\"\n type=\"button\"\n (click)=\"save()\"\n [disabled]=\"saving\"\n [attr.aria-busy]=\"saving\">\n @if (saving) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n } @else {\n <i class=\"fa-solid fa-save\" aria-hidden=\"true\"></i>\n }\n <span>{{ saving ? 'Saving...' : 'Save Preferences' }}</span>\n </button>\n </div>\n }\n </div>\n }\n</div>\n", styles: ["/* =============================================================================\n Notification Preferences Component - Material Design 3\n Following MD3 Design System Guidelines\n ============================================================================= */\n\n/* MD3 Color Tokens */\n:host {\n /* Primary - Deep Blue */\n --md-primary: #0076B6;\n --md-on-primary: #FFFFFF;\n --md-primary-container: #AAE7FD;\n --md-on-primary-container: #001F2A;\n\n /* Secondary - Light Orange */\n --md-secondary: #F5A623;\n --md-on-secondary: #FFFFFF;\n --md-secondary-container: #FFECD6;\n --md-on-secondary-container: #2D1600;\n\n /* Tertiary - Light Green */\n --md-tertiary: #4CAF50;\n --md-on-tertiary: #FFFFFF;\n --md-tertiary-container: #C8E6C9;\n --md-on-tertiary-container: #002204;\n\n /* Error - Red */\n --md-error: #D32F2F;\n --md-on-error: #FFFFFF;\n --md-error-container: #FFCDD2;\n --md-on-error-container: #410002;\n\n /* Warning - Amber */\n --md-warning: #FFC107;\n --md-on-warning: #2D1600;\n --md-warning-container: #FFF3CD;\n --md-on-warning-container: #856404;\n\n /* Surface Colors */\n --md-surface: #FAFCFF;\n --md-surface-container-lowest: #FFFFFF;\n --md-surface-container-low: #F3F5F9;\n --md-surface-container: #EDF0F4;\n --md-surface-container-high: #E7EAEE;\n --md-surface-container-highest: #E1E3E8;\n --md-on-surface: #191C20;\n --md-on-surface-variant: #43474E;\n --md-outline: #74777F;\n --md-outline-variant: #C4C6D0;\n\n /* Elevation (Box Shadows) */\n --md-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n --md-elevation-2: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n --md-elevation-3: 0 4px 8px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.08);\n --md-elevation-4: 0 6px 12px rgba(0, 0, 0, 0.1), 0 12px 24px rgba(0, 0, 0, 0.08);\n --md-elevation-5: 0 8px 16px rgba(0, 0, 0, 0.12), 0 16px 32px rgba(0, 0, 0, 0.1);\n\n /* Corner Radii */\n --md-corner-extra-small: 4px;\n --md-corner-small: 8px;\n --md-corner-medium: 12px;\n --md-corner-large: 16px;\n --md-corner-extra-large: 28px;\n --md-corner-full: 9999px;\n\n /* Host element configuration */\n display: block;\n width: 100%;\n}\n\n/* -----------------------------------------------------------------------------\n Container & Layout\n ----------------------------------------------------------------------------- */\n.notification-preferences-container {\n padding: 1.5rem;\n max-width: 1200px;\n margin: 0 auto;\n background: var(--md-surface);\n}\n\n/* -----------------------------------------------------------------------------\n Loading State\n ----------------------------------------------------------------------------- */\n.content {\n animation: fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* -----------------------------------------------------------------------------\n Empty State\n ----------------------------------------------------------------------------- */\n.empty-state {\n text-align: center;\n padding: 3rem 1.5rem;\n}\n\n.empty-state i {\n font-size: 4rem;\n color: var(--md-outline-variant);\n margin-bottom: 1.5rem;\n display: block;\n}\n\n.empty-state p {\n font-size: 1.125rem;\n font-weight: 500;\n color: var(--md-on-surface-variant);\n margin: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Notification Types Grid\n ----------------------------------------------------------------------------- */\n.notification-types-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));\n gap: 1.25rem;\n margin-bottom: 1.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Notification Type Card\n ----------------------------------------------------------------------------- */\n.notification-type-card {\n background: var(--md-surface-container-lowest);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n border-left: 4px solid var(--md-outline-variant);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--md-elevation-1);\n}\n\n.notification-type-card:hover {\n box-shadow: var(--md-elevation-2);\n border-color: var(--md-primary);\n}\n\n.notification-type-card.changed {\n border-left-color: var(--md-primary) !important;\n border-color: var(--md-primary);\n box-shadow: var(--md-elevation-3);\n background: var(--md-primary-container);\n}\n\n/* -----------------------------------------------------------------------------\n Card Header\n ----------------------------------------------------------------------------- */\n.card-header {\n display: flex;\n gap: 1rem;\n padding: 1.25rem;\n border-bottom: 1px solid var(--md-outline-variant);\n align-items: flex-start;\n}\n\n.icon-wrapper {\n width: 48px;\n height: 48px;\n border-radius: var(--md-corner-small);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: transform 0.2s;\n}\n\n.notification-type-card:hover .icon-wrapper {\n transform: scale(1.05);\n}\n\n.icon-wrapper i {\n font-size: 1.5rem;\n}\n\n.header-text {\n flex: 1;\n min-width: 0;\n}\n\n.header-text h4 {\n margin: 0 0 0.375rem 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--md-on-surface);\n}\n\n.type-description {\n margin: 0;\n font-size: 0.875rem;\n color: var(--md-on-surface-variant);\n line-height: 1.4;\n}\n\n/* -----------------------------------------------------------------------------\n Card Body\n ----------------------------------------------------------------------------- */\n.card-body {\n padding: 1.25rem;\n}\n\n.preference-row {\n margin-bottom: 1rem;\n}\n\n.preference-row:last-child {\n margin-bottom: 0;\n}\n\n.delivery-label {\n display: block;\n font-weight: 600;\n margin-bottom: 0.75rem;\n font-size: 0.875rem;\n color: var(--md-on-surface);\n letter-spacing: 0.01em;\n}\n\n/* -----------------------------------------------------------------------------\n Delivery Channel Checkboxes\n ----------------------------------------------------------------------------- */\n.delivery-checkboxes {\n display: flex;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.channel-checkbox {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 0.75rem 1rem;\n border: 2px solid var(--md-outline-variant);\n border-radius: var(--md-corner-small);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n user-select: none;\n background: var(--md-surface);\n min-height: 44px;\n}\n\n.channel-checkbox input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--md-primary);\n margin: 0;\n}\n\n.channel-checkbox input[type=\"checkbox\"]:disabled {\n cursor: not-allowed;\n}\n\n.channel-checkbox i {\n color: var(--md-on-surface-variant);\n font-size: 1rem;\n transition: color 0.2s;\n}\n\n.channel-checkbox span {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--md-on-surface);\n}\n\n.channel-checkbox:hover:not(:has(input:disabled)) {\n border-color: var(--md-primary);\n background: var(--md-primary-container);\n}\n\n.channel-checkbox:hover:not(:has(input:disabled)) i {\n color: var(--md-primary);\n}\n\n.channel-checkbox:has(input:checked) {\n border-color: var(--md-primary);\n background: var(--md-primary-container);\n}\n\n.channel-checkbox:has(input:checked) i {\n color: var(--md-primary);\n}\n\n.channel-checkbox:has(input:disabled) {\n opacity: 0.5;\n cursor: not-allowed;\n background: var(--md-surface-container-low);\n}\n\n.channel-checkbox:focus-within {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Info Message\n ----------------------------------------------------------------------------- */\n.info-message {\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: var(--md-warning-container);\n border-left: 3px solid var(--md-warning);\n border-radius: var(--md-corner-small);\n font-size: 0.8125rem;\n display: flex;\n gap: 0.75rem;\n align-items: flex-start;\n line-height: 1.4;\n color: var(--md-on-warning-container);\n}\n\n.info-message i {\n color: var(--md-on-warning-container);\n font-size: 1rem;\n margin-top: 0.1rem;\n flex-shrink: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Metadata Row\n ----------------------------------------------------------------------------- */\n.metadata-row {\n display: flex;\n gap: 0.625rem;\n align-items: center;\n font-size: 0.8125rem;\n color: var(--md-on-surface-variant);\n padding-top: 0.75rem;\n margin-top: 0.75rem;\n border-top: 1px solid var(--md-outline-variant);\n}\n\n.metadata-row i {\n color: var(--md-on-surface-variant);\n font-size: 0.875rem;\n flex-shrink: 0;\n}\n\n.metadata-text {\n line-height: 1.4;\n}\n\n/* -----------------------------------------------------------------------------\n Action Buttons Section\n ----------------------------------------------------------------------------- */\n.actions {\n display: flex;\n justify-content: flex-start;\n gap: 0.75rem;\n padding: 1.25rem;\n background: var(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n border: 1px solid var(--md-outline-variant);\n margin-top: 1.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Button System - MD3 Patterns\n ----------------------------------------------------------------------------- */\n.btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n border: none;\n border-radius: var(--md-corner-full);\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n min-height: 44px;\n}\n\n.btn:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.btn i {\n font-size: 1rem;\n}\n\n.btn-secondary {\n background: var(--md-surface);\n color: var(--md-primary);\n border: 1px solid var(--md-outline);\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n}\n\n.btn-secondary:active:not(:disabled) {\n background: #005A8C;\n border-color: #005A8C;\n transform: scale(0.98);\n}\n\n.btn-primary {\n background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n.btn-primary:hover:not(:disabled) {\n background: #3395C8;\n box-shadow: var(--md-elevation-2);\n}\n\n.btn-primary:active:not(:disabled) {\n background: #4BA5D4;\n transform: scale(0.98);\n}\n\n.btn-ghost {\n background: transparent;\n color: var(--md-on-surface-variant);\n border: none;\n}\n\n.btn-ghost:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.btn-ghost:active:not(:disabled) {\n background: #005A8C;\n transform: scale(0.98);\n}\n\n.btn-danger {\n background: var(--md-error);\n color: var(--md-on-error);\n box-shadow: var(--md-elevation-1);\n}\n\n.btn-danger:hover:not(:disabled) {\n background: #E57373;\n box-shadow: var(--md-elevation-2);\n}\n\n.btn-danger:active:not(:disabled) {\n background: #EF9A9A;\n transform: scale(0.98);\n}\n\n.btn-sm {\n padding: 0.5rem 0.875rem;\n font-size: 0.8125rem;\n min-height: 36px;\n}\n\n/* -----------------------------------------------------------------------------\n Badge System - MD3 Patterns\n ----------------------------------------------------------------------------- */\n.badge-system {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--md-corner-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n background: var(--md-secondary-container);\n color: #7A4D0C;\n border: 1px solid var(--md-secondary);\n}\n\n.badge-custom {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--md-corner-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n background: var(--md-tertiary-container);\n color: #1B5E20;\n border: 1px solid var(--md-tertiary);\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Focus Indicators\n ----------------------------------------------------------------------------- */\nbutton:focus-visible,\ninput:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Reduced Motion\n ----------------------------------------------------------------------------- */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Animations\n ----------------------------------------------------------------------------- */\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* -----------------------------------------------------------------------------\n Responsive Design - Mobile First\n ----------------------------------------------------------------------------- */\n@media (max-width: 639px) {\n .notification-preferences-container {\n padding: 1rem;\n }\n\n .notification-types-grid {\n grid-template-columns: 1fr;\n gap: 1rem;\n }\n\n .card-header {\n padding: 1rem;\n }\n\n .card-body {\n padding: 1rem;\n }\n\n .delivery-checkboxes {\n flex-direction: column;\n }\n\n .channel-checkbox {\n width: 100%;\n }\n\n .actions {\n flex-direction: column;\n padding: 1rem;\n }\n\n .actions .btn {\n width: 100%;\n justify-content: center;\n }\n}\n\n@media (min-width: 640px) and (max-width: 767px) {\n .notification-types-grid {\n grid-template-columns: 1fr;\n }\n}\n\n@media (min-width: 768px) {\n .notification-preferences-container {\n padding: 2rem;\n }\n\n .notification-types-grid {\n grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));\n }\n}\n\n@media (min-width: 1024px) {\n .notification-types-grid {\n grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));\n gap: 1.5rem;\n }\n}\n"] }]
381
+ args: [{ standalone: false, selector: 'mj-notification-preferences', template: "<div class=\"notification-preferences-container\">\n @if (loading) {\n <mj-loading text=\"Loading notification preferences...\"></mj-loading>\n } @else {\n <div class=\"content\">\n @if (viewModels.length === 0) {\n <!-- Empty state -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-bell-slash\"></i>\n <p>No notification types configured yet.</p>\n </div>\n } @else {\n <!-- Notification type cards -->\n <div class=\"notification-types-grid\">\n @for (vm of viewModels; track vm.type.ID) {\n <article class=\"notification-type-card\"\n [class.changed]=\"vm.changed\"\n role=\"region\"\n [attr.aria-label]=\"'Notification settings for ' + vm.type.Name\">\n\n <div class=\"card-header\" [style.border-left-color]=\"getTypeColor(vm.type)\">\n <div class=\"icon-wrapper\" [style.background-color]=\"getTypeColor(vm.type) + '20'\">\n <i [class]=\"'fa-solid ' + getTypeIcon(vm.type)\" [style.color]=\"getTypeColor(vm.type)\" [attr.aria-hidden]=\"true\"></i>\n </div>\n <div class=\"header-text\">\n <h4>{{ vm.type.Name }}</h4>\n <p class=\"type-description\">{{ vm.type.Description }}</p>\n </div>\n </div>\n\n <div class=\"card-body\">\n <!-- Delivery channel checkboxes -->\n <div class=\"preference-row\">\n <label class=\"delivery-label\" [attr.id]=\"'delivery-label-' + vm.type.ID\">Delivery Channels</label>\n\n <div class=\"delivery-checkboxes\" role=\"group\" [attr.aria-labelledby]=\"'delivery-label-' + vm.type.ID\">\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.inAppEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable in-app notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-bell\" aria-hidden=\"true\"></i>\n <span>In-App</span>\n </label>\n\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.emailEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable email notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span>Email</span>\n </label>\n\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.smsEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable SMS notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-mobile\" aria-hidden=\"true\"></i>\n <span>SMS</span>\n </label>\n </div>\n\n @if (!getAllowUserPreference(vm.type)) {\n <div class=\"info-message\" role=\"alert\" aria-live=\"polite\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n <span>This notification type's delivery channels cannot be customized.</span>\n </div>\n }\n </div>\n\n <!-- Auto-expire info -->\n @if (getTypeAutoExpireDays(vm.type)) {\n <div class=\"metadata-row\">\n <i class=\"fa-solid fa-clock\" aria-hidden=\"true\"></i>\n <span class=\"metadata-text\">\n Auto-marks as read after {{ getTypeAutoExpireDays(vm.type) }} day(s)\n </span>\n </div>\n }\n </div>\n </article>\n }\n </div>\n }\n\n <!-- Action buttons -->\n @if (hasChanges) {\n <div class=\"actions\" role=\"group\" aria-label=\"Save or cancel changes\">\n <button class=\"btn btn-secondary\"\n type=\"button\"\n (click)=\"cancel()\"\n [disabled]=\"saving\"\n [attr.aria-busy]=\"saving\">\n Cancel\n </button>\n <button class=\"btn btn-primary\"\n type=\"button\"\n (click)=\"save()\"\n [disabled]=\"saving\"\n [attr.aria-busy]=\"saving\">\n @if (saving) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n } @else {\n <i class=\"fa-solid fa-save\" aria-hidden=\"true\"></i>\n }\n <span>{{ saving ? 'Saving...' : 'Save Preferences' }}</span>\n </button>\n </div>\n }\n </div>\n }\n</div>\n", styles: ["/* =============================================================================\n Notification Preferences Component\n Using MJ Design Tokens\n ============================================================================= */\n\n/* Host element configuration */\n:host {\n display: block;\n width: 100%;\n}\n\n/* -----------------------------------------------------------------------------\n Container & Layout\n ----------------------------------------------------------------------------- */\n.notification-preferences-container {\n padding: 1.5rem;\n max-width: 1200px;\n margin: 0 auto;\n background: var(--mj-bg-page);\n}\n\n/* -----------------------------------------------------------------------------\n Loading State\n ----------------------------------------------------------------------------- */\n.content {\n animation: fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* -----------------------------------------------------------------------------\n Empty State\n ----------------------------------------------------------------------------- */\n.empty-state {\n text-align: center;\n padding: 3rem 1.5rem;\n}\n\n.empty-state i {\n font-size: 4rem;\n color: var(--mj-border-strong);\n margin-bottom: 1.5rem;\n display: block;\n}\n\n.empty-state p {\n font-size: 1.125rem;\n font-weight: 500;\n color: var(--mj-text-muted);\n margin: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Notification Types Grid\n ----------------------------------------------------------------------------- */\n.notification-types-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));\n gap: 1.25rem;\n margin-bottom: 1.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Notification Type Card\n ----------------------------------------------------------------------------- */\n.notification-type-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-radius: 12px;\n border-left: 4px solid var(--mj-border-strong);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.notification-type-card:hover {\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n border-color: var(--mj-brand-primary);\n}\n\n.notification-type-card.changed {\n border-left-color: var(--mj-brand-primary) !important;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.08);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n/* -----------------------------------------------------------------------------\n Card Header\n ----------------------------------------------------------------------------- */\n.card-header {\n display: flex;\n gap: 1rem;\n padding: 1.25rem;\n border-bottom: 1px solid var(--mj-border-strong);\n align-items: flex-start;\n}\n\n.icon-wrapper {\n width: 48px;\n height: 48px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: transform 0.2s;\n}\n\n.notification-type-card:hover .icon-wrapper {\n transform: scale(1.05);\n}\n\n.icon-wrapper i {\n font-size: 1.5rem;\n}\n\n.header-text {\n flex: 1;\n min-width: 0;\n}\n\n.header-text h4 {\n margin: 0 0 0.375rem 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.type-description {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mj-text-muted);\n line-height: 1.4;\n}\n\n/* -----------------------------------------------------------------------------\n Card Body\n ----------------------------------------------------------------------------- */\n.card-body {\n padding: 1.25rem;\n}\n\n.preference-row {\n margin-bottom: 1rem;\n}\n\n.preference-row:last-child {\n margin-bottom: 0;\n}\n\n.delivery-label {\n display: block;\n font-weight: 600;\n margin-bottom: 0.75rem;\n font-size: 0.875rem;\n color: var(--mj-text-primary);\n letter-spacing: 0.01em;\n}\n\n/* -----------------------------------------------------------------------------\n Delivery Channel Checkboxes\n ----------------------------------------------------------------------------- */\n.delivery-checkboxes {\n display: flex;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.channel-checkbox {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 0.75rem 1rem;\n border: 2px solid var(--mj-border-strong);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n user-select: none;\n background: var(--mj-bg-page);\n min-height: 44px;\n}\n\n.channel-checkbox input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n margin: 0;\n}\n\n.channel-checkbox input[type=\"checkbox\"]:disabled {\n cursor: not-allowed;\n}\n\n.channel-checkbox i {\n color: var(--mj-text-muted);\n font-size: 1rem;\n transition: color 0.2s;\n}\n\n.channel-checkbox span {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.channel-checkbox:hover:not(:has(input:disabled)) {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.channel-checkbox:hover:not(:has(input:disabled)) i {\n color: var(--mj-brand-primary);\n}\n\n.channel-checkbox:has(input:checked) {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.channel-checkbox:has(input:checked) i {\n color: var(--mj-brand-primary);\n}\n\n.channel-checkbox:has(input:disabled) {\n opacity: 0.5;\n cursor: not-allowed;\n background: var(--mj-bg-surface-sunken);\n}\n\n.channel-checkbox:focus-within {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Info Message\n ----------------------------------------------------------------------------- */\n.info-message {\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-status-warning);\n border-radius: 8px;\n font-size: 0.8125rem;\n display: flex;\n gap: 0.75rem;\n align-items: flex-start;\n line-height: 1.4;\n color: var(--mj-text-primary);\n}\n\n.info-message i {\n color: var(--mj-status-warning);\n font-size: 1rem;\n margin-top: 0.1rem;\n flex-shrink: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Metadata Row\n ----------------------------------------------------------------------------- */\n.metadata-row {\n display: flex;\n gap: 0.625rem;\n align-items: center;\n font-size: 0.8125rem;\n color: var(--mj-text-muted);\n padding-top: 0.75rem;\n margin-top: 0.75rem;\n border-top: 1px solid var(--mj-border-strong);\n}\n\n.metadata-row i {\n color: var(--mj-text-muted);\n font-size: 0.875rem;\n flex-shrink: 0;\n}\n\n.metadata-text {\n line-height: 1.4;\n}\n\n/* -----------------------------------------------------------------------------\n Action Buttons Section\n ----------------------------------------------------------------------------- */\n.actions {\n display: flex;\n justify-content: flex-start;\n gap: 0.75rem;\n padding: 1.25rem;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n border: 1px solid var(--mj-border-strong);\n margin-top: 1.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Button System\n ----------------------------------------------------------------------------- */\n.btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n border: none;\n border-radius: 9999px;\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n min-height: 44px;\n}\n\n.btn:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.btn i {\n font-size: 1rem;\n}\n\n.btn-secondary {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-border-strong);\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-bg-surface);\n border-color: var(--mj-brand-primary);\n}\n\n.btn-secondary:active:not(:disabled) {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n transform: scale(0.98);\n}\n\n.btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-bg-surface);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n}\n\n.btn-primary:active:not(:disabled) {\n background: var(--mj-brand-primary);\n transform: scale(0.98);\n}\n\n.btn-ghost {\n background: transparent;\n color: var(--mj-text-muted);\n border: none;\n}\n\n.btn-ghost:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-bg-surface);\n}\n\n.btn-ghost:active:not(:disabled) {\n background: var(--mj-brand-primary);\n transform: scale(0.98);\n}\n\n.btn-danger {\n background: var(--mj-status-error);\n color: var(--mj-bg-surface);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.btn-danger:hover:not(:disabled) {\n background: var(--mj-status-error);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n}\n\n.btn-danger:active:not(:disabled) {\n background: var(--mj-status-error);\n transform: scale(0.98);\n}\n\n.btn-sm {\n padding: 0.5rem 0.875rem;\n font-size: 0.8125rem;\n min-height: 36px;\n}\n\n/* -----------------------------------------------------------------------------\n Badge System\n ----------------------------------------------------------------------------- */\n.badge-system {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: 9999px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n border: 1px solid var(--mj-status-warning);\n}\n\n.badge-custom {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: 9999px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border: 1px solid var(--mj-status-success);\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Focus Indicators\n ----------------------------------------------------------------------------- */\nbutton:focus-visible,\ninput:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Reduced Motion\n ----------------------------------------------------------------------------- */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Animations\n ----------------------------------------------------------------------------- */\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* -----------------------------------------------------------------------------\n Responsive Design - Mobile First\n ----------------------------------------------------------------------------- */\n@media (max-width: 639px) {\n .notification-preferences-container {\n padding: 1rem;\n }\n\n .notification-types-grid {\n grid-template-columns: 1fr;\n gap: 1rem;\n }\n\n .card-header {\n padding: 1rem;\n }\n\n .card-body {\n padding: 1rem;\n }\n\n .delivery-checkboxes {\n flex-direction: column;\n }\n\n .channel-checkbox {\n width: 100%;\n }\n\n .actions {\n flex-direction: column;\n padding: 1rem;\n }\n\n .actions .btn {\n width: 100%;\n justify-content: center;\n }\n}\n\n@media (min-width: 640px) and (max-width: 767px) {\n .notification-types-grid {\n grid-template-columns: 1fr;\n }\n}\n\n@media (min-width: 768px) {\n .notification-preferences-container {\n padding: 2rem;\n }\n\n .notification-types-grid {\n grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));\n }\n}\n\n@media (min-width: 1024px) {\n .notification-types-grid {\n grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));\n gap: 1.5rem;\n }\n}\n"] }]
382
382
  }], () => [{ type: i1.SharedService }], null); })();
383
383
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(NotificationPreferencesComponent, { className: "NotificationPreferencesComponent", filePath: "src/lib/notification-preferences/notification-preferences.component.ts", lineNumber: 52 }); })();
384
384
  //# sourceMappingURL=notification-preferences.component.js.map