@koobiq/components 20.4.2 → 21.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/accordion/accordion-trigger.scss +3 -10
- package/accordion/accordion.scss +4 -6
- package/actions-panel/actions-panel-container.scss +45 -1
- package/alert/alert.component.scss +3 -2
- package/app-switcher/_app-switcher-theme.scss +0 -4
- package/app-switcher/app-switcher-dropdown-app.scss +3 -2
- package/app-switcher/app-switcher-dropdown-site.scss +2 -1
- package/app-switcher/{kbq-app-switcher-list-item.scss → app-switcher-list-item.scss} +18 -4
- package/app-switcher/app-switcher-tokens.scss +15 -0
- package/app-switcher/app-switcher.scss +14 -4
- package/autocomplete/autocomplete.scss +7 -6
- package/badge/badge.component.scss +5 -8
- package/breadcrumbs/breadcrumbs.scss +25 -10
- package/button/_button-base.scss +30 -7
- package/button/_button-theme.scss +16 -0
- package/button/button-group.scss +7 -0
- package/button/button-tokens.scss +0 -2
- package/button/button.scss +34 -2
- package/button-toggle/_button-toggle-theme.scss +7 -2
- package/button-toggle/button-toggle.scss +65 -15
- package/checkbox/_checkbox-theme.scss +4 -3
- package/checkbox/checkbox.scss +3 -6
- package/clamped-text/clamped-text.scss +6 -2
- package/code-block/code-block-tokens.scss +0 -224
- package/code-block/code-block.scss +20 -9
- package/content-panel/content-panel-aside.scss +3 -2
- package/content-panel/content-panel-container.scss +37 -0
- package/content-panel/content-panel.scss +4 -3
- package/core/highlight/_highlight-theme.scss +3 -1
- package/core/option/action-container.scss +2 -2
- package/core/option/action.scss +2 -1
- package/core/option/option.scss +2 -1
- package/core/pop-up/_pop-up.scss +0 -37
- package/core/selection/pseudo-checkbox/pseudo-checkbox.scss +5 -10
- package/core/styles/_core.scss +3 -0
- package/core/styles/_koobiq-theme.scss +5 -6
- package/core/styles/common/_animation.scss +44 -16
- package/core/styles/common/_groups-mixins.scss +21 -19
- package/core/styles/common/_groups.scss +4 -32
- package/core/styles/common/_index.scss +0 -2
- package/core/styles/common/_link.scss +117 -0
- package/core/styles/common/_list.scss +0 -26
- package/core/styles/common/_overlay.scss +8 -10
- package/core/styles/common/_rtl.scss +0 -14
- package/core/styles/common/_select.scss +33 -15
- package/core/styles/common/_squircle.scss +63 -0
- package/core/styles/common/_tokens.scss +0 -11
- package/core/styles/common/_vendor-prefixes.scss +0 -20
- package/core/styles/functions/_timing.scss +0 -22
- package/core/styles/theming/_scrollbar-theme.scss +6 -1
- package/core/styles/theming/_theming.scss +13 -65
- package/core/styles/typography/_index.scss +0 -1
- package/core/styles/typography/_typography.scss +0 -143
- package/core/styles/visual/_body.scss +1 -6
- package/core/styles/visual/_layout.scss +0 -12
- package/datepicker/calendar-body.scss +3 -1
- package/datepicker/calendar-header.scss +0 -1
- package/datepicker/datepicker-content.scss +33 -1
- package/datepicker/datepicker-toggle.scss +0 -38
- package/dl/dl-tokens.scss +10 -0
- package/dl/dl.scss +113 -13
- package/dropdown/_dropdown-theme.scss +4 -16
- package/dropdown/dropdown-item.scss +4 -10
- package/dropdown/dropdown.scss +2 -1
- package/empty-state/_empty-state-theme.scss +10 -4
- package/empty-state/empty-state-tokens.scss +4 -4
- package/empty-state/empty-state.scss +4 -0
- package/fesm2022/koobiq-components-accordion.mjs +347 -229
- package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
- package/fesm2022/koobiq-components-actions-panel.mjs +302 -187
- package/fesm2022/koobiq-components-actions-panel.mjs.map +1 -1
- package/fesm2022/koobiq-components-alert.mjs +39 -39
- package/fesm2022/koobiq-components-alert.mjs.map +1 -1
- package/fesm2022/koobiq-components-app-switcher.mjs +677 -367
- package/fesm2022/koobiq-components-app-switcher.mjs.map +1 -1
- package/fesm2022/koobiq-components-autocomplete.mjs +620 -253
- package/fesm2022/koobiq-components-autocomplete.mjs.map +1 -1
- package/fesm2022/koobiq-components-badge.mjs +46 -48
- package/fesm2022/koobiq-components-badge.mjs.map +1 -1
- package/fesm2022/koobiq-components-breadcrumbs.mjs +221 -169
- package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
- package/fesm2022/koobiq-components-button-toggle.mjs +565 -196
- package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
- package/fesm2022/koobiq-components-button.mjs +332 -116
- package/fesm2022/koobiq-components-button.mjs.map +1 -1
- package/fesm2022/koobiq-components-checkbox.mjs +172 -132
- package/fesm2022/koobiq-components-checkbox.mjs.map +1 -1
- package/fesm2022/koobiq-components-clamped-text.mjs +165 -158
- package/fesm2022/koobiq-components-clamped-text.mjs.map +1 -1
- package/fesm2022/koobiq-components-code-block.mjs +791 -609
- package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
- package/fesm2022/koobiq-components-content-panel.mjs +260 -143
- package/fesm2022/koobiq-components-content-panel.mjs.map +1 -1
- package/fesm2022/koobiq-components-core.mjs +4342 -1595
- package/fesm2022/koobiq-components-core.mjs.map +1 -1
- package/fesm2022/koobiq-components-datepicker.mjs +1713 -1606
- package/fesm2022/koobiq-components-datepicker.mjs.map +1 -1
- package/fesm2022/koobiq-components-divider.mjs +73 -36
- package/fesm2022/koobiq-components-divider.mjs.map +1 -1
- package/fesm2022/koobiq-components-dl.mjs +447 -89
- package/fesm2022/koobiq-components-dl.mjs.map +1 -1
- package/fesm2022/koobiq-components-dropdown.mjs +703 -599
- package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
- package/fesm2022/koobiq-components-dynamic-translation.mjs +20 -20
- package/fesm2022/koobiq-components-dynamic-translation.mjs.map +1 -1
- package/fesm2022/koobiq-components-ellipsis-center.mjs +46 -31
- package/fesm2022/koobiq-components-ellipsis-center.mjs.map +1 -1
- package/fesm2022/koobiq-components-empty-state.mjs +116 -60
- package/fesm2022/koobiq-components-empty-state.mjs.map +1 -1
- package/fesm2022/koobiq-components-file-upload.mjs +550 -290
- package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
- package/fesm2022/koobiq-components-filter-bar.mjs +2871 -2595
- package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
- package/fesm2022/koobiq-components-flag.mjs +79 -24
- package/fesm2022/koobiq-components-flag.mjs.map +1 -1
- package/fesm2022/koobiq-components-form-field.mjs +389 -525
- package/fesm2022/koobiq-components-form-field.mjs.map +1 -1
- package/fesm2022/koobiq-components-icon.mjs +400 -149
- package/fesm2022/koobiq-components-icon.mjs.map +1 -1
- package/fesm2022/koobiq-components-inline-edit.mjs +429 -212
- package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
- package/fesm2022/koobiq-components-input.mjs +601 -459
- package/fesm2022/koobiq-components-input.mjs.map +1 -1
- package/fesm2022/koobiq-components-link-deprecated.mjs +196 -0
- package/fesm2022/koobiq-components-link-deprecated.mjs.map +1 -0
- package/fesm2022/koobiq-components-link.mjs +328 -125
- package/fesm2022/koobiq-components-link.mjs.map +1 -1
- package/fesm2022/koobiq-components-list.mjs +583 -433
- package/fesm2022/koobiq-components-list.mjs.map +1 -1
- package/fesm2022/koobiq-components-loader-overlay.mjs +167 -68
- package/fesm2022/koobiq-components-loader-overlay.mjs.map +1 -1
- package/fesm2022/koobiq-components-markdown.mjs +55 -78
- package/fesm2022/koobiq-components-markdown.mjs.map +1 -1
- package/fesm2022/koobiq-components-modal.mjs +853 -475
- package/fesm2022/koobiq-components-modal.mjs.map +1 -1
- package/fesm2022/koobiq-components-navbar.mjs +895 -556
- package/fesm2022/koobiq-components-navbar.mjs.map +1 -1
- package/fesm2022/koobiq-components-notification-center.mjs +680 -310
- package/fesm2022/koobiq-components-notification-center.mjs.map +1 -1
- package/fesm2022/koobiq-components-overflow-items.mjs +46 -64
- package/fesm2022/koobiq-components-overflow-items.mjs.map +1 -1
- package/fesm2022/koobiq-components-popover.mjs +684 -285
- package/fesm2022/koobiq-components-popover.mjs.map +1 -1
- package/fesm2022/koobiq-components-progress-bar.mjs +87 -33
- package/fesm2022/koobiq-components-progress-bar.mjs.map +1 -1
- package/fesm2022/koobiq-components-progress-spinner.mjs +52 -43
- package/fesm2022/koobiq-components-progress-spinner.mjs.map +1 -1
- package/fesm2022/koobiq-components-radio.mjs +450 -231
- package/fesm2022/koobiq-components-radio.mjs.map +1 -1
- package/fesm2022/koobiq-components-resizer.mjs +127 -21
- package/fesm2022/koobiq-components-resizer.mjs.map +1 -1
- package/fesm2022/koobiq-components-scrollbar-deprecated.mjs +299 -0
- package/fesm2022/koobiq-components-scrollbar-deprecated.mjs.map +1 -0
- package/fesm2022/koobiq-components-scrollbar.mjs +745 -222
- package/fesm2022/koobiq-components-scrollbar.mjs.map +1 -1
- package/fesm2022/koobiq-components-search-expandable.mjs +288 -126
- package/fesm2022/koobiq-components-search-expandable.mjs.map +1 -1
- package/fesm2022/koobiq-components-select.mjs +883 -693
- package/fesm2022/koobiq-components-select.mjs.map +1 -1
- package/fesm2022/koobiq-components-sidebar.mjs +207 -88
- package/fesm2022/koobiq-components-sidebar.mjs.map +1 -1
- package/fesm2022/koobiq-components-sidepanel.mjs +689 -296
- package/fesm2022/koobiq-components-sidepanel.mjs.map +1 -1
- package/fesm2022/koobiq-components-skeleton.mjs +815 -41
- package/fesm2022/koobiq-components-skeleton.mjs.map +1 -1
- package/fesm2022/koobiq-components-split-button.mjs +109 -88
- package/fesm2022/koobiq-components-split-button.mjs.map +1 -1
- package/fesm2022/koobiq-components-splitter-deprecated.mjs +591 -0
- package/fesm2022/koobiq-components-splitter-deprecated.mjs.map +1 -0
- package/fesm2022/koobiq-components-splitter.mjs +890 -501
- package/fesm2022/koobiq-components-splitter.mjs.map +1 -1
- package/fesm2022/koobiq-components-table.mjs +63 -49
- package/fesm2022/koobiq-components-table.mjs.map +1 -1
- package/fesm2022/koobiq-components-tabs.mjs +1062 -603
- package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
- package/fesm2022/koobiq-components-tags.mjs +886 -733
- package/fesm2022/koobiq-components-tags.mjs.map +1 -1
- package/fesm2022/koobiq-components-textarea.mjs +213 -185
- package/fesm2022/koobiq-components-textarea.mjs.map +1 -1
- package/fesm2022/koobiq-components-time-range.mjs +299 -147
- package/fesm2022/koobiq-components-time-range.mjs.map +1 -1
- package/fesm2022/koobiq-components-timepicker.mjs +233 -245
- package/fesm2022/koobiq-components-timepicker.mjs.map +1 -1
- package/fesm2022/koobiq-components-timezone.mjs +344 -142
- package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
- package/fesm2022/koobiq-components-title.mjs +229 -145
- package/fesm2022/koobiq-components-title.mjs.map +1 -1
- package/fesm2022/koobiq-components-toast.mjs +463 -143
- package/fesm2022/koobiq-components-toast.mjs.map +1 -1
- package/fesm2022/koobiq-components-toggle.mjs +177 -130
- package/fesm2022/koobiq-components-toggle.mjs.map +1 -1
- package/fesm2022/koobiq-components-tooltip.mjs +657 -214
- package/fesm2022/koobiq-components-tooltip.mjs.map +1 -1
- package/fesm2022/koobiq-components-top-bar.mjs +61 -32
- package/fesm2022/koobiq-components-top-bar.mjs.map +1 -1
- package/fesm2022/koobiq-components-tree-select.mjs +734 -488
- package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
- package/fesm2022/koobiq-components-tree.mjs +1700 -617
- package/fesm2022/koobiq-components-tree.mjs.map +1 -1
- package/fesm2022/koobiq-components-username.mjs +290 -135
- package/fesm2022/koobiq-components-username.mjs.map +1 -1
- package/file-upload/dropzone.scss +31 -3
- package/file-upload/file-upload-tokens.scss +2 -22
- package/file-upload/file-upload.scss +6 -0
- package/file-upload/multiple-file-upload.component.scss +14 -12
- package/file-upload/single-file-upload.component.scss +3 -2
- package/filter-bar/filters.scss +7 -0
- package/filter-bar/pipes/base-pipe.scss +3 -3
- package/filter-bar/pipes/pipe-date.scss +8 -1
- package/flag/flag-tokens.scss +22 -0
- package/flag/flag.scss +34 -21
- package/form-field/{_fiedset-theme.scss → _fieldset-theme.scss} +1 -5
- package/form-field/_form-field-theme.scss +4 -9
- package/form-field/cleaner.scss +3 -1
- package/form-field/fieldset.scss +3 -4
- package/form-field/form-field.scss +26 -21
- package/form-field/password-toggle.scss +3 -1
- package/icon/_icon-button-theme.scss +7 -0
- package/icon/_icon-theme.scss +10 -7
- package/icon/icon-button.scss +0 -2
- package/icon/icon-tokens.scss +12 -9
- package/inline-edit/inline-edit.scss +40 -54
- package/input/input.scss +4 -0
- package/link/{_link-theme.scss → deprecated/_link-theme.scss} +11 -6
- package/link/deprecated/link-tokens.scss +27 -0
- package/link/link-tokens.scss +6 -25
- package/link/link.scss +137 -0
- package/list/list.scss +3 -2
- package/loader-overlay/_loader-overlay-theme.scss +19 -10
- package/loader-overlay/loader-overlay-tokens.scss +0 -2
- package/loader-overlay/loader-overlay.scss +7 -1
- package/markdown/_markdown-theme.scss +16 -0
- package/markdown/markdown-tokens.scss +5 -0
- package/markdown/markdown.scss +2 -1
- package/modal/_modal-animation.scss +23 -14
- package/modal/modal-tokens.scss +2 -1
- package/modal/modal.scss +35 -31
- package/navbar/_navbar-item_horizontal.scss +8 -6
- package/navbar/_navbar-item_vertical.scss +18 -6
- package/navbar/_navbar-theme.scss +9 -1
- package/navbar/navbar-brand.scss +8 -6
- package/navbar/navbar-divider.scss +1 -1
- package/navbar/navbar-item.scss +8 -9
- package/navbar/navbar-toggle.scss +3 -3
- package/navbar/navbar-tokens.scss +14 -0
- package/navbar/navbar.scss +1 -2
- package/navbar/vertical-navbar.scss +2 -2
- package/notification-center/_notification-center-theme.scss +11 -6
- package/notification-center/notification-center-tokens.scss +33 -0
- package/notification-center/notification-center.scss +58 -20
- package/notification-center/notification-item.scss +15 -6
- package/package.json +112 -81
- package/popover/popover-tokens.scss +0 -2
- package/popover/popover.scss +41 -19
- package/prebuilt-themes/theme.css +1 -1
- package/progress-bar/_progress-bar-theme.scss +20 -3
- package/progress-bar/progress-bar-tokens.scss +3 -0
- package/progress-bar/progress-bar.scss +36 -8
- package/progress-spinner/progress-spinner.scss +4 -3
- package/radio/_radio-theme.scss +21 -4
- package/radio/radio-tokens.scss +7 -3
- package/radio/radio.scss +55 -8
- package/schematics/collection.json +415 -18
- package/schematics/migrations/accordion-state-saving-default/README.md +60 -0
- package/schematics/migrations/accordion-state-saving-default/data.cjs +75 -0
- package/schematics/migrations/accordion-state-saving-default/index.cjs +61 -0
- package/schematics/migrations/accordion-state-saving-default/schema.json +15 -0
- package/schematics/migrations/actions-panel-overlay-container/README.md +35 -0
- package/schematics/migrations/actions-panel-overlay-container/data.cjs +47 -0
- package/schematics/migrations/actions-panel-overlay-container/index.cjs +55 -0
- package/schematics/migrations/actions-panel-overlay-container/schema.json +15 -0
- package/schematics/migrations/alert-signals/README.md +13 -7
- package/schematics/migrations/alert-signals/{data.js → data.cjs} +3 -0
- package/schematics/migrations/alert-signals/index.cjs +221 -0
- package/schematics/migrations/angular-animations-removal/README.md +46 -0
- package/schematics/migrations/angular-animations-removal/data.cjs +150 -0
- package/schematics/migrations/angular-animations-removal/index.cjs +21 -0
- package/schematics/migrations/angular-animations-removal/schema.json +15 -0
- package/schematics/migrations/app-switcher-signals/README.md +88 -0
- package/schematics/migrations/app-switcher-signals/data.cjs +136 -0
- package/schematics/migrations/app-switcher-signals/index.cjs +366 -0
- package/schematics/migrations/app-switcher-signals/schema.json +20 -0
- package/schematics/migrations/autocomplete-panel-width-auto/README.md +2 -2
- package/schematics/migrations/autocomplete-panel-width-auto/{index.js → index.cjs} +6 -5
- package/schematics/migrations/autocomplete-signals/README.md +92 -0
- package/schematics/migrations/autocomplete-signals/data.cjs +149 -0
- package/schematics/migrations/autocomplete-signals/index.cjs +707 -0
- package/schematics/migrations/autocomplete-signals/schema.json +20 -0
- package/schematics/migrations/badge-signals/README.md +77 -0
- package/schematics/migrations/badge-signals/data.cjs +109 -0
- package/schematics/migrations/badge-signals/index.cjs +694 -0
- package/schematics/migrations/badge-signals/schema.json +20 -0
- package/schematics/migrations/button-state-and-styles/README.md +129 -0
- package/schematics/migrations/button-state-and-styles/data.cjs +136 -0
- package/schematics/migrations/button-state-and-styles/index.cjs +221 -0
- package/schematics/migrations/button-state-and-styles/schema.json +20 -0
- package/schematics/migrations/button-supported-colors/README.md +73 -0
- package/schematics/migrations/button-supported-colors/data.cjs +106 -0
- package/schematics/migrations/button-supported-colors/index.cjs +261 -0
- package/schematics/migrations/button-supported-colors/schema.json +20 -0
- package/schematics/migrations/button-toggle-signals-and-aria/README.md +137 -0
- package/schematics/migrations/button-toggle-signals-and-aria/data.cjs +200 -0
- package/schematics/migrations/button-toggle-signals-and-aria/index.cjs +497 -0
- package/schematics/migrations/button-toggle-signals-and-aria/schema.json +20 -0
- package/schematics/migrations/button-truncation/README.md +110 -0
- package/schematics/migrations/button-truncation/data.cjs +88 -0
- package/schematics/migrations/button-truncation/index.cjs +270 -0
- package/schematics/migrations/button-truncation/schema.json +20 -0
- package/schematics/migrations/checkbox-signals/README.md +76 -0
- package/schematics/migrations/checkbox-signals/data.cjs +114 -0
- package/schematics/migrations/checkbox-signals/index.cjs +635 -0
- package/schematics/migrations/checkbox-signals/schema.json +20 -0
- package/schematics/migrations/clamped-text-disclosure/README.md +62 -0
- package/schematics/migrations/clamped-text-disclosure/data.cjs +101 -0
- package/schematics/migrations/clamped-text-disclosure/index.cjs +60 -0
- package/schematics/migrations/clamped-text-disclosure/schema.json +15 -0
- package/schematics/migrations/code-block-highlight-js-core/README.md +53 -0
- package/schematics/migrations/code-block-highlight-js-core/data.cjs +64 -0
- package/schematics/migrations/code-block-highlight-js-core/index.cjs +319 -0
- package/schematics/migrations/code-block-highlight-js-core/schema.json +20 -0
- package/schematics/migrations/code-block-signals/README.md +84 -0
- package/schematics/migrations/code-block-signals/data.cjs +121 -0
- package/schematics/migrations/code-block-signals/index.cjs +701 -0
- package/schematics/migrations/code-block-signals/schema.json +20 -0
- package/schematics/migrations/color-signals/README.md +46 -0
- package/schematics/migrations/color-signals/data.cjs +131 -0
- package/schematics/migrations/color-signals/index.cjs +20 -0
- package/schematics/migrations/color-signals/schema.json +20 -0
- package/schematics/migrations/core-mixins-removal/README.md +20 -0
- package/schematics/migrations/core-mixins-removal/data.cjs +27 -0
- package/schematics/migrations/core-mixins-removal/index.cjs +18 -0
- package/schematics/migrations/core-mixins-removal/schema.json +15 -0
- package/schematics/migrations/css-selectors/README.md +2 -2
- package/schematics/migrations/css-selectors/{index.js → index.cjs} +4 -3
- package/schematics/migrations/datepicker-signals/README.md +24 -0
- package/schematics/migrations/datepicker-signals/data.cjs +49 -0
- package/schematics/migrations/datepicker-signals/index.cjs +18 -0
- package/schematics/migrations/datepicker-signals/schema.json +15 -0
- package/schematics/migrations/deprecated-icons/README.md +2 -2
- package/schematics/migrations/deprecated-icons/{index.js → index.cjs} +8 -7
- package/schematics/migrations/design-tokens-v4/README.md +75 -0
- package/schematics/migrations/design-tokens-v4/index.cjs +60 -0
- package/schematics/migrations/design-tokens-v4/schema.json +15 -0
- package/schematics/migrations/divider-signals-and-aria/README.md +47 -0
- package/schematics/migrations/divider-signals-and-aria/data.cjs +62 -0
- package/schematics/migrations/divider-signals-and-aria/index.cjs +212 -0
- package/schematics/migrations/divider-signals-and-aria/schema.json +15 -0
- package/schematics/migrations/dl-attribute-coercion/README.md +59 -0
- package/schematics/migrations/dl-attribute-coercion/data.cjs +85 -0
- package/schematics/migrations/dl-attribute-coercion/index.cjs +162 -0
- package/schematics/migrations/dl-attribute-coercion/schema.json +15 -0
- package/schematics/migrations/dl-standalone-names/README.md +49 -0
- package/schematics/migrations/dl-standalone-names/data.cjs +44 -0
- package/schematics/migrations/dl-standalone-names/index.cjs +322 -0
- package/schematics/migrations/dl-standalone-names/schema.json +20 -0
- package/schematics/migrations/dropdown-demote-overlay/README.md +137 -0
- package/schematics/migrations/dropdown-demote-overlay/data.cjs +84 -0
- package/schematics/migrations/dropdown-demote-overlay/index.cjs +289 -0
- package/schematics/migrations/dropdown-demote-overlay/schema.json +20 -0
- package/schematics/migrations/dropdown-signals/README.md +83 -0
- package/schematics/migrations/dropdown-signals/data.cjs +152 -0
- package/schematics/migrations/dropdown-signals/index.cjs +20 -0
- package/schematics/migrations/dropdown-signals/schema.json +20 -0
- package/schematics/migrations/empty-state-error-color/README.md +84 -0
- package/schematics/migrations/empty-state-error-color/data.cjs +85 -0
- package/schematics/migrations/empty-state-error-color/index.cjs +72 -0
- package/schematics/migrations/empty-state-error-color/schema.json +15 -0
- package/schematics/migrations/empty-state-size-attr/README.md +2 -2
- package/schematics/migrations/empty-state-size-attr/{index.js → index.cjs} +6 -5
- package/schematics/migrations/file-upload-cva-and-primitives/README.md +70 -0
- package/schematics/migrations/file-upload-cva-and-primitives/data.cjs +97 -0
- package/schematics/migrations/file-upload-cva-and-primitives/index.cjs +61 -0
- package/schematics/migrations/file-upload-cva-and-primitives/schema.json +15 -0
- package/schematics/migrations/file-upload-deprecated-outputs/README.md +90 -0
- package/schematics/migrations/file-upload-deprecated-outputs/data.cjs +20 -0
- package/schematics/migrations/file-upload-deprecated-outputs/index.cjs +71 -0
- package/schematics/migrations/file-upload-deprecated-outputs/schema.json +20 -0
- package/schematics/migrations/filter-bar-rename-action/README.md +183 -0
- package/schematics/migrations/filter-bar-rename-action/data.cjs +151 -0
- package/schematics/migrations/filter-bar-rename-action/index.cjs +178 -0
- package/schematics/migrations/filter-bar-rename-action/schema.json +20 -0
- package/schematics/migrations/filter-bar-signals/README.md +27 -16
- package/schematics/migrations/filter-bar-signals/{data.js → data.cjs} +1 -2
- package/schematics/migrations/filter-bar-signals/index.cjs +225 -0
- package/schematics/migrations/filter-bar-state-saving-default/README.md +53 -0
- package/schematics/migrations/filter-bar-state-saving-default/data.cjs +87 -0
- package/schematics/migrations/filter-bar-state-saving-default/index.cjs +62 -0
- package/schematics/migrations/filter-bar-state-saving-default/schema.json +15 -0
- package/schematics/migrations/flag-inner-html/README.md +67 -0
- package/schematics/migrations/flag-inner-html/data.cjs +58 -0
- package/schematics/migrations/flag-inner-html/index.cjs +62 -0
- package/schematics/migrations/flag-inner-html/schema.json +15 -0
- package/schematics/migrations/form-field-signals/README.md +125 -0
- package/schematics/migrations/form-field-signals/data.cjs +288 -0
- package/schematics/migrations/form-field-signals/index.cjs +383 -0
- package/schematics/migrations/form-field-signals/schema.json +20 -0
- package/schematics/migrations/icon-semantics-and-api/README.md +65 -0
- package/schematics/migrations/icon-semantics-and-api/data.cjs +97 -0
- package/schematics/migrations/icon-semantics-and-api/index.cjs +65 -0
- package/schematics/migrations/icon-semantics-and-api/schema.json +15 -0
- package/schematics/migrations/icons-replacement/README.md +5 -5
- package/schematics/migrations/icons-replacement/{index.js → index.cjs} +4 -3
- package/schematics/migrations/inline-edit-a11y-and-types/README.md +82 -0
- package/schematics/migrations/inline-edit-a11y-and-types/data.cjs +117 -0
- package/schematics/migrations/inline-edit-a11y-and-types/index.cjs +98 -0
- package/schematics/migrations/inline-edit-a11y-and-types/schema.json +20 -0
- package/schematics/migrations/input-number-surface/README.md +140 -0
- package/schematics/migrations/input-number-surface/data.cjs +135 -0
- package/schematics/migrations/input-number-surface/index.cjs +293 -0
- package/schematics/migrations/input-number-surface/schema.json +20 -0
- package/schematics/migrations/input-signals/README.md +20 -0
- package/schematics/migrations/input-signals/data.cjs +30 -0
- package/schematics/migrations/input-signals/index.cjs +18 -0
- package/schematics/migrations/input-signals/schema.json +15 -0
- package/schematics/migrations/link-deprecated-path/README.md +144 -0
- package/schematics/migrations/link-deprecated-path/index.cjs +20 -0
- package/schematics/migrations/link-deprecated-path/schema.json +20 -0
- package/schematics/migrations/link-signals/README.md +71 -0
- package/schematics/migrations/link-signals/data.cjs +116 -0
- package/schematics/migrations/link-signals/index.cjs +416 -0
- package/schematics/migrations/link-signals/schema.json +20 -0
- package/schematics/migrations/list-signals/README.md +22 -0
- package/schematics/migrations/list-signals/data.cjs +35 -0
- package/schematics/migrations/list-signals/index.cjs +18 -0
- package/schematics/migrations/list-signals/schema.json +15 -0
- package/schematics/migrations/list-tree-multiple-input/README.md +105 -0
- package/schematics/migrations/list-tree-multiple-input/data.cjs +74 -0
- package/schematics/migrations/list-tree-multiple-input/index.cjs +222 -0
- package/schematics/migrations/list-tree-multiple-input/schema.json +20 -0
- package/schematics/migrations/loader-overlay-signals/README.md +62 -0
- package/schematics/migrations/loader-overlay-signals/data.cjs +101 -0
- package/schematics/migrations/loader-overlay-signals/index.cjs +698 -0
- package/schematics/migrations/loader-overlay-signals/schema.json +20 -0
- package/schematics/migrations/loader-overlay-size-attr/README.md +2 -2
- package/schematics/migrations/loader-overlay-size-attr/{index.js → index.cjs} +6 -5
- package/schematics/migrations/locale-configuration-providers/README.md +163 -0
- package/schematics/migrations/locale-configuration-providers/data.cjs +257 -0
- package/schematics/migrations/locale-configuration-providers/index.cjs +295 -0
- package/schematics/migrations/locale-configuration-providers/schema.json +20 -0
- package/schematics/migrations/mandatory-peer-dependencies/README.md +70 -0
- package/schematics/migrations/mandatory-peer-dependencies/index.cjs +43 -0
- package/schematics/migrations/mandatory-peer-dependencies/schema.json +15 -0
- package/schematics/migrations/markdown-signals/README.md +58 -0
- package/schematics/migrations/markdown-signals/data.cjs +79 -0
- package/schematics/migrations/markdown-signals/index.cjs +640 -0
- package/schematics/migrations/markdown-signals/schema.json +20 -0
- package/schematics/migrations/modal-dialog-semantics/README.md +106 -0
- package/schematics/migrations/modal-dialog-semantics/data.cjs +110 -0
- package/schematics/migrations/modal-dialog-semantics/index.cjs +59 -0
- package/schematics/migrations/modal-dialog-semantics/schema.json +15 -0
- package/schematics/migrations/modal-signals/README.md +88 -0
- package/schematics/migrations/modal-signals/data.cjs +132 -0
- package/schematics/migrations/modal-signals/index.cjs +20 -0
- package/schematics/migrations/modal-signals/schema.json +20 -0
- package/schematics/migrations/navbar-signals-and-aria/README.md +111 -0
- package/schematics/migrations/navbar-signals-and-aria/data.cjs +198 -0
- package/schematics/migrations/navbar-signals-and-aria/index.cjs +569 -0
- package/schematics/migrations/navbar-signals-and-aria/schema.json +20 -0
- package/schematics/migrations/new-icons-pack/README.md +10 -10
- package/schematics/migrations/new-icons-pack/{index.js → index.cjs} +8 -7
- package/schematics/migrations/notification-center-signals/README.md +67 -0
- package/schematics/migrations/notification-center-signals/data.cjs +66 -0
- package/schematics/migrations/notification-center-signals/index.cjs +62 -0
- package/schematics/migrations/notification-center-signals/schema.json +15 -0
- package/schematics/migrations/option-signals/README.md +37 -0
- package/schematics/migrations/option-signals/data.cjs +86 -0
- package/schematics/migrations/option-signals/index.cjs +20 -0
- package/schematics/migrations/option-signals/schema.json +20 -0
- package/schematics/migrations/popover-leave-delay/README.md +51 -0
- package/schematics/migrations/popover-leave-delay/data.cjs +61 -0
- package/schematics/migrations/popover-leave-delay/index.cjs +55 -0
- package/schematics/migrations/popover-leave-delay/schema.json +15 -0
- package/schematics/migrations/progress-bar-percentage-and-aria/README.md +54 -0
- package/schematics/migrations/progress-bar-percentage-and-aria/data.cjs +76 -0
- package/schematics/migrations/progress-bar-percentage-and-aria/index.cjs +59 -0
- package/schematics/migrations/progress-bar-percentage-and-aria/schema.json +15 -0
- package/schematics/migrations/progress-spinner-signals/README.md +72 -0
- package/schematics/migrations/progress-spinner-signals/data.cjs +83 -0
- package/schematics/migrations/progress-spinner-signals/index.cjs +695 -0
- package/schematics/migrations/progress-spinner-signals/schema.json +20 -0
- package/schematics/migrations/query-list-signals/README.md +32 -0
- package/schematics/migrations/query-list-signals/data.cjs +70 -0
- package/schematics/migrations/query-list-signals/index.cjs +18 -0
- package/schematics/migrations/query-list-signals/schema.json +15 -0
- package/schematics/migrations/radio-signals-and-aria/README.md +82 -0
- package/schematics/migrations/radio-signals-and-aria/data.cjs +163 -0
- package/schematics/migrations/radio-signals-and-aria/index.cjs +40 -0
- package/schematics/migrations/radio-signals-and-aria/schema.json +20 -0
- package/schematics/migrations/read-state-dwell-handlers/README.md +125 -0
- package/schematics/migrations/read-state-dwell-handlers/data.cjs +45 -0
- package/schematics/migrations/read-state-dwell-handlers/index.cjs +216 -0
- package/schematics/migrations/read-state-dwell-handlers/schema.json +20 -0
- package/schematics/migrations/scrollbar-deprecated-path/README.md +128 -0
- package/schematics/migrations/scrollbar-deprecated-path/index.cjs +21 -0
- package/schematics/migrations/scrollbar-deprecated-path/schema.json +20 -0
- package/schematics/migrations/select-signal-inputs/README.md +61 -0
- package/schematics/migrations/select-signal-inputs/data.cjs +99 -0
- package/schematics/migrations/select-signal-inputs/index.cjs +58 -0
- package/schematics/migrations/select-signal-inputs/schema.json +15 -0
- package/schematics/migrations/sidepanel-non-modal-behavior/README.md +57 -0
- package/schematics/migrations/sidepanel-non-modal-behavior/data.cjs +111 -0
- package/schematics/migrations/sidepanel-non-modal-behavior/index.cjs +58 -0
- package/schematics/migrations/sidepanel-non-modal-behavior/schema.json +15 -0
- package/schematics/migrations/signal-inputs-subclasses/README.md +28 -0
- package/schematics/migrations/signal-inputs-subclasses/data.cjs +69 -0
- package/schematics/migrations/signal-inputs-subclasses/index.cjs +18 -0
- package/schematics/migrations/signal-inputs-subclasses/schema.json +15 -0
- package/schematics/migrations/split-button-optional-disabled/README.md +47 -0
- package/schematics/migrations/split-button-optional-disabled/data.cjs +53 -0
- package/schematics/migrations/split-button-optional-disabled/index.cjs +58 -0
- package/schematics/migrations/split-button-optional-disabled/schema.json +15 -0
- package/schematics/migrations/splitter-deprecated-path/README.md +136 -0
- package/schematics/migrations/splitter-deprecated-path/index.cjs +21 -0
- package/schematics/migrations/splitter-deprecated-path/schema.json +20 -0
- package/schematics/migrations/state-saving-default/README.md +67 -0
- package/schematics/migrations/state-saving-default/data.cjs +88 -0
- package/schematics/migrations/state-saving-default/index.cjs +63 -0
- package/schematics/migrations/state-saving-default/schema.json +15 -0
- package/schematics/migrations/table-cell-content/README.md +55 -0
- package/schematics/migrations/table-cell-content/data.cjs +66 -0
- package/schematics/migrations/table-cell-content/index.cjs +67 -0
- package/schematics/migrations/table-cell-content/schema.json +15 -0
- package/schematics/migrations/tabs-signals-and-aria/README.md +93 -0
- package/schematics/migrations/tabs-signals-and-aria/data.cjs +139 -0
- package/schematics/migrations/tabs-signals-and-aria/index.cjs +66 -0
- package/schematics/migrations/tabs-signals-and-aria/schema.json +15 -0
- package/schematics/migrations/tag-list-cleaner/README.md +58 -0
- package/schematics/migrations/tag-list-cleaner/data.cjs +42 -0
- package/schematics/migrations/tag-list-cleaner/index.cjs +197 -0
- package/schematics/migrations/tag-list-cleaner/schema.json +20 -0
- package/schematics/migrations/tag-slots/README.md +41 -0
- package/schematics/migrations/tag-slots/index.cjs +191 -0
- package/schematics/migrations/tag-slots/schema.json +20 -0
- package/schematics/migrations/tags-signals/README.md +85 -0
- package/schematics/migrations/tags-signals/data.cjs +103 -0
- package/schematics/migrations/tags-signals/index.cjs +674 -0
- package/schematics/migrations/tags-signals/schema.json +20 -0
- package/schematics/migrations/textarea-signals/README.md +72 -0
- package/schematics/migrations/textarea-signals/data.cjs +121 -0
- package/schematics/migrations/textarea-signals/index.cjs +380 -0
- package/schematics/migrations/textarea-signals/schema.json +20 -0
- package/schematics/migrations/time-range-title-for/README.md +164 -0
- package/schematics/migrations/time-range-title-for/data.cjs +139 -0
- package/schematics/migrations/time-range-title-for/index.cjs +164 -0
- package/schematics/migrations/time-range-title-for/schema.json +20 -0
- package/schematics/migrations/timepicker-signals/README.md +78 -0
- package/schematics/migrations/timepicker-signals/data.cjs +82 -0
- package/schematics/migrations/timepicker-signals/index.cjs +710 -0
- package/schematics/migrations/timepicker-signals/schema.json +20 -0
- package/schematics/migrations/timezone-grouping-utils/README.md +73 -0
- package/schematics/migrations/timezone-grouping-utils/data.cjs +101 -0
- package/schematics/migrations/timezone-grouping-utils/index.cjs +65 -0
- package/schematics/migrations/timezone-grouping-utils/schema.json +15 -0
- package/schematics/migrations/title-encapsulation/README.md +49 -0
- package/schematics/migrations/title-encapsulation/data.cjs +69 -0
- package/schematics/migrations/title-encapsulation/index.cjs +58 -0
- package/schematics/migrations/title-encapsulation/schema.json +15 -0
- package/schematics/migrations/toast-stack-and-defaults/README.md +102 -0
- package/schematics/migrations/toast-stack-and-defaults/data.cjs +79 -0
- package/schematics/migrations/toast-stack-and-defaults/index.cjs +54 -0
- package/schematics/migrations/toast-stack-and-defaults/schema.json +15 -0
- package/schematics/migrations/tooltip-pointer-events-and-types/README.md +53 -0
- package/schematics/migrations/tooltip-pointer-events-and-types/data.cjs +89 -0
- package/schematics/migrations/tooltip-pointer-events-and-types/index.cjs +61 -0
- package/schematics/migrations/tooltip-pointer-events-and-types/schema.json +15 -0
- package/schematics/migrations/top-bar-container-selectors/README.md +111 -0
- package/schematics/migrations/top-bar-container-selectors/data.cjs +56 -0
- package/schematics/migrations/top-bar-container-selectors/index.cjs +85 -0
- package/schematics/migrations/top-bar-container-selectors/schema.json +20 -0
- package/schematics/migrations/tree-select-signals/README.md +61 -0
- package/schematics/migrations/tree-select-signals/data.cjs +106 -0
- package/schematics/migrations/tree-select-signals/index.cjs +59 -0
- package/schematics/migrations/tree-select-signals/schema.json +15 -0
- package/schematics/migrations/tree-signals/README.md +82 -0
- package/schematics/migrations/tree-signals/data.cjs +123 -0
- package/schematics/migrations/tree-signals/index.cjs +55 -0
- package/schematics/migrations/tree-signals/schema.json +15 -0
- package/schematics/migrations/tree-state-saving-default/README.md +66 -0
- package/schematics/migrations/tree-state-saving-default/data.cjs +78 -0
- package/schematics/migrations/tree-state-saving-default/index.cjs +61 -0
- package/schematics/migrations/tree-state-saving-default/schema.json +15 -0
- package/schematics/migrations/username-pipe-injection/README.md +59 -0
- package/schematics/migrations/username-pipe-injection/data.cjs +78 -0
- package/schematics/migrations/username-pipe-injection/index.cjs +59 -0
- package/schematics/migrations/username-pipe-injection/schema.json +15 -0
- package/schematics/migrations/v20-upgrade/README.md +36 -16
- package/schematics/migrations/v20-upgrade/{data.js → data.cjs} +124 -77
- package/schematics/migrations/v20-upgrade/index.cjs +19 -0
- package/schematics/migrations/v21-upgrade/README.md +271 -0
- package/schematics/migrations/v21-upgrade/data.cjs +1371 -0
- package/schematics/migrations/v21-upgrade/index.cjs +95 -0
- package/schematics/migrations/v21-upgrade/schema.json +20 -0
- package/schematics/migrations/zoneless-change-detection/README.md +30 -0
- package/schematics/migrations/zoneless-change-detection/data.cjs +29 -0
- package/schematics/migrations/zoneless-change-detection/index.cjs +21 -0
- package/schematics/migrations/zoneless-change-detection/schema.json +15 -0
- package/schematics/migrations.json +401 -6
- package/schematics/ng-add/index.cjs +266 -0
- package/schematics/ng-add/schema.json +15 -0
- package/schematics/utils/{angular-parsing.js → angular-parsing.cjs} +2 -2
- package/schematics/utils/deprecated-path-migration.cjs +62 -0
- package/schematics/utils/html-config.cjs +148 -0
- package/schematics/utils/{icon-migration.js → icon-migration.cjs} +2 -2
- package/schematics/utils/list-item-pattern.cjs +16 -0
- package/schematics/utils/{package-config.js → package-config.cjs} +3 -32
- package/schematics/utils/project-files.cjs +25 -0
- package/schematics/utils/replacement-driver.cjs +337 -0
- package/schematics/utils/safe-rule.cjs +23 -0
- package/schematics/utils/signal-members-migration.cjs +779 -0
- package/schematics/utils/tag-patterns.cjs +21 -0
- package/schematics/utils/template-ref-access.cjs +155 -0
- package/schematics/utils/{typescript.js → typescript.cjs} +1 -1
- package/schematics/utils/warn-only-migration.cjs +52 -0
- package/schematics/utils/workspace-styles.cjs +123 -0
- package/scrollbar/{_scrollbar-component-theme.scss → deprecated/_scrollbar-component-theme.scss} +1 -1
- package/scrollbar/{scrollbar.component.scss → deprecated/scrollbar.component.scss} +1 -1
- package/scrollbar/native-scrollbar.scss +68 -0
- package/scrollbar/scrollbar-tokens.scss +13 -22
- package/scrollbar/scrollbar-track.scss +94 -0
- package/scrollbar/scrollbar-viewport.scss +33 -0
- package/scrollbar/scrollbar.scss +24 -0
- package/search-expandable/search-expandable-tokens.scss +4 -0
- package/search-expandable/search-expandable.scss +4 -2
- package/select/_select-theme.scss +3 -16
- package/select/select.scss +0 -6
- package/sidebar/sidebar.scss +20 -0
- package/sidepanel/_sidepanel-theme.scss +1 -1
- package/sidepanel/sidepanel-tokens.scss +7 -1
- package/sidepanel/sidepanel.scss +41 -5
- package/skeleton/skeleton-presets.scss +350 -0
- package/skeleton/skeleton-tokens.scss +127 -0
- package/skeleton/skeleton.scss +53 -45
- package/split-button/_split-button-theme.scss +4 -4
- package/split-button/split-button.scss +2 -6
- package/splitter/{_splitter-theme.scss → deprecated/_splitter-theme.scss} +1 -1
- package/splitter/deprecated/splitter.scss +51 -0
- package/splitter/splitter-tokens.scss +19 -0
- package/splitter/splitter.scss +148 -28
- package/table/_table-theme.scss +13 -12
- package/table/table-tokens.scss +8 -0
- package/table/table.scss +47 -22
- package/tabs/_tabs-common.scss +14 -14
- package/tabs/_tabs-theme.scss +4 -5
- package/tabs/tab-body.scss +49 -1
- package/tabs/tab-header.scss +2 -1
- package/tags/tag-list.scss +4 -0
- package/tags/tag.scss +19 -1
- package/time-range/time-range.scss +9 -0
- package/timezone/timezone-option.component.scss +4 -7
- package/timezone/timezone-select.component.scss +3 -0
- package/toast/_toast-theme.scss +1 -4
- package/toast/toast-container.component.scss +19 -13
- package/toast/toast-tokens.scss +12 -6
- package/toast/toast.component.scss +42 -19
- package/toggle/_toggle-theme.scss +4 -10
- package/toggle/toggle.scss +67 -26
- package/tooltip/_tooltip-theme.scss +7 -1
- package/tooltip/tooltip-tokens.scss +1 -2
- package/tooltip/tooltip.scss +55 -9
- package/top-bar/top-bar-tokens.scss +13 -2
- package/top-bar/top-bar.scss +24 -19
- package/tree/_tree-theme.scss +0 -1
- package/tree/toggle.scss +5 -9
- package/tree/tree-option.scss +2 -4
- package/tree/tree-tokens.scss +2 -1
- package/tree/tree.scss +3 -5
- package/tree-select/_tree-select-theme.scss +4 -15
- package/tree-select/tree-select-tokens.scss +16 -0
- package/tree-select/tree-select.scss +0 -6
- package/{accordion/index.d.ts → types/koobiq-components-accordion.d.ts} +102 -84
- package/{actions-panel/index.d.ts → types/koobiq-components-actions-panel.d.ts} +44 -59
- package/{alert/index.d.ts → types/koobiq-components-alert.d.ts} +8 -3
- package/types/koobiq-components-app-switcher.d.ts +406 -0
- package/types/koobiq-components-autocomplete.d.ts +443 -0
- package/{badge/index.d.ts → types/koobiq-components-badge.d.ts} +25 -20
- package/{breadcrumbs/index.d.ts → types/koobiq-components-breadcrumbs.d.ts} +97 -46
- package/types/koobiq-components-button-toggle.d.ts +340 -0
- package/types/koobiq-components-button.d.ts +296 -0
- package/types/koobiq-components-checkbox.d.ts +172 -0
- package/types/koobiq-components-clamped-text.d.ts +184 -0
- package/{code-block/index.d.ts → types/koobiq-components-code-block.d.ts} +150 -88
- package/{content-panel/index.d.ts → types/koobiq-components-content-panel.d.ts} +81 -25
- package/{core/index.d.ts → types/koobiq-components-core.d.ts} +2827 -865
- package/{datepicker/index.d.ts → types/koobiq-components-datepicker.d.ts} +161 -116
- package/types/koobiq-components-divider.d.ts +43 -0
- package/types/koobiq-components-dl.d.ts +235 -0
- package/{dropdown/index.d.ts → types/koobiq-components-dropdown.d.ts} +245 -239
- package/types/koobiq-components-ellipsis-center.d.ts +85 -0
- package/types/koobiq-components-empty-state.d.ts +106 -0
- package/{file-upload/index.d.ts → types/koobiq-components-file-upload.d.ts} +214 -107
- package/{filter-bar/index.d.ts → types/koobiq-components-filter-bar.d.ts} +410 -495
- package/types/koobiq-components-flag.d.ts +68 -0
- package/{form-field/index.d.ts → types/koobiq-components-form-field.d.ts} +167 -191
- package/types/koobiq-components-icon.d.ts +333 -0
- package/{inline-edit/index.d.ts → types/koobiq-components-inline-edit.d.ts} +109 -46
- package/types/koobiq-components-input.d.ts +477 -0
- package/types/koobiq-components-link-deprecated.d.ts +101 -0
- package/types/koobiq-components-link.d.ts +176 -0
- package/{list/index.d.ts → types/koobiq-components-list.d.ts} +162 -99
- package/types/koobiq-components-loader-overlay.d.ts +101 -0
- package/{markdown/index.d.ts → types/koobiq-components-markdown.d.ts} +16 -24
- package/types/koobiq-components-modal.d.ts +666 -0
- package/types/koobiq-components-navbar.d.ts +569 -0
- package/types/koobiq-components-notification-center.d.ts +500 -0
- package/{overflow-items/index.d.ts → types/koobiq-components-overflow-items.d.ts} +8 -22
- package/types/koobiq-components-popover.d.ts +468 -0
- package/types/koobiq-components-progress-bar.d.ts +67 -0
- package/{progress-spinner/index.d.ts → types/koobiq-components-progress-spinner.d.ts} +33 -10
- package/types/koobiq-components-radio.d.ts +294 -0
- package/{resizer/index.d.ts → types/koobiq-components-resizer.d.ts} +37 -2
- package/{scrollbar/index.d.ts → types/koobiq-components-scrollbar-deprecated.d.ts} +18 -1
- package/types/koobiq-components-scrollbar.d.ts +154 -0
- package/types/koobiq-components-search-expandable.d.ts +164 -0
- package/{select/index.d.ts → types/koobiq-components-select.d.ts} +360 -167
- package/types/koobiq-components-sidebar.d.ts +152 -0
- package/types/koobiq-components-sidepanel.d.ts +436 -0
- package/types/koobiq-components-skeleton.d.ts +234 -0
- package/types/koobiq-components-split-button.d.ts +65 -0
- package/{splitter/index.d.ts → types/koobiq-components-splitter-deprecated.d.ts} +44 -1
- package/types/koobiq-components-splitter.d.ts +406 -0
- package/types/koobiq-components-table.d.ts +44 -0
- package/types/koobiq-components-tabs.d.ts +888 -0
- package/{tags/index.d.ts → types/koobiq-components-tags.d.ts} +249 -133
- package/types/koobiq-components-textarea.d.ts +178 -0
- package/{time-range/index.d.ts → types/koobiq-components-time-range.d.ts} +135 -62
- package/types/koobiq-components-timepicker.d.ts +223 -0
- package/types/koobiq-components-timezone.d.ts +266 -0
- package/types/koobiq-components-title.d.ts +184 -0
- package/types/koobiq-components-toast.d.ts +289 -0
- package/types/koobiq-components-toggle.d.ts +121 -0
- package/types/koobiq-components-tooltip.d.ts +610 -0
- package/types/koobiq-components-top-bar.d.ts +61 -0
- package/types/koobiq-components-tree-select.d.ts +670 -0
- package/types/koobiq-components-tree.d.ts +1339 -0
- package/types/koobiq-components-username.d.ts +340 -0
- package/username/_username-theme.scss +35 -0
- package/username/username.scss +10 -34
- package/app-switcher/index.d.ts +0 -276
- package/autocomplete/index.d.ts +0 -286
- package/button/index.d.ts +0 -153
- package/button-toggle/index.d.ts +0 -162
- package/checkbox/index.d.ts +0 -163
- package/clamped-text/index.d.ts +0 -146
- package/core/styles/_tokens.scss +0 -7
- package/core/styles/common/_clearfix.scss +0 -13
- package/core/styles/common/_popup.scss +0 -6
- package/core/styles/functions/_index.scss +0 -3
- package/core/styles/functions/_number.scss +0 -60
- package/core/styles/functions/_string.scss +0 -18
- package/core/styles/theming/scrollbar-tokens.scss +0 -25
- package/core/styles/typography/_typography-utils.scss +0 -84
- package/divider/index.d.ts +0 -20
- package/dl/index.d.ts +0 -45
- package/ellipsis-center/index.d.ts +0 -71
- package/empty-state/index.d.ts +0 -45
- package/flag/index.d.ts +0 -44
- package/icon/index.d.ts +0 -200
- package/input/index.d.ts +0 -354
- package/link/index.d.ts +0 -56
- package/loader-overlay/index.d.ts +0 -57
- package/modal/index.d.ts +0 -339
- package/navbar/index.d.ts +0 -372
- package/notification-center/index.d.ts +0 -323
- package/popover/index.d.ts +0 -182
- package/prebuilt-themes/dark-theme.css +0 -1
- package/prebuilt-themes/light-theme.css +0 -1
- package/progress-bar/index.d.ts +0 -31
- package/radio/index.d.ts +0 -203
- package/schematics/migrations/alert-signals/index.js +0 -353
- package/schematics/migrations/filter-bar-signals/index.js +0 -319
- package/schematics/migrations/v20-upgrade/index.js +0 -225
- package/schematics/ng-add/index.js +0 -39
- package/search-expandable/index.d.ts +0 -101
- package/sidebar/index.d.ts +0 -94
- package/sidepanel/index.d.ts +0 -272
- package/skeleton/index.d.ts +0 -26
- package/split-button/index.d.ts +0 -46
- package/table/index.d.ts +0 -25
- package/tabs/index.d.ts +0 -677
- package/textarea/index.d.ts +0 -138
- package/timepicker/index.d.ts +0 -197
- package/timezone/index.d.ts +0 -125
- package/title/index.d.ts +0 -139
- package/toast/index.d.ts +0 -178
- package/toggle/index.d.ts +0 -104
- package/tooltip/index.d.ts +0 -335
- package/top-bar/index.d.ts +0 -33
- package/tree/index.d.ts +0 -802
- package/tree-select/index.d.ts +0 -475
- package/username/index.d.ts +0 -194
- /package/schematics/migrations/css-selectors/{data.js → data.cjs} +0 -0
- /package/schematics/migrations/deprecated-icons/{data.js → data.cjs} +0 -0
- /package/schematics/migrations/icons-replacement/{data.js → data.cjs} +0 -0
- /package/schematics/migrations/new-icons-pack/{data.js → data.cjs} +0 -0
- /package/schematics/utils/{ast.js → ast.cjs} +0 -0
- /package/schematics/utils/{messages.js → messages.cjs} +0 -0
- /package/{dynamic-translation/index.d.ts → types/koobiq-components-dynamic-translation.d.ts} +0 -0
- /package/{index.d.ts → types/koobiq-components.d.ts} +0 -0
|
@@ -1,192 +1,255 @@
|
|
|
1
|
+
import { _IdGenerator, FocusMonitor, InputModalityDetector, CdkTrapFocus, ConfigurableFocusTrapFactory, FocusTrapFactory, FOCUS_TRAP_INERT_STRATEGY } from '@angular/cdk/a11y';
|
|
1
2
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
2
3
|
import { Overlay } from '@angular/cdk/overlay';
|
|
3
|
-
import {
|
|
4
|
+
import { ScrollDispatcher, CdkScrollable } from '@angular/cdk/scrolling';
|
|
5
|
+
import { NgTemplateOutlet, DOCUMENT } from '@angular/common';
|
|
4
6
|
import * as i0 from '@angular/core';
|
|
5
|
-
import { inject,
|
|
6
|
-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
7
|
+
import { inject, signal, computed, untracked, Injectable, InjectionToken, input, TemplateRef, ViewEncapsulation, ChangeDetectionStrategy, Component, RendererStyleFlags2, Injector, NgZone, viewChild, afterNextRender, forwardRef, numberAttribute, EventEmitter, booleanAttribute, Directive, NgModule } from '@angular/core';
|
|
8
|
+
import { takeUntilDestroyed, outputFromObservable } from '@angular/core/rxjs-interop';
|
|
7
9
|
import { KbqBadgeModule } from '@koobiq/components/badge';
|
|
8
10
|
import * as i3$1 from '@koobiq/components/button';
|
|
9
11
|
import { KbqButtonModule } from '@koobiq/components/button';
|
|
10
|
-
import * as i1
|
|
11
|
-
import {
|
|
12
|
+
import * as i1 from '@koobiq/components/core';
|
|
13
|
+
import { DateAdapter, DateFormatter, KBQ_LOCALE_SERVICE, ruRULocaleData, kbqLocaleConfigurationOverrideProvider, KbqReadStateDirective, PopUpPlacements, KbqPopUp, KbqLocaleOverridesDirective, KBQ_A11Y_LOCALE_CONFIGURATION, applyPopupMargins, KbqOverflowShadowContainer, KbqOverflowShadowTop, KbqOverflowShadowBottom, EmptyFocusTrapStrategy, KbqPopUpTrigger, PopUpTriggers, POSITION_TO_CSS_MAP, PopUpSizes, kbqSiblingPopupProvider } from '@koobiq/components/core';
|
|
12
14
|
import * as i4 from '@koobiq/components/divider';
|
|
13
15
|
import { KbqDividerModule } from '@koobiq/components/divider';
|
|
14
16
|
import * as i5 from '@koobiq/components/dropdown';
|
|
15
17
|
import { KbqDropdownModule } from '@koobiq/components/dropdown';
|
|
16
|
-
import * as
|
|
18
|
+
import * as i2 from '@koobiq/components/icon';
|
|
17
19
|
import { KbqIconModule } from '@koobiq/components/icon';
|
|
18
20
|
import * as i7 from '@koobiq/components/loader-overlay';
|
|
19
21
|
import { KbqLoaderOverlayModule } from '@koobiq/components/loader-overlay';
|
|
20
22
|
import * as i8 from '@koobiq/components/progress-spinner';
|
|
21
23
|
import { KbqProgressSpinnerModule } from '@koobiq/components/progress-spinner';
|
|
22
|
-
import
|
|
23
|
-
import { KbqScrollbar, KbqScrollbarModule } from '@koobiq/components/scrollbar';
|
|
24
|
+
import { KbqScrollbarViewport } from '@koobiq/components/scrollbar';
|
|
24
25
|
import * as i6 from '@koobiq/components/tooltip';
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import { map, filter, auditTime, distinctUntilChanged
|
|
28
|
-
import {
|
|
29
|
-
import { KbqToastService } from '@koobiq/components/toast';
|
|
26
|
+
import { KbqToolTipModule } from '@koobiq/components/tooltip';
|
|
27
|
+
import { Subject, BehaviorSubject, merge } from 'rxjs';
|
|
28
|
+
import { skip, map, filter, auditTime, distinctUntilChanged } from 'rxjs/operators';
|
|
29
|
+
import { KbqToastService, KbqToastStyle } from '@koobiq/components/toast';
|
|
30
30
|
import * as i3 from '@koobiq/components/title';
|
|
31
31
|
import { KbqTitleModule } from '@koobiq/components/title';
|
|
32
|
-
import { ConfigurableFocusTrapFactory, FocusTrapFactory, FOCUS_TRAP_INERT_STRATEGY } from '@angular/cdk/a11y';
|
|
33
|
-
|
|
34
|
-
/** @docs-private */
|
|
35
|
-
const KbqNotificationCenterAnimations = {
|
|
36
|
-
/** Animation that transitions a tooltip in and out. */
|
|
37
|
-
state: trigger('state', [
|
|
38
|
-
state('initial', style({
|
|
39
|
-
opacity: 0,
|
|
40
|
-
transform: 'scale(1, 0.8)'
|
|
41
|
-
})),
|
|
42
|
-
transition('* => visible', animate('120ms cubic-bezier(0, 0, 0.2, 1)', style({
|
|
43
|
-
opacity: 1,
|
|
44
|
-
transform: 'scale(1, 1)'
|
|
45
|
-
}))),
|
|
46
|
-
transition('* => hidden', animate(`${KbqAnimationDurations.Rapid} linear`, style({ opacity: 0 })))
|
|
47
|
-
])
|
|
48
|
-
};
|
|
49
32
|
|
|
33
|
+
/** Number of unread notifications above which the trigger counter switches to `"99+"`. */
|
|
50
34
|
const maxUnreadItemsLength = 99;
|
|
35
|
+
/** Suffix appended to a generated id so items ingested within the same millisecond stay distinct. */
|
|
36
|
+
let uniqueIdCounter = 0;
|
|
37
|
+
/** State and commands of the notification center: the list itself, its modes, and the removal events. */
|
|
51
38
|
class KbqNotificationCenterService {
|
|
52
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* The notifications, as a snapshot: reading them does not make an `effect()` or a `computed()` depend on the
|
|
41
|
+
* list, so an effect can read and reassign it. Follow `changes` to react to updates.
|
|
42
|
+
*/
|
|
53
43
|
get items() {
|
|
54
|
-
return this.
|
|
44
|
+
return this.currentItems();
|
|
55
45
|
}
|
|
56
46
|
set items(values) {
|
|
57
|
-
this.
|
|
58
|
-
}
|
|
59
|
-
/** Number of unread notifications */
|
|
60
|
-
get unreadItemsCounter() {
|
|
61
|
-
return this.originalItems.pipe(map((items) => items.filter((item) => item.read === false).length)).pipe(combineLatestWith(this.onRead), map(([value]) => {
|
|
62
|
-
if (value < maxUnreadItemsLength) {
|
|
63
|
-
return value ? value.toString() : '';
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
return `${maxUnreadItemsLength}+`;
|
|
67
|
-
}
|
|
68
|
-
}));
|
|
47
|
+
this.setItems(this.setReadState(this.setIds(values)));
|
|
69
48
|
}
|
|
70
|
-
/**
|
|
49
|
+
/** Whether there are no notifications. A snapshot, like `items`. */
|
|
71
50
|
get isEmpty() {
|
|
72
|
-
return this.
|
|
51
|
+
return this.currentItems().length === 0;
|
|
73
52
|
}
|
|
74
53
|
constructor() {
|
|
75
|
-
/** @docs-private */
|
|
76
54
|
this.adapter = inject(DateAdapter);
|
|
77
|
-
/** @docs-private */
|
|
78
55
|
this.formatter = inject(DateFormatter);
|
|
79
|
-
/** @docs-private */
|
|
80
56
|
this.toastService = inject(KbqToastService);
|
|
57
|
+
this.localeService = inject(KBQ_LOCALE_SERVICE, { optional: true });
|
|
58
|
+
/** Parsed `date` per item. Keyed by the item itself, so no consumer-owned object is written to. */
|
|
59
|
+
this.parsedDates = new WeakMap();
|
|
60
|
+
this._silentMode = signal(false, ...(ngDevMode ? [{ debugName: "_silentMode" }] : /* istanbul ignore next */ []));
|
|
61
|
+
this._loadingMode = signal(false, ...(ngDevMode ? [{ debugName: "_loadingMode" }] : /* istanbul ignore next */ []));
|
|
62
|
+
this._errorMode = signal(false, ...(ngDevMode ? [{ debugName: "_errorMode" }] : /* istanbul ignore next */ []));
|
|
63
|
+
this._loadingMore = signal(false, ...(ngDevMode ? [{ debugName: "_loadingMore" }] : /* istanbul ignore next */ []));
|
|
64
|
+
this._loadMoreErrorMode = signal(false, ...(ngDevMode ? [{ debugName: "_loadMoreErrorMode" }] : /* istanbul ignore next */ []));
|
|
65
|
+
this._hasMore = signal(true, ...(ngDevMode ? [{ debugName: "_hasMore" }] : /* istanbul ignore next */ []));
|
|
66
|
+
this.originalItems = signal([], ...(ngDevMode ? [{ debugName: "originalItems" }] : /* istanbul ignore next */ []));
|
|
67
|
+
/**
|
|
68
|
+
* Bumped on every `onRead` emission: `read` is flipped in place on the consumer's object, so the list
|
|
69
|
+
* itself does not change when a notification is read.
|
|
70
|
+
*/
|
|
71
|
+
this.readVersion = signal(0, ...(ngDevMode ? [{ debugName: "readVersion" }] : /* istanbul ignore next */ []));
|
|
72
|
+
/**
|
|
73
|
+
* Read state of each notification a view follows, as last reported by `onRead` or a list update. One per
|
|
74
|
+
* item, so that reading a notification refreshes its own row only.
|
|
75
|
+
*/
|
|
76
|
+
this.readStates = new WeakMap();
|
|
77
|
+
/** Pinged by every state setter; `changes` merges it with `onRead`. */
|
|
78
|
+
this.stateChanges = new Subject();
|
|
81
79
|
/** @docs-private */
|
|
82
|
-
this.silentMode =
|
|
80
|
+
this.silentMode = this._silentMode.asReadonly();
|
|
83
81
|
/** @docs-private */
|
|
84
|
-
this.loadingMode =
|
|
82
|
+
this.loadingMode = this._loadingMode.asReadonly();
|
|
85
83
|
/** @docs-private */
|
|
86
|
-
this.errorMode =
|
|
84
|
+
this.errorMode = this._errorMode.asReadonly();
|
|
87
85
|
/**
|
|
88
86
|
* Whether the bottom "load more" spinner is shown while the next page is being loaded.
|
|
89
87
|
* Note: this is the infinite-scroll indicator and is distinct from `loadingMode`,
|
|
90
|
-
* which renders the full-screen loader instead of the list.
|
|
88
|
+
* which renders the full-screen loader instead of the list. Set it with `setLoadingMore()`.
|
|
91
89
|
*/
|
|
92
|
-
this.loadingMore =
|
|
90
|
+
this.loadingMore = this._loadingMore.asReadonly();
|
|
93
91
|
/**
|
|
94
92
|
* Whether the bottom "load more" error row (with a retry button) is shown.
|
|
95
93
|
* Distinct from `errorMode`, which replaces the whole list with the full-screen error state.
|
|
94
|
+
* Set it with `setLoadMoreErrorMode()`.
|
|
96
95
|
*/
|
|
97
|
-
this.loadMoreErrorMode =
|
|
96
|
+
this.loadMoreErrorMode = this._loadMoreErrorMode.asReadonly();
|
|
98
97
|
/**
|
|
99
98
|
* Whether there are more notifications to load. While `true`, scrolling to the bottom
|
|
100
|
-
* emits `onNextPage`; set it to `false` to stop further infinite-scroll requests.
|
|
99
|
+
* emits `onNextPage`; set it to `false` with `setHasMore()` to stop further infinite-scroll requests.
|
|
101
100
|
*/
|
|
102
|
-
this.hasMore =
|
|
103
|
-
/**
|
|
101
|
+
this.hasMore = this._hasMore.asReadonly();
|
|
102
|
+
/** Emits a notification the moment it flips from unread to read. */
|
|
104
103
|
this.onRead = new BehaviorSubject(null);
|
|
105
104
|
/** Triggers an event when the user presses the reload button. */
|
|
106
|
-
this.onReload = new
|
|
105
|
+
this.onReload = new Subject();
|
|
107
106
|
/** Triggers an event when the list is scrolled to the bottom and the next page should be loaded. */
|
|
108
|
-
this.onNextPage = new
|
|
107
|
+
this.onNextPage = new Subject();
|
|
109
108
|
/** Triggers an event when an item, a group, or all notifications are removed. */
|
|
110
|
-
this.onDelete = new
|
|
111
|
-
this.originalItems = new BehaviorSubject([]);
|
|
109
|
+
this.onDelete = new Subject();
|
|
112
110
|
/**
|
|
113
111
|
* Grouped notifications, always ordered from newest to oldest: day groups are sorted by date
|
|
114
|
-
* descending, and notifications within each day are sorted by date descending.
|
|
112
|
+
* descending, and notifications within each day are sorted by date descending. Notifications whose
|
|
113
|
+
* `date` the adapter cannot parse keep their raw value as a group heading and sort last.
|
|
114
|
+
*
|
|
115
115
|
* @docs-private
|
|
116
116
|
*/
|
|
117
|
-
this.groupedItems =
|
|
117
|
+
this.groupedItems = computed(() => {
|
|
118
|
+
// The day headings are localized, so a runtime `setLocale()` has to rebuild them.
|
|
119
|
+
this.localeService?.localeId();
|
|
118
120
|
const result = {};
|
|
119
|
-
|
|
121
|
+
this.originalItems().forEach((item) => this.makeGroup(item, result));
|
|
120
122
|
const groups = Object.values(result);
|
|
121
123
|
// Newest notifications first within each day.
|
|
122
124
|
groups.forEach((group) => group.items.sort(this.compareByDateDesc));
|
|
123
125
|
// Newest day first.
|
|
124
126
|
return groups.sort((a, b) => this.compareByDateDesc(a.items[0], b.items[0]));
|
|
125
|
-
}));
|
|
126
|
-
/**
|
|
127
|
-
|
|
127
|
+
}, ...(ngDevMode ? [{ debugName: "groupedItems" }] : /* istanbul ignore next */ []));
|
|
128
|
+
/**
|
|
129
|
+
* Emits whenever any part of the center's state changes. Carries no payload — it is a ping — and
|
|
130
|
+
* emits nothing on subscription.
|
|
131
|
+
*/
|
|
132
|
+
this.changes = merge(this.stateChanges,
|
|
133
|
+
// The replayed current value is not a change.
|
|
134
|
+
this.onRead.pipe(skip(1))).pipe(map(() => undefined));
|
|
135
|
+
/**
|
|
136
|
+
* Number of unread notifications, formatted for the trigger badge: empty while nothing is unread,
|
|
137
|
+
* and `"99+"` above `maxUnreadItemsLength`.
|
|
138
|
+
*/
|
|
139
|
+
this.unreadItemsCounter = computed(() => {
|
|
140
|
+
this.readVersion();
|
|
141
|
+
const value = this.originalItems().filter((item) => item.read === false).length;
|
|
142
|
+
if (value > maxUnreadItemsLength) {
|
|
143
|
+
return `${maxUnreadItemsLength}+`;
|
|
144
|
+
}
|
|
145
|
+
return value ? value.toString() : '';
|
|
146
|
+
}, ...(ngDevMode ? [{ debugName: "unreadItemsCounter" }] : /* istanbul ignore next */ []));
|
|
147
|
+
/**
|
|
148
|
+
* Whether there are no notifications, for the center's own view to follow.
|
|
149
|
+
*
|
|
150
|
+
* @internal
|
|
151
|
+
*/
|
|
152
|
+
this.empty = computed(() => this.originalItems().length === 0, ...(ngDevMode ? [{ debugName: "empty" }] : /* istanbul ignore next */ []));
|
|
128
153
|
this.makeGroup = (item, groups) => {
|
|
129
|
-
const
|
|
130
|
-
const groupId = this.adapter.format(parsedDate, 'yyyyMMdd');
|
|
131
|
-
const groupTitle = this.formatter.absoluteLongDate(parsedDate);
|
|
154
|
+
const { groupId, source, value } = this.getParsedDate(item);
|
|
132
155
|
if (groups[groupId]) {
|
|
133
156
|
groups[groupId].items.push(item);
|
|
134
157
|
}
|
|
135
158
|
else {
|
|
136
159
|
groups[groupId] = {
|
|
137
|
-
|
|
160
|
+
id: groupId,
|
|
161
|
+
// Formatted on every recomputation rather than cached with the parsed value: the heading is
|
|
162
|
+
// localized, and a cached one would leave the group in the locale it was built in while
|
|
163
|
+
// a group created afterwards renders in the current one.
|
|
164
|
+
title: value === null ? source : this.formatter.absoluteLongDate(value),
|
|
138
165
|
items: [item]
|
|
139
166
|
};
|
|
140
167
|
}
|
|
141
168
|
};
|
|
142
|
-
/** Compares two notifications by date so the newest comes first. */
|
|
169
|
+
/** Compares two notifications by date so the newest comes first; unparsable dates sort last. */
|
|
143
170
|
this.compareByDateDesc = (a, b) => {
|
|
144
|
-
const parsedA = this.
|
|
145
|
-
const parsedB = this.
|
|
146
|
-
if (
|
|
147
|
-
return
|
|
171
|
+
const parsedA = this.getParsedDate(a).value;
|
|
172
|
+
const parsedB = this.getParsedDate(b).value;
|
|
173
|
+
if (parsedA === null || parsedB === null) {
|
|
174
|
+
return Number(parsedA === null) - Number(parsedB === null);
|
|
148
175
|
}
|
|
149
176
|
return this.adapter.compareDateTime(parsedB, parsedA);
|
|
150
177
|
};
|
|
178
|
+
this.onRead.pipe(takeUntilDestroyed()).subscribe((item) => {
|
|
179
|
+
this.readVersion.update((version) => version + 1);
|
|
180
|
+
if (item)
|
|
181
|
+
this.syncReadState(item);
|
|
182
|
+
});
|
|
151
183
|
this.toastService?.read.pipe(takeUntilDestroyed()).subscribe((toastData) => {
|
|
152
|
-
const item = this.
|
|
184
|
+
const item = this.currentItems().find((item) => item.id === toastData?.id);
|
|
153
185
|
if (item && !item.read) {
|
|
154
186
|
item.read = true;
|
|
155
|
-
this.onRead.next(
|
|
187
|
+
this.onRead.next(item);
|
|
156
188
|
}
|
|
157
189
|
});
|
|
158
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Whether a notification is read, for a view to follow: `read` is flipped in place on the consumer's object,
|
|
193
|
+
* so a view handed that object is not told.
|
|
194
|
+
*
|
|
195
|
+
* @internal
|
|
196
|
+
*/
|
|
197
|
+
isRead(item) {
|
|
198
|
+
let state = this.readStates.get(item);
|
|
199
|
+
if (!state) {
|
|
200
|
+
state = signal(!!item.read);
|
|
201
|
+
this.readStates.set(item, state);
|
|
202
|
+
}
|
|
203
|
+
// Followed for the dependency only: a view rendered anew shows the object as it is, even after a flip
|
|
204
|
+
// nothing reported.
|
|
205
|
+
state();
|
|
206
|
+
return !!item.read;
|
|
207
|
+
}
|
|
159
208
|
/** Set silent mode */
|
|
160
209
|
setSilentMode(value) {
|
|
161
|
-
this.
|
|
210
|
+
this._silentMode.set(value);
|
|
211
|
+
this.notify();
|
|
162
212
|
}
|
|
163
213
|
/** Set loading mode */
|
|
164
214
|
setLoadingMode(value) {
|
|
165
|
-
this.
|
|
215
|
+
this._loadingMode.set(value);
|
|
216
|
+
this.notify();
|
|
166
217
|
}
|
|
167
218
|
/** Set error mode */
|
|
168
219
|
setErrorMode(value) {
|
|
169
|
-
this.
|
|
220
|
+
this._errorMode.set(value);
|
|
221
|
+
this.notify();
|
|
170
222
|
}
|
|
171
223
|
/** Set the bottom "load more" spinner visibility. */
|
|
172
224
|
setLoadingMore(value) {
|
|
173
|
-
this.
|
|
225
|
+
this._loadingMore.set(value);
|
|
226
|
+
this.notify();
|
|
174
227
|
}
|
|
175
228
|
/** Set the bottom "load more" error state visibility. */
|
|
176
229
|
setLoadMoreErrorMode(value) {
|
|
177
|
-
this.
|
|
230
|
+
this._loadMoreErrorMode.set(value);
|
|
231
|
+
this.notify();
|
|
178
232
|
}
|
|
179
233
|
/** Set whether there are more notifications to load via infinite scroll. */
|
|
180
234
|
setHasMore(value) {
|
|
181
|
-
this.
|
|
235
|
+
this._hasMore.set(value);
|
|
236
|
+
this.notify();
|
|
182
237
|
}
|
|
183
|
-
/**
|
|
238
|
+
/**
|
|
239
|
+
* Adds a notification to the list and, unless silent mode is on, shows it as a toast.
|
|
240
|
+
* Re-pushing the very same notification object is a no-op: a duplicate would show a second toast
|
|
241
|
+
* and produce a colliding list key. A different notification carrying an `id` the list already
|
|
242
|
+
* uses is added under a freshly generated one instead of being dropped.
|
|
243
|
+
*/
|
|
184
244
|
push(item) {
|
|
185
|
-
this.
|
|
186
|
-
|
|
245
|
+
if (this.currentItems().includes(item)) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
this.setReadState(this.setIds([item], this.currentItems()));
|
|
249
|
+
if (!untracked(this.silentMode)) {
|
|
187
250
|
item.toastId = this.toastService.show(item).id;
|
|
188
251
|
}
|
|
189
|
-
|
|
252
|
+
this.setItems([...this.currentItems(), item]);
|
|
190
253
|
}
|
|
191
254
|
/** Hides the toast that corresponds to the given notification item. */
|
|
192
255
|
hideToast(item) {
|
|
@@ -196,67 +259,188 @@ class KbqNotificationCenterService {
|
|
|
196
259
|
this.toastService.hide(item.toastId);
|
|
197
260
|
item.toastId = undefined;
|
|
198
261
|
}
|
|
199
|
-
/**
|
|
262
|
+
/** Removes a notification. Removing one that is not in the list is a no-op and emits nothing. */
|
|
200
263
|
remove(removedItem) {
|
|
264
|
+
if (!this.currentItems().includes(removedItem)) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
201
267
|
this.hideToast(removedItem);
|
|
202
|
-
this.
|
|
203
|
-
this.onDelete.
|
|
268
|
+
this.setItems(this.currentItems().filter((item) => removedItem !== item));
|
|
269
|
+
untracked(() => this.onDelete.next({ type: 'item', items: [removedItem] }));
|
|
204
270
|
}
|
|
205
|
-
/**
|
|
271
|
+
/**
|
|
272
|
+
* Removes a whole day group. Only the notifications that are actually in the list are removed and
|
|
273
|
+
* reported; a group holding none of them — a stale reference kept from an earlier `groupedItems`
|
|
274
|
+
* value — is a no-op and emits nothing.
|
|
275
|
+
*/
|
|
206
276
|
removeGroup(group) {
|
|
207
|
-
group.items.
|
|
208
|
-
|
|
209
|
-
|
|
277
|
+
const removedItems = group.items.filter((item) => this.currentItems().includes(item));
|
|
278
|
+
if (removedItems.length === 0) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
removedItems.forEach((item) => this.hideToast(item));
|
|
282
|
+
this.setItems(this.currentItems().filter((item) => !removedItems.includes(item)));
|
|
283
|
+
untracked(() => this.onDelete.next({ type: 'group', items: removedItems }));
|
|
210
284
|
}
|
|
211
|
-
/**
|
|
285
|
+
/** Removes every notification. Removing from an already empty list is a no-op and emits nothing. */
|
|
212
286
|
removeAll() {
|
|
213
|
-
const items = this.
|
|
287
|
+
const items = this.currentItems();
|
|
288
|
+
if (items.length === 0) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
214
291
|
items.forEach((item) => this.hideToast(item));
|
|
215
|
-
this.
|
|
216
|
-
this.onDelete.
|
|
292
|
+
this.setItems([]);
|
|
293
|
+
untracked(() => this.onDelete.next({ type: 'all', items }));
|
|
217
294
|
}
|
|
218
|
-
|
|
219
|
-
|
|
295
|
+
/**
|
|
296
|
+
* The list as the commands see it: untracked, so a command called from a reactive context does not
|
|
297
|
+
* make it depend on the list it is about to write.
|
|
298
|
+
*/
|
|
299
|
+
currentItems() {
|
|
300
|
+
return untracked(this.originalItems);
|
|
301
|
+
}
|
|
302
|
+
setItems(items) {
|
|
303
|
+
this.originalItems.set(items);
|
|
304
|
+
// The list may be handed back with `read` flipped in place.
|
|
305
|
+
items.forEach((item) => this.syncReadState(item));
|
|
306
|
+
this.notify();
|
|
307
|
+
}
|
|
308
|
+
/** Tells the view of `item` its read state, which refreshes it only when the state has changed. */
|
|
309
|
+
syncReadState(item) {
|
|
310
|
+
this.readStates.get(item)?.set(!!item.read);
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* `changes` subscribers run synchronously, inside whatever called the command: untracked, so a command called
|
|
314
|
+
* from an `effect()` does not make it depend on the signals they read.
|
|
315
|
+
*/
|
|
316
|
+
notify() {
|
|
317
|
+
untracked(() => this.stateChanges.next());
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Parses a notification's `date` once and remembers the result.
|
|
321
|
+
*
|
|
322
|
+
* `DateAdapter.parse` returns `null` for anything it does not recognise, and both the Luxon and the
|
|
323
|
+
* Moment adapter throw when a `null` is passed on to `format`, so every derived value is resolved
|
|
324
|
+
* here behind a single validity check.
|
|
325
|
+
*/
|
|
326
|
+
getParsedDate(item) {
|
|
327
|
+
const source = String(item.date ?? '');
|
|
328
|
+
const cached = this.parsedDates.get(item);
|
|
329
|
+
if (cached?.source === source) {
|
|
330
|
+
return cached;
|
|
331
|
+
}
|
|
332
|
+
const parsed = this.adapter.parse(source, '');
|
|
333
|
+
const isValid = parsed !== null && this.adapter.isValid(parsed);
|
|
334
|
+
const entry = isValid
|
|
335
|
+
? {
|
|
336
|
+
source,
|
|
337
|
+
// Built from adapter accessors instead of a format string: format tokens are not
|
|
338
|
+
// portable, e.g. `'yyyyMMdd'` keys every day of a week identically under Moment.
|
|
339
|
+
groupId: `date:${this.adapter.getYear(parsed)}-${this.adapter.getMonth(parsed)}-${this.adapter.getDate(parsed)}`,
|
|
340
|
+
value: parsed
|
|
341
|
+
}
|
|
342
|
+
: { source, groupId: `raw:${source}`, value: null };
|
|
343
|
+
this.parsedDates.set(item, entry);
|
|
344
|
+
return entry;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Fills in the missing ids of `items` and re-keys the ones already taken, so that every ingested
|
|
348
|
+
* notification ends up with an id of its own.
|
|
349
|
+
*
|
|
350
|
+
* @param existing notifications `items` is joining, whose ids are therefore taken as well; empty
|
|
351
|
+
* when the list is being replaced wholesale.
|
|
352
|
+
*/
|
|
353
|
+
setIds(items, existing = []) {
|
|
354
|
+
const takenIds = new Set(existing.map((item) => item.id));
|
|
355
|
+
items.forEach((item) => {
|
|
356
|
+
// A supplied id is taken on trust only while it is free: a backend that repeats one across
|
|
357
|
+
// pages would otherwise collide on the list's track key and on the toast-to-item lookup in
|
|
358
|
+
// the constructor. `Date.now()` alone collides for every item ingested in the same tick.
|
|
359
|
+
if (item.id === undefined || takenIds.has(item.id)) {
|
|
360
|
+
item.id = `${Date.now()}-${uniqueIdCounter++}`;
|
|
361
|
+
}
|
|
362
|
+
takenIds.add(item.id);
|
|
363
|
+
});
|
|
220
364
|
return items;
|
|
221
365
|
}
|
|
222
366
|
setReadState(items) {
|
|
223
367
|
items.forEach((item) => (item.read = item.read ?? false));
|
|
224
368
|
return items;
|
|
225
369
|
}
|
|
226
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
227
|
-
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
370
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
371
|
+
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterService, providedIn: 'root' }); }
|
|
228
372
|
}
|
|
229
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
373
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterService, decorators: [{
|
|
230
374
|
type: Injectable,
|
|
231
375
|
args: [{ providedIn: 'root' }]
|
|
232
376
|
}], ctorParameters: () => [] });
|
|
233
377
|
|
|
234
|
-
|
|
378
|
+
/** Default configuration of notification-center. */
|
|
379
|
+
const KBQ_NOTIFICATION_CENTER_DEFAULT_LOCALE_CONFIGURATION = ruRULocaleData.notificationCenter;
|
|
380
|
+
/** Injection Token for providing configuration of notification-center. */
|
|
381
|
+
const KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION = new InjectionToken('KbqNotificationCenterLocaleConfiguration', {
|
|
382
|
+
factory: () => KBQ_NOTIFICATION_CENTER_DEFAULT_LOCALE_CONFIGURATION
|
|
383
|
+
});
|
|
384
|
+
/**
|
|
385
|
+
* Utility provider for `KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION`. Only the strings you pass are overridden; the
|
|
386
|
+
* rest keep following the active locale.
|
|
387
|
+
*/
|
|
388
|
+
const kbqNotificationCenterLocaleConfigurationProvider = (configuration) => kbqLocaleConfigurationOverrideProvider('notificationCenter', configuration);
|
|
389
|
+
/** @deprecated Use {@link KBQ_NOTIFICATION_CENTER_DEFAULT_LOCALE_CONFIGURATION}. Will be removed in 22.0.0. */
|
|
390
|
+
const KBQ_NOTIFICATION_CENTER_DEFAULT_CONFIGURATION = KBQ_NOTIFICATION_CENTER_DEFAULT_LOCALE_CONFIGURATION;
|
|
391
|
+
/** @deprecated Use {@link KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION}. Will be removed in 22.0.0. */
|
|
392
|
+
const KBQ_NOTIFICATION_CENTER_CONFIGURATION = KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION;
|
|
393
|
+
/**
|
|
394
|
+
* Narrow contract a `kbq-notification-item` consumes from the panel that renders it, instead of
|
|
395
|
+
* injecting the panel component itself.
|
|
396
|
+
*/
|
|
397
|
+
const KBQ_NOTIFICATION_CENTER_PANEL = new InjectionToken('KbqNotificationCenterPanel');
|
|
398
|
+
|
|
235
399
|
/** @docs-private */
|
|
236
400
|
class KbqNotificationItemComponent {
|
|
401
|
+
// `KbqToastService` used to write these defaults into the item handed to `push()`; it now leaves the
|
|
402
|
+
// caller's object untouched, so the row resolves them itself instead of rendering an unstyled,
|
|
403
|
+
// icon-less notification.
|
|
237
404
|
get style() {
|
|
238
|
-
return
|
|
239
|
-
|
|
240
|
-
|
|
405
|
+
return this.data.style || KbqToastStyle.Contrast;
|
|
406
|
+
}
|
|
407
|
+
get icon() {
|
|
408
|
+
return this.data.icon ?? true;
|
|
409
|
+
}
|
|
410
|
+
get read() {
|
|
411
|
+
return this.service.isRead(this.data);
|
|
241
412
|
}
|
|
242
|
-
// TODO: Skipped for migration because:
|
|
243
|
-
// Accessor inputs cannot be migrated as they are too complex.
|
|
244
413
|
get data() {
|
|
245
414
|
return this._data;
|
|
246
415
|
}
|
|
247
416
|
set data(value) {
|
|
248
417
|
this._data = value;
|
|
249
|
-
this.
|
|
418
|
+
this.context = { $implicit: value };
|
|
419
|
+
// Through `style`, so an item pushed without one still gets the contrast modifier rather than
|
|
420
|
+
// no class at all.
|
|
421
|
+
this.styleClass = `kbq-notification-item_${this.style}`;
|
|
422
|
+
// `DateAdapter.parse` returns null for anything it does not recognise, and every adapter throws
|
|
423
|
+
// when that null reaches `format` — which would take the whole panel down with it.
|
|
424
|
+
const parsed = this.adapter.parse(value.date, '');
|
|
425
|
+
this.time = parsed !== null && this.adapter.isValid(parsed) ? this.adapter.format(parsed, 'HH:mm') : '';
|
|
426
|
+
}
|
|
427
|
+
ngOnChanges(changes) {
|
|
428
|
+
// A bound input is handed to its member; unbound, it leaves what code wrote.
|
|
429
|
+
if (changes['dataInput']) {
|
|
430
|
+
const data = this.dataInput();
|
|
431
|
+
if (data !== undefined)
|
|
432
|
+
this.data = data;
|
|
433
|
+
}
|
|
250
434
|
}
|
|
251
435
|
constructor() {
|
|
252
436
|
this.adapter = inject(DateAdapter);
|
|
253
437
|
this.service = inject(KbqNotificationCenterService);
|
|
254
438
|
this.readStateDirective = inject(KbqReadStateDirective, { host: true });
|
|
255
|
-
this.
|
|
256
|
-
|
|
257
|
-
this.
|
|
258
|
-
|
|
259
|
-
this
|
|
439
|
+
this.panel = inject(KBQ_NOTIFICATION_CENTER_PANEL);
|
|
440
|
+
/** Style modifier class of the host, recomputed with `data` instead of allocated on every check. */
|
|
441
|
+
this.styleClass = '';
|
|
442
|
+
/** @docs-private */
|
|
443
|
+
this.dataInput = input(undefined, { ...(ngDevMode ? { debugName: "dataInput" } : /* istanbul ignore next */ {}), alias: 'data' });
|
|
260
444
|
this.readStateDirective.read
|
|
261
445
|
.pipe(filter((value) => value), takeUntilDestroyed())
|
|
262
446
|
.subscribe(() => {
|
|
@@ -267,30 +451,33 @@ class KbqNotificationItemComponent {
|
|
|
267
451
|
this.service.onRead.next(this.data);
|
|
268
452
|
});
|
|
269
453
|
}
|
|
454
|
+
/** Removes this notification, keeping keyboard focus inside the panel once the button unmounts. */
|
|
455
|
+
remove() {
|
|
456
|
+
this.panel.restoreFocusAfterRemove();
|
|
457
|
+
this.service.remove(this.data);
|
|
458
|
+
}
|
|
270
459
|
isTemplateRef(value) {
|
|
271
460
|
return value instanceof TemplateRef;
|
|
272
461
|
}
|
|
273
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
274
|
-
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqNotificationItemComponent, isStandalone: true, selector: "kbq-notification-item", inputs: { data: "data" }, host: { attributes: { "data-testid": "kbq-notification-item" }, properties: { "class": "style" }, classAttribute: "kbq-notification-item" }, hostDirectives: [{ directive: i1$1.KbqReadStateDirective }], ngImport: i0, template: "@if (data.icon) {\n <div class=\"kbq-notification-item__icon-container layout-row layout-align-start-start\">\n @if (data.icon === true) {\n @switch (data.style) {\n @case ('contrast') {\n <i\n kbq-icon=\"kbq-circle-info_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('success') {\n <i\n kbq-icon=\"kbq-circle-check_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('warning') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('error') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"$any(data.style)\"\n [class]=\"data.iconClass\"\n ></i>\n }\n }\n } @else if (isTemplateRef(data.icon)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.icon)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n }\n </div>\n}\n\n<div class=\"kbq-notification-item__container\">\n @if (data.title) {\n <div\n kbq-title\n class=\"kbq-notification-item__title\"\n [class.kbq-notification-item__title_with-content]=\"data.caption || data.content\"\n >\n @if (isTemplateRef(data.title)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.title)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n <p data-testid=\"kbq-notification-item-title\">{{ data.title }}</p>\n }\n\n <div\n class=\"kbq-notification-item-time\"\n data-testid=\"kbq-notification-item-time\"\n [class.kbq-notification-item-time_read]=\"data.read\"\n >\n <div class=\"kbq-notification-item-time__value\" data-testid=\"kbq-notification-item-time-value\">\n {{ time }}\n </div>\n <i class=\"kbq-notification-item-time__state\" kbq-icon=\"kbq-circle-xs_16\" [color]=\"'theme'\"></i>\n </div>\n </div>\n }\n\n @if (data.caption) {\n <div\n kbq-title\n [class.kbq-notification-item__text]=\"data.title\"\n [class.kbq-notification-item__title]=\"!data.title\"\n >\n @if (isTemplateRef(data.caption)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.caption)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n {{ data.caption }}\n }\n </div>\n }\n\n @if (data.content) {\n <div class=\"kbq-notification-item__content\">\n @if (isTemplateRef(data.content)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.content)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n {{ data.content }}\n }\n </div>\n }\n\n @if (data.actions) {\n <div class=\"kbq-notification-item__actions\">\n @if (isTemplateRef(data.actions)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.actions)\" [ngTemplateOutletContext]=\"{ $implicit }\" />\n } @else {\n {{ data.actions }}\n }\n </div>\n }\n</div>\n\n<button\n kbq-button\n class=\"kbq-notification-item__remove-button\"\n data-testid=\"kbq-notification-item-remove-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltipArrow]=\"false\"\n [kbqTooltip]=\"center.localeData.remove\"\n [kbqPlacement]=\"popUpPlacements.Right\"\n (click)=\"service.remove(data)\"\n>\n <i kbq-icon=\"kbq-trash_16\"></i>\n</button>\n", styles: [".kbq-notification-item{display:flex;box-sizing:border-box;position:relative;border-radius:var(--kbq-size-s);height:auto;margin-left:var(--kbq-size-m);margin-right:var(--kbq-size-m)}.kbq-notification-item:hover .kbq-notification-item-time,.kbq-notification-item:focus-within .kbq-notification-item-time{visibility:hidden}.kbq-notification-item:hover .kbq-notification-item__remove-button,.kbq-notification-item:focus-within .kbq-notification-item__remove-button{display:block}.kbq-notification-item__icon-container{flex-shrink:0;box-sizing:content-box;width:var(--kbq-size-l);max-width:var(--kbq-size-l);height:var(--kbq-size-l);max-height:var(--kbq-size-l);margin-right:var(--kbq-size-s);padding-left:var(--kbq-size-m);padding-top:14px}.kbq-notification-item__container{display:flex;flex-direction:column;flex:1;padding-top:var(--kbq-size-m);padding-right:var(--kbq-size-s);padding-bottom:var(--kbq-size-m);overflow:hidden}.kbq-notification-item__title{display:flex;flex-direction:row;justify-content:space-between;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title>p{margin:0;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title.kbq-notification-item__title_with-content{margin-bottom:var(--kbq-size-xxs)}.kbq-notification-item-time{display:flex;flex-direction:row;height:var(--kbq-size-xl);align-items:center;padding-left:22px}.kbq-notification-item-time .kbq-notification-item-time__value{margin-right:var(--kbq-size-3xs)}.kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__state{visibility:hidden;order:-1}.kbq-notification-item__text{display:flex;flex:1;align-items:center}.kbq-notification-item__content{display:flex;flex-direction:column;white-space:pre-wrap}.kbq-notification-item__actions{display:flex;padding-top:var(--kbq-size-s);gap:var(--kbq-size-m)}.kbq-notification-item__remove-button{position:absolute;top:var(--kbq-size-xs);right:var(--kbq-size-s);display:none}.kbq-notification-item{background:var(--kbq-background-card)}.kbq-notification-item .kbq-notification-item__title{color:var(--kbq-foreground-contrast)}.kbq-notification-item .kbq-notification-item__text,.kbq-notification-item .kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__value{color:var(--kbq-foreground-contrast-secondary)}.kbq-notification-item:hover{background:var(--kbq-states-background-transparent-hover)}.kbq-notification-item{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-notification-item .kbq-notification-item-time{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i1.KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }, { kind: "ngmodule", type: KbqTitleModule }, { kind: "directive", type: i3.KbqTitleDirective, selector: "[kbq-title]", inputs: ["kbq-title"], exportAs: ["kbqTitle"] }, { kind: "ngmodule", type: KbqButtonModule }, { kind: "component", type: i3$1.KbqButton, selector: "[kbq-button]", inputs: ["kbqStyle", "disabled", "tabIndex"] }, { kind: "directive", type: i3$1.KbqButtonCssStyler, selector: "[kbq-button]" }, { kind: "directive", type: KbqTooltipTrigger, selector: "[kbqTooltip]", inputs: ["kbqTooltipScrollStrategy", "forDisabledComponent", "ignoreTooltipPointerEvents", "kbqTooltipSingleInstance", "hideWithTimeout", "kbqVisible", "kbqPlacement", "kbqRelativeToPointer", "kbqPlacementPriority", "kbqTooltip", "kbqTooltipDisabled", "kbqEnterDelay", "kbqLeaveDelay", "kbqTrigger", "kbqTooltipClass", "kbqTooltipContext", "kbqTooltipColor", "kbqTooltipArrow", "kbqTooltipOffset", "kbqTooltipModifier", "kbqTooltipHeader"], outputs: ["kbqPlacementChange", "kbqVisibleChange"], exportAs: ["kbqTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
462
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
463
|
+
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: KbqNotificationItemComponent, isStandalone: true, selector: "kbq-notification-item", inputs: { dataInput: { classPropertyName: "dataInput", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-testid": "kbq-notification-item" }, properties: { "class": "styleClass" }, classAttribute: "kbq-notification-item" }, usesOnChanges: true, hostDirectives: [{ directive: i1.KbqReadStateDirective }], ngImport: i0, template: "@if (icon) {\n <div class=\"kbq-notification-item__icon-container layout-row layout-align-start-start\">\n @if (icon === true) {\n @switch (style) {\n @case ('contrast') {\n <i\n kbq-icon=\"kbq-circle-info_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'contrast'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('success') {\n <i\n kbq-icon=\"kbq-circle-check_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'success'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('warning') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'warning'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('error') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'error'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n }\n } @else if (isTemplateRef(icon)) {\n <ng-container [ngTemplateOutlet]=\"$any(icon)\" [ngTemplateOutletContext]=\"context\" />\n }\n </div>\n}\n\n<div class=\"kbq-notification-item__container\">\n @if (data.title) {\n <div\n kbq-title\n class=\"kbq-notification-item__title\"\n [class.kbq-notification-item__title_with-content]=\"data.caption || data.content\"\n >\n @if (isTemplateRef(data.title)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.title)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n <p data-testid=\"kbq-notification-item-title\">{{ data.title }}</p>\n }\n\n @if (!read) {\n <!-- Unread is otherwise conveyed by the dot below alone. It sits outside the time block\n because that block is visually hidden while the row is hovered or focused, which would\n take the text out of the accessibility tree with it. -->\n <span class=\"cdk-visually-hidden\">{{ panel.localeConfiguration().unread }}</span>\n }\n\n <div\n class=\"kbq-notification-item-time\"\n data-testid=\"kbq-notification-item-time\"\n [class.kbq-notification-item-time_read]=\"read\"\n >\n <div class=\"kbq-notification-item-time__value\" data-testid=\"kbq-notification-item-time-value\">\n {{ time }}\n </div>\n <i\n class=\"kbq-notification-item-time__state\"\n kbq-icon=\"kbq-circle-xs_16\"\n aria-hidden=\"true\"\n [color]=\"'theme'\"\n ></i>\n </div>\n </div>\n }\n\n @if (data.caption) {\n <div\n kbq-title\n [class.kbq-notification-item__text]=\"data.title\"\n [class.kbq-notification-item__title]=\"!data.title\"\n >\n @if (isTemplateRef(data.caption)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.caption)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.caption }}\n }\n </div>\n }\n\n @if (data.content) {\n <div class=\"kbq-notification-item__content\">\n @if (isTemplateRef(data.content)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.content)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.content }}\n }\n </div>\n }\n\n @if (data.actions) {\n <div class=\"kbq-notification-item__actions\">\n @if (isTemplateRef(data.actions)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.actions)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.actions }}\n }\n </div>\n }\n</div>\n\n<button\n kbq-button\n class=\"kbq-notification-item__remove-button\"\n data-testid=\"kbq-notification-item-remove-button\"\n [attr.aria-label]=\"panel.localeConfiguration().remove\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"remove()\"\n>\n <i kbq-icon=\"kbq-trash_16\"></i>\n</button>\n", styles: [".kbq-notification-item{display:flex;box-sizing:border-box;position:relative;border-radius:var(--kbq-size-s)}@supports (corner-shape: squircle){.kbq-notification-item{corner-shape:squircle;border-radius:clamp(var(--kbq-size-s) * 1.85,var(--kbq-size-s) * 2.3 - 3.6px,var(--kbq-size-s) * 2)}}.kbq-notification-item{height:auto;margin-left:var(--kbq-size-m);margin-right:var(--kbq-size-m)}.kbq-notification-item:hover .kbq-notification-item-time,.kbq-notification-item:focus-within .kbq-notification-item-time{visibility:hidden}.kbq-notification-item:hover .kbq-notification-item__remove-button,.kbq-notification-item:focus-within .kbq-notification-item__remove-button{opacity:1;pointer-events:auto}.kbq-notification-item__icon-container{flex-shrink:0;box-sizing:content-box;width:var(--kbq-size-l);max-width:var(--kbq-size-l);height:var(--kbq-size-l);max-height:var(--kbq-size-l);margin-right:var(--kbq-size-s);padding-left:var(--kbq-size-m);padding-top:var(--kbq-notification-center-size-item-icon-padding-top)}.kbq-notification-item__container{display:flex;flex-direction:column;flex:1;padding-top:var(--kbq-size-m);padding-right:var(--kbq-size-s);padding-bottom:var(--kbq-size-m);overflow:hidden}.kbq-notification-item__title{display:flex;flex-direction:row;justify-content:space-between;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title>p{margin:0;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title.kbq-notification-item__title_with-content{margin-bottom:var(--kbq-size-xxs)}.kbq-notification-item-time{display:flex;flex-direction:row;height:var(--kbq-size-xl);align-items:center;padding-left:var(--kbq-notification-center-size-item-time-padding-left)}.kbq-notification-item-time .kbq-notification-item-time__value{margin-right:var(--kbq-size-3xs)}.kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__state{visibility:hidden;order:-1}.kbq-notification-item__text{display:flex;flex:1;align-items:center}.kbq-notification-item__content{display:flex;flex-direction:column;white-space:pre-wrap}.kbq-notification-item__actions{display:flex;padding-top:var(--kbq-size-s);gap:var(--kbq-size-m)}.kbq-notification-item__remove-button{position:absolute;top:var(--kbq-size-xs);right:var(--kbq-size-s);display:block;opacity:0;pointer-events:none}.kbq-notification-item{background:var(--kbq-background-card)}.kbq-notification-item .kbq-notification-item__title{color:var(--kbq-foreground-contrast)}.kbq-notification-item .kbq-notification-item__text,.kbq-notification-item .kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__value{color:var(--kbq-foreground-contrast-secondary)}.kbq-notification-item:hover,.kbq-notification-item:focus-within{background:var(--kbq-states-background-transparent-hover)}.kbq-notification-item{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-notification-item .kbq-notification-item-time{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i2.KbqIcon, selector: "[kbq-icon]", inputs: ["aria-hidden", "iconSize", "autoColor", "kbq-icon"] }, { kind: "ngmodule", type: KbqTitleModule }, { kind: "directive", type: i3.KbqTitleDirective, selector: "[kbq-title]", inputs: ["kbq-title", "ignoreTooltipPointerEvents"], exportAs: ["kbqTitle"] }, { kind: "ngmodule", type: KbqButtonModule }, { kind: "component", type: i3$1.KbqButton, selector: "[kbq-button]", inputs: ["kbqStyle", "disabled", "tabIndex"] }, { kind: "directive", type: i3$1.KbqButtonCssStyler, selector: "[kbq-button]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
275
464
|
}
|
|
276
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
465
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationItemComponent, decorators: [{
|
|
277
466
|
type: Component,
|
|
278
467
|
args: [{ selector: 'kbq-notification-item', imports: [
|
|
279
468
|
NgTemplateOutlet,
|
|
280
469
|
KbqIconModule,
|
|
281
470
|
KbqTitleModule,
|
|
282
|
-
KbqButtonModule
|
|
283
|
-
KbqTooltipTrigger
|
|
471
|
+
KbqButtonModule
|
|
284
472
|
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
285
473
|
class: 'kbq-notification-item',
|
|
286
|
-
'[class]': '
|
|
474
|
+
'[class]': 'styleClass',
|
|
287
475
|
'data-testid': 'kbq-notification-item'
|
|
288
|
-
}, hostDirectives: [KbqReadStateDirective], template: "@if (
|
|
289
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
290
|
-
type: Input
|
|
291
|
-
}] } });
|
|
476
|
+
}, hostDirectives: [KbqReadStateDirective], template: "@if (icon) {\n <div class=\"kbq-notification-item__icon-container layout-row layout-align-start-start\">\n @if (icon === true) {\n @switch (style) {\n @case ('contrast') {\n <i\n kbq-icon=\"kbq-circle-info_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'contrast'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('success') {\n <i\n kbq-icon=\"kbq-circle-check_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'success'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('warning') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'warning'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n @case ('error') {\n <i\n kbq-icon=\"kbq-triangle-exclamation_16\"\n class=\"kbq-notification-item__icon\"\n [color]=\"'error'\"\n [class]=\"data.iconClass\"\n ></i>\n }\n }\n } @else if (isTemplateRef(icon)) {\n <ng-container [ngTemplateOutlet]=\"$any(icon)\" [ngTemplateOutletContext]=\"context\" />\n }\n </div>\n}\n\n<div class=\"kbq-notification-item__container\">\n @if (data.title) {\n <div\n kbq-title\n class=\"kbq-notification-item__title\"\n [class.kbq-notification-item__title_with-content]=\"data.caption || data.content\"\n >\n @if (isTemplateRef(data.title)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.title)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n <p data-testid=\"kbq-notification-item-title\">{{ data.title }}</p>\n }\n\n @if (!read) {\n <!-- Unread is otherwise conveyed by the dot below alone. It sits outside the time block\n because that block is visually hidden while the row is hovered or focused, which would\n take the text out of the accessibility tree with it. -->\n <span class=\"cdk-visually-hidden\">{{ panel.localeConfiguration().unread }}</span>\n }\n\n <div\n class=\"kbq-notification-item-time\"\n data-testid=\"kbq-notification-item-time\"\n [class.kbq-notification-item-time_read]=\"read\"\n >\n <div class=\"kbq-notification-item-time__value\" data-testid=\"kbq-notification-item-time-value\">\n {{ time }}\n </div>\n <i\n class=\"kbq-notification-item-time__state\"\n kbq-icon=\"kbq-circle-xs_16\"\n aria-hidden=\"true\"\n [color]=\"'theme'\"\n ></i>\n </div>\n </div>\n }\n\n @if (data.caption) {\n <div\n kbq-title\n [class.kbq-notification-item__text]=\"data.title\"\n [class.kbq-notification-item__title]=\"!data.title\"\n >\n @if (isTemplateRef(data.caption)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.caption)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.caption }}\n }\n </div>\n }\n\n @if (data.content) {\n <div class=\"kbq-notification-item__content\">\n @if (isTemplateRef(data.content)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.content)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.content }}\n }\n </div>\n }\n\n @if (data.actions) {\n <div class=\"kbq-notification-item__actions\">\n @if (isTemplateRef(data.actions)) {\n <ng-container [ngTemplateOutlet]=\"$any(data.actions)\" [ngTemplateOutletContext]=\"context\" />\n } @else {\n {{ data.actions }}\n }\n </div>\n }\n</div>\n\n<button\n kbq-button\n class=\"kbq-notification-item__remove-button\"\n data-testid=\"kbq-notification-item-remove-button\"\n [attr.aria-label]=\"panel.localeConfiguration().remove\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"remove()\"\n>\n <i kbq-icon=\"kbq-trash_16\"></i>\n</button>\n", styles: [".kbq-notification-item{display:flex;box-sizing:border-box;position:relative;border-radius:var(--kbq-size-s)}@supports (corner-shape: squircle){.kbq-notification-item{corner-shape:squircle;border-radius:clamp(var(--kbq-size-s) * 1.85,var(--kbq-size-s) * 2.3 - 3.6px,var(--kbq-size-s) * 2)}}.kbq-notification-item{height:auto;margin-left:var(--kbq-size-m);margin-right:var(--kbq-size-m)}.kbq-notification-item:hover .kbq-notification-item-time,.kbq-notification-item:focus-within .kbq-notification-item-time{visibility:hidden}.kbq-notification-item:hover .kbq-notification-item__remove-button,.kbq-notification-item:focus-within .kbq-notification-item__remove-button{opacity:1;pointer-events:auto}.kbq-notification-item__icon-container{flex-shrink:0;box-sizing:content-box;width:var(--kbq-size-l);max-width:var(--kbq-size-l);height:var(--kbq-size-l);max-height:var(--kbq-size-l);margin-right:var(--kbq-size-s);padding-left:var(--kbq-size-m);padding-top:var(--kbq-notification-center-size-item-icon-padding-top)}.kbq-notification-item__container{display:flex;flex-direction:column;flex:1;padding-top:var(--kbq-size-m);padding-right:var(--kbq-size-s);padding-bottom:var(--kbq-size-m);overflow:hidden}.kbq-notification-item__title{display:flex;flex-direction:row;justify-content:space-between;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title>p{margin:0;overflow:hidden;text-overflow:ellipsis}.kbq-notification-item__title.kbq-notification-item__title_with-content{margin-bottom:var(--kbq-size-xxs)}.kbq-notification-item-time{display:flex;flex-direction:row;height:var(--kbq-size-xl);align-items:center;padding-left:var(--kbq-notification-center-size-item-time-padding-left)}.kbq-notification-item-time .kbq-notification-item-time__value{margin-right:var(--kbq-size-3xs)}.kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__state{visibility:hidden;order:-1}.kbq-notification-item__text{display:flex;flex:1;align-items:center}.kbq-notification-item__content{display:flex;flex-direction:column;white-space:pre-wrap}.kbq-notification-item__actions{display:flex;padding-top:var(--kbq-size-s);gap:var(--kbq-size-m)}.kbq-notification-item__remove-button{position:absolute;top:var(--kbq-size-xs);right:var(--kbq-size-s);display:block;opacity:0;pointer-events:none}.kbq-notification-item{background:var(--kbq-background-card)}.kbq-notification-item .kbq-notification-item__title{color:var(--kbq-foreground-contrast)}.kbq-notification-item .kbq-notification-item__text,.kbq-notification-item .kbq-notification-item-time.kbq-notification-item-time_read .kbq-notification-item-time__value{color:var(--kbq-foreground-contrast-secondary)}.kbq-notification-item:hover,.kbq-notification-item:focus-within{background:var(--kbq-states-background-transparent-hover)}.kbq-notification-item{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-notification-item .kbq-notification-item-time{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}\n"] }]
|
|
477
|
+
}], ctorParameters: () => [], propDecorators: { dataInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
|
|
292
478
|
|
|
293
479
|
const defaultOffsetX = 8;
|
|
480
|
+
const defaultPlacement = PopUpPlacements.Right;
|
|
294
481
|
/** Rate-limit window (ms) for the scroll-to-bottom check that drives infinite scroll. */
|
|
295
482
|
const SCROLLED_TO_BOTTOM_AUDIT_TIME = 100;
|
|
296
483
|
/**
|
|
@@ -304,13 +491,18 @@ const SCROLLED_TO_BOTTOM_AUDIT_TIME = 100;
|
|
|
304
491
|
* 100% zoom one device pixel is wider than one CSS pixel, which scales the residual by ~1/zoom and
|
|
305
492
|
* pushes it past 1. 2px covers zoom down to 50% and is imperceptible as a trigger threshold.
|
|
306
493
|
*
|
|
307
|
-
*
|
|
494
|
+
* See [`Element.scrollHeight`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight) on MDN.
|
|
308
495
|
*/
|
|
309
496
|
const SCROLLED_TO_BOTTOM_TOLERANCE = 2;
|
|
310
|
-
/**
|
|
311
|
-
const
|
|
312
|
-
/**
|
|
313
|
-
const
|
|
497
|
+
/** Custom property the panel height is published through, so the stylesheet stays the single owner. */
|
|
498
|
+
const POPOVER_HEIGHT_PROPERTY = '--kbq-notification-center-popover-height';
|
|
499
|
+
/** Delete buttons of the day groups and of the individual notifications. */
|
|
500
|
+
const REMOVE_BUTTON_SELECTOR = '.kbq-notification-center-sub-header__button, .kbq-notification-item__remove-button';
|
|
501
|
+
/**
|
|
502
|
+
* Rate-limit window (ms) the reposition scroll strategy runs on. The panel re-applies its
|
|
503
|
+
* stick-to-window styles on the same window, so the two stay in step.
|
|
504
|
+
*/
|
|
505
|
+
const SCROLL_REPOSITION_THROTTLE = 20;
|
|
314
506
|
/** @docs-private */
|
|
315
507
|
const KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY = new InjectionToken('kbq-notification-center-scroll-strategy', {
|
|
316
508
|
providedIn: 'root',
|
|
@@ -318,59 +510,92 @@ const KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY = new InjectionToken('kbq-notifica
|
|
|
318
510
|
});
|
|
319
511
|
/** @docs-private */
|
|
320
512
|
function kbqNotificationCenterScrollStrategyFactory(overlay) {
|
|
321
|
-
return () => overlay.scrollStrategies.reposition({ scrollThrottle:
|
|
513
|
+
return () => overlay.scrollStrategies.reposition({ scrollThrottle: SCROLL_REPOSITION_THROTTLE });
|
|
322
514
|
}
|
|
323
515
|
/** @docs-private */
|
|
324
|
-
const KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY_FACTORY_PROVIDER = {
|
|
325
|
-
provide: KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY,
|
|
326
|
-
deps: [Overlay],
|
|
327
|
-
useFactory: kbqNotificationCenterScrollStrategyFactory
|
|
328
|
-
};
|
|
329
|
-
/** @docs-private */
|
|
330
516
|
class KbqNotificationCenterComponent extends KbqPopUp {
|
|
331
|
-
/**
|
|
332
|
-
*
|
|
333
|
-
|
|
334
|
-
|
|
517
|
+
/**
|
|
518
|
+
* Text of the panel's single live region. The panel keeps one persistent region and only changes
|
|
519
|
+
* its text, because a region inserted together with its content is not reliably announced.
|
|
520
|
+
*
|
|
521
|
+
* @docs-private
|
|
522
|
+
*/
|
|
523
|
+
get statusMessage() {
|
|
524
|
+
// Branch in the template's own order, or the region announces a state that is not on screen:
|
|
525
|
+
// the full-screen error wins over everything, then the full-screen loader, then the bottom
|
|
526
|
+
// spinner, then the bottom error row, and only an otherwise idle empty list reads as empty.
|
|
527
|
+
if (this.service.errorMode()) {
|
|
528
|
+
return this.localeConfiguration().failedToLoadNotifications;
|
|
529
|
+
}
|
|
530
|
+
if (this.service.loadingMode() || this.service.loadingMore()) {
|
|
531
|
+
return this.localeConfiguration().loadingMore;
|
|
532
|
+
}
|
|
533
|
+
if (this.service.loadMoreErrorMode()) {
|
|
534
|
+
return this.localeConfiguration().failedToLoadNotifications;
|
|
535
|
+
}
|
|
536
|
+
return this.service.empty() ? this.localeConfiguration().noNotifications : '';
|
|
335
537
|
}
|
|
336
538
|
get popoverHeight() {
|
|
337
539
|
return this._popoverHeight;
|
|
338
540
|
}
|
|
339
541
|
set popoverHeight(value) {
|
|
340
542
|
this._popoverHeight = value;
|
|
341
|
-
|
|
543
|
+
if (value) {
|
|
544
|
+
this.renderer.setStyle(this.elementRef.nativeElement, POPOVER_HEIGHT_PROPERTY, value, RendererStyleFlags2.DashCase);
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
this.renderer.removeStyle(this.elementRef.nativeElement, POPOVER_HEIGHT_PROPERTY, RendererStyleFlags2.DashCase);
|
|
548
|
+
}
|
|
342
549
|
}
|
|
343
550
|
constructor() {
|
|
344
551
|
super();
|
|
345
552
|
/** @docs-private */
|
|
346
|
-
this.changeDetectorRef = inject(ChangeDetectorRef);
|
|
347
|
-
/** @docs-private */
|
|
348
|
-
this.localeService = inject(KBQ_LOCALE_SERVICE, { optional: true });
|
|
349
|
-
/** @docs-private */
|
|
350
|
-
this.dateAdapter = inject(DateAdapter);
|
|
351
|
-
/** @docs-private */
|
|
352
553
|
this.service = inject(KbqNotificationCenterService);
|
|
353
|
-
this.
|
|
354
|
-
|
|
355
|
-
|
|
554
|
+
this.injector = inject(Injector);
|
|
555
|
+
this.ngZone = inject(NgZone);
|
|
556
|
+
this.idGenerator = inject(_IdGenerator);
|
|
557
|
+
this.scrollDispatcher = inject(ScrollDispatcher);
|
|
558
|
+
this.document = inject(DOCUMENT);
|
|
559
|
+
this.focusMonitor = inject(FocusMonitor);
|
|
560
|
+
this.inputModalityDetector = inject(InputModalityDetector);
|
|
561
|
+
this.carrier = inject(KbqLocaleOverridesDirective, { self: true });
|
|
562
|
+
/**
|
|
563
|
+
* Accessible names for the icon-only toolbar buttons.
|
|
564
|
+
*
|
|
565
|
+
* @docs-private
|
|
566
|
+
*/
|
|
567
|
+
this.a11yLocaleConfiguration = this.carrier.read('a11y', KBQ_A11Y_LOCALE_CONFIGURATION);
|
|
568
|
+
/**
|
|
569
|
+
* Localized strings of the notification center.
|
|
570
|
+
*
|
|
571
|
+
* Read through a signal so that a runtime `setLocale()` reaches `KbqNotificationItemComponent`, which
|
|
572
|
+
* renders these strings from its own `OnPush` view: a `markForCheck()` here would mark this component
|
|
573
|
+
* only, never the already-rendered items.
|
|
574
|
+
*/
|
|
575
|
+
this.localeConfiguration = this.carrier.read('notificationCenter', KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION);
|
|
576
|
+
/**
|
|
577
|
+
* Id of the panel heading, referenced by the host's `aria-labelledby`.
|
|
578
|
+
*
|
|
579
|
+
* @docs-private
|
|
580
|
+
*/
|
|
581
|
+
this.titleId = this.idGenerator.getId('kbq-notification-center-title-');
|
|
582
|
+
/**
|
|
583
|
+
* Distance in pixels from the bottom of the list at which the next page is requested.
|
|
584
|
+
*
|
|
585
|
+
* @docs-private
|
|
586
|
+
*/
|
|
356
587
|
this.scrolledToBottomOffset = 0;
|
|
357
|
-
/**
|
|
358
|
-
|
|
588
|
+
/** Re-measures the list outside of a scroll event: on first render and whenever the state changes. */
|
|
589
|
+
/** Whether a re-measurement is already queued for the next render. */
|
|
590
|
+
this.scrolledToBottomRecheckPending = false;
|
|
591
|
+
this.scrolledToBottomRecheck = new Subject();
|
|
359
592
|
/** @docs-private */
|
|
360
593
|
this.prefix = 'kbq-notification-center';
|
|
361
594
|
/** @docs-private */
|
|
362
595
|
this.isTrapFocus = false;
|
|
363
596
|
this.switcher = viewChild.required('notificationSwitcher');
|
|
364
597
|
/** Scrollable list container; used to measure scroll position for infinite scroll. */
|
|
365
|
-
this.scrollContainer = viewChild.required(
|
|
366
|
-
this.updateLocaleParams = () => {
|
|
367
|
-
this.configuration = this.externalConfiguration || this.localeService?.getParams('notificationCenter');
|
|
368
|
-
this.changeDetectorRef.markForCheck();
|
|
369
|
-
};
|
|
370
|
-
this.localeService?.changes.pipe(takeUntilDestroyed()).subscribe(this.updateLocaleParams);
|
|
371
|
-
if (!this.localeService) {
|
|
372
|
-
this.initDefaultParams();
|
|
373
|
-
}
|
|
598
|
+
this.scrollContainer = viewChild.required(KbqScrollbarViewport);
|
|
374
599
|
}
|
|
375
600
|
ngAfterViewInit() {
|
|
376
601
|
this.visibleChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((state) => {
|
|
@@ -379,21 +604,90 @@ class KbqNotificationCenterComponent extends KbqPopUp {
|
|
|
379
604
|
}
|
|
380
605
|
this.setStickPosition();
|
|
381
606
|
});
|
|
607
|
+
// The reposition scroll strategy rewrites the pane's top/left/bottom/right on every scroll the
|
|
608
|
+
// application makes — including the panel's own list, which is a registered `CdkScrollable` —
|
|
609
|
+
// wiping the manual styles `setStickPosition()` writes. This subscription is created after the
|
|
610
|
+
// strategy has been enabled (`OverlayRef.attach()` runs before the panel's first change
|
|
611
|
+
// detection), so on the same audit window it re-applies them behind the strategy.
|
|
612
|
+
// The panel is also rendered on its own, without a trigger, so the guard covers more than the
|
|
613
|
+
// absent `stickToWindow`.
|
|
614
|
+
this.scrollDispatcher
|
|
615
|
+
.scrolled(SCROLL_REPOSITION_THROTTLE)
|
|
616
|
+
.pipe(filter(() => !!this.trigger?.stickToWindow), takeUntilDestroyed(this.destroyRef))
|
|
617
|
+
.subscribe(() => this.setStickPosition());
|
|
382
618
|
this.service.changes
|
|
383
619
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
384
|
-
.subscribe(() => this.
|
|
385
|
-
|
|
620
|
+
.subscribe(() => this.scheduleScrolledToBottomCheck());
|
|
621
|
+
// Focused with the modality the user actually opened the panel with, so a keyboard-driven open
|
|
622
|
+
// keeps its focus ring while a click does not. Not `KbqButton.focusViaKeyboard()`, which hardcodes
|
|
623
|
+
// `'keyboard'` and paints the ring on the toggle for a mouse user, and not FocusMonitor's own last
|
|
624
|
+
// origin, which reports `program` for a click landing outside its detection window (same rule as
|
|
625
|
+
// `KbqBasePipe.currentFocusOrigin`).
|
|
626
|
+
const switcher = this.switcher();
|
|
627
|
+
// Mirrors `focusViaKeyboard()`'s own early return, which this no longer goes through.
|
|
628
|
+
if (!switcher.disabled) {
|
|
629
|
+
this.focusMonitor.focusVia(switcher.getHostElement(), this.inputModalityDetector.mostRecentModality ?? 'program');
|
|
630
|
+
}
|
|
386
631
|
this.subscribeToScrolledToBottom();
|
|
387
632
|
this.subscribeToRevealLoadMoreRow();
|
|
633
|
+
// A first page too short to overflow the viewport produces no scroll event at all, so measure
|
|
634
|
+
// once the panel has rendered or infinite scroll would never start.
|
|
635
|
+
this.scheduleScrolledToBottomCheck();
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Removes a whole day group, keeping keyboard focus inside the panel.
|
|
639
|
+
*
|
|
640
|
+
* @docs-private
|
|
641
|
+
*/
|
|
642
|
+
removeGroup(group) {
|
|
643
|
+
this.restoreFocusAfterRemove();
|
|
644
|
+
this.service.removeGroup(group);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Removes every notification, keeping keyboard focus inside the panel.
|
|
648
|
+
*
|
|
649
|
+
* @docs-private
|
|
650
|
+
*/
|
|
651
|
+
removeAll() {
|
|
652
|
+
this.restoreFocusAfterRemove();
|
|
653
|
+
this.service.removeAll();
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Moves focus to a surviving delete button — or to the list container when the last one is gone —
|
|
657
|
+
* once the removal has rendered. Without it, focus falls back to `<body>` and the Escape handler
|
|
658
|
+
* and the rest of the panel become unreachable.
|
|
659
|
+
*/
|
|
660
|
+
restoreFocusAfterRemove() {
|
|
661
|
+
// Read before the removal renders, while the activated button is still in the DOM: its place in
|
|
662
|
+
// document order is what decides where focus goes next. Asking for the first match afterwards
|
|
663
|
+
// would always answer with the first day group's "delete this day" button, wherever the user
|
|
664
|
+
// actually was — a destructive control they never aimed at, hidden behind that group's own
|
|
665
|
+
// sticky header.
|
|
666
|
+
const removedIndex = this.getRemoveButtons().indexOf(this.document.activeElement);
|
|
667
|
+
afterNextRender(() => {
|
|
668
|
+
const survivors = this.getRemoveButtons();
|
|
669
|
+
// The button that took the removed one's place, or the last one before it. A removal
|
|
670
|
+
// that did not start from a delete button — or that took the last one with it — falls
|
|
671
|
+
// back to the list container, which keeps the panel operable without parking focus on
|
|
672
|
+
// an arbitrary destructive control.
|
|
673
|
+
const survivor = removedIndex < 0 ? undefined : survivors[removedIndex] || survivors[survivors.length - 1];
|
|
674
|
+
if (survivor) {
|
|
675
|
+
survivor.focus();
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
this.focusScrollContainer();
|
|
679
|
+
}
|
|
680
|
+
}, { injector: this.injector });
|
|
388
681
|
}
|
|
389
|
-
/**
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
onContainerScroll() {
|
|
393
|
-
this.scroll$.next();
|
|
682
|
+
/** Delete buttons of the day groups and of the individual notifications, in document order. */
|
|
683
|
+
getRemoveButtons() {
|
|
684
|
+
return Array.from(this.elementRef.nativeElement.querySelectorAll(REMOVE_BUTTON_SELECTOR));
|
|
394
685
|
}
|
|
395
|
-
/**
|
|
396
|
-
*
|
|
686
|
+
/**
|
|
687
|
+
* Retries loading the next page from the bottom error row.
|
|
688
|
+
*
|
|
689
|
+
* @docs-private
|
|
690
|
+
*/
|
|
397
691
|
retryLoadMore() {
|
|
398
692
|
// The retry button is about to unmount; keep keyboard focus inside the panel instead of
|
|
399
693
|
// letting it fall back to <body>.
|
|
@@ -401,57 +695,88 @@ class KbqNotificationCenterComponent extends KbqPopUp {
|
|
|
401
695
|
// Clear the bottom error state here so the spinner and the error row can never be shown at
|
|
402
696
|
// the same time, regardless of what the consumer's `onNextPage` handler does.
|
|
403
697
|
this.service.setLoadMoreErrorMode(false);
|
|
404
|
-
this.service.onNextPage.
|
|
698
|
+
this.service.onNextPage.next();
|
|
405
699
|
}
|
|
406
700
|
/**
|
|
407
701
|
* Requests the next page (via `service.onNextPage`) once the list is scrolled to within
|
|
408
702
|
* `scrolledToBottomOffset` pixels of the bottom. Two triggers feed it: the user scrolling, and a
|
|
409
|
-
*
|
|
410
|
-
* overflow the viewport — otherwise no further scroll event would fire
|
|
411
|
-
* stall. Suppressed while a load is in flight, errored, or when there is
|
|
703
|
+
* re-measurement after the panel's state has rendered. The latter keeps paging when a freshly
|
|
704
|
+
* loaded page is too short to overflow the viewport — otherwise no further scroll event would fire
|
|
705
|
+
* and pagination would stall. Suppressed while a load is in flight, errored, or when there is
|
|
706
|
+
* nothing more to load.
|
|
412
707
|
*/
|
|
413
708
|
subscribeToScrolledToBottom() {
|
|
414
|
-
const scrolledToBottom$ = this.
|
|
415
|
-
//
|
|
416
|
-
//
|
|
417
|
-
const
|
|
418
|
-
merge(scrolledToBottom$,
|
|
709
|
+
const scrolledToBottom$ = this.scrollContainer().scrollChanges.pipe(auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME), map(() => this.isScrolledToBottom()), distinctUntilChanged(), filter(Boolean));
|
|
710
|
+
// Deliberately without `distinctUntilChanged`: a re-measurement that finds the list still at
|
|
711
|
+
// the bottom must keep paging even though the previous measurement said the same.
|
|
712
|
+
const rechecked$ = this.scrolledToBottomRecheck.pipe(auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME), filter(() => this.isScrolledToBottom()));
|
|
713
|
+
merge(scrolledToBottom$, rechecked$)
|
|
419
714
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
420
|
-
.
|
|
715
|
+
// `scrollChanges` is `CdkScrollable.elementScrolled()` and emits outside Angular's zone, so
|
|
716
|
+
// re-enter before touching consumer-facing state.
|
|
717
|
+
.subscribe(() => this.ngZone.run(() => this.requestNextPage()));
|
|
421
718
|
}
|
|
422
|
-
/**
|
|
423
|
-
|
|
719
|
+
/** Queues a re-measurement for after the next render, when the DOM reflects the new state. */
|
|
720
|
+
scheduleScrolledToBottomCheck() {
|
|
721
|
+
// At most one pending re-measurement: `requestNextPage` flips the service's own loading flags,
|
|
722
|
+
// which ping `changes` in turn, so an unguarded schedule feeds itself for as long as the list
|
|
723
|
+
// reports it is at the bottom — each render callback queueing the next one.
|
|
724
|
+
if (this.scrolledToBottomRecheckPending) {
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
this.scrolledToBottomRecheckPending = true;
|
|
728
|
+
afterNextRender(() => {
|
|
729
|
+
this.scrolledToBottomRecheckPending = false;
|
|
730
|
+
this.scrolledToBottomRecheck.next();
|
|
731
|
+
}, { injector: this.injector });
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Whether the list is scrolled to within `scrolledToBottomOffset` pixels of the bottom.
|
|
735
|
+
* Sub-pixel measurement error is absorbed by `SCROLLED_TO_BOTTOM_TOLERANCE`.
|
|
736
|
+
*/
|
|
424
737
|
isScrolledToBottom() {
|
|
425
|
-
const { scrollTop, clientHeight, scrollHeight } = this.scrollContainer().
|
|
738
|
+
const { scrollTop, clientHeight, scrollHeight } = this.scrollContainer().getNativeElement();
|
|
739
|
+
// A container that has not been laid out yet has no bottom to reach. Without this guard the
|
|
740
|
+
// all-zero measurement reads as "at the bottom" and requests page after page into nothing.
|
|
741
|
+
if (clientHeight === 0) {
|
|
742
|
+
return false;
|
|
743
|
+
}
|
|
426
744
|
return scrollHeight - scrollTop - clientHeight <= this.scrolledToBottomOffset + SCROLLED_TO_BOTTOM_TOLERANCE;
|
|
427
745
|
}
|
|
428
746
|
/** Emits `onNextPage` unless a load is already in flight, errored, or there is nothing more to load. */
|
|
429
747
|
requestNextPage() {
|
|
430
|
-
if (this.service.hasMore
|
|
431
|
-
this.service.onNextPage.
|
|
748
|
+
if (this.service.hasMore() && !this.service.loadingMore() && !this.service.loadMoreErrorMode()) {
|
|
749
|
+
this.service.onNextPage.next();
|
|
432
750
|
}
|
|
433
751
|
}
|
|
434
752
|
/**
|
|
435
753
|
* Reveals the bottom "load more" spinner / error row when it first appears. Both rows are appended
|
|
436
754
|
* below the last item and can land outside the viewport (the next page is requested while the user
|
|
437
755
|
* is up to `scrolledToBottomOffset` px above the true bottom). Only a genuine false->true transition
|
|
438
|
-
* reveals the row
|
|
439
|
-
*
|
|
440
|
-
* is still set never jumps to the bottom.
|
|
756
|
+
* after the panel opened reveals the row, so the panel always opens scrolled to the top — reopening
|
|
757
|
+
* it while a load-more error is still set never jumps to the bottom.
|
|
441
758
|
*/
|
|
442
759
|
subscribeToRevealLoadMoreRow() {
|
|
443
|
-
const reveal = (
|
|
444
|
-
|
|
760
|
+
const reveal = (isShown) => {
|
|
761
|
+
let wasShown = isShown();
|
|
762
|
+
return this.service.changes.pipe(filter(() => {
|
|
763
|
+
const shown = isShown();
|
|
764
|
+
const appeared = shown && !wasShown;
|
|
765
|
+
wasShown = shown;
|
|
766
|
+
return appeared;
|
|
767
|
+
}), auditTime(SCROLLED_TO_BOTTOM_AUDIT_TIME));
|
|
768
|
+
};
|
|
769
|
+
merge(reveal(() => this.service.loadingMore()), reveal(() => this.service.loadMoreErrorMode()))
|
|
445
770
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
446
771
|
.subscribe(() => this.scrollToBottom());
|
|
447
772
|
}
|
|
448
773
|
/** Scrolls the list container to its bottom so a freshly-appended bottom row becomes visible. */
|
|
449
774
|
scrollToBottom() {
|
|
450
|
-
const { scrollHeight } = this.scrollContainer().
|
|
775
|
+
const { scrollHeight } = this.scrollContainer().getNativeElement();
|
|
451
776
|
this.scrollContainer().scrollTo({ top: scrollHeight });
|
|
452
777
|
}
|
|
453
778
|
focusScrollContainer() {
|
|
454
|
-
const element = this.scrollContainer().
|
|
779
|
+
const element = this.scrollContainer().getNativeElement();
|
|
455
780
|
// tabindex -1 keeps the container out of the Tab order while allowing programmatic focus.
|
|
456
781
|
element.setAttribute('tabindex', '-1');
|
|
457
782
|
element.focus({ preventScroll: true });
|
|
@@ -464,70 +789,100 @@ class KbqNotificationCenterComponent extends KbqPopUp {
|
|
|
464
789
|
updateTrapFocus(isTrapFocus) {
|
|
465
790
|
this.isTrapFocus = isTrapFocus;
|
|
466
791
|
}
|
|
467
|
-
/**
|
|
468
|
-
|
|
792
|
+
/**
|
|
793
|
+
* Closes the panel on `Escape` inside it, unless a control there spent the key closing a popup of its own.
|
|
794
|
+
*
|
|
795
|
+
* @docs-private
|
|
796
|
+
*/
|
|
797
|
+
escapeHandler(event) {
|
|
798
|
+
if (event?.defaultPrevented)
|
|
799
|
+
return;
|
|
800
|
+
// Spent, so that a container closing on Escape underneath, such as a sidepanel, stays open.
|
|
801
|
+
event?.preventDefault();
|
|
469
802
|
this.hide(0);
|
|
470
803
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqNotificationCenterComponent, isStandalone: true, selector: "kbq-notification-center", host: { listeners: { "keydown.escape": "escapeHandler()" }, properties: { "class.kbq-notification-center_popover": "popoverMode" }, classAttribute: "kbq-notification-center" }, viewQueries: [{ propertyName: "switcher", first: true, predicate: ["notificationSwitcher"], descendants: true, isSignal: true }, { propertyName: "scrollContainer", first: true, predicate: KbqScrollbar, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"kbq-notification-center-header\">\n <div class=\"kbq-notification-center-title\">\n <div class=\"kbq-notification-center-title__text\">{{ localeData.notifications }}</div>\n <button\n #notificationSwitcher\n kbq-button\n class=\"kbq-notification-center-title__button\"\n data-testid=\"kbq-notification-center-silent-mode-toggle\"\n [kbqDropdownTriggerFor]=\"notificationSwitcherDropdown\"\n [kbqTooltip]=\"service.silentMode.value ? localeData.doNotDisturb : localeData.showPopUpNotifications\"\n [kbqTooltipArrow]=\"false\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipOffset]=\"4\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n >\n <i kbq-icon=\"{{ service.silentMode.value ? 'kbq-bell-slash_16' : 'kbq-bell_16' }}\"></i>\n </button>\n </div>\n <div class=\"kbq-notification-center-toolbar\">\n @if (!service.isEmpty) {\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-remove-all-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"service.removeAll()\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n\n <kbq-divider [vertical]=\"true\" />\n }\n\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-close-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"hide(0)\"\n >\n <i kbq-icon=\"kbq-xmark_16\"></i>\n </button>\n </div>\n</div>\n\n<div\n #notificationCenterContainer=\"kbqOverflowShadowContainer\"\n kbq-scrollbar\n kbqOverflowShadowContainer\n class=\"kbq-notification-center-container\"\n data-testid=\"kbq-notification-center-container\"\n [kbqOverflowShadowBottom]=\"notificationCenterContainer\"\n [shadow]=\"'var(--kbq-shadow-overflow-normal-bottom)'\"\n (onScroll)=\"onContainerScroll()\"\n>\n @if (!service.errorMode.value) {\n @if (!service.loadingMode.value) {\n @for (group of service.groupedItems | async; track group) {\n <div\n class=\"kbq-notification-center-sub-header\"\n data-testid=\"kbq-notification-center-group\"\n [kbqOverflowShadowTop]=\"$first ? notificationCenterContainer : undefined\"\n >\n <div class=\"kbq-notification-center-sub-header__date\">{{ group.title }}</div>\n\n <button\n kbq-button\n class=\"kbq-notification-center-sub-header__button\"\n data-testid=\"kbq-notification-center-remove-group-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeData.remove\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"service.removeGroup(group)\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n </div>\n\n @for (item of group.items; track item) {\n <kbq-notification-item [data]=\"item\" />\n }\n } @empty {\n @if (!service.loadingMore.value) {\n <div class=\"kbq-notification-center-empty-container\" data-testid=\"kbq-notification-center-empty\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'contrast-fade'\"></i>\n {{ localeData.noNotifications }}\n </div>\n }\n }\n\n @if (service.loadingMore.value) {\n <div\n class=\"kbq-notification-center-load-more\"\n data-testid=\"kbq-notification-center-load-more\"\n role=\"status\"\n [attr.aria-label]=\"localeData.loadingMore\"\n >\n <kbq-progress-spinner [mode]=\"'indeterminate'\" [size]=\"'compact'\" />\n </div>\n }\n\n @if (service.loadMoreErrorMode.value) {\n <div\n class=\"kbq-notification-center-load-more-error\"\n data-testid=\"kbq-notification-center-load-more-error\"\n role=\"alert\"\n >\n {{ localeData.failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-load-more-retry-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"retryLoadMore()\"\n >\n {{ localeData.repeat }}\n </button>\n </div>\n }\n } @else {\n <kbq-loader-overlay data-testid=\"kbq-notification-center-loader\" [transparent]=\"true\" />\n }\n } @else {\n <div class=\"kbq-notification-center-error-container\" data-testid=\"kbq-notification-center-error\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'error'\" [fade]=\"true\"></i>\n {{ localeData.failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-reload-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"service.onReload.emit()\"\n >\n {{ localeData.repeat }}\n </button>\n </div>\n }\n</div>\n\n<kbq-dropdown #notificationSwitcherDropdown=\"kbqDropdown\">\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-show-notifications-button\"\n (click)=\"service.setSilentMode(false)\"\n >\n <i kbq-icon=\"{{ !service.silentMode.value ? 'kbq-circle-xs_16' : '' }}\" [style.min-width.px]=\"16\"></i>\n {{ localeData.showPopUpNotifications }}\n </button>\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-do-not-disturb-button\"\n (click)=\"service.setSilentMode(true)\"\n >\n <i kbq-icon=\"{{ service.silentMode.value ? 'kbq-circle-xs_16' : '' }}\" [style.min-width.px]=\"16\"></i>\n {{ localeData.doNotDisturb }}\n </button>\n</kbq-dropdown>\n", styles: [".kbq-notification-center{position:relative;display:flex;flex-direction:column;width:400px;height:100vh;box-sizing:border-box;z-index:1}.kbq-notification-center:not(.kbq-notification-center_popover){border-right:1px solid;border-left:1px solid}.kbq-notification-center.kbq-notification-center_popover{margin-top:var(--kbq-size-xxs);margin-bottom:var(--kbq-size-xxs);border-radius:var(--kbq-size-xs);height:calc(100vh - 48px);box-shadow:var(--kbq-shadow-popup)}.kbq-notification-center-header{display:flex;flex-direction:row;justify-content:space-between;padding:var(--kbq-size-m) var(--kbq-size-xl) var(--kbq-size-xxs) var(--kbq-size-xxl)}.kbq-notification-center-title{display:flex;flex-direction:row;align-items:center;gap:var(--kbq-size-xxs)}.kbq-notification-center-toolbar{display:flex;flex-direction:row;align-items:center}.kbq-notification-center-toolbar .kbq-divider.kbq-divider_vertical{height:var(--kbq-size-m)}.kbq-notification-center-sub-header{position:sticky;top:0;z-index:100;display:flex;flex-direction:row;padding:var(--kbq-size-s) var(--kbq-size-xl)}.kbq-notification-center-sub-header .kbq-notification-center-sub-header__button{position:absolute;top:0;right:var(--kbq-size-xl);display:none}.kbq-notification-center-sub-header:hover .kbq-notification-center-sub-header__button,.kbq-notification-center-sub-header:focus-within .kbq-notification-center-sub-header__button{display:flex}.kbq-notification-center-container{height:100%;border-radius:inherit;padding-bottom:var(--kbq-size-xl)}.kbq-notification-center-container [data-overlayscrollbars-viewport]{scroll-behavior:smooth}@media(prefers-reduced-motion:reduce){.kbq-notification-center-container [data-overlayscrollbars-viewport]{scroll-behavior:auto}}.kbq-notification-center-container .kbq-loader-overlay_parent{border-radius:inherit}.kbq-notification-center-load-more{display:flex;align-items:center;justify-content:center;padding:26px 0}.kbq-notification-center-load-more-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--kbq-size-xxs) var(--kbq-size-xxl);text-align:center}.kbq-notification-center-load-more-error .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center-empty-container,.kbq-notification-center-error-container{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}.kbq-notification-center-empty-container .kbq-icon,.kbq-notification-center-error-container .kbq-icon{margin-bottom:var(--kbq-size-xl)}.kbq-notification-center-empty-container .kbq-button,.kbq-notification-center-error-container .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center,.kbq-notification-center-sub-header{background:var(--kbq-background-card)}.kbq-notification-center:not(.kbq-notification-center_popover),.kbq-notification-center-sub-header:not(.kbq-notification-center_popover){border-right-color:var(--kbq-line-contrast-less);border-left-color:var(--kbq-line-contrast-less)}.kbq-notification-center-error-container,.kbq-notification-center-load-more-error{color:var(--kbq-foreground-error)}.kbq-notification-center{font-size:var(--kbq-typography-text-normal-medium-font-size);font-style:var(--kbq-typography-text-normal-medium-font-style);font-weight:var(--kbq-typography-text-normal-medium-font-weight);line-height:var(--kbq-typography-text-normal-medium-line-height);font-family:var(--kbq-typography-text-normal-medium-font-family);text-transform:var(--kbq-typography-text-normal-medium-text-transform);font-feature-settings:var(--kbq-typography-text-normal-medium-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-medium-letter-spacing)}.kbq-notification-center-title__text{font-size:var(--kbq-typography-text-big-strong-font-size);font-style:var(--kbq-typography-text-big-strong-font-style);font-weight:var(--kbq-typography-text-big-strong-font-weight);line-height:var(--kbq-typography-text-big-strong-line-height);font-family:var(--kbq-typography-text-big-strong-font-family);text-transform:var(--kbq-typography-text-big-strong-text-transform);font-feature-settings:var(--kbq-typography-text-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-text-big-strong-letter-spacing)}\n"], dependencies: [{ kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i1.KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }, { kind: "component", type: i1.KbqIconItem, selector: "[kbq-icon-item]", inputs: ["kbq-icon-item", "fade", "big"] }, { kind: "ngmodule", type: KbqBadgeModule }, { kind: "ngmodule", type: KbqScrollbarModule }, { kind: "component", type: i2.KbqScrollbar, selector: "kbq-scrollbar, [kbq-scrollbar]", inputs: ["initializationTarget", "options", "events", "defer"], outputs: ["onInitialize", "onUpdate", "onDestroy", "onScroll"], exportAs: ["kbqScrollbar"] }, { kind: "ngmodule", type: KbqButtonModule }, { kind: "component", type: i3$1.KbqButton, selector: "[kbq-button]", inputs: ["kbqStyle", "disabled", "tabIndex"] }, { kind: "directive", type: i3$1.KbqButtonCssStyler, selector: "[kbq-button]" }, { kind: "directive", type: i3$1.KbqButtonDropdownTrigger, selector: "[kbq-button][kbqDropdownTriggerFor]" }, { kind: "ngmodule", type: KbqDividerModule }, { kind: "component", type: i4.KbqDivider, selector: "kbq-divider", inputs: ["vertical", "paddings"] }, { kind: "ngmodule", type: KbqDropdownModule }, { kind: "component", type: i5.KbqDropdown, selector: "kbq-dropdown", inputs: ["navigationWithWrap", "xPosition", "yPosition", "overlapTriggerY", "overlapTriggerX", "hasBackdrop", "class", "backdropClass", "panelWidth", "panelMinWidth", "panelMaxWidth", "safeArea"], outputs: ["closed"], exportAs: ["kbqDropdown"] }, { kind: "component", type: i5.KbqDropdownItem, selector: "kbq-dropdown-item, [kbq-dropdown-item]", inputs: ["disabled", "progress"], exportAs: ["kbqDropdownItem"] }, { kind: "directive", type: i5.KbqDropdownTrigger, selector: "[kbqDropdownTriggerFor]", inputs: ["offsetX", "offsetY", "kbqDropdownTriggerData", "openByArrowDown", "demoteOverlay", "kbqDropdownTriggerRestoreFocus", "kbqDropdownTriggerFor"], outputs: ["dropdownOpened", "dropdownClosed"], exportAs: ["kbqDropdownTrigger"] }, { kind: "ngmodule", type: KbqToolTipModule }, { kind: "directive", type: i6.KbqTooltipTrigger, selector: "[kbqTooltip]", inputs: ["kbqTooltipScrollStrategy", "forDisabledComponent", "ignoreTooltipPointerEvents", "kbqTooltipSingleInstance", "hideWithTimeout", "kbqVisible", "kbqPlacement", "kbqRelativeToPointer", "kbqPlacementPriority", "kbqTooltip", "kbqTooltipDisabled", "kbqEnterDelay", "kbqLeaveDelay", "kbqTrigger", "kbqTooltipClass", "kbqTooltipContext", "kbqTooltipColor", "kbqTooltipArrow", "kbqTooltipOffset", "kbqTooltipModifier", "kbqTooltipHeader"], outputs: ["kbqPlacementChange", "kbqVisibleChange"], exportAs: ["kbqTooltip"] }, { kind: "component", type: KbqNotificationItemComponent, selector: "kbq-notification-item", inputs: ["data"] }, { kind: "ngmodule", type: KbqLoaderOverlayModule }, { kind: "component", type: i7.KbqLoaderOverlay, selector: "kbq-loader-overlay", inputs: ["text", "caption", "size", "transparent", "card"] }, { kind: "ngmodule", type: KbqProgressSpinnerModule }, { kind: "component", type: i8.KbqProgressSpinner, selector: "kbq-progress-spinner", inputs: ["id", "value", "mode", "size"] }, { kind: "directive", type: KbqOverflowShadowContainer, selector: "[kbqOverflowShadowContainer]", inputs: ["debounce"], exportAs: ["kbqOverflowShadowContainer"] }, { kind: "directive", type: KbqOverflowShadowTop, selector: "[kbqOverflowShadowTop]", inputs: ["kbqOverflowShadowTop", "shadow"], exportAs: ["kbqOverflowShadowTop"] }, { kind: "directive", type: KbqOverflowShadowBottom, selector: "[kbqOverflowShadowBottom]", inputs: ["kbqOverflowShadowBottom", "shadow"], exportAs: ["kbqOverflowShadowBottom"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], animations: [KbqNotificationCenterAnimations.state], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
804
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
805
|
+
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: KbqNotificationCenterComponent, isStandalone: true, selector: "kbq-notification-center", host: { attributes: { "role": "dialog" }, listeners: { "keydown.escape": "escapeHandler($any($event))" }, properties: { "attr.id": "panelId", "attr.aria-labelledby": "titleId", "class.kbq-notification-center_popover": "popoverMode" }, classAttribute: "kbq-notification-center" }, providers: [
|
|
806
|
+
// The panel traps focus, so it needs a configurable trap even when it is imported standalone —
|
|
807
|
+
// these used to be reachable only through KbqNotificationCenterModule.
|
|
808
|
+
{ provide: FocusTrapFactory, useClass: ConfigurableFocusTrapFactory },
|
|
809
|
+
{ provide: FOCUS_TRAP_INERT_STRATEGY, useClass: EmptyFocusTrapStrategy },
|
|
810
|
+
{ provide: KBQ_NOTIFICATION_CENTER_PANEL, useExisting: forwardRef((() => KbqNotificationCenterComponent)) }
|
|
811
|
+
], viewQueries: [{ propertyName: "switcher", first: true, predicate: ["notificationSwitcher"], descendants: true, isSignal: true }, { propertyName: "scrollContainer", first: true, predicate: KbqScrollbarViewport, descendants: true, isSignal: true }], usesInheritance: true, hostDirectives: [{ directive: i1.KbqLocaleOverridesDirective }], ngImport: i0, template: "<!-- `display: contents` keeps the trap out of the panel's flex layout while still scoping the focus trap\nto everything the panel renders. -->\n<div class=\"kbq-notification-center__trap\" [cdkTrapFocus]=\"isTrapFocus\">\n <div class=\"kbq-notification-center-header\">\n <div class=\"kbq-notification-center-title\">\n <div class=\"kbq-notification-center-title__text\" [id]=\"titleId\">\n {{ localeConfiguration().notifications }}\n </div>\n <button\n #notificationSwitcher\n kbq-button\n class=\"kbq-notification-center-title__button\"\n data-testid=\"kbq-notification-center-silent-mode-toggle\"\n [kbqDropdownTriggerFor]=\"notificationSwitcherDropdown\"\n [attr.aria-label]=\"\n service.silentMode()\n ? localeConfiguration().doNotDisturb\n : localeConfiguration().showPopUpNotifications\n \"\n [kbqTooltip]=\"\n service.silentMode()\n ? localeConfiguration().doNotDisturb\n : localeConfiguration().showPopUpNotifications\n \"\n [kbqTooltipArrow]=\"false\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipOffset]=\"4\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n >\n <i kbq-icon=\"{{ service.silentMode() ? 'kbq-bell-slash_16' : 'kbq-bell_16' }}\"></i>\n </button>\n </div>\n <div class=\"kbq-notification-center-toolbar\">\n @if (!service.empty()) {\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-remove-all-button\"\n [attr.aria-label]=\"a11yLocaleConfiguration().removeAll\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeConfiguration().removeAll\"\n [kbqPlacement]=\"'bottom'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"removeAll()\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n\n <kbq-divider [vertical]=\"true\" />\n }\n\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-close-button\"\n [attr.aria-label]=\"a11yLocaleConfiguration().close\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"hide(0)\"\n >\n <i kbq-icon=\"kbq-xmark_16\"></i>\n </button>\n </div>\n </div>\n\n <!-- One persistent live region for the whole panel: a region inserted together with its text is\n not reliably announced, so only the text below ever changes. -->\n <div class=\"cdk-visually-hidden\" data-testid=\"kbq-notification-center-status\" role=\"status\" aria-live=\"polite\">\n {{ statusMessage }}\n </div>\n\n <div\n #notificationCenterContainer=\"kbqOverflowShadowContainer\"\n kbqScrollbarViewport\n kbqOverflowShadowContainer\n class=\"kbq-notification-center-container\"\n data-testid=\"kbq-notification-center-container\"\n [class.kbq-animations-disabled]=\"animationsDisabled\"\n [kbqOverflowShadowBottom]=\"notificationCenterContainer\"\n [shadow]=\"'var(--kbq-shadow-overflow-normal-bottom)'\"\n >\n @if (!service.errorMode()) {\n @if (!service.loadingMode()) {\n @for (group of service.groupedItems(); track group.id) {\n <div\n class=\"kbq-notification-center-sub-header\"\n data-testid=\"kbq-notification-center-group\"\n [kbqOverflowShadowTop]=\"$first ? notificationCenterContainer : undefined\"\n >\n <div class=\"kbq-notification-center-sub-header__date\">{{ group.title }}</div>\n\n <button\n kbq-button\n class=\"kbq-notification-center-sub-header__button\"\n data-testid=\"kbq-notification-center-remove-group-button\"\n [attr.aria-label]=\"localeConfiguration().remove\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeConfiguration().remove\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"removeGroup(group)\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n </div>\n\n @for (item of group.items; track item.id) {\n <kbq-notification-item [data]=\"item\" />\n }\n } @empty {\n @if (!service.loadingMore() && !service.loadMoreErrorMode()) {\n <div\n class=\"kbq-notification-center-empty-container\"\n data-testid=\"kbq-notification-center-empty\"\n >\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'contrast-fade'\"></i>\n {{ localeConfiguration().noNotifications }}\n </div>\n }\n }\n\n @if (service.loadingMore()) {\n <div class=\"kbq-notification-center-load-more\" data-testid=\"kbq-notification-center-load-more\">\n <kbq-progress-spinner [mode]=\"'indeterminate'\" [size]=\"'compact'\" />\n </div>\n } @else if (service.loadMoreErrorMode()) {\n <div\n class=\"kbq-notification-center-load-more-error\"\n data-testid=\"kbq-notification-center-load-more-error\"\n >\n {{ localeConfiguration().failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-load-more-retry-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"retryLoadMore()\"\n >\n {{ localeConfiguration().repeat }}\n </button>\n </div>\n }\n } @else {\n <kbq-loader-overlay data-testid=\"kbq-notification-center-loader\" />\n }\n } @else {\n <div class=\"kbq-notification-center-error-container\" data-testid=\"kbq-notification-center-error\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'error'\" [fade]=\"true\"></i>\n {{ localeConfiguration().failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-reload-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"service.onReload.next()\"\n >\n {{ localeConfiguration().repeat }}\n </button>\n </div>\n }\n </div>\n\n <!-- `class` is KbqDropdown's own input: it moves the class onto the panel rendered in the overlay,\n which is where the check-mark width token has to be declared to reach the marks. -->\n <kbq-dropdown #notificationSwitcherDropdown=\"kbqDropdown\" class=\"kbq-notification-center-switcher\">\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-show-notifications-button\"\n (click)=\"service.setSilentMode(false)\"\n >\n <i\n class=\"kbq-notification-center-switcher__mark\"\n kbq-icon=\"kbq-circle-xs_16\"\n [class.kbq-notification-center-switcher__mark_hidden]=\"service.silentMode()\"\n ></i>\n {{ localeConfiguration().showPopUpNotifications }}\n </button>\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-do-not-disturb-button\"\n (click)=\"service.setSilentMode(true)\"\n >\n <i\n class=\"kbq-notification-center-switcher__mark\"\n kbq-icon=\"kbq-circle-xs_16\"\n [class.kbq-notification-center-switcher__mark_hidden]=\"!service.silentMode()\"\n ></i>\n {{ localeConfiguration().doNotDisturb }}\n </button>\n </kbq-dropdown>\n</div>\n", styles: [".kbq-notification-center{position:relative;display:flex;flex-direction:column;width:var(--kbq-notification-center-size-container-width);height:var(--kbq-notification-center-popover-height, 100vh);box-sizing:border-box;z-index:1}.kbq-notification-center:not(.kbq-notification-center_popover){border-right:1px solid;border-left:1px solid}.kbq-notification-center.kbq-notification-center_popover{margin-top:var(--kbq-size-xxs);margin-bottom:var(--kbq-size-xxs);border-radius:var(--kbq-notification-center-size-container-border-radius)}@supports (corner-shape: squircle){.kbq-notification-center.kbq-notification-center_popover{corner-shape:squircle;border-radius:clamp(var(--kbq-notification-center-size-container-border-radius) * 1.85,var(--kbq-notification-center-size-container-border-radius) * 2.3 - 3.6px,var(--kbq-notification-center-size-container-border-radius) * 2)}}.kbq-notification-center.kbq-notification-center_popover{height:var(--kbq-notification-center-popover-height, calc(100vh - var(--kbq-notification-center-size-navbar-height)));box-shadow:var(--kbq-notification-center-container-shadow)}.kbq-notification-center__trap{display:contents}.kbq-notification-center-header{display:flex;flex-direction:row;justify-content:space-between;padding:var(--kbq-size-m) var(--kbq-size-xl) var(--kbq-size-xxs) var(--kbq-size-xxl)}.kbq-notification-center-title{display:flex;flex-direction:row;align-items:center;gap:var(--kbq-size-xxs)}.kbq-notification-center-toolbar{display:flex;flex-direction:row;align-items:center}.kbq-notification-center-toolbar .kbq-divider.kbq-divider_vertical{height:var(--kbq-size-m)}.kbq-notification-center-switcher__mark{min-width:var(--kbq-notification-center-size-switcher-mark-width)}.kbq-notification-center-switcher__mark.kbq-notification-center-switcher__mark_hidden{visibility:hidden}.kbq-notification-center-sub-header{position:sticky;top:0;z-index:var(--kbq-notification-center-sub-header-z-index);display:flex;flex-direction:row;padding:var(--kbq-size-s) var(--kbq-size-xl)}.kbq-notification-center-sub-header .kbq-notification-center-sub-header__button{position:absolute;top:0;right:var(--kbq-size-xl);display:flex;opacity:0;pointer-events:none}.kbq-notification-center-sub-header:hover .kbq-notification-center-sub-header__button,.kbq-notification-center-sub-header:focus-within .kbq-notification-center-sub-header__button{opacity:1;pointer-events:auto}.kbq-notification-center-container{--kbq-scrollbar-track-z-index: calc(var(--kbq-notification-center-sub-header-z-index) + 1);height:100%;overflow:auto;border-radius:inherit;corner-shape:inherit;padding-bottom:var(--kbq-size-xl);scroll-padding-top:var(--kbq-notification-center-size-sub-header-height);scroll-behavior:smooth}.kbq-notification-center-container.kbq-animations-disabled{scroll-behavior:auto}@media(prefers-reduced-motion:reduce){.kbq-notification-center-container{scroll-behavior:auto}}.kbq-notification-center-container .kbq-loader-overlay_parent{border-radius:inherit;corner-shape:inherit}.kbq-notification-center-load-more{display:flex;align-items:center;justify-content:center;padding:var(--kbq-notification-center-size-load-more-padding-vertical) 0}.kbq-notification-center-load-more-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--kbq-size-xxs) var(--kbq-size-xxl);text-align:center}.kbq-notification-center-load-more-error .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center-empty-container,.kbq-notification-center-error-container{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}.kbq-notification-center-empty-container .kbq-icon,.kbq-notification-center-error-container .kbq-icon{margin-bottom:var(--kbq-size-xl)}.kbq-notification-center-empty-container .kbq-button,.kbq-notification-center-error-container .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center{background:var(--kbq-notification-center-container-background)}.kbq-notification-center:not(.kbq-notification-center_popover){border-right-color:var(--kbq-notification-center-container-border-color);border-left-color:var(--kbq-notification-center-container-border-color)}.kbq-notification-center-sub-header{background:var(--kbq-notification-center-container-background)}.kbq-notification-center-error-container,.kbq-notification-center-load-more-error{color:var(--kbq-notification-center-error-text-color)}.kbq-notification-center{font-size:var(--kbq-typography-text-normal-medium-font-size);font-style:var(--kbq-typography-text-normal-medium-font-style);font-weight:var(--kbq-typography-text-normal-medium-font-weight);line-height:var(--kbq-typography-text-normal-medium-line-height);font-family:var(--kbq-typography-text-normal-medium-font-family);text-transform:var(--kbq-typography-text-normal-medium-text-transform);font-feature-settings:var(--kbq-typography-text-normal-medium-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-medium-letter-spacing)}.kbq-notification-center-title__text{font-size:var(--kbq-typography-text-big-strong-font-size);font-style:var(--kbq-typography-text-big-strong-font-style);font-weight:var(--kbq-typography-text-big-strong-font-weight);line-height:var(--kbq-typography-text-big-strong-line-height);font-family:var(--kbq-typography-text-big-strong-font-family);text-transform:var(--kbq-typography-text-big-strong-text-transform);font-feature-settings:var(--kbq-typography-text-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-text-big-strong-letter-spacing)}\n", ".kbq-notification-center{--kbq-notification-center-size-container-width: 400px;--kbq-notification-center-size-navbar-height: var(--kbq-size-5xl);--kbq-notification-center-size-container-border-radius: var(--kbq-size-xs);--kbq-notification-center-sub-header-z-index: 2;--kbq-notification-center-size-sub-header-height: calc(var(--kbq-size-s) * 2 + var(--kbq-size-xl));--kbq-notification-center-size-item-icon-padding-top: calc(var(--kbq-size-m) + var(--kbq-size-3xs));--kbq-notification-center-size-item-time-padding-left: calc(var(--kbq-size-xl) + var(--kbq-size-3xs));--kbq-notification-center-size-load-more-padding-vertical: calc(var(--kbq-size-xxl) + var(--kbq-size-3xs));--kbq-notification-center-container-background: var(--kbq-background-card);--kbq-notification-center-container-border-color: var(--kbq-line-contrast-less);--kbq-notification-center-container-shadow: var(--kbq-shadow-popup);--kbq-notification-center-error-text-color: var(--kbq-foreground-error)}.kbq-notification-center-switcher{--kbq-notification-center-size-switcher-mark-width: var(--kbq-size-l)}\n"], dependencies: [{ kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i2.KbqIcon, selector: "[kbq-icon]", inputs: ["aria-hidden", "iconSize", "autoColor", "kbq-icon"] }, { kind: "component", type: i2.KbqIconItem, selector: "[kbq-icon-item]", inputs: ["kbq-icon-item", "fade", "big"] }, { kind: "ngmodule", type: KbqBadgeModule }, { kind: "directive", type: KbqScrollbarViewport, selector: "[kbqScrollbarViewport]", inputs: ["kbqScrollbarMode", "kbqScrollbarHideDelay"] }, { kind: "ngmodule", type: KbqButtonModule }, { kind: "component", type: i3$1.KbqButton, selector: "[kbq-button]", inputs: ["kbqStyle", "disabled", "tabIndex"] }, { kind: "directive", type: i3$1.KbqButtonCssStyler, selector: "[kbq-button]" }, { kind: "directive", type: i3$1.KbqButtonDropdownTrigger, selector: "[kbq-button][kbqDropdownTriggerFor]" }, { kind: "ngmodule", type: KbqDividerModule }, { kind: "component", type: i4.KbqDivider, selector: "kbq-divider", inputs: ["vertical", "paddings", "decorative", "length"] }, { kind: "ngmodule", type: KbqDropdownModule }, { kind: "component", type: i5.KbqDropdown, selector: "kbq-dropdown", inputs: ["activeDescendantNavigation", "navigationWithWrap", "xPosition", "yPosition", "overlapTriggerY", "overlapTriggerX", "hasBackdrop", "class", "backdropClass", "panelWidth", "panelMinWidth", "panelMaxWidth", "safeArea"], outputs: ["xPositionChange", "yPositionChange", "overlapTriggerYChange", "overlapTriggerXChange", "closed"], exportAs: ["kbqDropdown"] }, { kind: "component", type: i5.KbqDropdownItem, selector: "kbq-dropdown-item, [kbq-dropdown-item]", inputs: ["disabled", "progress"], exportAs: ["kbqDropdownItem"] }, { kind: "directive", type: i5.KbqDropdownTrigger, selector: "[kbqDropdownTriggerFor]", inputs: ["offsetX", "offsetY", "kbqDropdownTriggerData", "openByArrowDown", "kbqDropdownTriggerOrigin", "kbqDropdownTriggerAutoFocus", "kbqDropdownTriggerRestoreFocus", "kbqDropdownTriggerFor"], outputs: ["offsetXChange", "openByArrowDownChange", "kbqDropdownTriggerRestoreFocusChange", "dropdownOpened", "dropdownClosed"], exportAs: ["kbqDropdownTrigger"] }, { kind: "ngmodule", type: KbqToolTipModule }, { kind: "directive", type: i6.KbqTooltipTrigger, selector: "[kbqTooltip]", inputs: ["kbqTooltipScrollStrategy", "forDisabledComponent", "ignoreTooltipPointerEvents", "kbqTooltipSingleInstance", "kbqTrigger", "hideWithTimeout", "kbqEnterDelay", "kbqLeaveDelay", "kbqRelativeToPointer", "kbqRelativeToCaret", "kbqRelativeToCaretVertical", "kbqTooltip", "kbqTooltipHeader", "kbqTooltipModifier", "kbqTooltipContext", "kbqTooltipClass", "kbqTooltipColor", "kbqTooltipArrow", "kbqTooltipOffset", "kbqTooltipDisabled", "kbqPlacementPriority", "kbqPlacement", "kbqVisible"], outputs: ["kbqPlacementChange", "kbqVisibleChange"], exportAs: ["kbqTooltip"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: KbqNotificationItemComponent, selector: "kbq-notification-item", inputs: ["data"] }, { kind: "ngmodule", type: KbqLoaderOverlayModule }, { kind: "component", type: i7.KbqLoaderOverlay, selector: "kbq-loader-overlay", inputs: ["text", "caption", "size", "surface", "transparent", "card"] }, { kind: "ngmodule", type: KbqProgressSpinnerModule }, { kind: "component", type: i8.KbqProgressSpinner, selector: "kbq-progress-spinner", inputs: ["id", "value", "mode", "size"] }, { kind: "directive", type: KbqOverflowShadowContainer, selector: "[kbqOverflowShadowContainer]", inputs: ["debounce"], exportAs: ["kbqOverflowShadowContainer"] }, { kind: "directive", type: KbqOverflowShadowTop, selector: "[kbqOverflowShadowTop]", inputs: ["kbqOverflowShadowTop", "shadow"], exportAs: ["kbqOverflowShadowTop"] }, { kind: "directive", type: KbqOverflowShadowBottom, selector: "[kbqOverflowShadowBottom]", inputs: ["kbqOverflowShadowBottom", "shadow"], exportAs: ["kbqOverflowShadowBottom"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
476
812
|
}
|
|
477
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
813
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterComponent, decorators: [{
|
|
478
814
|
type: Component,
|
|
479
815
|
args: [{ selector: 'kbq-notification-center', imports: [
|
|
480
816
|
KbqIconModule,
|
|
481
817
|
KbqBadgeModule,
|
|
482
|
-
|
|
818
|
+
KbqScrollbarViewport,
|
|
483
819
|
KbqButtonModule,
|
|
484
820
|
KbqDividerModule,
|
|
485
821
|
KbqDropdownModule,
|
|
486
822
|
KbqToolTipModule,
|
|
487
|
-
|
|
823
|
+
CdkTrapFocus,
|
|
488
824
|
KbqNotificationItemComponent,
|
|
489
825
|
KbqLoaderOverlayModule,
|
|
490
826
|
KbqProgressSpinnerModule,
|
|
491
827
|
KbqOverflowShadowContainer,
|
|
492
828
|
KbqOverflowShadowTop,
|
|
493
829
|
KbqOverflowShadowBottom
|
|
830
|
+
], providers: [
|
|
831
|
+
// The panel traps focus, so it needs a configurable trap even when it is imported standalone —
|
|
832
|
+
// these used to be reachable only through KbqNotificationCenterModule.
|
|
833
|
+
{ provide: FocusTrapFactory, useClass: ConfigurableFocusTrapFactory },
|
|
834
|
+
{ provide: FOCUS_TRAP_INERT_STRATEGY, useClass: EmptyFocusTrapStrategy },
|
|
835
|
+
{ provide: KBQ_NOTIFICATION_CENTER_PANEL, useExisting: forwardRef((() => KbqNotificationCenterComponent)) }
|
|
494
836
|
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
495
837
|
class: 'kbq-notification-center',
|
|
838
|
+
role: 'dialog',
|
|
839
|
+
'[attr.id]': 'panelId',
|
|
840
|
+
'[attr.aria-labelledby]': 'titleId',
|
|
496
841
|
'[class.kbq-notification-center_popover]': 'popoverMode',
|
|
497
|
-
'(keydown.escape)': 'escapeHandler()'
|
|
498
|
-
}, animations: [KbqNotificationCenterAnimations.state], preserveWhitespaces: false, template: "<div class=\"kbq-notification-center-header\">\n <div class=\"kbq-notification-center-title\">\n <div class=\"kbq-notification-center-title__text\">{{ localeData.notifications }}</div>\n <button\n #notificationSwitcher\n kbq-button\n class=\"kbq-notification-center-title__button\"\n data-testid=\"kbq-notification-center-silent-mode-toggle\"\n [kbqDropdownTriggerFor]=\"notificationSwitcherDropdown\"\n [kbqTooltip]=\"service.silentMode.value ? localeData.doNotDisturb : localeData.showPopUpNotifications\"\n [kbqTooltipArrow]=\"false\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipOffset]=\"4\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n >\n <i kbq-icon=\"{{ service.silentMode.value ? 'kbq-bell-slash_16' : 'kbq-bell_16' }}\"></i>\n </button>\n </div>\n <div class=\"kbq-notification-center-toolbar\">\n @if (!service.isEmpty) {\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-remove-all-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"service.removeAll()\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n\n <kbq-divider [vertical]=\"true\" />\n }\n\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-close-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"hide(0)\"\n >\n <i kbq-icon=\"kbq-xmark_16\"></i>\n </button>\n </div>\n</div>\n\n<div\n #notificationCenterContainer=\"kbqOverflowShadowContainer\"\n kbq-scrollbar\n kbqOverflowShadowContainer\n class=\"kbq-notification-center-container\"\n data-testid=\"kbq-notification-center-container\"\n [kbqOverflowShadowBottom]=\"notificationCenterContainer\"\n [shadow]=\"'var(--kbq-shadow-overflow-normal-bottom)'\"\n (onScroll)=\"onContainerScroll()\"\n>\n @if (!service.errorMode.value) {\n @if (!service.loadingMode.value) {\n @for (group of service.groupedItems | async; track group) {\n <div\n class=\"kbq-notification-center-sub-header\"\n data-testid=\"kbq-notification-center-group\"\n [kbqOverflowShadowTop]=\"$first ? notificationCenterContainer : undefined\"\n >\n <div class=\"kbq-notification-center-sub-header__date\">{{ group.title }}</div>\n\n <button\n kbq-button\n class=\"kbq-notification-center-sub-header__button\"\n data-testid=\"kbq-notification-center-remove-group-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeData.remove\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"service.removeGroup(group)\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n </div>\n\n @for (item of group.items; track item) {\n <kbq-notification-item [data]=\"item\" />\n }\n } @empty {\n @if (!service.loadingMore.value) {\n <div class=\"kbq-notification-center-empty-container\" data-testid=\"kbq-notification-center-empty\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'contrast-fade'\"></i>\n {{ localeData.noNotifications }}\n </div>\n }\n }\n\n @if (service.loadingMore.value) {\n <div\n class=\"kbq-notification-center-load-more\"\n data-testid=\"kbq-notification-center-load-more\"\n role=\"status\"\n [attr.aria-label]=\"localeData.loadingMore\"\n >\n <kbq-progress-spinner [mode]=\"'indeterminate'\" [size]=\"'compact'\" />\n </div>\n }\n\n @if (service.loadMoreErrorMode.value) {\n <div\n class=\"kbq-notification-center-load-more-error\"\n data-testid=\"kbq-notification-center-load-more-error\"\n role=\"alert\"\n >\n {{ localeData.failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-load-more-retry-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"retryLoadMore()\"\n >\n {{ localeData.repeat }}\n </button>\n </div>\n }\n } @else {\n <kbq-loader-overlay data-testid=\"kbq-notification-center-loader\" [transparent]=\"true\" />\n }\n } @else {\n <div class=\"kbq-notification-center-error-container\" data-testid=\"kbq-notification-center-error\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'error'\" [fade]=\"true\"></i>\n {{ localeData.failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-reload-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"service.onReload.emit()\"\n >\n {{ localeData.repeat }}\n </button>\n </div>\n }\n</div>\n\n<kbq-dropdown #notificationSwitcherDropdown=\"kbqDropdown\">\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-show-notifications-button\"\n (click)=\"service.setSilentMode(false)\"\n >\n <i kbq-icon=\"{{ !service.silentMode.value ? 'kbq-circle-xs_16' : '' }}\" [style.min-width.px]=\"16\"></i>\n {{ localeData.showPopUpNotifications }}\n </button>\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-do-not-disturb-button\"\n (click)=\"service.setSilentMode(true)\"\n >\n <i kbq-icon=\"{{ service.silentMode.value ? 'kbq-circle-xs_16' : '' }}\" [style.min-width.px]=\"16\"></i>\n {{ localeData.doNotDisturb }}\n </button>\n</kbq-dropdown>\n", styles: [".kbq-notification-center{position:relative;display:flex;flex-direction:column;width:400px;height:100vh;box-sizing:border-box;z-index:1}.kbq-notification-center:not(.kbq-notification-center_popover){border-right:1px solid;border-left:1px solid}.kbq-notification-center.kbq-notification-center_popover{margin-top:var(--kbq-size-xxs);margin-bottom:var(--kbq-size-xxs);border-radius:var(--kbq-size-xs);height:calc(100vh - 48px);box-shadow:var(--kbq-shadow-popup)}.kbq-notification-center-header{display:flex;flex-direction:row;justify-content:space-between;padding:var(--kbq-size-m) var(--kbq-size-xl) var(--kbq-size-xxs) var(--kbq-size-xxl)}.kbq-notification-center-title{display:flex;flex-direction:row;align-items:center;gap:var(--kbq-size-xxs)}.kbq-notification-center-toolbar{display:flex;flex-direction:row;align-items:center}.kbq-notification-center-toolbar .kbq-divider.kbq-divider_vertical{height:var(--kbq-size-m)}.kbq-notification-center-sub-header{position:sticky;top:0;z-index:100;display:flex;flex-direction:row;padding:var(--kbq-size-s) var(--kbq-size-xl)}.kbq-notification-center-sub-header .kbq-notification-center-sub-header__button{position:absolute;top:0;right:var(--kbq-size-xl);display:none}.kbq-notification-center-sub-header:hover .kbq-notification-center-sub-header__button,.kbq-notification-center-sub-header:focus-within .kbq-notification-center-sub-header__button{display:flex}.kbq-notification-center-container{height:100%;border-radius:inherit;padding-bottom:var(--kbq-size-xl)}.kbq-notification-center-container [data-overlayscrollbars-viewport]{scroll-behavior:smooth}@media(prefers-reduced-motion:reduce){.kbq-notification-center-container [data-overlayscrollbars-viewport]{scroll-behavior:auto}}.kbq-notification-center-container .kbq-loader-overlay_parent{border-radius:inherit}.kbq-notification-center-load-more{display:flex;align-items:center;justify-content:center;padding:26px 0}.kbq-notification-center-load-more-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--kbq-size-xxs) var(--kbq-size-xxl);text-align:center}.kbq-notification-center-load-more-error .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center-empty-container,.kbq-notification-center-error-container{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}.kbq-notification-center-empty-container .kbq-icon,.kbq-notification-center-error-container .kbq-icon{margin-bottom:var(--kbq-size-xl)}.kbq-notification-center-empty-container .kbq-button,.kbq-notification-center-error-container .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center,.kbq-notification-center-sub-header{background:var(--kbq-background-card)}.kbq-notification-center:not(.kbq-notification-center_popover),.kbq-notification-center-sub-header:not(.kbq-notification-center_popover){border-right-color:var(--kbq-line-contrast-less);border-left-color:var(--kbq-line-contrast-less)}.kbq-notification-center-error-container,.kbq-notification-center-load-more-error{color:var(--kbq-foreground-error)}.kbq-notification-center{font-size:var(--kbq-typography-text-normal-medium-font-size);font-style:var(--kbq-typography-text-normal-medium-font-style);font-weight:var(--kbq-typography-text-normal-medium-font-weight);line-height:var(--kbq-typography-text-normal-medium-line-height);font-family:var(--kbq-typography-text-normal-medium-font-family);text-transform:var(--kbq-typography-text-normal-medium-text-transform);font-feature-settings:var(--kbq-typography-text-normal-medium-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-medium-letter-spacing)}.kbq-notification-center-title__text{font-size:var(--kbq-typography-text-big-strong-font-size);font-style:var(--kbq-typography-text-big-strong-font-style);font-weight:var(--kbq-typography-text-big-strong-font-weight);line-height:var(--kbq-typography-text-big-strong-line-height);font-family:var(--kbq-typography-text-big-strong-font-family);text-transform:var(--kbq-typography-text-big-strong-text-transform);font-feature-settings:var(--kbq-typography-text-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-text-big-strong-letter-spacing)}\n"] }]
|
|
499
|
-
}], ctorParameters: () => [], propDecorators: { switcher: [{ type: i0.ViewChild, args: ['notificationSwitcher', { isSignal: true }] }], scrollContainer: [{ type: i0.ViewChild, args: [i0.forwardRef(() =>
|
|
842
|
+
'(keydown.escape)': 'escapeHandler($any($event))'
|
|
843
|
+
}, hostDirectives: [KbqLocaleOverridesDirective], preserveWhitespaces: false, template: "<!-- `display: contents` keeps the trap out of the panel's flex layout while still scoping the focus trap\nto everything the panel renders. -->\n<div class=\"kbq-notification-center__trap\" [cdkTrapFocus]=\"isTrapFocus\">\n <div class=\"kbq-notification-center-header\">\n <div class=\"kbq-notification-center-title\">\n <div class=\"kbq-notification-center-title__text\" [id]=\"titleId\">\n {{ localeConfiguration().notifications }}\n </div>\n <button\n #notificationSwitcher\n kbq-button\n class=\"kbq-notification-center-title__button\"\n data-testid=\"kbq-notification-center-silent-mode-toggle\"\n [kbqDropdownTriggerFor]=\"notificationSwitcherDropdown\"\n [attr.aria-label]=\"\n service.silentMode()\n ? localeConfiguration().doNotDisturb\n : localeConfiguration().showPopUpNotifications\n \"\n [kbqTooltip]=\"\n service.silentMode()\n ? localeConfiguration().doNotDisturb\n : localeConfiguration().showPopUpNotifications\n \"\n [kbqTooltipArrow]=\"false\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipOffset]=\"4\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n >\n <i kbq-icon=\"{{ service.silentMode() ? 'kbq-bell-slash_16' : 'kbq-bell_16' }}\"></i>\n </button>\n </div>\n <div class=\"kbq-notification-center-toolbar\">\n @if (!service.empty()) {\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-remove-all-button\"\n [attr.aria-label]=\"a11yLocaleConfiguration().removeAll\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeConfiguration().removeAll\"\n [kbqPlacement]=\"'bottom'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"removeAll()\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n\n <kbq-divider [vertical]=\"true\" />\n }\n\n <button\n kbq-button\n class=\"kbq-notification-center-toolbar__button\"\n data-testid=\"kbq-notification-center-close-button\"\n [attr.aria-label]=\"a11yLocaleConfiguration().close\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n (click)=\"hide(0)\"\n >\n <i kbq-icon=\"kbq-xmark_16\"></i>\n </button>\n </div>\n </div>\n\n <!-- One persistent live region for the whole panel: a region inserted together with its text is\n not reliably announced, so only the text below ever changes. -->\n <div class=\"cdk-visually-hidden\" data-testid=\"kbq-notification-center-status\" role=\"status\" aria-live=\"polite\">\n {{ statusMessage }}\n </div>\n\n <div\n #notificationCenterContainer=\"kbqOverflowShadowContainer\"\n kbqScrollbarViewport\n kbqOverflowShadowContainer\n class=\"kbq-notification-center-container\"\n data-testid=\"kbq-notification-center-container\"\n [class.kbq-animations-disabled]=\"animationsDisabled\"\n [kbqOverflowShadowBottom]=\"notificationCenterContainer\"\n [shadow]=\"'var(--kbq-shadow-overflow-normal-bottom)'\"\n >\n @if (!service.errorMode()) {\n @if (!service.loadingMode()) {\n @for (group of service.groupedItems(); track group.id) {\n <div\n class=\"kbq-notification-center-sub-header\"\n data-testid=\"kbq-notification-center-group\"\n [kbqOverflowShadowTop]=\"$first ? notificationCenterContainer : undefined\"\n >\n <div class=\"kbq-notification-center-sub-header__date\">{{ group.title }}</div>\n\n <button\n kbq-button\n class=\"kbq-notification-center-sub-header__button\"\n data-testid=\"kbq-notification-center-remove-group-button\"\n [attr.aria-label]=\"localeConfiguration().remove\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'contrast'\"\n [kbqTooltip]=\"localeConfiguration().remove\"\n [kbqPlacement]=\"'right'\"\n [kbqTooltipArrow]=\"false\"\n (click)=\"removeGroup(group)\"\n >\n <i kbq-icon=\"kbq-trash_16\"></i>\n </button>\n </div>\n\n @for (item of group.items; track item.id) {\n <kbq-notification-item [data]=\"item\" />\n }\n } @empty {\n @if (!service.loadingMore() && !service.loadMoreErrorMode()) {\n <div\n class=\"kbq-notification-center-empty-container\"\n data-testid=\"kbq-notification-center-empty\"\n >\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'contrast-fade'\"></i>\n {{ localeConfiguration().noNotifications }}\n </div>\n }\n }\n\n @if (service.loadingMore()) {\n <div class=\"kbq-notification-center-load-more\" data-testid=\"kbq-notification-center-load-more\">\n <kbq-progress-spinner [mode]=\"'indeterminate'\" [size]=\"'compact'\" />\n </div>\n } @else if (service.loadMoreErrorMode()) {\n <div\n class=\"kbq-notification-center-load-more-error\"\n data-testid=\"kbq-notification-center-load-more-error\"\n >\n {{ localeConfiguration().failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-load-more-retry-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"retryLoadMore()\"\n >\n {{ localeConfiguration().repeat }}\n </button>\n </div>\n }\n } @else {\n <kbq-loader-overlay data-testid=\"kbq-notification-center-loader\" />\n }\n } @else {\n <div class=\"kbq-notification-center-error-container\" data-testid=\"kbq-notification-center-error\">\n <i kbq-icon-item=\"kbq-bell_16\" [big]=\"true\" [color]=\"'error'\" [fade]=\"true\"></i>\n {{ localeConfiguration().failedToLoadNotifications }}\n <button\n kbq-button\n data-testid=\"kbq-notification-center-reload-button\"\n [kbqStyle]=\"'transparent'\"\n [color]=\"'theme'\"\n (click)=\"service.onReload.next()\"\n >\n {{ localeConfiguration().repeat }}\n </button>\n </div>\n }\n </div>\n\n <!-- `class` is KbqDropdown's own input: it moves the class onto the panel rendered in the overlay,\n which is where the check-mark width token has to be declared to reach the marks. -->\n <kbq-dropdown #notificationSwitcherDropdown=\"kbqDropdown\" class=\"kbq-notification-center-switcher\">\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-show-notifications-button\"\n (click)=\"service.setSilentMode(false)\"\n >\n <i\n class=\"kbq-notification-center-switcher__mark\"\n kbq-icon=\"kbq-circle-xs_16\"\n [class.kbq-notification-center-switcher__mark_hidden]=\"service.silentMode()\"\n ></i>\n {{ localeConfiguration().showPopUpNotifications }}\n </button>\n <button\n kbq-dropdown-item\n data-testid=\"kbq-notification-center-do-not-disturb-button\"\n (click)=\"service.setSilentMode(true)\"\n >\n <i\n class=\"kbq-notification-center-switcher__mark\"\n kbq-icon=\"kbq-circle-xs_16\"\n [class.kbq-notification-center-switcher__mark_hidden]=\"!service.silentMode()\"\n ></i>\n {{ localeConfiguration().doNotDisturb }}\n </button>\n </kbq-dropdown>\n</div>\n", styles: [".kbq-notification-center{position:relative;display:flex;flex-direction:column;width:var(--kbq-notification-center-size-container-width);height:var(--kbq-notification-center-popover-height, 100vh);box-sizing:border-box;z-index:1}.kbq-notification-center:not(.kbq-notification-center_popover){border-right:1px solid;border-left:1px solid}.kbq-notification-center.kbq-notification-center_popover{margin-top:var(--kbq-size-xxs);margin-bottom:var(--kbq-size-xxs);border-radius:var(--kbq-notification-center-size-container-border-radius)}@supports (corner-shape: squircle){.kbq-notification-center.kbq-notification-center_popover{corner-shape:squircle;border-radius:clamp(var(--kbq-notification-center-size-container-border-radius) * 1.85,var(--kbq-notification-center-size-container-border-radius) * 2.3 - 3.6px,var(--kbq-notification-center-size-container-border-radius) * 2)}}.kbq-notification-center.kbq-notification-center_popover{height:var(--kbq-notification-center-popover-height, calc(100vh - var(--kbq-notification-center-size-navbar-height)));box-shadow:var(--kbq-notification-center-container-shadow)}.kbq-notification-center__trap{display:contents}.kbq-notification-center-header{display:flex;flex-direction:row;justify-content:space-between;padding:var(--kbq-size-m) var(--kbq-size-xl) var(--kbq-size-xxs) var(--kbq-size-xxl)}.kbq-notification-center-title{display:flex;flex-direction:row;align-items:center;gap:var(--kbq-size-xxs)}.kbq-notification-center-toolbar{display:flex;flex-direction:row;align-items:center}.kbq-notification-center-toolbar .kbq-divider.kbq-divider_vertical{height:var(--kbq-size-m)}.kbq-notification-center-switcher__mark{min-width:var(--kbq-notification-center-size-switcher-mark-width)}.kbq-notification-center-switcher__mark.kbq-notification-center-switcher__mark_hidden{visibility:hidden}.kbq-notification-center-sub-header{position:sticky;top:0;z-index:var(--kbq-notification-center-sub-header-z-index);display:flex;flex-direction:row;padding:var(--kbq-size-s) var(--kbq-size-xl)}.kbq-notification-center-sub-header .kbq-notification-center-sub-header__button{position:absolute;top:0;right:var(--kbq-size-xl);display:flex;opacity:0;pointer-events:none}.kbq-notification-center-sub-header:hover .kbq-notification-center-sub-header__button,.kbq-notification-center-sub-header:focus-within .kbq-notification-center-sub-header__button{opacity:1;pointer-events:auto}.kbq-notification-center-container{--kbq-scrollbar-track-z-index: calc(var(--kbq-notification-center-sub-header-z-index) + 1);height:100%;overflow:auto;border-radius:inherit;corner-shape:inherit;padding-bottom:var(--kbq-size-xl);scroll-padding-top:var(--kbq-notification-center-size-sub-header-height);scroll-behavior:smooth}.kbq-notification-center-container.kbq-animations-disabled{scroll-behavior:auto}@media(prefers-reduced-motion:reduce){.kbq-notification-center-container{scroll-behavior:auto}}.kbq-notification-center-container .kbq-loader-overlay_parent{border-radius:inherit;corner-shape:inherit}.kbq-notification-center-load-more{display:flex;align-items:center;justify-content:center;padding:var(--kbq-notification-center-size-load-more-padding-vertical) 0}.kbq-notification-center-load-more-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--kbq-size-xxs) var(--kbq-size-xxl);text-align:center}.kbq-notification-center-load-more-error .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center-empty-container,.kbq-notification-center-error-container{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}.kbq-notification-center-empty-container .kbq-icon,.kbq-notification-center-error-container .kbq-icon{margin-bottom:var(--kbq-size-xl)}.kbq-notification-center-empty-container .kbq-button,.kbq-notification-center-error-container .kbq-button{margin-top:var(--kbq-size-s)}.kbq-notification-center{background:var(--kbq-notification-center-container-background)}.kbq-notification-center:not(.kbq-notification-center_popover){border-right-color:var(--kbq-notification-center-container-border-color);border-left-color:var(--kbq-notification-center-container-border-color)}.kbq-notification-center-sub-header{background:var(--kbq-notification-center-container-background)}.kbq-notification-center-error-container,.kbq-notification-center-load-more-error{color:var(--kbq-notification-center-error-text-color)}.kbq-notification-center{font-size:var(--kbq-typography-text-normal-medium-font-size);font-style:var(--kbq-typography-text-normal-medium-font-style);font-weight:var(--kbq-typography-text-normal-medium-font-weight);line-height:var(--kbq-typography-text-normal-medium-line-height);font-family:var(--kbq-typography-text-normal-medium-font-family);text-transform:var(--kbq-typography-text-normal-medium-text-transform);font-feature-settings:var(--kbq-typography-text-normal-medium-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-medium-letter-spacing)}.kbq-notification-center-title__text{font-size:var(--kbq-typography-text-big-strong-font-size);font-style:var(--kbq-typography-text-big-strong-font-style);font-weight:var(--kbq-typography-text-big-strong-font-weight);line-height:var(--kbq-typography-text-big-strong-line-height);font-family:var(--kbq-typography-text-big-strong-font-family);text-transform:var(--kbq-typography-text-big-strong-text-transform);font-feature-settings:var(--kbq-typography-text-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-text-big-strong-letter-spacing)}\n", ".kbq-notification-center{--kbq-notification-center-size-container-width: 400px;--kbq-notification-center-size-navbar-height: var(--kbq-size-5xl);--kbq-notification-center-size-container-border-radius: var(--kbq-size-xs);--kbq-notification-center-sub-header-z-index: 2;--kbq-notification-center-size-sub-header-height: calc(var(--kbq-size-s) * 2 + var(--kbq-size-xl));--kbq-notification-center-size-item-icon-padding-top: calc(var(--kbq-size-m) + var(--kbq-size-3xs));--kbq-notification-center-size-item-time-padding-left: calc(var(--kbq-size-xl) + var(--kbq-size-3xs));--kbq-notification-center-size-load-more-padding-vertical: calc(var(--kbq-size-xxl) + var(--kbq-size-3xs));--kbq-notification-center-container-background: var(--kbq-background-card);--kbq-notification-center-container-border-color: var(--kbq-line-contrast-less);--kbq-notification-center-container-shadow: var(--kbq-shadow-popup);--kbq-notification-center-error-text-color: var(--kbq-foreground-error)}.kbq-notification-center-switcher{--kbq-notification-center-size-switcher-mark-width: var(--kbq-size-l)}\n"] }]
|
|
844
|
+
}], ctorParameters: () => [], propDecorators: { switcher: [{ type: i0.ViewChild, args: ['notificationSwitcher', { isSignal: true }] }], scrollContainer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => KbqScrollbarViewport), { isSignal: true }] }] } });
|
|
500
845
|
class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
|
|
501
|
-
/** Number of unread notifications */
|
|
846
|
+
/** Number of unread notifications, formatted for the trigger badge. */
|
|
502
847
|
get unreadItemsCounter() {
|
|
503
848
|
return this.service.unreadItemsCounter;
|
|
504
849
|
}
|
|
505
850
|
/** Use popover or not */
|
|
506
|
-
// TODO: Skipped for migration because:
|
|
507
|
-
// Accessor inputs cannot be migrated as they are too complex.
|
|
508
851
|
get popoverMode() {
|
|
509
852
|
return this._popoverMode;
|
|
510
853
|
}
|
|
511
854
|
set popoverMode(value) {
|
|
855
|
+
if (value === this._popoverMode) {
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
512
858
|
this._popoverMode = value;
|
|
513
|
-
|
|
514
|
-
|
|
859
|
+
// The placement in force before the mode took over is remembered rather than assumed: a consumer
|
|
860
|
+
// may have bound one of its own, and turning the mode off used to leave the popover placement
|
|
861
|
+
// behind for good.
|
|
862
|
+
if (value) {
|
|
863
|
+
this.placementBeforePopoverMode = { placement: this.placement, priority: this.placementPriority };
|
|
864
|
+
this.placement = PopUpPlacements.Bottom;
|
|
865
|
+
this.updatePlacementPriority(['bottomCenter', 'bottomLeft', 'bottomRight']);
|
|
866
|
+
}
|
|
867
|
+
else if (this.placementBeforePopoverMode) {
|
|
868
|
+
this.placement = this.placementBeforePopoverMode.placement;
|
|
869
|
+
this.updatePlacementPriority(this.placementBeforePopoverMode.priority);
|
|
870
|
+
this.placementBeforePopoverMode = null;
|
|
871
|
+
}
|
|
515
872
|
}
|
|
516
|
-
/** Set height of popover. Default is calc(100vh -
|
|
517
|
-
// TODO: Skipped for migration because:
|
|
518
|
-
// Accessor inputs cannot be migrated as they are too complex.
|
|
873
|
+
/** Set height of popover. Default is `calc(100vh - <navbar height>)`. */
|
|
519
874
|
get popoverHeight() {
|
|
520
875
|
return this._popoverHeight;
|
|
521
876
|
}
|
|
522
877
|
set popoverHeight(value) {
|
|
523
878
|
this._popoverHeight = value;
|
|
524
|
-
|
|
879
|
+
// Guarding on the open panel, not on its current height: the previous `instance?.popoverHeight`
|
|
880
|
+
// check made the first set a no-op and made clearing the height impossible.
|
|
881
|
+
if (this.instance) {
|
|
525
882
|
this.instance.popoverHeight = value;
|
|
526
883
|
}
|
|
527
884
|
}
|
|
528
885
|
/** Whether the trigger is disabled. */
|
|
529
|
-
// TODO: Skipped for migration because:
|
|
530
|
-
// Accessor inputs cannot be migrated as they are too complex.
|
|
531
886
|
get disabled() {
|
|
532
887
|
return this._disabled;
|
|
533
888
|
}
|
|
@@ -544,64 +899,103 @@ class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
|
|
|
544
899
|
/** @docs-private */
|
|
545
900
|
get overlayConfig() {
|
|
546
901
|
const defaultPanelClass = 'kbq-notification-center__panel';
|
|
902
|
+
const panelClass = this.panelClass();
|
|
547
903
|
return {
|
|
548
|
-
panelClass:
|
|
549
|
-
hasBackdrop:
|
|
550
|
-
backdropClass: this.backdropClass
|
|
904
|
+
panelClass: panelClass ? [defaultPanelClass, panelClass] : defaultPanelClass,
|
|
905
|
+
hasBackdrop: false,
|
|
906
|
+
backdropClass: this.backdropClass()
|
|
551
907
|
};
|
|
552
908
|
}
|
|
909
|
+
ngOnChanges(changes) {
|
|
910
|
+
// A bound input is handed to its member, a bound `undefined` as the member's default; unbound, it leaves
|
|
911
|
+
// what code wrote.
|
|
912
|
+
if (changes['placementInput']) {
|
|
913
|
+
this.placement = this.placementInput() ?? defaultPlacement;
|
|
914
|
+
}
|
|
915
|
+
if (changes['popoverModeInput']) {
|
|
916
|
+
const popoverMode = this.popoverModeInput();
|
|
917
|
+
if (popoverMode !== undefined)
|
|
918
|
+
this.popoverMode = popoverMode;
|
|
919
|
+
}
|
|
920
|
+
if (changes['popoverHeightInput']) {
|
|
921
|
+
this.popoverHeight = this.popoverHeightInput() ?? '';
|
|
922
|
+
}
|
|
923
|
+
if (changes['stickToWindowInput']) {
|
|
924
|
+
this.stickToWindow = this.stickToWindowInput();
|
|
925
|
+
}
|
|
926
|
+
if (changes['containerInput']) {
|
|
927
|
+
this.container = this.containerInput();
|
|
928
|
+
}
|
|
929
|
+
if (changes['disabledInput']) {
|
|
930
|
+
const disabled = this.disabledInput();
|
|
931
|
+
if (disabled !== undefined)
|
|
932
|
+
this.disabled = disabled;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
553
935
|
constructor() {
|
|
554
936
|
super();
|
|
555
937
|
/** @docs-private */
|
|
556
938
|
this.scrollStrategy = inject(KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY);
|
|
557
939
|
/** @docs-private */
|
|
558
940
|
this.service = inject(KbqNotificationCenterService);
|
|
559
|
-
|
|
560
|
-
|
|
941
|
+
/**
|
|
942
|
+
* Id handed to the panel so `aria-controls` can point at it while it is open.
|
|
943
|
+
*
|
|
944
|
+
* @docs-private
|
|
945
|
+
*/
|
|
946
|
+
this.panelId = inject(_IdGenerator).getId('kbq-notification-center-panel-');
|
|
947
|
+
/**
|
|
948
|
+
* Not used.
|
|
949
|
+
*
|
|
950
|
+
* @docs-private
|
|
951
|
+
*/
|
|
561
952
|
this.arrow = false;
|
|
562
|
-
/** @docs-private */
|
|
563
|
-
this.hasBackdrop = false;
|
|
564
|
-
/** @docs-private */
|
|
565
|
-
this.size = PopUpSizes.Medium;
|
|
566
953
|
/** Placement of popUp */
|
|
567
|
-
|
|
568
|
-
// Your application code writes to the input. This prevents migration.
|
|
569
|
-
this.placement = PopUpPlacements.Right;
|
|
954
|
+
this.placement = defaultPlacement;
|
|
570
955
|
/** Class that will be used in the background */
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
this.
|
|
956
|
+
this.backdropClass = input('cdk-overlay-transparent-backdrop', ...(ngDevMode ? [{ debugName: "backdropClass" }] : /* istanbul ignore next */ []));
|
|
957
|
+
/** Class that will be used in the panel */
|
|
958
|
+
this.panelClass = input('', { ...(ngDevMode ? { debugName: "panelClass" } : /* istanbul ignore next */ {}), alias: 'kbqNotificationCenterPanelClass' });
|
|
574
959
|
/** Offset of popUp */
|
|
575
|
-
|
|
576
|
-
// Class of this input is referenced in the signature of another class.
|
|
577
|
-
this.offset = defaultOffsetX;
|
|
960
|
+
this.offset = input(defaultOffsetX, { ...(ngDevMode ? { debugName: "offset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
578
961
|
/** Distance in pixels from the bottom of the list at which the next page is requested via `onNextPage`. */
|
|
579
|
-
this.scrolledToBottomOffset = 0;
|
|
962
|
+
this.scrolledToBottomOffset = input(0, { ...(ngDevMode ? { debugName: "scrolledToBottomOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
963
|
+
/** Placement and priority in force before `popoverMode` replaced them. */
|
|
964
|
+
this.placementBeforePopoverMode = null;
|
|
580
965
|
this._popoverMode = false;
|
|
581
966
|
/** Emits a change event whenever the placement state changes. */
|
|
582
967
|
this.placementChange = new EventEmitter();
|
|
968
|
+
/** @docs-private */
|
|
969
|
+
this.placementChangeOutput = outputFromObservable(this.placementChange, { alias: 'kbqPlacementChange' });
|
|
583
970
|
/** Emits a change event whenever the visible state changes. */
|
|
584
971
|
this.visibleChange = new EventEmitter();
|
|
585
972
|
/** @docs-private */
|
|
973
|
+
this.visibleChangeOutput = outputFromObservable(this.visibleChange, { alias: 'kbqVisibleChange' });
|
|
974
|
+
/** @docs-private */
|
|
586
975
|
this.trigger = `${PopUpTriggers.Click}, ${PopUpTriggers.Keydown}`;
|
|
587
976
|
/** @docs-private */
|
|
588
977
|
this.originSelector = '.kbq-notification-center';
|
|
978
|
+
/** @docs-private */
|
|
979
|
+
this.placementInput = input(undefined, { ...(ngDevMode ? { debugName: "placementInput" } : /* istanbul ignore next */ {}), alias: 'kbqNotificationCenterPlacement' });
|
|
980
|
+
/** @docs-private */
|
|
981
|
+
this.popoverModeInput = input(undefined, { ...(ngDevMode ? { debugName: "popoverModeInput" } : /* istanbul ignore next */ {}), alias: 'popoverMode',
|
|
982
|
+
transform: booleanAttribute });
|
|
983
|
+
/** @docs-private */
|
|
984
|
+
this.popoverHeightInput = input(undefined, { ...(ngDevMode ? { debugName: "popoverHeightInput" } : /* istanbul ignore next */ {}), alias: 'popoverHeight' });
|
|
985
|
+
/** @docs-private */
|
|
986
|
+
this.stickToWindowInput = input(undefined, { ...(ngDevMode ? { debugName: "stickToWindowInput" } : /* istanbul ignore next */ {}), alias: 'stickToWindow' });
|
|
987
|
+
/** @docs-private */
|
|
988
|
+
this.containerInput = input(undefined, { ...(ngDevMode ? { debugName: "containerInput" } : /* istanbul ignore next */ {}), alias: 'container' });
|
|
989
|
+
/** @docs-private */
|
|
990
|
+
this.disabledInput = input(undefined, { ...(ngDevMode ? { debugName: "disabledInput" } : /* istanbul ignore next */ {}), alias: 'disabled',
|
|
991
|
+
transform: booleanAttribute });
|
|
589
992
|
this.updatePlacementPriority(['right', 'rightBottom', 'rightTop']);
|
|
590
993
|
}
|
|
591
994
|
ngAfterContentInit() {
|
|
995
|
+
// On close, return focus to the trigger. Suppressing the close on an inner scroll lives in
|
|
996
|
+
// `closingActions()`, so no per-visibility subscription is needed here.
|
|
592
997
|
this.visibleChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((visible) => {
|
|
593
|
-
if (visible) {
|
|
594
|
-
// eslint-disable-next-line rxjs-x/no-nested-subscribe
|
|
595
|
-
this.preventClosingByInnerScrollSubscription = this.closingActions().subscribe((event) => {
|
|
596
|
-
if (event && event['scrollDispatcher']) {
|
|
597
|
-
this.instance.setStickPosition();
|
|
598
|
-
event['kbqPopoverPreventHide'] = true;
|
|
599
|
-
event['type'] = 'click';
|
|
600
|
-
}
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
else {
|
|
604
|
-
this.preventClosingByInnerScrollSubscription?.unsubscribe();
|
|
998
|
+
if (!visible) {
|
|
605
999
|
this.focus();
|
|
606
1000
|
}
|
|
607
1001
|
});
|
|
@@ -610,22 +1004,24 @@ class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
|
|
|
610
1004
|
updateData() {
|
|
611
1005
|
if (!this.instance)
|
|
612
1006
|
return;
|
|
613
|
-
this.instance.
|
|
1007
|
+
this.instance.panelId = this.panelId;
|
|
614
1008
|
this.instance.content = this.content;
|
|
615
1009
|
this.instance.arrow = this.arrow;
|
|
616
|
-
this.instance.offset = this.offset;
|
|
617
|
-
this.instance.footer = this.footer;
|
|
1010
|
+
this.instance.offset = this.offset();
|
|
618
1011
|
this.instance.popoverMode = this.popoverMode;
|
|
619
1012
|
this.instance.popoverHeight = this.popoverHeight;
|
|
620
|
-
this.instance.scrolledToBottomOffset = this.scrolledToBottomOffset;
|
|
1013
|
+
this.instance.scrolledToBottomOffset = this.scrolledToBottomOffset();
|
|
621
1014
|
this.instance.updateTrapFocus(this.trigger !== PopUpTriggers.Focus);
|
|
1015
|
+
this.instance.detectChanges();
|
|
622
1016
|
if (this.isOpen) {
|
|
623
1017
|
this.updatePosition(true);
|
|
624
1018
|
}
|
|
625
1019
|
}
|
|
626
|
-
/**
|
|
1020
|
+
/**
|
|
1021
|
+
* Updates the current position.
|
|
627
1022
|
*
|
|
628
|
-
* @docs-private
|
|
1023
|
+
* @docs-private
|
|
1024
|
+
*/
|
|
629
1025
|
updatePosition(reapplyPosition = false) {
|
|
630
1026
|
this.overlayRef = this.createOverlay();
|
|
631
1027
|
const position = this.overlayRef.getConfig().positionStrategy
|
|
@@ -643,84 +1039,58 @@ class KbqNotificationCenterTrigger extends KbqPopUpTrigger {
|
|
|
643
1039
|
updateClassMap(newPlacement = this.placement) {
|
|
644
1040
|
if (!this.instance)
|
|
645
1041
|
return;
|
|
646
|
-
this.instance.updateClassMap(POSITION_TO_CSS_MAP[newPlacement], this.customClass,
|
|
647
|
-
this.instance.markForCheck();
|
|
1042
|
+
this.instance.updateClassMap(POSITION_TO_CSS_MAP[newPlacement], this.customClass, PopUpSizes.Medium);
|
|
648
1043
|
}
|
|
649
1044
|
/** @docs-private */
|
|
650
1045
|
closingActions() {
|
|
651
|
-
return merge(this.overlayRef.outsidePointerEvents(), this.overlayRef.backdropClick(),
|
|
1046
|
+
return merge(this.overlayRef.outsidePointerEvents(), this.overlayRef.backdropClick(),
|
|
1047
|
+
// Only a scroll outside the panel should close it. The list viewport is a `CdkScrollable`,
|
|
1048
|
+
// so its own scrolling reaches the root `ScrollDispatcher` too — filtering it out here is
|
|
1049
|
+
// what keeps the panel open, instead of tagging the shared scrollable with a "prevent hide"
|
|
1050
|
+
// flag that would then follow it around the whole application.
|
|
1051
|
+
this.scrollDispatcher.scrolled().pipe(filter((scrollable) => !this.isInnerScroll(scrollable))));
|
|
652
1052
|
}
|
|
653
|
-
/**
|
|
654
|
-
|
|
1053
|
+
/** Whether a `ScrollDispatcher` emission originates from inside this panel's own scrollable content. */
|
|
1054
|
+
isInnerScroll(scrollable) {
|
|
1055
|
+
return (scrollable instanceof CdkScrollable &&
|
|
1056
|
+
!!scrollable.getElementRef().nativeElement.closest('.kbq-notification-center'));
|
|
1057
|
+
}
|
|
1058
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1059
|
+
/** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.25", type: KbqNotificationCenterTrigger, isStandalone: true, selector: "[kbqNotificationCenterTrigger]", inputs: { backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "kbqNotificationCenterPanelClass", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, scrolledToBottomOffset: { classPropertyName: "scrolledToBottomOffset", publicName: "scrolledToBottomOffset", isSignal: true, isRequired: false, transformFunction: null }, placementInput: { classPropertyName: "placementInput", publicName: "kbqNotificationCenterPlacement", isSignal: true, isRequired: false, transformFunction: null }, popoverModeInput: { classPropertyName: "popoverModeInput", publicName: "popoverMode", isSignal: true, isRequired: false, transformFunction: null }, popoverHeightInput: { classPropertyName: "popoverHeightInput", publicName: "popoverHeight", isSignal: true, isRequired: false, transformFunction: null }, stickToWindowInput: { classPropertyName: "stickToWindowInput", publicName: "stickToWindow", isSignal: true, isRequired: false, transformFunction: null }, containerInput: { classPropertyName: "containerInput", publicName: "container", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { placementChangeOutput: "kbqPlacementChange", visibleChangeOutput: "kbqVisibleChange" }, host: { properties: { "class.kbq-notification-center_open": "isOpen", "class.kbq-active": "hasClickTrigger && isOpen", "attr.aria-expanded": "isOpen", "attr.aria-controls": "isOpen ? panelId : null" } }, providers: [kbqSiblingPopupProvider(KbqNotificationCenterTrigger)], exportAs: ["kbqNotificationCenterTrigger"], usesInheritance: true, usesOnChanges: true, ngImport: i0 }); }
|
|
655
1060
|
}
|
|
656
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1061
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterTrigger, decorators: [{
|
|
657
1062
|
type: Directive,
|
|
658
1063
|
args: [{
|
|
659
1064
|
selector: '[kbqNotificationCenterTrigger]',
|
|
660
1065
|
providers: [kbqSiblingPopupProvider(KbqNotificationCenterTrigger)],
|
|
661
1066
|
host: {
|
|
662
1067
|
'[class.kbq-notification-center_open]': 'isOpen',
|
|
663
|
-
'[class.kbq-active]': 'hasClickTrigger && isOpen'
|
|
1068
|
+
'[class.kbq-active]': 'hasClickTrigger && isOpen',
|
|
1069
|
+
'[attr.aria-expanded]': 'isOpen',
|
|
1070
|
+
'[attr.aria-controls]': 'isOpen ? panelId : null'
|
|
664
1071
|
},
|
|
665
1072
|
exportAs: 'kbqNotificationCenterTrigger'
|
|
666
1073
|
}]
|
|
667
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
668
|
-
type: Input,
|
|
669
|
-
args: ['kbqNotificationCenterPlacement']
|
|
670
|
-
}], backdropClass: [{
|
|
671
|
-
type: Input
|
|
672
|
-
}], panelClass: [{
|
|
673
|
-
type: Input,
|
|
674
|
-
args: ['kbqNotificationCenterPanelClass']
|
|
675
|
-
}], offset: [{
|
|
676
|
-
type: Input,
|
|
677
|
-
args: [{ transform: numberAttribute }]
|
|
678
|
-
}], scrolledToBottomOffset: [{
|
|
679
|
-
type: Input,
|
|
680
|
-
args: [{ transform: numberAttribute }]
|
|
681
|
-
}], popoverMode: [{
|
|
682
|
-
type: Input,
|
|
683
|
-
args: [{ transform: booleanAttribute }]
|
|
684
|
-
}], popoverHeight: [{
|
|
685
|
-
type: Input
|
|
686
|
-
}], disabled: [{
|
|
687
|
-
type: Input,
|
|
688
|
-
args: [{ transform: booleanAttribute }]
|
|
689
|
-
}], stickToWindow: [{
|
|
690
|
-
type: Input
|
|
691
|
-
}], container: [{
|
|
692
|
-
type: Input
|
|
693
|
-
}], placementChange: [{
|
|
694
|
-
type: Output,
|
|
695
|
-
args: ['kbqPlacementChange']
|
|
696
|
-
}], visibleChange: [{
|
|
697
|
-
type: Output,
|
|
698
|
-
args: ['kbqVisibleChange']
|
|
699
|
-
}] } });
|
|
1074
|
+
}], ctorParameters: () => [], propDecorators: { backdropClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdropClass", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "kbqNotificationCenterPanelClass", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], scrolledToBottomOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrolledToBottomOffset", required: false }] }], placementChangeOutput: [{ type: i0.Output, args: ["kbqPlacementChange"] }], visibleChangeOutput: [{ type: i0.Output, args: ["kbqVisibleChange"] }], placementInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "kbqNotificationCenterPlacement", required: false }] }], popoverModeInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "popoverMode", required: false }] }], popoverHeightInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "popoverHeight", required: false }] }], stickToWindowInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickToWindow", required: false }] }], containerInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "container", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
700
1075
|
|
|
1076
|
+
/**
|
|
1077
|
+
* Compatibility wrapper around the standalone notification center. Importing
|
|
1078
|
+
* `KbqNotificationCenterTrigger` directly is equivalent.
|
|
1079
|
+
*/
|
|
701
1080
|
class KbqNotificationCenterModule {
|
|
702
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
703
|
-
/** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
1081
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
1082
|
+
/** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterModule, imports: [KbqNotificationCenterComponent,
|
|
704
1083
|
KbqNotificationCenterTrigger], exports: [KbqNotificationCenterComponent,
|
|
705
1084
|
KbqNotificationCenterTrigger] }); }
|
|
706
|
-
/** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
707
|
-
{ provide: FocusTrapFactory, useClass: ConfigurableFocusTrapFactory },
|
|
708
|
-
{ provide: FOCUS_TRAP_INERT_STRATEGY, useClass: EmptyFocusTrapStrategy },
|
|
709
|
-
KbqNotificationCenterService
|
|
710
|
-
], imports: [KbqNotificationCenterComponent] }); }
|
|
1085
|
+
/** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterModule, imports: [KbqNotificationCenterComponent] }); }
|
|
711
1086
|
}
|
|
712
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1087
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KbqNotificationCenterModule, decorators: [{
|
|
713
1088
|
type: NgModule,
|
|
714
1089
|
args: [{
|
|
715
1090
|
imports: [
|
|
716
1091
|
KbqNotificationCenterComponent,
|
|
717
1092
|
KbqNotificationCenterTrigger
|
|
718
1093
|
],
|
|
719
|
-
providers: [
|
|
720
|
-
{ provide: FocusTrapFactory, useClass: ConfigurableFocusTrapFactory },
|
|
721
|
-
{ provide: FOCUS_TRAP_INERT_STRATEGY, useClass: EmptyFocusTrapStrategy },
|
|
722
|
-
KbqNotificationCenterService
|
|
723
|
-
],
|
|
724
1094
|
exports: [
|
|
725
1095
|
KbqNotificationCenterComponent,
|
|
726
1096
|
KbqNotificationCenterTrigger
|
|
@@ -732,5 +1102,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
|
|
|
732
1102
|
* Generated bundle index. Do not edit.
|
|
733
1103
|
*/
|
|
734
1104
|
|
|
735
|
-
export { KBQ_NOTIFICATION_CENTER_CONFIGURATION, KBQ_NOTIFICATION_CENTER_DEFAULT_CONFIGURATION,
|
|
1105
|
+
export { KBQ_NOTIFICATION_CENTER_CONFIGURATION, KBQ_NOTIFICATION_CENTER_DEFAULT_CONFIGURATION, KBQ_NOTIFICATION_CENTER_DEFAULT_LOCALE_CONFIGURATION, KBQ_NOTIFICATION_CENTER_LOCALE_CONFIGURATION, KBQ_NOTIFICATION_CENTER_PANEL, KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY, KbqNotificationCenterComponent, KbqNotificationCenterModule, KbqNotificationCenterService, KbqNotificationCenterTrigger, kbqNotificationCenterLocaleConfigurationProvider, kbqNotificationCenterScrollStrategyFactory, maxUnreadItemsLength };
|
|
736
1106
|
//# sourceMappingURL=koobiq-components-notification-center.mjs.map
|