ngwr 15.0.1 → 15.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/anchor/styles/_index.scss +13 -2
- package/bits/aurora/styles/_rules.scss +11 -0
- package/bits/dot-grid/dot-grid.scss +1 -0
- package/bits/dot-grid/styles/_index.scss +8 -0
- package/bits/dot-grid/styles/_rules.scss +54 -0
- package/bits/iridescence/iridescence.scss +1 -0
- package/bits/iridescence/styles/_index.scss +8 -0
- package/bits/iridescence/styles/_rules.scss +72 -0
- package/bits/marquee/styles/_rules.scss +7 -3
- package/bits/ripple-grid/ripple-grid.scss +1 -0
- package/bits/ripple-grid/styles/_index.scss +8 -0
- package/bits/ripple-grid/styles/_rules.scss +63 -0
- package/bits/spotlight-card/styles/_rules.scss +7 -4
- package/bits/star-border/styles/_rules.scss +5 -2
- package/bits/threads/styles/_index.scss +8 -0
- package/bits/threads/styles/_rules.scss +76 -0
- package/bits/threads/threads.scss +1 -0
- package/bits/waves/styles/_rules.scss +8 -1
- package/charts/bar-chart/styles/_index.scss +607 -7
- package/charts/boxplot-chart/styles/_index.scss +297 -0
- package/charts/bullet-chart/styles/_index.scss +268 -0
- package/charts/calendar-heatmap/styles/_index.scss +25 -3
- package/charts/candlestick-chart/styles/_index.scss +307 -0
- package/charts/chart-legend/styles/_index.scss +143 -0
- package/charts/core/styles/_index.scss +30 -0
- package/charts/donut-chart/styles/_index.scss +39 -3
- package/charts/funnel-chart/styles/_index.scss +237 -0
- package/charts/gauge/styles/_index.scss +4 -2
- package/charts/heatmap-chart/styles/_index.scss +329 -0
- package/charts/line-chart/styles/_index.scss +141 -8
- package/charts/meter-group/styles/_index.scss +44 -13
- package/charts/radar-chart/styles/_index.scss +206 -0
- package/charts/scatter-chart/styles/_index.scss +245 -0
- package/charts/sparkline/styles/_index.scss +10 -1
- package/charts/treemap-chart/styles/_index.scss +215 -0
- package/charts/waterfall-chart/styles/_index.scss +321 -0
- package/collapse/styles/_index.scss +6 -1
- package/fesm2022/ngwr-affix.mjs +3 -3
- package/fesm2022/ngwr-alert.mjs +3 -3
- package/fesm2022/ngwr-anchor.mjs +3 -3
- package/fesm2022/ngwr-avatar.mjs +3 -3
- package/fesm2022/ngwr-back-top.mjs +3 -3
- package/fesm2022/ngwr-badge.mjs +6 -6
- package/fesm2022/ngwr-bits-aurora.mjs +30 -38
- package/fesm2022/ngwr-bits-aurora.mjs.map +1 -1
- package/fesm2022/ngwr-bits-blur-text.mjs +3 -3
- package/fesm2022/ngwr-bits-border-glow-testing.mjs.map +1 -1
- package/fesm2022/ngwr-bits-border-glow.mjs +11 -5
- package/fesm2022/ngwr-bits-border-glow.mjs.map +1 -1
- package/fesm2022/ngwr-bits-circular-text.mjs +3 -3
- package/fesm2022/ngwr-bits-click-spark.mjs +3 -3
- package/fesm2022/ngwr-bits-confetti.mjs +3 -3
- package/fesm2022/ngwr-bits-decrypt-text.mjs +3 -3
- package/fesm2022/ngwr-bits-dot-grid-testing.mjs +40 -0
- package/fesm2022/ngwr-bits-dot-grid-testing.mjs.map +1 -0
- package/fesm2022/ngwr-bits-dot-grid.mjs +482 -0
- package/fesm2022/ngwr-bits-dot-grid.mjs.map +1 -0
- package/fesm2022/ngwr-bits-falling-text.mjs +3 -3
- package/fesm2022/ngwr-bits-fuzzy-text.mjs +3 -3
- package/fesm2022/ngwr-bits-glitch-text.mjs +3 -3
- package/fesm2022/ngwr-bits-gradient-text.mjs +3 -3
- package/fesm2022/ngwr-bits-iridescence-testing.mjs +31 -0
- package/fesm2022/ngwr-bits-iridescence-testing.mjs.map +1 -0
- package/fesm2022/ngwr-bits-iridescence.mjs +591 -0
- package/fesm2022/ngwr-bits-iridescence.mjs.map +1 -0
- package/fesm2022/ngwr-bits-marquee-testing.mjs +1 -1
- package/fesm2022/ngwr-bits-marquee-testing.mjs.map +1 -1
- package/fesm2022/ngwr-bits-marquee.mjs +7 -7
- package/fesm2022/ngwr-bits-marquee.mjs.map +1 -1
- package/fesm2022/ngwr-bits-ripple-grid-testing.mjs +40 -0
- package/fesm2022/ngwr-bits-ripple-grid-testing.mjs.map +1 -0
- package/fesm2022/ngwr-bits-ripple-grid.mjs +805 -0
- package/fesm2022/ngwr-bits-ripple-grid.mjs.map +1 -0
- package/fesm2022/ngwr-bits-rotating-text.mjs +3 -3
- package/fesm2022/ngwr-bits-shiny-text.mjs +6 -6
- package/fesm2022/ngwr-bits-splash-cursor.mjs +3 -3
- package/fesm2022/ngwr-bits-split-text.mjs +3 -3
- package/fesm2022/ngwr-bits-spotlight-card-testing.mjs +1 -1
- package/fesm2022/ngwr-bits-spotlight-card-testing.mjs.map +1 -1
- package/fesm2022/ngwr-bits-spotlight-card.mjs +10 -10
- package/fesm2022/ngwr-bits-spotlight-card.mjs.map +1 -1
- package/fesm2022/ngwr-bits-star-border-testing.mjs +1 -1
- package/fesm2022/ngwr-bits-star-border-testing.mjs.map +1 -1
- package/fesm2022/ngwr-bits-star-border.mjs +7 -7
- package/fesm2022/ngwr-bits-star-border.mjs.map +1 -1
- package/fesm2022/ngwr-bits-threads-testing.mjs +41 -0
- package/fesm2022/ngwr-bits-threads-testing.mjs.map +1 -0
- package/fesm2022/ngwr-bits-threads.mjs +482 -0
- package/fesm2022/ngwr-bits-threads.mjs.map +1 -0
- package/fesm2022/ngwr-bits-tilt-card.mjs +6 -6
- package/fesm2022/ngwr-bits-typewriter.mjs +3 -3
- package/fesm2022/ngwr-bits-waves-testing.mjs.map +1 -1
- package/fesm2022/ngwr-bits-waves.mjs +60 -41
- package/fesm2022/ngwr-bits-waves.mjs.map +1 -1
- package/fesm2022/ngwr-breadcrumbs.mjs +8 -8
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-burger.mjs +3 -3
- package/fesm2022/ngwr-button.mjs +6 -6
- package/fesm2022/ngwr-calendar.mjs +3 -3
- package/fesm2022/ngwr-card.mjs +9 -9
- package/fesm2022/ngwr-carousel.mjs +6 -6
- package/fesm2022/ngwr-cascader.mjs +5 -5
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-charts-bar-chart-testing.mjs +127 -3
- package/fesm2022/ngwr-charts-bar-chart-testing.mjs.map +1 -1
- package/fesm2022/ngwr-charts-bar-chart.mjs +683 -49
- package/fesm2022/ngwr-charts-bar-chart.mjs.map +1 -1
- package/fesm2022/ngwr-charts-boxplot-chart-testing.mjs +161 -0
- package/fesm2022/ngwr-charts-boxplot-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-charts-boxplot-chart.mjs +517 -0
- package/fesm2022/ngwr-charts-boxplot-chart.mjs.map +1 -0
- package/fesm2022/ngwr-charts-bullet-chart-testing.mjs +68 -0
- package/fesm2022/ngwr-charts-bullet-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-charts-bullet-chart.mjs +459 -0
- package/fesm2022/ngwr-charts-bullet-chart.mjs.map +1 -0
- package/fesm2022/ngwr-charts-calendar-heatmap-testing.mjs +27 -0
- package/fesm2022/ngwr-charts-calendar-heatmap-testing.mjs.map +1 -1
- package/fesm2022/ngwr-charts-calendar-heatmap.mjs +96 -17
- package/fesm2022/ngwr-charts-calendar-heatmap.mjs.map +1 -1
- package/fesm2022/ngwr-charts-candlestick-chart-testing.mjs +107 -0
- package/fesm2022/ngwr-charts-candlestick-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-charts-candlestick-chart.mjs +508 -0
- package/fesm2022/ngwr-charts-candlestick-chart.mjs.map +1 -0
- package/fesm2022/ngwr-charts-chart-legend-testing.mjs +126 -0
- package/fesm2022/ngwr-charts-chart-legend-testing.mjs.map +1 -0
- package/fesm2022/ngwr-charts-chart-legend.mjs +251 -0
- package/fesm2022/ngwr-charts-chart-legend.mjs.map +1 -0
- package/fesm2022/ngwr-charts-core.mjs +383 -0
- package/fesm2022/ngwr-charts-core.mjs.map +1 -0
- package/fesm2022/ngwr-charts-donut-chart-testing.mjs +10 -1
- package/fesm2022/ngwr-charts-donut-chart-testing.mjs.map +1 -1
- package/fesm2022/ngwr-charts-donut-chart.mjs +187 -31
- package/fesm2022/ngwr-charts-donut-chart.mjs.map +1 -1
- package/fesm2022/ngwr-charts-funnel-chart-testing.mjs +100 -0
- package/fesm2022/ngwr-charts-funnel-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-charts-funnel-chart.mjs +415 -0
- package/fesm2022/ngwr-charts-funnel-chart.mjs.map +1 -0
- package/fesm2022/ngwr-charts-gauge-testing.mjs +9 -3
- package/fesm2022/ngwr-charts-gauge-testing.mjs.map +1 -1
- package/fesm2022/ngwr-charts-gauge.mjs +9 -15
- package/fesm2022/ngwr-charts-gauge.mjs.map +1 -1
- package/fesm2022/ngwr-charts-heatmap-chart-testing.mjs +120 -0
- package/fesm2022/ngwr-charts-heatmap-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-charts-heatmap-chart.mjs +519 -0
- package/fesm2022/ngwr-charts-heatmap-chart.mjs.map +1 -0
- package/fesm2022/ngwr-charts-line-chart-testing.mjs +43 -1
- package/fesm2022/ngwr-charts-line-chart-testing.mjs.map +1 -1
- package/fesm2022/ngwr-charts-line-chart.mjs +436 -122
- package/fesm2022/ngwr-charts-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-charts-meter-group-testing.mjs +14 -2
- package/fesm2022/ngwr-charts-meter-group-testing.mjs.map +1 -1
- package/fesm2022/ngwr-charts-meter-group.mjs +101 -32
- package/fesm2022/ngwr-charts-meter-group.mjs.map +1 -1
- package/fesm2022/ngwr-charts-radar-chart-testing.mjs +98 -0
- package/fesm2022/ngwr-charts-radar-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-charts-radar-chart.mjs +720 -0
- package/fesm2022/ngwr-charts-radar-chart.mjs.map +1 -0
- package/fesm2022/ngwr-charts-scatter-chart-testing.mjs +132 -0
- package/fesm2022/ngwr-charts-scatter-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-charts-scatter-chart.mjs +545 -0
- package/fesm2022/ngwr-charts-scatter-chart.mjs.map +1 -0
- package/fesm2022/ngwr-charts-sparkline-testing.mjs.map +1 -1
- package/fesm2022/ngwr-charts-sparkline.mjs +14 -16
- package/fesm2022/ngwr-charts-sparkline.mjs.map +1 -1
- package/fesm2022/ngwr-charts-treemap-chart-testing.mjs +103 -0
- package/fesm2022/ngwr-charts-treemap-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-charts-treemap-chart.mjs +535 -0
- package/fesm2022/ngwr-charts-treemap-chart.mjs.map +1 -0
- package/fesm2022/ngwr-charts-waterfall-chart-testing.mjs +131 -0
- package/fesm2022/ngwr-charts-waterfall-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-charts-waterfall-chart.mjs +462 -0
- package/fesm2022/ngwr-charts-waterfall-chart.mjs.map +1 -0
- package/fesm2022/ngwr-checkbox.mjs +6 -6
- package/fesm2022/ngwr-clipboard.mjs +3 -3
- package/fesm2022/ngwr-collapse.mjs +9 -9
- package/fesm2022/ngwr-color-picker.mjs +6 -6
- package/fesm2022/ngwr-command-palette.mjs +3 -3
- package/fesm2022/ngwr-compare.mjs +3 -3
- package/fesm2022/ngwr-context-menu.mjs +12 -12
- package/fesm2022/ngwr-cookie.mjs +3 -3
- package/fesm2022/ngwr-counter.mjs +6 -6
- package/fesm2022/ngwr-date-picker.mjs +21 -21
- package/fesm2022/ngwr-date.mjs +6 -6
- package/fesm2022/ngwr-density.mjs +6 -6
- package/fesm2022/ngwr-descriptions.mjs +6 -6
- package/fesm2022/ngwr-dialog.mjs +15 -15
- package/fesm2022/ngwr-directives.mjs +12 -12
- package/fesm2022/ngwr-divider.mjs +3 -3
- package/fesm2022/ngwr-drawer.mjs +18 -18
- package/fesm2022/ngwr-dropdown.mjs +9 -9
- package/fesm2022/ngwr-editor.mjs +3 -3
- package/fesm2022/ngwr-empty.mjs +3 -3
- package/fesm2022/ngwr-event-calendar.mjs +6 -6
- package/fesm2022/ngwr-file-upload.mjs +3 -3
- package/fesm2022/ngwr-form.mjs +9 -9
- package/fesm2022/ngwr-graph.mjs +6 -6
- package/fesm2022/ngwr-hotkey.mjs +6 -6
- package/fesm2022/ngwr-i18n-ar.mjs +90 -4
- package/fesm2022/ngwr-i18n-ar.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-cs.mjs +90 -4
- package/fesm2022/ngwr-i18n-cs.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-de.mjs +90 -4
- package/fesm2022/ngwr-i18n-de.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +90 -4
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-es.mjs +90 -4
- package/fesm2022/ngwr-i18n-es.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-fr.mjs +90 -4
- package/fesm2022/ngwr-i18n-fr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-he.mjs +90 -4
- package/fesm2022/ngwr-i18n-he.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-hi.mjs +90 -4
- package/fesm2022/ngwr-i18n-hi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-id.mjs +90 -4
- package/fesm2022/ngwr-i18n-id.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-it.mjs +90 -4
- package/fesm2022/ngwr-i18n-it.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ja.mjs +90 -4
- package/fesm2022/ngwr-i18n-ja.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ko.mjs +90 -4
- package/fesm2022/ngwr-i18n-ko.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-nl.mjs +90 -4
- package/fesm2022/ngwr-i18n-nl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pl.mjs +90 -4
- package/fesm2022/ngwr-i18n-pl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pt.mjs +90 -4
- package/fesm2022/ngwr-i18n-pt.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +90 -4
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-sv.mjs +90 -4
- package/fesm2022/ngwr-i18n-sv.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-tr.mjs +90 -4
- package/fesm2022/ngwr-i18n-tr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-uk.mjs +90 -4
- package/fesm2022/ngwr-i18n-uk.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-vi.mjs +90 -4
- package/fesm2022/ngwr-i18n-vi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh-tw.mjs +90 -4
- package/fesm2022/ngwr-i18n-zh-tw.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh.mjs +90 -4
- package/fesm2022/ngwr-i18n-zh.mjs.map +1 -1
- package/fesm2022/ngwr-i18n.mjs +9 -9
- package/fesm2022/ngwr-icon.mjs +6 -6
- package/fesm2022/ngwr-image-cropper.mjs +3 -3
- package/fesm2022/ngwr-input-number.mjs +3 -3
- package/fesm2022/ngwr-input-otp.mjs +3 -3
- package/fesm2022/ngwr-input.mjs +15 -15
- package/fesm2022/ngwr-keyboard.mjs +3 -3
- package/fesm2022/ngwr-knob.mjs +3 -3
- package/fesm2022/ngwr-layout.mjs +15 -15
- package/fesm2022/ngwr-lightbox.mjs +5 -5
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-list.mjs +8 -8
- package/fesm2022/ngwr-list.mjs.map +1 -1
- package/fesm2022/ngwr-loading-bar.mjs +6 -6
- package/fesm2022/ngwr-mention.mjs +6 -6
- package/fesm2022/ngwr-meta.mjs +6 -6
- package/fesm2022/ngwr-overlay.mjs +6 -6
- package/fesm2022/ngwr-page-header.mjs +3 -3
- package/fesm2022/ngwr-pagination.mjs +3 -3
- package/fesm2022/ngwr-pipes.mjs +21 -21
- package/fesm2022/ngwr-platform.mjs +6 -6
- package/fesm2022/ngwr-popconfirm.mjs +6 -6
- package/fesm2022/ngwr-popover.mjs +43 -20
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-progress.mjs +3 -3
- package/fesm2022/ngwr-pull-to-refresh.mjs +3 -3
- package/fesm2022/ngwr-qr.mjs +4 -3
- package/fesm2022/ngwr-qr.mjs.map +1 -1
- package/fesm2022/ngwr-radio.mjs +6 -6
- package/fesm2022/ngwr-rating.mjs +3 -3
- package/fesm2022/ngwr-result.mjs +12 -12
- package/fesm2022/ngwr-schema-form.mjs +3 -3
- package/fesm2022/ngwr-scroll.mjs +3 -3
- package/fesm2022/ngwr-segmented.mjs +3 -3
- package/fesm2022/ngwr-select.mjs +12 -12
- package/fesm2022/ngwr-sidebar.mjs +3 -3
- package/fesm2022/ngwr-skeleton.mjs +3 -3
- package/fesm2022/ngwr-slider.mjs +3 -3
- package/fesm2022/ngwr-sortable-list.mjs +11 -11
- package/fesm2022/ngwr-sortable-list.mjs.map +1 -1
- package/fesm2022/ngwr-speed-dial.mjs +3 -3
- package/fesm2022/ngwr-spinner.mjs +3 -3
- package/fesm2022/ngwr-splitter.mjs +3 -3
- package/fesm2022/ngwr-statistic.mjs +9 -9
- package/fesm2022/ngwr-stepper.mjs +6 -6
- package/fesm2022/ngwr-storage.mjs +3 -3
- package/fesm2022/ngwr-switch.mjs +3 -3
- package/fesm2022/ngwr-table.mjs +18 -18
- package/fesm2022/ngwr-tabs-router.mjs +3 -3
- package/fesm2022/ngwr-tabs.mjs +6 -6
- package/fesm2022/ngwr-textarea.mjs +3 -3
- package/fesm2022/ngwr-theme.mjs +3 -3
- package/fesm2022/ngwr-timeline.mjs +6 -6
- package/fesm2022/ngwr-toast-testing.mjs +2 -1
- package/fesm2022/ngwr-toast-testing.mjs.map +1 -1
- package/fesm2022/ngwr-toast.mjs +34 -15
- package/fesm2022/ngwr-toast.mjs.map +1 -1
- package/fesm2022/ngwr-toolbar.mjs +3 -3
- package/fesm2022/ngwr-tour.mjs +6 -6
- package/fesm2022/ngwr-transfer.mjs +3 -3
- package/fesm2022/ngwr-tree.mjs +3 -3
- package/fesm2022/ngwr-typography.mjs +3 -3
- package/fesm2022/ngwr-utils.mjs +31 -1
- package/fesm2022/ngwr-utils.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/fesm2022/ngwr-virtual-scroll.mjs +3 -3
- package/fesm2022/ngwr-window-testing.mjs +61 -5
- package/fesm2022/ngwr-window-testing.mjs.map +1 -1
- package/fesm2022/ngwr-window.mjs +1538 -895
- package/fesm2022/ngwr-window.mjs.map +1 -1
- package/fesm2022/ngwr.mjs.map +1 -1
- package/i18n/ar.json +84 -4
- package/i18n/cs.json +84 -4
- package/i18n/de.json +84 -4
- package/i18n/en.json +84 -4
- package/i18n/es.json +84 -4
- package/i18n/fr.json +84 -4
- package/i18n/he.json +84 -4
- package/i18n/hi.json +84 -4
- package/i18n/id.json +84 -4
- package/i18n/it.json +84 -4
- package/i18n/ja.json +84 -4
- package/i18n/ko.json +84 -4
- package/i18n/nl.json +84 -4
- package/i18n/pl.json +84 -4
- package/i18n/pt.json +84 -4
- package/i18n/ru.json +84 -4
- package/i18n/sv.json +84 -4
- package/i18n/tr.json +84 -4
- package/i18n/uk.json +84 -4
- package/i18n/vi.json +84 -4
- package/i18n/zh-TW.json +84 -4
- package/i18n/zh.json +84 -4
- package/llms-full.txt +266 -9
- package/llms.txt +30 -7
- package/mcp/api.js +69 -1
- package/mcp/catalog.js +10 -1
- package/mcp/server.js +15 -1
- package/mcp/tools.js +122 -26
- package/package.json +132 -1
- package/popover/styles/_index.scss +75 -7
- package/schematics/component-style/index.js +3 -0
- package/schematics/migrations/v15/index.js +3 -26
- package/schematics/ng-add/index.js +2 -2
- package/schematics/use/symbol-map.json +14 -0
- package/schematics/utility/global-styles.js +19 -4
- package/schematics/utility/v15-moves.js +55 -0
- package/skills/ngwr/SKILL.md +8 -2
- package/skills/ngwr/references/catalog.md +28 -0
- package/skills/ngwr/references/setup.md +5 -4
- package/theme/styles/_focus.scss +8 -0
- package/toast/styles/_index.scss +103 -12
- package/types/ngwr-bits-aurora.d.ts +11 -0
- package/types/ngwr-bits-border-glow-testing.d.ts +5 -6
- package/types/ngwr-bits-border-glow.d.ts +5 -1
- package/types/ngwr-bits-dot-grid-testing.d.ts +92 -0
- package/types/ngwr-bits-dot-grid.d.ts +158 -0
- package/types/ngwr-bits-iridescence-testing.d.ts +85 -0
- package/types/ngwr-bits-iridescence.d.ts +244 -0
- package/types/ngwr-bits-ripple-grid-testing.d.ts +96 -0
- package/types/ngwr-bits-ripple-grid.d.ts +294 -0
- package/types/ngwr-bits-splash-cursor.d.ts +0 -1
- package/types/ngwr-bits-spotlight-card-testing.d.ts +3 -1
- package/types/ngwr-bits-star-border-testing.d.ts +7 -7
- package/types/ngwr-bits-threads-testing.d.ts +97 -0
- package/types/ngwr-bits-threads.d.ts +216 -0
- package/types/ngwr-bits-waves-testing.d.ts +1 -1
- package/types/ngwr-bits-waves.d.ts +20 -3
- package/types/ngwr-charts-bar-chart-testing.d.ts +193 -14
- package/types/ngwr-charts-bar-chart.d.ts +546 -38
- package/types/ngwr-charts-boxplot-chart-testing.d.ts +165 -0
- package/types/ngwr-charts-boxplot-chart.d.ts +308 -0
- package/types/ngwr-charts-bullet-chart-testing.d.ts +99 -0
- package/types/ngwr-charts-bullet-chart.d.ts +262 -0
- package/types/ngwr-charts-calendar-heatmap-testing.d.ts +32 -1
- package/types/ngwr-charts-calendar-heatmap.d.ts +55 -6
- package/types/ngwr-charts-candlestick-chart-testing.d.ts +135 -0
- package/types/ngwr-charts-candlestick-chart.d.ts +361 -0
- package/types/ngwr-charts-chart-legend-testing.d.ts +84 -0
- package/types/ngwr-charts-chart-legend.d.ts +178 -0
- package/types/ngwr-charts-core.d.ts +391 -0
- package/types/ngwr-charts-donut-chart-testing.d.ts +28 -5
- package/types/ngwr-charts-donut-chart.d.ts +124 -12
- package/types/ngwr-charts-funnel-chart-testing.d.ts +130 -0
- package/types/ngwr-charts-funnel-chart.d.ts +296 -0
- package/types/ngwr-charts-gauge-testing.d.ts +5 -0
- package/types/ngwr-charts-gauge.d.ts +6 -4
- package/types/ngwr-charts-heatmap-chart-testing.d.ts +148 -0
- package/types/ngwr-charts-heatmap-chart.d.ts +359 -0
- package/types/ngwr-charts-line-chart-testing.d.ts +72 -11
- package/types/ngwr-charts-line-chart.d.ts +291 -67
- package/types/ngwr-charts-meter-group-testing.d.ts +16 -2
- package/types/ngwr-charts-meter-group.d.ts +71 -11
- package/types/ngwr-charts-radar-chart-testing.d.ts +162 -0
- package/types/ngwr-charts-radar-chart.d.ts +461 -0
- package/types/ngwr-charts-scatter-chart-testing.d.ts +147 -0
- package/types/ngwr-charts-scatter-chart.d.ts +396 -0
- package/types/ngwr-charts-sparkline-testing.d.ts +4 -1
- package/types/ngwr-charts-sparkline.d.ts +8 -6
- package/types/ngwr-charts-treemap-chart-testing.d.ts +131 -0
- package/types/ngwr-charts-treemap-chart.d.ts +295 -0
- package/types/ngwr-charts-waterfall-chart-testing.d.ts +149 -0
- package/types/ngwr-charts-waterfall-chart.d.ts +338 -0
- package/types/ngwr-color-picker.d.ts +0 -21
- package/types/ngwr-dropdown.d.ts +0 -52
- package/types/ngwr-editor.d.ts +2 -84
- package/types/ngwr-i18n.d.ts +0 -15
- package/types/ngwr-mention.d.ts +0 -13
- package/types/ngwr-popconfirm.d.ts +0 -33
- package/types/ngwr-popover.d.ts +29 -53
- package/types/ngwr-toast-testing.d.ts +6 -1
- package/types/ngwr-tour.d.ts +0 -2
- package/types/ngwr-utils.d.ts +49 -7
- package/types/ngwr-version.d.ts +1 -1
- package/types/ngwr-window-testing.d.ts +65 -7
- package/types/ngwr-window.d.ts +831 -207
- package/types/ngwr.d.ts +1 -0
- package/window/styles/_index.scss +528 -82
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-window.mjs","names":["NO_OVERRIDE"],"sources":["../../../projects/lib/window/tokens.ts","../../../projects/lib/window/storage-key.ts","../../../projects/lib/window/window.ts","../../../projects/lib/window/window.html","../../../projects/lib/window/window-container.ts","../../../projects/lib/window/window-container.html","../../../projects/lib/window/window-ref.ts","../../../projects/lib/window/services/window-manager.ts","../../../projects/lib/window/window-taskbar.ts","../../../projects/lib/window/window-taskbar.html"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrWindowRef } from './window-ref';\n\n/** Resolves to the active `WrWindowRef` inside a programmatically-opened window's content tree. */\nexport const WR_WINDOW_REF = new InjectionToken<WrWindowRef<unknown, unknown>>('WR_WINDOW_REF');\n\n/** Resolves to the `data` passed in `WrWindowConfig.data`. */\nexport const WR_WINDOW_DATA = new InjectionToken<unknown>('WR_WINDOW_DATA');\n","import type { WrWindowStorageConfig } from './types';\n\n/** Namespaced localStorage key for a persisted window / workspace. */\nexport function storageKey(cfg: WrWindowStorageConfig): string {\n const prefix = cfg.prefix ? `${cfg.prefix}:` : '';\n return `wr:window:${prefix}${cfg.key}`;\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { FocusTrapFactory } from '@angular/cdk/a11y';\nimport { type BooleanInput, coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\n\nimport { useI18nText } from 'ngwr/i18n';\nimport { clamp, randomId } from 'ngwr/utils';\n\nimport { WrWindowManager } from './services/window-manager';\nimport type {\n WrWindowChromeSize,\n WrWindowOs,\n WrWindowResolvedOs,\n WrWindowSize,\n WrWindowSnap,\n WrWindowSnapTarget,\n WrWindowState,\n} from './types';\n\n/**\n * Stands in for the consumer input `useI18nText` expects. The chrome buttons take no\n * label input — they are icon-only OS affordances — but their names still have to\n * come from the catalog rather than from the template, which is where they used to\n * live as English literals.\n */\nconst NO_OVERRIDE = signal<string | null>(null).asReadonly();\n\n/**\n * Best-effort OS detection — runs once at module load. Looks at the\n * new `navigator.userAgentData.platform` first (Chromium, no UA\n * sniffing required), falls back to `navigator.platform` /\n * `navigator.userAgent`. SSR-safe — returns `'windows'` when there's\n * no `window`.\n */\nfunction detectOs(): WrWindowResolvedOs {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') return 'windows';\n\n const uaData = (navigator as unknown as { userAgentData?: { platform?: string } }).userAgentData;\n // First non-empty source — `??` alone would keep an empty platform\n // string and skip the user-agent fallback.\n const candidates = [uaData?.platform, navigator.platform, navigator.userAgent];\n const platform = (candidates.find(v => !!v) ?? '').toLowerCase();\n if (\n platform.includes('mac') ||\n platform.includes('darwin') ||\n platform.includes('iphone') ||\n platform.includes('ipad')\n ) {\n return 'macos';\n }\n if (platform.includes('linux') || platform.includes('x11') || platform.includes('cros')) return 'linux';\n return 'windows';\n}\n\nconst DETECTED_OS = detectOs();\n\n/**\n * `coerceBooleanProperty` that keeps `null` as `null`.\n *\n * The plain coercion maps `null` and `undefined` to `false`, which is the one\n * thing a tri-state input must not do: \"unset\" has to survive as its own value\n * or the OS default can never be told apart from an explicit `false`. Attribute\n * presence (`<wr-window showMinimize>`, i.e. `''`) still means `true`.\n */\nfunction optionalBoolean(value: BooleanInput | null): boolean | null {\n return value === null || value === undefined ? null : coerceBooleanProperty(value);\n}\n\nconst SIZE_PRESETS: Readonly<Record<WrWindowSize, { width: number; height: number }>> = {\n sm: { width: 320, height: 200 },\n md: { width: 480, height: 320 },\n lg: { width: 720, height: 480 },\n};\n\ninterface Edges {\n readonly t?: boolean;\n readonly r?: boolean;\n readonly b?: boolean;\n readonly l?: boolean;\n}\n\nconst MIN_ON_VIEWPORT = 24; // keep at least this many px of the window inside the viewport\n\nfunction viewportWidth(): number {\n return typeof window === 'undefined' ? 1024 : window.innerWidth;\n}\n\nfunction viewportHeight(): number {\n return typeof window === 'undefined' ? 768 : window.innerHeight;\n}\n\n/**\n * Internal rendering primitive for a single floating window.\n *\n * Not part of the public API — windows are opened through\n * `WrWindowManager.open(Component, config)`, which portals this\n * component for each call. Inputs map 1:1 to `WrWindowConfig`\n * fields so the container can wire them up declaratively.\n *\n * @internal\n */\n@Component({\n selector: 'wr-window',\n templateUrl: './window.html',\n encapsulation: ViewEncapsulation.None,\n host: {\n // See `WrAlert`: a static `title=` feeds the input AND lands on the host.\n '[attr.title]': 'null',\n role: 'dialog',\n // Focusable by script, never by Tab: it is where focus lands when the\n // window opens with no control in its body, and it is what a click on the\n // window's own surface focuses, so the window the user is in is the one\n // `WrWindowManager` hands Escape to.\n tabindex: '-1',\n '[class]': 'classes()',\n '[style.left.px]': 'x()',\n '[style.top.px]': 'y()',\n '[style.width.px]': 'width()',\n '[style.height.px]': 'height()',\n '[style.z-index]': 'z()',\n '[attr.aria-hidden]': '!open()',\n '[attr.aria-labelledby]': 'titleId',\n '(pointerdown)': 'focusWindow()',\n },\n})\nexport class WrWindow {\n /** Two-way bindable visibility. `false` removes the window from the layer. */\n readonly open = model<boolean>(true);\n\n /** Two-way bindable state. */\n readonly state = model<WrWindowState>('normal');\n\n /** Header title. */\n readonly title = input<string>('');\n\n /** Auto-generated id for the title element, referenced by `aria-labelledby`. */\n protected readonly titleId = randomId('wr-window-title');\n\n // `window.close` had been sitting in both catalogs unread while the template\n // hard-coded the same English beside it; the other four had no key at all, so a\n // Russian app announced four of its five window buttons in English.\n protected readonly closeLabel = useI18nText(NO_OVERRIDE, 'window.close', 'Close');\n private readonly minimizeLabel = useI18nText(NO_OVERRIDE, 'window.minimize', 'Minimize');\n private readonly maximizeLabel = useI18nText(NO_OVERRIDE, 'window.maximize', 'Maximize');\n private readonly restoreLabel = useI18nText(NO_OVERRIDE, 'window.restore', 'Restore');\n private readonly restoreDownLabel = useI18nText(NO_OVERRIDE, 'window.restoreDown', 'Restore down');\n\n /** The minimize button doubles as restore, and says which it is. */\n protected readonly minimizeActionLabel = computed(() =>\n this.state() === 'minimized' ? this.restoreLabel() : this.minimizeLabel()\n );\n\n /** Same for maximize, whose restore has its own wording. */\n protected readonly maximizeActionLabel = computed(() =>\n this.state() === 'maximized' ? this.restoreDownLabel() : this.maximizeLabel()\n );\n\n /** Initial position. `null` = auto-cascade from the manager. */\n readonly initialX = input<number | null>(null, {\n transform: (v: unknown): number | null => (v == null ? null : coerceNumberProperty(v, 0)),\n });\n /**\n * Initial top offset in px. `null` = auto-cascade from the manager, which is\n * what keeps several windows from opening on top of each other.\n */\n readonly initialY = input<number | null>(null, {\n transform: (v: unknown): number | null => (v == null ? null : coerceNumberProperty(v, 0)),\n });\n\n /**\n * Size preset — seeds initial width / height when `[initialWidth]` /\n * `[initialHeight]` are not provided. `null` keeps the explicit\n * pixel inputs in charge. @default 'md'\n */\n readonly size = input<WrWindowSize | null>('md');\n\n /** Initial / forced size in pixels. Wins over `[size]` when set. */\n readonly initialWidth = input<number | null>(null, {\n transform: (v: unknown): number | null => (v == null ? null : coerceNumberProperty(v, 480)),\n });\n /**\n * Initial height in px, overriding the `size` preset. Clamped to `minHeight` /\n * `maxHeight` before it is applied.\n */\n readonly initialHeight = input<number | null>(null, {\n transform: (v: unknown): number | null => (v == null ? null : coerceNumberProperty(v, 320)),\n });\n\n /**\n * OS chrome style. `'auto'` reads `navigator.userAgentData.platform`\n * / `navigator.platform` and picks the matching preset (SSR-safe;\n * unknown platforms fall back to `windows`).\n * @default 'auto'\n */\n readonly os = input<WrWindowOs>('auto');\n\n /** Resolved OS — `auto` → detected platform. */\n readonly resolvedOs = computed<WrWindowResolvedOs>(() => {\n const o = this.os();\n return o === 'auto' ? DETECTED_OS : o;\n });\n\n /**\n * Whether each control is rendered: the input wins, the chrome decides the\n * default. Linux is close-only unless asked otherwise — see\n * {@link showMinimize} for why that is an input and not a template gate.\n */\n protected readonly minimizeVisible = computed(() => this.showMinimize() ?? this.resolvedOs() !== 'linux');\n protected readonly maximizeVisible = computed(() => this.showMaximize() ?? this.resolvedOs() !== 'linux');\n\n /** Title-bar density. @default 'md' */\n readonly chromeSize = input<WrWindowChromeSize>('md');\n\n /**\n * Enter / leave animations. Set to `false` to disable the open-fade\n * and the minimize / maximize transitions. Honoured automatically\n * when `prefers-reduced-motion: reduce`. @default true\n */\n readonly animations = input(true, { transform: coerceBooleanProperty });\n\n /**\n * Narrowest the user may drag it. Also the floor for `initialWidth`.\n */\n readonly minWidth = input<number>(220, { transform: (v: unknown): number => coerceNumberProperty(v, 220) });\n /**\n * Shortest the user may drag it. Also the floor for `initialHeight`.\n */\n readonly minHeight = input<number>(140, { transform: (v: unknown): number => coerceNumberProperty(v, 140) });\n /**\n * Widest the user may drag it. Unbounded by default.\n */\n readonly maxWidth = input<number>(Number.POSITIVE_INFINITY, {\n transform: (v: unknown): number => (v == null ? Number.POSITIVE_INFINITY : coerceNumberProperty(v, Infinity)),\n });\n /**\n * Tallest the user may drag it. Unbounded by default.\n */\n readonly maxHeight = input<number>(Number.POSITIVE_INFINITY, {\n transform: (v: unknown): number => (v == null ? Number.POSITIVE_INFINITY : coerceNumberProperty(v, Infinity)),\n });\n\n /**\n * Allow dragging by the header. `false` pins the window where it opened; the\n * header still carries the title and the action buttons.\n */\n readonly movable = input(true, { transform: coerceBooleanProperty });\n /**\n * Allow dragging the edges and corners. `false` also hides the maximize button,\n * since there would be no way back to a custom size.\n */\n readonly resizable = input(true, { transform: coerceBooleanProperty });\n /**\n * Hold the window inside the viewport while it is dragged or the page is\n * resized. `false` lets it go off-screen, which only a custom chrome wants.\n */\n readonly keepInViewport = input(true, { transform: coerceBooleanProperty });\n\n /** Drag-to-edge snap behaviour. @default 'none' */\n readonly snap = input<WrWindowSnap>('none');\n\n /**\n * CSS selector inside the projected body that restricts the move\n * grab — pointer-downs outside this selector won't start a drag.\n * Use to keep interactive body content (sliders, inputs) from\n * hijacking the title-bar drag. `null` (default) means the whole\n * title bar is grabbable.\n */\n readonly dragHandle = input<string | null>(null);\n\n // Tri-state, and the third state is the point. While this defaulted to `true`,\n // \"not set\" and \"explicitly asked for\" were the same value, so the Linux\n // preset had to gate minimize out of the template unconditionally — and\n // `<wr-window-taskbar>` became unreachable on that chrome: `ref.minimize()`\n // still filed a window into it, but no user could press anything to get it\n // there. `null` restores the distinction the chrome docs always claimed.\n /**\n * Show the minimize control. `null` (the default) follows the chrome: every OS\n * but Linux shows it, and the Linux preset is close-only by convention. Pass\n * `true` to override that — on Linux it is what puts a window within reach of\n * `<wr-window-taskbar>`.\n */\n readonly showMinimize = input<boolean | null, BooleanInput | null>(null, { transform: optionalBoolean });\n\n /** Show the maximize control. `null` (the default) follows the chrome, as with {@link showMinimize}. */\n readonly showMaximize = input<boolean | null, BooleanInput | null>(null, { transform: optionalBoolean });\n\n /** Show the close control. Not per-OS: every chrome closes. */\n readonly showClose = input(true, { transform: coerceBooleanProperty });\n\n /** Fires when the window closes — from the header button or from `close()`. */\n readonly closed = output<void>();\n\n /**\n * Fires ONCE when a header drag ends — on `pointerup` or `pointercancel` —\n * with the window's final position. Not per pointer move: a consumer\n * persisting the position wants the landing, not the path.\n *\n * Programmatic moves (`moveTo`, `center`, the initial cascade) are silent:\n * the caller already knows where it put the window, and echoing those back\n * would double-count.\n */\n readonly moved = output<{ readonly x: number; readonly y: number }>();\n\n /** Fires once when an edge drag ends, and once when a snap target is applied. */\n readonly resized = output<{ readonly width: number; readonly height: number }>();\n\n /**\n * Fires when the window is minimized while focus is inside it. A minimized\n * window is `display: none`, so the focus it held is gone, and the container\n * hands it to the window's taskbar tab.\n *\n * @internal\n */\n readonly minimizedWithFocus = output<void>();\n\n private readonly manager = inject(WrWindowManager);\n private readonly destroyRef = inject(DestroyRef);\n private readonly elRef = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly focusTraps = inject(FocusTrapFactory);\n\n /**\n * The viewport, as a SIGNAL. The maximized geometry and the keep-in-viewport\n * clamp used to read `window.innerWidth` / `innerHeight` directly, which no\n * computed can depend on: a window maximized at 1440×900 stayed 1440×900 in a\n * 1024×700 viewport with its close and maximize buttons off-screen, and a\n * window dragged to the bottom-right corner was left entirely outside an\n * 800×600 one — while `keepInViewport` promised to hold it \"while it is\n * dragged or the page is resized\". Kept in step by a `resize` listener\n * installed after the first render; on the server it holds the fallback size.\n */\n private readonly viewport = signal({ width: viewportWidth(), height: viewportHeight() });\n\n // Position / size signals are the source of truth at runtime.\n // Inputs (x/y/initialWidth/initialHeight) seed them in afterNextRender.\n /** Live X (top-left). @internal */ readonly x_ = signal(0);\n /** Live Y (top-left). @internal */ readonly y_ = signal(0);\n /** Live width. @internal */ readonly width_ = signal(0);\n /** Live height. @internal */ readonly height_ = signal(0);\n\n // Saved geometry to restore from `maximized`.\n private restoreGeometry: { x: number; y: number; width: number; height: number } | null = null;\n\n /** Stack z-index — pulled from the manager on focus. @internal */\n readonly z = signal(this.manager.bringToFront());\n\n protected readonly classes = computed(() => {\n const parts = [\n 'wr-window',\n `wr-window--${this.state()}`,\n `wr-window--os-${this.resolvedOs()}`,\n `wr-window--chrome-${this.chromeSize()}`,\n ];\n if (!this.open()) parts.push('wr-window--closed');\n if (this.resizable() && this.state() === 'normal') parts.push('wr-window--resizable');\n if (!this.animations()) parts.push('wr-window--no-anim');\n return parts.join(' ');\n });\n\n // Effective geometry exposed to the host bindings AND to programmatic\n // consumers (`WrWindowRef`). When maximized we ignore the live\n // x_/y_/width_/height_ and fill the viewport instead.\n readonly x = computed(() => (this.state() === 'maximized' ? 0 : this.x_()));\n readonly y = computed(() => (this.state() === 'maximized' ? 0 : this.y_()));\n readonly width = computed(() => (this.state() === 'maximized' ? this.viewport().width : this.width_()));\n readonly height = computed(() =>\n this.state() === 'maximized'\n ? this.viewport().height\n : this.state() === 'minimized'\n ? this.minimizedHeight()\n : this.height_()\n );\n\n protected readonly minimizedHeight = signal(40); // header-only height\n\n /**\n * Visible during drag when a snap target is engaged — drives the\n * SCSS hint rendered by `WrWindowContainer` (NOT here — `.wr-window`\n * has `overflow: hidden` which clips position-fixed descendants\n * during the open animation while a transform is applied).\n */\n readonly snapTarget = signal<WrWindowSnapTarget | null>(null);\n\n constructor() {\n afterNextRender(() => {\n const measure = (): void => this.viewport.set({ width: viewportWidth(), height: viewportHeight() });\n measure();\n window.addEventListener('resize', measure);\n this.destroyRef.onDestroy(() => window.removeEventListener('resize', measure));\n this.seedInitialGeometry();\n });\n\n // Re-clamp into viewport when window or viewport changes.\n effect(() => {\n if (this.state() !== 'normal') return;\n this.clampToViewport();\n });\n }\n\n // Public API\n\n close(): void {\n // A REQUEST to close, not the close itself. `WrWindowContainer` binds\n // `(closed)` to `WrWindowRef.close()`, which awaits the `beforeClose` hook\n // and — only if the hook agrees — disposes the overlay, so the owner is what\n // takes the window away and this component never has to hide itself. Hiding\n // here first defeated the veto: `.wr-window--closed` is `display: none`, so\n // a vetoed window vanished while its ref stayed in `manager.windows()` in\n // state `normal` — off screen, absent from the taskbar, and unreachable by\n // `restore()` / `focus()` / `moveTo()`, none of which write `open`. Escape\n // goes straight to `ref.close()` and so never had the bug, which is the\n // contrast that exposed it.\n this.closed.emit();\n }\n\n minimize(): void {\n const minimizing = this.state() !== 'minimized';\n // Read before the state flips: once the class lands, nothing inside has\n // a box and the browser has already dropped focus on `<body>`.\n const hadFocus = minimizing && this.hasFocus();\n this.state.set(minimizing ? 'minimized' : 'normal');\n if (hadFocus) this.minimizedWithFocus.emit();\n }\n\n maximize(): void {\n if (this.state() === 'maximized') {\n this.restore();\n } else {\n this.restoreGeometry = { x: this.x_(), y: this.y_(), width: this.width_(), height: this.height_() };\n this.state.set('maximized');\n }\n }\n\n /** Force back to `normal` from minimized / maximized. */\n restore(): void {\n if (this.state() === 'maximized' && this.restoreGeometry) {\n this.x_.set(this.restoreGeometry.x);\n this.y_.set(this.restoreGeometry.y);\n this.width_.set(this.restoreGeometry.width);\n this.height_.set(this.restoreGeometry.height);\n this.restoreGeometry = null;\n }\n this.state.set('normal');\n }\n\n /** Programmatic move — clamped to the viewport when `keepInViewport`. */\n moveTo(x: number, y: number): void {\n this.x_.set(x);\n this.y_.set(y);\n this.clampToViewport();\n }\n\n /** Programmatic resize — clamped to min/max bounds. */\n resizeTo(width: number, height: number): void {\n this.width_.set(clamp(width, this.minWidth(), this.maxWidth()));\n this.height_.set(clamp(height, this.minHeight(), this.maxHeight()));\n this.clampToViewport();\n }\n\n /** Re-position centered against the current viewport. */\n center(): void {\n const w = this.width_();\n const h = this.height_();\n const { width: vw, height: vh } = this.viewport();\n this.x_.set(Math.max(0, (vw - w) / 2));\n this.y_.set(Math.max(0, (vh - h) / 2));\n }\n\n /** Bring this window to the top of the stack. */\n focus(): void {\n this.z.set(this.manager.bringToFront());\n }\n\n /**\n * Move focus into the window: to `[cdkFocusInitial]` or the first control in\n * its body — the CDK's rule, the one `WrDialog` and `WrDrawer` follow — else\n * to the window itself. The chrome buttons are not candidates: landing on\n * Close, the first of them on macOS, is the one place a window must not open\n * onto. Called after a render, by the container.\n *\n * @internal\n */\n focusInitial(): void {\n const host = this.elRef.nativeElement;\n if (!host.isConnected || this.state() === 'minimized') return;\n const body = host.querySelector<HTMLElement>('.wr-window__body');\n if (body) {\n // `deferAnchors`: no anchors go into the page, and nothing is trapped.\n const finder = this.focusTraps.create(body, true);\n const moved = finder.focusInitialElement({ preventScroll: true });\n finder.destroy();\n if (moved) return;\n }\n host.focus({ preventScroll: true });\n }\n\n /** Whether focus is inside the window. @internal */\n hasFocus(): boolean {\n const host = this.elRef.nativeElement;\n return host.contains(host.ownerDocument.activeElement);\n }\n\n // Host handlers\n\n /** @internal — alias kept for the host `(pointerdown)` binding. */\n protected focusWindow(): void {\n this.focus();\n }\n\n protected startMove(event: PointerEvent): void {\n if (!this.movable() || this.state() !== 'normal') return;\n const targetEl = event.target as HTMLElement;\n if (targetEl.closest('.wr-window__chrome-action')) return;\n const handle = this.dragHandle();\n if (handle && !targetEl.closest(handle)) return;\n event.preventDefault();\n const target = event.currentTarget as HTMLElement;\n target.setPointerCapture(event.pointerId);\n\n const startX = this.x_();\n const startY = this.y_();\n const originX = event.clientX;\n const originY = event.clientY;\n\n const move = (e: PointerEvent): void => {\n this.x_.set(startX + (e.clientX - originX));\n this.y_.set(startY + (e.clientY - originY));\n this.clampToViewport();\n this.snapTarget.set(this.detectSnapTarget(e.clientX, e.clientY));\n };\n const cleanup = (e: PointerEvent): void => {\n target.releasePointerCapture(e.pointerId);\n target.removeEventListener('pointermove', move);\n target.removeEventListener('pointerup', cleanup);\n target.removeEventListener('pointercancel', cleanup);\n const snap = this.snapTarget();\n this.snapTarget.set(null);\n if (snap) {\n this.applySnap(snap);\n }\n this.moved.emit({ x: this.x_(), y: this.y_() });\n };\n\n target.addEventListener('pointermove', move);\n target.addEventListener('pointerup', cleanup);\n // `pointercancel` is never followed by a `pointerup` (a pen leaving range, a\n // long-press menu, an OS gesture taking over), so without this the move\n // listener outlived the drag on a chrome element that lives as long as the\n // component: every later hover over the title bar dragged the window.\n // The cancelled gesture's geometry is kept rather than rolled back, so\n // `moved` still reports where the window ended up.\n target.addEventListener('pointercancel', cleanup);\n }\n\n /** Map a cursor position to a snap target, honouring `[snap]`. */\n private detectSnapTarget(clientX: number, clientY: number): WrWindowSnapTarget | null {\n const mode = this.snap();\n if (mode === 'none') return null;\n const HOT = 12;\n const { width: vw, height: vh } = this.viewport();\n const nearLeft = clientX <= HOT;\n const nearRight = clientX >= vw - HOT;\n const nearTop = clientY <= HOT;\n const nearBottom = clientY >= vh - HOT;\n if (mode === 'all') {\n if (nearTop && nearLeft) return 'top-left';\n if (nearTop && nearRight) return 'top-right';\n if (nearBottom && nearLeft) return 'bottom-left';\n if (nearBottom && nearRight) return 'bottom-right';\n }\n if (nearTop) return 'top'; // top edge → maximise\n if (nearLeft) return 'left';\n if (nearRight) return 'right';\n return null;\n }\n\n /** Move + resize the window into the requested snap region. */\n private applySnap(target: WrWindowSnapTarget): void {\n const { width: vw, height: vh } = this.viewport();\n const halfW = Math.floor(vw / 2);\n const halfH = Math.floor(vh / 2);\n switch (target) {\n case 'top':\n // Maximise — share state so the chrome reflects it.\n this.restoreGeometry = { x: this.x_(), y: this.y_(), width: this.width_(), height: this.height_() };\n this.state.set('maximized');\n return;\n case 'left':\n this.x_.set(0);\n this.y_.set(0);\n this.width_.set(halfW);\n this.height_.set(vh);\n break;\n case 'right':\n this.x_.set(halfW);\n this.y_.set(0);\n this.width_.set(vw - halfW);\n this.height_.set(vh);\n break;\n case 'top-left':\n this.x_.set(0);\n this.y_.set(0);\n this.width_.set(halfW);\n this.height_.set(halfH);\n break;\n case 'top-right':\n this.x_.set(halfW);\n this.y_.set(0);\n this.width_.set(vw - halfW);\n this.height_.set(halfH);\n break;\n case 'bottom-left':\n this.x_.set(0);\n this.y_.set(halfH);\n this.width_.set(halfW);\n this.height_.set(vh - halfH);\n break;\n case 'bottom-right':\n this.x_.set(halfW);\n this.y_.set(halfH);\n this.width_.set(vw - halfW);\n this.height_.set(vh - halfH);\n break;\n }\n this.resized.emit({ width: this.width_(), height: this.height_() });\n }\n\n protected startResize(event: PointerEvent, edges: Edges): void {\n if (!this.resizable() || this.state() !== 'normal') return;\n event.preventDefault();\n event.stopPropagation();\n const target = event.currentTarget as HTMLElement;\n target.setPointerCapture(event.pointerId);\n\n const startX = this.x_();\n const startY = this.y_();\n const startW = this.width_();\n const startH = this.height_();\n const originX = event.clientX;\n const originY = event.clientY;\n\n const move = (e: PointerEvent): void => {\n const dx = e.clientX - originX;\n const dy = e.clientY - originY;\n\n let nextX = startX;\n let nextY = startY;\n let nextW = startW;\n let nextH = startH;\n\n if (edges.r) nextW = startW + dx;\n if (edges.b) nextH = startH + dy;\n if (edges.l) {\n nextW = startW - dx;\n nextX = startX + dx;\n }\n if (edges.t) {\n nextH = startH - dy;\n nextY = startY + dy;\n }\n\n // Enforce min/max — when shrinking from left/top we have to fix the position too.\n const clampedW = clamp(nextW, this.minWidth(), this.maxWidth());\n const clampedH = clamp(nextH, this.minHeight(), this.maxHeight());\n if (edges.l) nextX += nextW - clampedW;\n if (edges.t) nextY += nextH - clampedH;\n\n this.x_.set(nextX);\n this.y_.set(nextY);\n this.width_.set(clampedW);\n this.height_.set(clampedH);\n this.clampToViewport();\n };\n const cleanup = (e: PointerEvent): void => {\n target.releasePointerCapture(e.pointerId);\n target.removeEventListener('pointermove', move);\n target.removeEventListener('pointerup', cleanup);\n target.removeEventListener('pointercancel', cleanup);\n this.resized.emit({ width: this.width_(), height: this.height_() });\n };\n\n target.addEventListener('pointermove', move);\n target.addEventListener('pointerup', cleanup);\n // Same cancelled-gesture leak as `startMove` — a resize handle that is\n // still listening for `pointermove` resizes the window on a bare hover.\n target.addEventListener('pointercancel', cleanup);\n }\n\n // Bound resize handlers for the template — avoids inline object literals\n // re-creating on every change-detection tick.\n protected resizeTL = (e: PointerEvent): void => this.startResize(e, { t: true, l: true });\n protected resizeT = (e: PointerEvent): void => this.startResize(e, { t: true });\n protected resizeTR = (e: PointerEvent): void => this.startResize(e, { t: true, r: true });\n protected resizeR = (e: PointerEvent): void => this.startResize(e, { r: true });\n protected resizeBR = (e: PointerEvent): void => this.startResize(e, { b: true, r: true });\n protected resizeB = (e: PointerEvent): void => this.startResize(e, { b: true });\n protected resizeBL = (e: PointerEvent): void => this.startResize(e, { b: true, l: true });\n protected resizeL = (e: PointerEvent): void => this.startResize(e, { l: true });\n\n // Internals\n\n private seedInitialGeometry(): void {\n const sizePreset = this.size();\n const preset = sizePreset ? SIZE_PRESETS[sizePreset] : SIZE_PRESETS.md;\n const explicitW = this.initialWidth();\n const explicitH = this.initialHeight();\n const keep = this.keepInViewport();\n const { width: vw, height: vh } = this.viewport();\n // A window OPENS on screen when it can. The preset is a desktop size — `md`\n // is 480px — and a phone is 390: the window opened at x=50 with its right\n // edge at 530, and the Windows chrome's three buttons off the glass. So the\n // size is capped at the viewport (the minimum still wins, since it is the\n // consumer's floor), and a CASCADE position is moved in until the whole box\n // fits. A coordinate the consumer passed is theirs, held only to the same\n // reach a drag is.\n const fit = (size: number, room: number): number => (keep ? Math.min(size, room) : size);\n const w = clamp(fit(explicitW ?? preset.width, vw), this.minWidth(), this.maxWidth());\n const h = clamp(fit(explicitH ?? preset.height, vh), this.minHeight(), this.maxHeight());\n this.width_.set(w);\n this.height_.set(h);\n\n const xIn = this.initialX();\n const yIn = this.initialY();\n let x: number;\n let y: number;\n if (xIn != null && yIn != null) {\n x = xIn;\n y = yIn;\n } else {\n const cascade = this.manager.nextStartOffset();\n x = xIn ?? cascade.x;\n y = yIn ?? cascade.y;\n }\n this.x_.set(keep && xIn == null ? clamp(x, 0, Math.max(0, vw - w)) : x);\n this.y_.set(keep && yIn == null ? clamp(y, 0, Math.max(0, vh - h)) : y);\n\n this.clampToViewport();\n }\n\n /**\n * Keep enough of the window on screen to grab it again. Reads the viewport\n * SIGNAL, so the constructor's effect re-runs it when the page is resized.\n */\n private clampToViewport(): void {\n if (!this.keepInViewport()) return;\n const { width: vw, height: vh } = this.viewport();\n const w = this.width_();\n this.x_.set(clamp(this.x_(), MIN_ON_VIEWPORT - w, vw - MIN_ON_VIEWPORT));\n this.y_.set(clamp(this.y_(), 0, vh - MIN_ON_VIEWPORT));\n }\n}\n","<!--\n The double-click gate is `!== false`, NOT `maximizeVisible()`, and the\n difference is a window nobody can get out of. The Linux preset hides the\n maximize BUTTON; the gesture is how GNOME maximizes, and it worked on every\n chrome before this input went tri-state. Gating it on button visibility would\n have killed it there — and `maximized` is reachable on Linux with no button at\n all (a snap to the top edge, `ref.maximize()`, a restored layout), after which\n every exit disappears at once: no restore-down button, no minimize button,\n `startMove` refuses while the state is not `normal`, the resize handles are not\n rendered, and the only key the window listens for is Escape, which closes it.\n An explicit `showMaximize: false` still turns the gesture off everywhere.\n-->\n<div class=\"wr-window__chrome\" (pointerdown)=\"startMove($event)\" (dblclick)=\"showMaximize() !== false && maximize()\">\n <div class=\"wr-window__title\" [attr.id]=\"titleId\">{{ title() }}</div>\n <div class=\"wr-window__title-extra\">\n <ng-content select=\"[wrWindowTitleExtra]\" />\n </div>\n\n <div class=\"wr-window__chrome-actions\">\n @if (resolvedOs() === 'macos') {\n <!-- macOS-style traffic-light cluster: close → minimize → maximize.\n Glyphs (×, −, +) appear on cluster hover. -->\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--close\"\n [attr.aria-label]=\"closeLabel()\"\n (click)=\"close()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path\n d=\"M2.2 2.2 L7.8 7.8 M7.8 2.2 L2.2 7.8\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n }\n @if (minimizeVisible()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--minimize\"\n [attr.aria-label]=\"minimizeActionLabel()\"\n (click)=\"minimize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <line x1=\"2\" y1=\"5\" x2=\"8\" y2=\"5\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n @if (maximizeVisible()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--maximize\"\n [attr.aria-label]=\"maximizeActionLabel()\"\n (click)=\"maximize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n @if (state() === 'maximized') {\n <path\n d=\"M3 1 L1 1 L1 3 M7 1 L9 1 L9 3 M1 7 L1 9 L3 9 M9 7 L9 9 L7 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n fill=\"none\"\n />\n } @else {\n <path d=\"M2 5 L8 5 M5 2 L5 8\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n }\n </svg>\n </button>\n }\n } @else {\n <!-- Windows / Linux glyph buttons. Linux hides minimize and maximize by\n DEFAULT, not by rule: `minimizeVisible()` resolves the input first, so\n `[showMinimize]=\"true\"` puts the button back — which is the only way a\n user on Linux can reach `<wr-window-taskbar>` at all. -->\n @if (minimizeVisible()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--minimize\"\n [attr.aria-label]=\"minimizeActionLabel()\"\n (click)=\"minimize()\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <line x1=\"1\" y1=\"8\" x2=\"9\" y2=\"8\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n\n @if (maximizeVisible()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--maximize\"\n [attr.aria-label]=\"maximizeActionLabel()\"\n (click)=\"maximize()\"\n >\n @if (state() === 'maximized') {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <rect x=\"1.5\" y=\"2.5\" width=\"6\" height=\"6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n <rect x=\"3\" y=\"1\" width=\"6\" height=\"6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n </svg>\n } @else {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <rect x=\"1\" y=\"1\" width=\"8\" height=\"8\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n </svg>\n }\n </button>\n }\n\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--close\"\n [attr.aria-label]=\"closeLabel()\"\n (click)=\"close()\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M1 1 L9 9 M9 1 L1 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n }\n </div>\n</div>\n\n<div class=\"wr-window__body\">\n <ng-content />\n</div>\n\n<div class=\"wr-window__status-bar\">\n <ng-content select=\"[wrWindowStatusBar]\" />\n</div>\n\n@if (resizable() && state() === 'normal') {\n <span class=\"wr-window__handle wr-window__handle--t\" (pointerdown)=\"resizeT($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--r\" (pointerdown)=\"resizeR($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--b\" (pointerdown)=\"resizeB($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--l\" (pointerdown)=\"resizeL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--tl\" (pointerdown)=\"resizeTL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--tr\" (pointerdown)=\"resizeTR($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--bl\" (pointerdown)=\"resizeBL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--br\" (pointerdown)=\"resizeBR($event)\"></span>\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type ComponentType } from '@angular/cdk/portal';\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n Injector,\n ViewContainerRef,\n ViewEncapsulation,\n afterNextRender,\n effect,\n inject,\n runInInjectionContext,\n viewChild,\n} from '@angular/core';\n\nimport { WrStorage } from 'ngwr/storage';\n\nimport { WrWindowManager } from './services/window-manager';\nimport { storageKey } from './storage-key';\nimport type { WrWindowConfig } from './types';\nimport { WrWindow } from './window';\nimport type { WrWindowRef } from './window-ref';\n\ninterface PersistedGeometry {\n readonly x?: number;\n readonly y?: number;\n readonly width?: number;\n readonly height?: number;\n}\n\n/** Coalesce live position/size writes — drag/resize fires every move. */\nconst PERSIST_DEBOUNCE_MS = 200;\n\n/**\n * Internal host attached by `WrWindowManager.open()`. Reads the config,\n * configures a `<wr-window>`, projects the consumer's component into\n * its body, and wires the resulting instance back to the `WrWindowRef`\n * so consumers can drive everything imperatively.\n *\n * @internal\n */\n@Component({\n selector: 'wr-window-container',\n templateUrl: './window-container.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [WrWindow],\n})\nexport class WrWindowContainer<C> {\n /** Set by the manager before view init. */\n config!: WrWindowConfig;\n /** Set by the manager before view init. */\n ref!: WrWindowRef<C, unknown>;\n /** Set by the manager before view init. */\n componentType!: ComponentType<C>;\n /** Custom injector with `WR_WINDOW_REF` / `WR_WINDOW_DATA` populated. */\n childInjector!: Injector;\n /** Set by the manager: move focus into the window once it has rendered. */\n autoFocus = true;\n\n private readonly hostInjector = inject(Injector);\n private readonly manager = inject(WrWindowManager);\n private readonly storage = inject(WrStorage);\n private readonly destroyRef = inject(DestroyRef);\n private persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n private readonly contentVcr = viewChild.required('content', { read: ViewContainerRef });\n private readonly wrWindow = viewChild.required(WrWindow);\n\n constructor() {\n afterNextRender(() => this.attach());\n this.destroyRef.onDestroy(() => {\n if (this.persistTimer !== null) clearTimeout(this.persistTimer);\n });\n }\n\n private attach(): void {\n // 1. Create the consumer's component inside the body slot.\n const componentRef = this.contentVcr().createComponent(this.componentType, {\n injector: this.childInjector,\n });\n this.ref.componentRef = componentRef;\n\n // 2. Bridge imperative actions to the underlying <wr-window>.\n const w = this.wrWindow();\n this.ref._doMinimize = () => w.minimize();\n this.ref._doMaximize = () => w.maximize();\n this.ref._doRestore = () => w.restore();\n this.ref._doFocus = () => w.focus();\n this.ref._doMoveTo = (x, y) => w.moveTo(x, y);\n this.ref._doResizeTo = (width, height) => w.resizeTo(width, height);\n this.ref._doCenter = () => w.center();\n this.ref._doSetTitle = title => this.ref._title.set(title);\n // After a render, not now: the consumer's component was created a line\n // above and has not drawn its template yet, and a window coming back from\n // the taskbar is still `display: none` until its class updates.\n this.ref._doFocusInitial = () => afterNextRender(() => w.focusInitial(), { injector: this.hostInjector });\n // A ref outlives its window; a render hook must not be registered on an\n // injector that is gone.\n this.destroyRef.onDestroy(() => (this.ref._doFocusInitial = null));\n\n // 3. Sync the live geometry/state into the ref's signals so\n // consumers can read them reactively without poking at <wr-window>.\n // Angular 22 always allows signal writes inside effects — the\n // `allowSignalWrites` option was deprecated in this version.\n runInInjectionContext(this.hostInjector, () => {\n effect(() => this.ref._state.set(w.state()));\n effect(() => this.ref._x.set(w.x()));\n effect(() => this.ref._y.set(w.y()));\n effect(() => this.ref._width.set(w.width()));\n effect(() => this.ref._height.set(w.height()));\n // Alongside the effective values, not instead of them: `saveLayout` needs\n // the geometry a maximized or minimized window would go back to.\n effect(() => this.ref._rawX.set(w.x_()));\n effect(() => this.ref._rawY.set(w.y_()));\n effect(() => this.ref._rawWidth.set(w.width_()));\n effect(() => this.ref._rawHeight.set(w.height_()));\n effect(() => this.ref._z.set(w.z()));\n\n // The z-index has to land on the OVERLAY HOST, not only on `.wr-window`.\n // Each window sits in its own CDK global wrapper, and that wrapper is\n // `position: fixed` with a numeric `z-index` — which makes it a stacking\n // context. A z-index written INSIDE it therefore only orders things\n // against its own siblings, never against another window: the wrappers\n // all carry the same z and stack by DOM order, so the most recently\n // opened window painted on top for good. `bringToFront()` raised the\n // number and nothing moved — measured in Chromium, `elementFromPoint` in\n // the overlap kept returning the newer window after the older one's title\n // bar was clicked.\n effect(() => {\n const host = this.ref._overlayRef?.hostElement;\n if (host) host.style.zIndex = String(w.z());\n });\n });\n\n // 4. Seed the title signal from config.\n this.ref._title.set(this.config.title ?? '');\n\n // 5. Storage — hydrate from disk + auto-save on geometry change.\n if (this.config.storage) {\n this.hydrateFromStorage(w);\n this.installAutosave(w);\n }\n\n // 6. Apply any state the manager pinned for restore — bridges are\n // now wired so `ref.minimize()` / `maximize()` actually fire.\n const pending = this.ref.pendingStateOnMount;\n if (pending) {\n this.ref.pendingStateOnMount = null;\n if (pending === 'minimized') this.ref.minimize();\n else if (pending === 'maximized') this.ref.maximize();\n }\n\n // 7. Focus — never into a window that opened straight into the taskbar.\n if (this.autoFocus && w.state() !== 'minimized') this.ref._doFocusInitial();\n }\n\n /** The window was minimized while it held focus: hand focus to its taskbar tab. */\n protected onMinimizedWithFocus(): void {\n // After the render that lists the window in the taskbar.\n afterNextRender(() => this.manager._focusAfterMinimize(this.ref as WrWindowRef<unknown, unknown>), {\n injector: this.hostInjector,\n });\n }\n\n /** Apply persisted geometry on top of config defaults, before the user sees the window. */\n private hydrateFromStorage(w: WrWindow): void {\n const cfg = this.config.storage;\n if (!cfg) return;\n const saved = this.storage.get<PersistedGeometry>(storageKey(cfg));\n if (!saved) return;\n const persist = cfg.persist ?? 'all';\n if (persist !== 'size') {\n if (typeof saved.x === 'number') w.x_.set(saved.x);\n if (typeof saved.y === 'number') w.y_.set(saved.y);\n }\n if (persist !== 'position') {\n if (typeof saved.width === 'number') w.width_.set(saved.width);\n if (typeof saved.height === 'number') w.height_.set(saved.height);\n }\n }\n\n /** Persist geometry whenever it changes, debounced. */\n private installAutosave(w: WrWindow): void {\n const cfg = this.config.storage;\n if (!cfg) return;\n const persist = cfg.persist ?? 'all';\n const key = storageKey(cfg);\n\n runInInjectionContext(this.hostInjector, () => {\n effect(() => {\n // Read every signal we want to watch; ignore minimized/maximized\n // overlay values — we only persist the user's chosen geometry.\n const x = w.x_();\n const y = w.y_();\n const width = w.width_();\n const height = w.height_();\n\n if (this.persistTimer !== null) clearTimeout(this.persistTimer);\n this.persistTimer = setTimeout(() => {\n this.persistTimer = null;\n const payload: PersistedGeometry = {};\n if (persist !== 'size') {\n (payload as { x?: number; y?: number }).x = x;\n (payload as { x?: number; y?: number }).y = y;\n }\n if (persist !== 'position') {\n (payload as { width?: number; height?: number }).width = width;\n (payload as { width?: number; height?: number }).height = height;\n }\n this.storage.set(key, payload);\n }, PERSIST_DEBOUNCE_MS);\n });\n });\n }\n}\n","<wr-window\n [open]=\"true\"\n [title]=\"ref.title()\"\n [os]=\"config.os ?? 'auto'\"\n [size]=\"config.size ?? 'md'\"\n [chromeSize]=\"config.chromeSize ?? 'md'\"\n [animations]=\"config.animations ?? true\"\n [initialX]=\"config.x ?? null\"\n [initialY]=\"config.y ?? null\"\n [initialWidth]=\"config.width ?? null\"\n [initialHeight]=\"config.height ?? null\"\n [minWidth]=\"config.minWidth ?? 220\"\n [minHeight]=\"config.minHeight ?? 140\"\n [maxWidth]=\"config.maxWidth ?? 1000000\"\n [maxHeight]=\"config.maxHeight ?? 1000000\"\n [movable]=\"config.movable ?? true\"\n [resizable]=\"config.resizable ?? true\"\n [keepInViewport]=\"config.keepInViewport ?? true\"\n [snap]=\"config.snap ?? 'none'\"\n [dragHandle]=\"config.dragHandle ?? null\"\n [showMinimize]=\"config.showMinimize ?? null\"\n [showMaximize]=\"config.showMaximize ?? null\"\n [showClose]=\"config.showClose ?? true\"\n (closed)=\"ref.close()\"\n (minimizedWithFocus)=\"onMinimizedWithFocus()\"\n #window\n>\n <ng-container #content />\n</wr-window>\n\n@if (window.snapTarget(); as target) {\n <div class=\"wr-window__snap-hint\" [attr.data-target]=\"target\" aria-hidden=\"true\"></div>\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { OverlayRef } from '@angular/cdk/overlay';\nimport { type ComponentRef, type Signal, type WritableSignal, signal } from '@angular/core';\n\nimport { ReplaySubject, Subject } from 'rxjs';\n\nimport type { WrWindowState, WrWindowBeforeCloseHook } from './types';\n\n/**\n * Handle returned by `WrWindowManager.open()`.\n *\n * Wraps the underlying overlay, exposes signals for the live geometry,\n * and gives the consumer programmatic control over the window\n * (focus, move, resize, minimize, maximize, close).\n *\n * @example\n * ```ts\n * const ref = manager.open(EditorComponent, {\n * title: 'Untitled.md',\n * storage: { key: 'editor', prefix: 'app' },\n * });\n *\n * ref.beforeClose(async () => {\n * if (!isDirty) return true;\n * return await confirmDiscard();\n * });\n *\n * const saved = await ref.afterClosed(); // resolves with whatever the\n * // component passed to ref.close(value)\n * ```\n */\nexport class WrWindowRef<C, R = unknown> {\n /** Stable id — used by the taskbar, workspace save, and DI. */\n readonly id: string;\n\n /** @internal — emits the close result once and completes. */\n /**\n * A `ReplaySubject`, not a plain `Subject`, so the result survives a late\n * subscriber — the same reasoning `WrDialogRef` already carries. A caller\n * that holds the ref and awaits `afterClosed()` after any intervening\n * `await` subscribes to an already-completed stream, and a plain Subject\n * hands it nothing but `complete`: the promise resolved `undefined` and a\n * saved result was indistinguishable from a dismissal.\n */\n readonly _closed = new ReplaySubject<R | undefined>(1);\n\n /** @internal — emits whenever the visual state changes. */\n readonly _stateChanged = new Subject<WrWindowState>();\n\n /** @internal — set by the container right after attach. */\n componentRef: ComponentRef<C> | null = null;\n\n /** @internal — whether this window opts into the taskbar list. */\n taskbarVisible = true;\n\n /**\n * @internal — non-`normal` state to apply right after the container\n * wires its bridges (so `restoreLayout` can land a window straight\n * into `minimized` / `maximized` even though it just opened).\n */\n pendingStateOnMount: WrWindowState | null = null;\n\n // Live geometry signals (writable internally, exposed read-only)\n /** @internal */ readonly _state: WritableSignal<WrWindowState> = signal('normal');\n /** @internal */ readonly _x = signal(0);\n /** @internal */ readonly _y = signal(0);\n /** @internal */ readonly _width = signal(0);\n /** @internal */ readonly _height = signal(0);\n /** @internal */ readonly _z = signal(0);\n\n /**\n * The geometry the USER chose, as opposed to the one the current state\n * imposes. `_x` and friends mirror the window's EFFECTIVE values — a\n * maximized window reports the viewport, a minimized one reports its\n * collapsed header height — which is right for anything drawing the window\n * and wrong for anything persisting it.\n *\n * @internal\n */\n readonly _rawX = signal(0);\n /** @internal */ readonly _rawY = signal(0);\n /** @internal */ readonly _rawWidth = signal(0);\n /** @internal */ readonly _rawHeight = signal(0);\n /** @internal */ readonly _title: WritableSignal<string> = signal('');\n\n /** Window state. */\n readonly state: Signal<WrWindowState> = this._state.asReadonly();\n /** Live X. */\n readonly x: Signal<number> = this._x.asReadonly();\n /** Live Y. */\n readonly y: Signal<number> = this._y.asReadonly();\n /** Live width. */\n readonly width: Signal<number> = this._width.asReadonly();\n /** Live height. */\n readonly height: Signal<number> = this._height.asReadonly();\n /** Stack z-index. */\n readonly z: Signal<number> = this._z.asReadonly();\n /** Live title. */\n readonly title: Signal<string> = this._title.asReadonly();\n\n // Hooks\n private _beforeCloseHook: WrWindowBeforeCloseHook<R> | null = null;\n\n // Imperative bridges — wired by the manager / container after attach\n /** @internal */ _doClose: ((result: R | undefined) => void) | null = null;\n /** @internal */ _doMinimize: (() => void) | null = null;\n /** @internal */ _doMaximize: (() => void) | null = null;\n /** @internal */ _doRestore: (() => void) | null = null;\n /** @internal */ _doFocus: (() => void) | null = null;\n /** @internal */ _doMoveTo: ((x: number, y: number) => void) | null = null;\n /** @internal */ _doResizeTo: ((w: number, h: number) => void) | null = null;\n /** @internal */ _doCenter: (() => void) | null = null;\n /** @internal */ _doSetTitle: ((title: string) => void) | null = null;\n /** @internal — move focus into the window after the next render. */\n _doFocusInitial: (() => void) | null = null;\n\n /**\n * @internal — what had focus when `open()` was called, and where closing the\n * window sends it back. `null` when focus was on nothing.\n */\n _returnFocus: HTMLElement | null = null;\n\n constructor(\n id: string,\n public readonly _overlayRef: OverlayRef\n ) {\n this.id = id;\n }\n\n /** Resolved instance of the projected component. */\n get componentInstance(): C {\n if (!this.componentRef) {\n throw new Error('WrWindowRef: component not yet attached');\n }\n return this.componentRef.instance;\n }\n\n // Lifecycle\n\n private isClosed = false;\n\n /**\n * Close the window, optionally returning a result. If a `beforeClose`\n * hook is registered it is consulted first — a falsy resolution\n * cancels the close.\n */\n async close(result?: R): Promise<void> {\n // `WrDialogRef` / `WrDrawerRef` latch the same way on their own `isClosed`,\n // but theirs are synchronous: this is the only one of the three that AWAITS,\n // so it is the\n // only one a second call can enter mid-flight and run the hook again. Two\n // Escapes in a row do it, and so does `manager.closeAll()` while a hook is\n // pending — `_doClose` is what removes the ref from the manager's list, and\n // it has not run yet.\n if (this.isClosed) return;\n this.isClosed = true;\n\n let proceed = false;\n try {\n proceed = this._beforeCloseHook ? !!(await this._beforeCloseHook(result)) : true;\n } finally {\n // A veto is not a close, and neither is a hook that threw — release the\n // latch in both cases, or a declined close would disable the window for\n // good.\n if (!proceed) this.isClosed = false;\n }\n\n if (proceed) this._doClose?.(result);\n }\n\n /** Toggle the minimized state. */\n minimize(): void {\n this._doMinimize?.();\n }\n\n /** Toggle the maximized state. */\n maximize(): void {\n this._doMaximize?.();\n }\n\n /** Force-restore from minimized / maximized to `normal`. */\n restore(): void {\n this._doRestore?.();\n }\n\n /** Bring this window to the top of the stack. */\n focus(): void {\n this._doFocus?.();\n }\n\n // Programmatic geometry\n\n moveTo(x: number, y: number): void {\n this._doMoveTo?.(x, y);\n }\n\n resizeTo(width: number, height: number): void {\n this._doResizeTo?.(width, height);\n }\n\n /** Re-position the window so it sits centered in the current viewport. */\n center(): void {\n this._doCenter?.();\n }\n\n setTitle(title: string): void {\n this._doSetTitle?.(title);\n }\n\n // Hooks\n\n /**\n * Register a guard that runs before `close()`. Return `false` (or a\n * Promise resolving to false) to veto. Only one hook per ref —\n * subsequent calls replace the previous.\n */\n beforeClose(hook: WrWindowBeforeCloseHook<R>): void {\n this._beforeCloseHook = hook;\n }\n\n /** Resolves with the result passed to `close()` (or `undefined`). */\n afterClosed(): Promise<R | undefined> {\n return new Promise(resolve => {\n this._closed.subscribe({\n next: value => resolve(value),\n complete: () => resolve(undefined),\n });\n });\n }\n\n /** Escape hatch — the underlying CDK overlay ref. */\n get overlayRef(): OverlayRef {\n return this._overlayRef;\n }\n}\n\nexport type { WrWindowBeforeCloseHook } from './types';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directionality } from '@angular/cdk/bidi';\nimport { type OverlayRef } from '@angular/cdk/overlay';\nimport { ComponentPortal, type ComponentType } from '@angular/cdk/portal';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n EnvironmentInjector,\n Injector,\n PLATFORM_ID,\n Service,\n type Signal,\n computed,\n inject,\n signal,\n} from '@angular/core';\n\nimport { WR_OVERLAY, wrFollowDirection } from 'ngwr/overlay';\nimport { WrStorage } from 'ngwr/storage';\nimport { randomId, toClassList } from 'ngwr/utils';\n\nimport { storageKey } from '../storage-key';\nimport { WR_WINDOW_DATA, WR_WINDOW_REF } from '../tokens';\nimport type { WrWindowConfig, WrWindowLayoutSnapshot, WrWindowStorageConfig } from '../types';\nimport { WrWindowContainer } from '../window-container';\nimport { WrWindowRef } from '../window-ref';\n\n/**\n * What `WrWindowManager` needs from a `<wr-window-taskbar>` on the page: the\n * row a window's tab sits in, so focus can land on it when the window is\n * minimized and be recognised there when the window is closed from it.\n *\n * @internal\n */\nexport interface WrWindowTaskbarTabs {\n /** The `.wr-window-taskbar__tab` row for `ref`, or `null` when this taskbar does not list it. */\n tabFor(ref: WrWindowRef<unknown, unknown>): HTMLElement | null;\n}\n\n/**\n * Owns the open `<wr-window>` stack, hands out z-indexes, cascades the\n * default spawn position, and opens programmatic windows that wrap a\n * consumer component.\n *\n * Inject the singleton and call `open(component, config)` for a\n * dialog-style flow:\n *\n * ```ts\n * const manager = inject(WrWindowManager);\n *\n * const ref = manager.open(EditorComponent, {\n * title: 'Untitled.md',\n * size: 'lg',\n * storage: { key: 'editor', prefix: 'my-app' },\n * });\n *\n * const saved = await ref.afterClosed();\n * ```\n *\n * Declarative `<wr-window [(open)]=\"...\">` instances also register with\n * the manager on focus, so both styles share the same stack ordering.\n */\n@Service()\nexport class WrWindowManager {\n private readonly overlay = inject(WR_OVERLAY);\n private readonly parentInjector = inject(EnvironmentInjector);\n private readonly storage = inject(WrStorage);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly dir = inject(Directionality, { optional: true });\n\n private readonly baseZ = 1000;\n private topZ = this.baseZ;\n private openCount = 0;\n\n /** All open windows opened via `open()` — declarative `<wr-window>` is not tracked here. */\n private readonly _windows = signal<readonly WrWindowRef<unknown, unknown>[]>([]);\n\n /**\n * Filled by `restoreLayout` right before it invokes the consumer's\n * opener callback. The next `open()` call with a matching `config.id`\n * pops the entry and uses it as the initial geometry (so the seed\n * lands at the saved coords instead of the cascade default) and\n * applies any non-`normal` state after the bridges are wired.\n */\n private readonly pendingRestores = new Map<string, WrWindowLayoutSnapshot>();\n\n /** The taskbars on the page, registered by each `<wr-window-taskbar>` for its lifetime. */\n private readonly taskbars = new Set<WrWindowTaskbarTabs>();\n\n /** All currently-open programmatic windows. */\n readonly windows: Signal<readonly WrWindowRef<unknown, unknown>[]> = this._windows.asReadonly();\n\n /** Programmatic windows that are minimized AND opted into the taskbar. */\n readonly minimized = computed(() => this._windows().filter(w => w.taskbarVisible && w.state() === 'minimized'));\n\n /** Reserve the next z-index. Strictly increasing across the app's lifetime. */\n bringToFront(): number {\n this.topZ += 1;\n return this.topZ;\n }\n\n /** Cascade offset for new windows, so two opens don't perfectly overlap. */\n nextStartOffset(): { readonly x: number; readonly y: number } {\n const offset = (this.openCount % 10) * 30;\n this.openCount += 1;\n return { x: 50 + offset, y: 50 + offset };\n }\n\n /**\n * Open a window with `component` rendered as its body. Returns a ref\n * the caller can use to drive the window programmatically and await\n * its result.\n *\n * **Singleton by id** — if `config.id` is set and a window with that\n * id is already open, the existing ref is restored (if minimized),\n * brought to the front, and returned. No duplicate window is\n * created. Use this to coalesce repeated open() calls (e.g. a\n * \"Settings\" menu item that should always re-focus the same window).\n */\n open<C, R = unknown, D = unknown>(component: ComponentType<C>, config: WrWindowConfig<D> = {}): WrWindowRef<C, R> {\n // Where focus goes back to when the window closes — read before anything\n // here moves it.\n const opener = this.focusedElement();\n\n if (config.id) {\n const existing = this.findById(config.id);\n if (existing) {\n existing.restore();\n existing.focus();\n // A second open is still an open: focus goes to the window, and back to\n // whatever asked for it this time — unless that was the window itself.\n if (config.autoFocus !== false) {\n if (opener && !existing._overlayRef.overlayElement?.contains(opener)) existing._returnFocus = opener;\n existing._doFocusInitial?.();\n }\n return existing as WrWindowRef<C, R>;\n }\n }\n\n // Honour a pending restore — `restoreLayout` populates this Map\n // right before invoking the consumer's opener so the new window\n // seeds at the saved geometry instead of the cascade default.\n const pending = config.id ? this.pendingRestores.get(config.id) : undefined;\n if (pending) {\n this.pendingRestores.delete(config.id!);\n config = {\n ...config,\n x: pending.x,\n y: pending.y,\n width: pending.width,\n height: pending.height,\n title: pending.title || config.title,\n };\n }\n\n // Assigned right after the ref exists; the predicate below only ever runs\n // from a keydown, long after.\n let self: WrWindowRef<unknown, unknown> | null = null;\n\n // Each window gets its own CDK overlay pane positioned `static` —\n // <wr-window> itself uses `position: fixed`, so the pane is only a\n // mount point. Windows are never modal — reach for `WrDialog` when\n // you need a backdrop + focus trap + scroll block.\n const overlayRef: OverlayRef = this.overlay.create({\n positionStrategy: this.overlay.position().global(),\n panelClass: toClassList('wr-window-overlay', config.panelClass),\n hasBackdrop: false,\n // Which window an Escape belongs to is a question the CDK cannot answer\n // here. Its keyboard dispatcher walks the attached overlays newest-first\n // and hands the key to the first one willing to take it — and attach order\n // is frozen at OPEN order, because `focus()` re-stacks with a z-index and\n // never re-attaches. So the last window opened swallowed every Escape,\n // even sitting behind the one the user was in. Declining here is what makes\n // it recoverable: a rejected event walks on down the stack instead of being\n // eaten, so the window that does own it still gets its Escape.\n eventPredicate: () => self === null || this.ownsKeyboard(self),\n // OUT of the top layer, deliberately. The CDK puts overlay hosts there by\n // default (`popover=\"manual\"`), and the top layer orders strictly by\n // ENTRY: whatever opened last paints on top and no z-index can change it.\n // That is right for a menu or a modal and exactly wrong for a window\n // manager, whose whole job is letting the user decide which window is in\n // front. It also fixes the ordering against modals: a dialog stays in the\n // top layer, so it now sits above every window instead of below whichever\n // window happened to open after it.\n usePopover: false,\n });\n\n // Windows are long-lived — a session can leave one open across any number\n // of direction changes — and while `x` / `y` are physical by design (as are\n // the resize grips, deliberately), the chrome is not: the macOS title bar\n // parks its button cluster with `row-reverse`, which resolves against `dir`,\n // so a stale attribute leaves the dots and the gutter that counterbalances\n // them on opposite edges. The strategy is bare, so nothing moves. Each\n // `open()` has its own ref, and `_doClose` disposes it, which is what ends\n // this follower.\n wrFollowDirection(overlayRef, this.dir, this.parentInjector);\n\n const id = config.id ?? randomId('wr-window');\n const ref = new WrWindowRef<C, R>(id, overlayRef);\n self = ref as unknown as WrWindowRef<unknown, unknown>;\n ref.taskbarVisible = config.taskbar !== false;\n\n // Provide WR_WINDOW_REF + WR_WINDOW_DATA inside the projected\n // component's subtree so it can `inject(WR_WINDOW_REF)` etc.\n const childInjector = Injector.create({\n parent: this.parentInjector,\n providers: [\n { provide: WR_WINDOW_REF, useValue: ref },\n { provide: WR_WINDOW_DATA, useValue: config.data ?? null },\n ],\n });\n\n const portal = new ComponentPortal<WrWindowContainer<C>>(WrWindowContainer);\n const containerRef = overlayRef.attach(portal);\n const container = containerRef.instance;\n container.config = config;\n container.ref = ref as WrWindowRef<C, unknown>;\n container.componentType = component;\n container.childInjector = childInjector;\n // A window `restoreLayout()` re-opens stays out of focus's way unless its\n // opener says otherwise: a workspace of five windows coming back must not\n // pull focus through each of them and leave it in whichever came last.\n container.autoFocus = config.autoFocus ?? !pending;\n ref._returnFocus = opener;\n\n // No role on the pane: `<wr-window>` inside it is the named `role=\"dialog\"`,\n // and a second, unnamed one around it read as \"dialog > dialog\" and tripped\n // axe's `aria-dialog-name` on every open window.\n\n if (config.closeOnEscape !== false) {\n overlayRef.keydownEvents().subscribe(event => {\n if (event.key === 'Escape') {\n event.preventDefault();\n void ref.close();\n }\n });\n }\n\n // Wire close → disposal + completion of the result subject. The\n // ref's `close()` already runs the beforeClose hook before reaching\n // this bridge.\n ref._doClose = result => {\n // Read before disposal takes the focused element out of the page. Focus\n // goes back only when it was the window's to give: inside it, on its\n // taskbar tab, or already lost. A window closed by code while the reader\n // works elsewhere leaves them there.\n const back = this.holdsFocus(ref as unknown as WrWindowRef<unknown, unknown>) ? ref._returnFocus : null;\n ref._returnFocus = null;\n overlayRef.dispose();\n ref._closed.next(result);\n ref._closed.complete();\n this._windows.update(list => list.filter(r => r !== (ref as unknown as WrWindowRef<unknown, unknown>)));\n if (back?.isConnected) back.focus();\n };\n\n this._windows.update(list => [...list, ref as unknown as WrWindowRef<unknown, unknown>]);\n\n // If the pending restore had a non-`normal` state, hand it to the\n // container so it can apply it right after wiring the bridges.\n // queueMicrotask would fire before afterNextRender — the bridges\n // wouldn't be set yet and ref.minimize() / maximize() would no-op.\n if (pending && pending.state !== 'normal') {\n ref.pendingStateOnMount = pending.state;\n }\n\n return ref;\n }\n\n /**\n * Whether a keyboard event routed to `ref`'s overlay is actually meant for it.\n *\n * The window holding real DOM focus owns the key. When focus is outside every\n * window — the common case, since a window is not modal and traps nothing —\n * the FRONT-most one does, by the manager's own z stack rather than by attach\n * order. A tie (nothing has ever been focused, so no z has been handed out\n * yet) leaves every window willing, and the dispatcher's newest-first walk\n * settles it as before.\n *\n * A MINIMIZED window never owns a key it did not receive through focus, and\n * never counts as being in front: it is `display: none`, so an Escape pressed\n * on the page closed a window the user could not see — and threw away its\n * taskbar entry with it — while the visible one stayed put.\n *\n * Focus on a taskbar tab is the minimized window's (as `holdsFocus` reads\n * it), so NO window owns that key: a tab lists only minimized windows, and\n * handing the key to the front-most one closed a window the reader was not\n * in, right after minimizing had put them on the tab.\n */\n private ownsKeyboard(ref: WrWindowRef<unknown, unknown>): boolean {\n const open = this._windows();\n const active = this.isBrowser ? document.activeElement : null;\n const focused = active ? open.find(w => w._overlayRef.overlayElement?.contains(active)) : undefined;\n if (focused) return focused === ref;\n if (active && open.some(w => this.taskbarTab(w)?.contains(active))) return false;\n if (ref.state() === 'minimized') return false;\n return open.every(w => w === ref || w.state() === 'minimized' || w.z() <= ref.z());\n }\n\n /**\n * Register a taskbar for as long as it is on the page. Returns the\n * unregister call.\n *\n * @internal\n */\n _registerTaskbar(taskbar: WrWindowTaskbarTabs): () => void {\n this.taskbars.add(taskbar);\n return () => this.taskbars.delete(taskbar);\n }\n\n /**\n * A window was minimized while it held focus, and the render that lists it\n * in the taskbar has happened: put focus on its tab's restore button. With no\n * taskbar listing it (none on the page, or `taskbar: false`), focus goes back\n * to where the window was opened from rather than being left on `<body>`.\n *\n * @internal\n */\n _focusAfterMinimize(ref: WrWindowRef<unknown, unknown>): void {\n // The restore button is the row's first: the close button sits after it.\n const restore = this.taskbarTab(ref)?.querySelector<HTMLElement>('button');\n if (restore) restore.focus();\n else if (ref._returnFocus?.isConnected) ref._returnFocus.focus();\n // Nowhere to go: at least never leave focus parked inside a window that is\n // `display: none`, where it would keep claiming every Escape. Browsers\n // that run the focus fixup rule have already done this.\n const active = this.focusedElement();\n if (active && ref._overlayRef.overlayElement?.contains(active)) active.blur();\n }\n\n private taskbarTab(ref: WrWindowRef<unknown, unknown>): HTMLElement | null {\n for (const taskbar of this.taskbars) {\n const tab = taskbar.tabFor(ref);\n if (tab) return tab;\n }\n return null;\n }\n\n /** The focused element, or `null` when that is `<body>` or nothing. */\n private focusedElement(): HTMLElement | null {\n if (!this.isBrowser) return null;\n const active = document.activeElement;\n return active instanceof HTMLElement && active !== document.body ? active : null;\n }\n\n /** Whether focus is `ref`'s to hand back: inside it, on its taskbar tab, or nowhere. */\n private holdsFocus(ref: WrWindowRef<unknown, unknown>): boolean {\n if (!this.isBrowser) return false;\n const active = this.focusedElement();\n if (!active) return true;\n return !!ref._overlayRef.overlayElement?.contains(active) || !!this.taskbarTab(ref)?.contains(active);\n }\n\n /** Close every programmatically-opened window. */\n closeAll(): void {\n for (const ref of [...this._windows()]) {\n void ref.close();\n }\n }\n\n /** Look up an open window by its `config.id`. Returns `null` when no match. */\n findById(id: string): WrWindowRef<unknown, unknown> | null {\n return this._windows().find(r => r.id === id) ?? null;\n }\n\n /**\n * Drop the persisted geometry for a window so the next open uses the\n * config defaults again. Matches `WrWindowConfig.storage` exactly.\n */\n clearPersistedPosition(cfg: WrWindowStorageConfig): void {\n this.storage.remove(storageKey(cfg));\n }\n\n // Workspace save/restore\n //\n // A workspace is a snapshot of every open window's id + state +\n // geometry. Reopening is the consumer's job (component identities\n // aren't serialisable), so `restoreLayout` returns the captured\n // snapshots and a helper that re-applies geometry once the windows\n // have been opened again.\n\n /** Snapshot of one window — what `saveLayout` writes / `restoreLayout` returns. */\n private layoutKey(name: string): string {\n return `wr:window-layout:${name}`;\n }\n\n /**\n * Persist the geometry + state of every open programmatic window\n * under `name`. Pair with `restoreLayout(name)` after re-opening the\n * matching components.\n */\n saveLayout(name: string): void {\n // The RAW geometry, not the live one. `ref.x()` / `ref.width()` report what\n // is on screen — a maximized window measures the viewport, a minimized one\n // measures its collapsed header — so saving those threw away the size the\n // user actually chose. Restoring then re-maximized over viewport-sized\n // \"restore\" geometry, and \"Restore down\" left the window filling the screen\n // with no way back; a minimized window came back from the taskbar as a stub\n // clamped to `minHeight`. The window knows the real numbers all along.\n const snapshot = this._windows().map(ref => ({\n id: ref.id,\n state: ref.state(),\n x: ref._rawX(),\n y: ref._rawY(),\n width: ref._rawWidth(),\n height: ref._rawHeight(),\n title: ref.title(),\n }));\n this.storage.set(this.layoutKey(name), snapshot);\n }\n\n /** Read a saved workspace. Returns `null` when no snapshot is found. */\n readLayout(name: string): readonly WrWindowLayoutSnapshot[] | null {\n return this.storage.get(this.layoutKey(name));\n }\n\n /**\n * Apply a saved workspace.\n *\n * Each saved entry is matched to a currently-open window by `id`. For\n * matches, the geometry / state / title is re-applied immediately.\n * For misses, the optional `open` callback is invoked so the consumer\n * can re-open the right component for that id — the freshly-opened\n * window then seeds straight to the saved geometry (no cascade flicker)\n * and the saved state lands once the bridges are wired.\n *\n * ```ts\n * manager.restoreLayout('default', (id, snap) => {\n * if (id.startsWith('editor:')) {\n * manager.open(EditorComponent, { id, title: snap.title, data: ... });\n * }\n * });\n * ```\n */\n restoreLayout(name: string, open?: (id: string, snapshot: { readonly title: string }) => void): void {\n const snapshot = this.readLayout(name);\n if (!snapshot) return;\n\n for (const snap of snapshot) {\n const existing = this.findById(snap.id);\n if (existing) {\n this.applyRestore(existing, snap);\n continue;\n }\n if (!open) continue;\n // Stash the geometry so the next `open()` call with this id\n // consumes it as the seed instead of cascading.\n this.pendingRestores.set(snap.id, snap);\n open(snap.id, { title: snap.title });\n // Belt + braces: if the opener didn't actually open a window (or\n // opened with a different id), drop the stale pending entry so it\n // doesn't ambush a future open.\n if (!this.findById(snap.id)) this.pendingRestores.delete(snap.id);\n }\n }\n\n private applyRestore(ref: WrWindowRef<unknown, unknown>, snap: WrWindowLayoutSnapshot): void {\n // Force back to a known 'normal' baseline before applying state —\n // ref.minimize() / maximize() are toggles, so this prevents a\n // saved 'minimized' from un-minimizing an already-minimized window.\n ref.restore();\n if (snap.title) ref.setTitle(snap.title);\n ref.moveTo(snap.x, snap.y);\n ref.resizeTo(snap.width, snap.height);\n if (snap.state === 'minimized') ref.minimize();\n else if (snap.state === 'maximized') ref.maximize();\n }\n\n /** Drop a saved workspace. */\n clearLayout(name: string): void {\n this.storage.remove(this.layoutKey(name));\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n type ElementRef,\n ViewEncapsulation,\n computed,\n inject,\n input,\n signal,\n viewChildren,\n} from '@angular/core';\n\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\n\nimport { WrWindowManager } from './services/window-manager';\nimport type { WrWindowRef } from './window-ref';\n\n/**\n * Stands in for the consumer input `useI18nText` expects — the taskbar exposes no\n * label inputs. Read reactively rather than once at construction: the rail is as\n * long-lived as the app, so a catalog that arrives later, or a locale switch, has to\n * reach it.\n */\nconst NO_OVERRIDE = signal<string | null>(null).asReadonly();\n\n/**\n * OS-style window taskbar. Drop one anywhere in the app — typically\n * fixed to the bottom of the viewport — and it lists every window\n * `WrWindowManager.open()` has handed out that's currently\n * `minimized`. Clicking a tab restores the window; clicking the close\n * glyph dismisses it without restoring.\n *\n * Focus follows the window in and out of the rail: minimizing a window\n * that holds focus puts focus on its tab here, and restoring it from the\n * tab moves focus into the window.\n *\n * Windows opted out via `config.taskbar = false` never show up here.\n *\n * @example\n * ```html\n * <wr-window-taskbar />\n * <wr-window-taskbar position=\"top\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/window\n */\n@Component({\n selector: 'wr-window-taskbar',\n templateUrl: './window-taskbar.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()', role: 'toolbar', '[attr.aria-label]': 'railLabel()' },\n})\nexport class WrWindowTaskbar {\n // Four English literals lived in this component's markup, next to a catalog that\n // already carried `window.close`. A `toolbar` with no name and tabs announced in\n // the wrong language are both invisible on screen.\n /** @internal */ protected readonly railLabel = useI18nText(NO_OVERRIDE, 'window.taskbar', 'Minimized windows');\n /** @internal */ protected readonly closeLabel = useI18nText(NO_OVERRIDE, 'window.closeWindow', 'Close window');\n /** @internal */ protected readonly untitled = useI18nText(NO_OVERRIDE, 'window.untitled', 'Untitled');\n /** @internal */ protected readonly restoreLabel = useI18nFormatter('window.restoreWindow', 'Restore {{title}}');\n\n /** Edge the taskbar pins itself to. @default 'bottom' */\n readonly position = input<'top' | 'bottom'>('bottom');\n\n private readonly manager = inject(WrWindowManager);\n\n /** @internal — minimized windows that haven't opted out via `taskbar: false`. */\n protected readonly items = computed(() => this.manager.minimized());\n\n protected readonly classes = computed(() => `wr-window-taskbar wr-window-taskbar--${this.position()}`);\n\n /** One row per entry of `items()`, in the same order. */\n private readonly tabs = viewChildren<ElementRef<HTMLElement>>('tab');\n\n constructor() {\n // So a window minimized with focus inside can hand it to its tab here, and\n // a window closed from its tab knows the focus there was its own.\n const unregister = this.manager._registerTaskbar({\n tabFor: ref => {\n const index = this.items().indexOf(ref);\n return index < 0 ? null : (this.tabs()[index]?.nativeElement ?? null);\n },\n });\n inject(DestroyRef).onDestroy(unregister);\n }\n\n /** A window with no title still needs a name in the rail. */\n protected tabTitle(ref: WrWindowRef<unknown, unknown>): string {\n return ref.title() || this.untitled();\n }\n\n protected restore(ref: WrWindowRef<unknown, unknown>): void {\n ref.restore();\n ref.focus();\n // The tab this was pressed on is about to leave the rail, which would drop\n // focus on `<body>`: it goes into the window instead, by the same rule as\n // opening one.\n ref._doFocusInitial?.();\n }\n\n protected close(ref: WrWindowRef<unknown, unknown>, event: Event): void {\n event.stopPropagation();\n void ref.close();\n }\n}\n","@if (items().length > 0) {\n <div class=\"wr-window-taskbar__rail\">\n @for (ref of items(); track ref.id) {\n <!--\n Two SIBLING buttons in a plain container, not a close button nested\n inside the tab. The close used to be a `role=\"button\"` span with\n `tabindex=\"0\"` inside the tab's own `<button>` — interactive content\n inside interactive content, which the HTML parser and `nested-interactive`\n both object to. Nothing caught it: a taskbar tab exists only while a\n window is minimized, and the a11y sweep reads prerendered HTML, where the\n rail is not rendered at all.\n -->\n <div #tab class=\"wr-window-taskbar__tab\">\n <button\n type=\"button\"\n class=\"wr-window-taskbar__tab-restore\"\n [attr.aria-label]=\"restoreLabel({ title: tabTitle(ref) })\"\n (click)=\"restore(ref)\"\n >\n <span class=\"wr-window-taskbar__tab-title\">{{ tabTitle(ref) }}</span>\n </button>\n <button\n type=\"button\"\n class=\"wr-window-taskbar__tab-close\"\n [attr.aria-label]=\"closeLabel()\"\n (click)=\"close(ref, $event)\"\n >\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M1 1 L9 9 M9 1 L1 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </button>\n </div>\n }\n </div>\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-window.mjs","names":["NO_OVERRIDE","NO_RESERVE"],"sources":["../../../projects/lib/window/tokens.ts","../../../projects/lib/window/storage-key.ts","../../../projects/lib/window/window.ts","../../../projects/lib/window/window.html","../../../projects/lib/window/window-container.ts","../../../projects/lib/window/window-container.html","../../../projects/lib/window/window-model.ts","../../../projects/lib/window/window-ref.ts","../../../projects/lib/window/services/window-manager.ts","../../../projects/lib/window/window-taskbar.ts","../../../projects/lib/window/window-taskbar.html","../../../projects/lib/window/with-windows.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrWindowDefaults } from './types';\nimport type { WrWindowRef } from './window-ref';\n\n/** Resolves to the active `WrWindowRef` inside a programmatically-opened window's content tree. */\nexport const WR_WINDOW_REF = new InjectionToken<WrWindowRef<unknown, unknown>>('WR_WINDOW_REF');\n\n/** Resolves to the `data` passed in `WrWindowConfig.data`. */\nexport const WR_WINDOW_DATA = new InjectionToken<unknown>('WR_WINDOW_DATA');\n\n/** What `withWindows()` provides. @internal */\nexport const WR_WINDOW_DEFAULTS = new InjectionToken<WrWindowDefaults>('WR_WINDOW_DEFAULTS');\n","import type { WrWindowStorageConfig } from './types';\n\n/** Namespaced localStorage key for a persisted window / workspace. */\nexport function storageKey(cfg: WrWindowStorageConfig): string {\n const prefix = cfg.prefix ? `${cfg.prefix}:` : '';\n return `wr:window:${prefix}${cfg.key}`;\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { FocusTrapFactory } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport type { ComponentType } from '@angular/cdk/portal';\nimport { NgComponentOutlet, NgTemplateOutlet } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n type Injector,\n type OnInit,\n TemplateRef,\n ViewEncapsulation,\n computed,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\nimport { randomId } from 'ngwr/utils';\n\nimport { WrWindowManager } from './services/window-manager';\nimport type { WrWindowResolvedOs, WrWindowSlotContent, WrWindowSlotContext, WrWindowSnapTarget } from './types';\nimport type { WrWindowKeyboardMode, WrWindowModel } from './window-model';\nimport type { WrWindowRef } from './window-ref';\n\n/**\n * Stands in for the consumer input `useI18nText` expects. The chrome buttons take no\n * label input — they are icon-only OS affordances — but their names still have to\n * come from the catalog rather than from the template, which is where they used to\n * live as English literals.\n */\nconst NO_OVERRIDE = signal<string | null>(null).asReadonly();\n\n/**\n * Best-effort OS detection — runs once at module load. Looks at the\n * new `navigator.userAgentData.platform` first (Chromium, no UA\n * sniffing required), falls back to `navigator.platform` /\n * `navigator.userAgent`. SSR-safe — returns `'windows'` when there's\n * no `window`.\n */\nfunction detectOs(): WrWindowResolvedOs {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') return 'windows';\n\n const uaData = (navigator as unknown as { userAgentData?: { platform?: string } }).userAgentData;\n // First non-empty source — `??` alone would keep an empty platform\n // string and skip the user-agent fallback.\n const candidates = [uaData?.platform, navigator.platform, navigator.userAgent];\n const platform = (candidates.find(v => !!v) ?? '').toLowerCase();\n if (\n platform.includes('mac') ||\n platform.includes('darwin') ||\n platform.includes('iphone') ||\n platform.includes('ipad')\n ) {\n return 'macos';\n }\n if (platform.includes('linux') || platform.includes('x11') || platform.includes('cros')) return 'linux';\n return 'windows';\n}\n\nconst DETECTED_OS = detectOs();\n\n/** How close to an edge of the work area the pointer has to be to snap there. */\nconst SNAP_HOT_ZONE = 12;\n\n/** How far a drag on a maximized or snapped window travels before the window restores under it. */\nconst DRAG_THRESHOLD = 4;\n\n/**\n * What never starts a drag, even inside a `dragHandle`: a press on a control is\n * for the control. Checked only up to the window's own element.\n */\nconst INTERACTIVE =\n 'button, input, select, textarea, a[href], label, [contenteditable]:not([contenteditable=\"false\"]), ' +\n '[role=\"button\"], [role=\"link\"], [role=\"checkbox\"], [role=\"switch\"], [role=\"radio\"], [role=\"slider\"], ' +\n '[role=\"spinbutton\"], [role=\"textbox\"], [role=\"combobox\"], [role=\"tab\"], [role=\"menuitem\"], [role=\"option\"]';\n\ninterface Edges {\n readonly t?: boolean;\n readonly r?: boolean;\n readonly b?: boolean;\n readonly l?: boolean;\n}\n\nfunction asTemplate(content: WrWindowSlotContent | null): TemplateRef<WrWindowSlotContext> | null {\n return content instanceof TemplateRef ? content : null;\n}\n\nfunction asComponent(content: WrWindowSlotContent | null): ComponentType<unknown> | null {\n return content && !(content instanceof TemplateRef) ? content : null;\n}\n\n/**\n * Internal rendering primitive for a single floating window.\n *\n * Not part of the public API — windows are opened through\n * `WrWindowManager.open(Component, config)`, which creates the window's\n * `WrWindowModel` and portals this component to draw it. Every state and\n * geometry change goes through the model; this component turns pointer and\n * key events into calls on it and owns the DOM-only parts: focus and the live\n * region.\n *\n * @internal\n */\n@Component({\n selector: 'wr-window',\n templateUrl: './window.html',\n encapsulation: ViewEncapsulation.None,\n imports: [NgTemplateOutlet, NgComponentOutlet],\n host: {\n role: 'dialog',\n // Focusable by script, never by Tab: it is where focus lands when the\n // window opens with no control in its body, and it is what a click on the\n // window's own surface focuses, so the window the user is in is the one\n // `WrWindowManager` hands Escape to.\n tabindex: '-1',\n '[class]': 'classes()',\n '[style.left.px]': 'rect().left',\n '[style.top.px]': 'rect().top',\n '[style.width.px]': 'rect().width',\n '[style.height.px]': 'rect().height',\n '[style.z-index]': 'model().z()',\n '[attr.aria-labelledby]': 'titleId',\n '(pointerdown)': 'onPointerDown($event)',\n '(dblclick)': 'onBodyDblClick($event)',\n '(keydown)': 'onKeydown($event)',\n '(focusin)': 'onFocusIn($event)',\n '(focusout)': 'onFocusOut($event)',\n },\n})\nexport class WrWindow implements OnInit {\n /** The window's state and geometry. */\n readonly model = input.required<WrWindowModel>();\n /** The ref, handed to slot templates as `$implicit` and to the manager on activation. */\n readonly windowRef = input<WrWindowRef<unknown, unknown> | null>(null);\n /** The window's injector — what a slot component resolves `WR_WINDOW_REF` from. */\n readonly injector = input<Injector | undefined>(undefined);\n /** Content for the title bar, between the title and the buttons. */\n readonly titleExtra = input<WrWindowSlotContent | null>(null);\n /** Content for the status bar. */\n readonly statusBar = input<WrWindowSlotContent | null>(null);\n\n /**\n * A REQUEST to close, not the close itself. `WrWindowContainer` binds\n * `(closed)` to `WrWindowRef.close()`, which awaits the `beforeClose` hook and\n * — only if the hook agrees — disposes the overlay, so the owner is what takes\n * the window away and this component never has to hide itself.\n */\n readonly closed = output<void>();\n\n /** Auto-generated id for the title element, referenced by `aria-labelledby`. */\n protected readonly titleId = randomId('wr-window-title');\n\n // `window.close` had been sitting in both catalogs unread while the template\n // hard-coded the same English beside it; the other four had no key at all, so a\n // Russian app announced four of its five window buttons in English.\n protected readonly closeLabel = useI18nText(NO_OVERRIDE, 'window.close', 'Close');\n private readonly minimizeLabel = useI18nText(NO_OVERRIDE, 'window.minimize', 'Minimize');\n private readonly maximizeLabel = useI18nText(NO_OVERRIDE, 'window.maximize', 'Maximize');\n private readonly restoreLabel = useI18nText(NO_OVERRIDE, 'window.restore', 'Restore');\n private readonly restoreDownLabel = useI18nText(NO_OVERRIDE, 'window.restoreDown', 'Restore down');\n // The taskbar has named an untitled window this way since v13; the window\n // itself announced an empty name — `aria-labelledby` pointing at nothing.\n private readonly untitled = useI18nText(NO_OVERRIDE, 'window.untitled', 'Untitled');\n private readonly moveModeText = useI18nText(\n NO_OVERRIDE,\n 'window.moveMode',\n 'Moving the window. Use the arrow keys, Enter to finish, Escape to cancel.'\n );\n private readonly resizeModeText = useI18nText(\n NO_OVERRIDE,\n 'window.resizeMode',\n 'Resizing the window. Use the arrow keys, Enter to finish, Escape to cancel.'\n );\n private readonly movedText = useI18nFormatter('window.moved', 'Window moved to {{x}}, {{y}}');\n private readonly resizedText = useI18nFormatter('window.resized', 'Window resized to {{width}} by {{height}}');\n\n private readonly manager = inject(WrWindowManager);\n private readonly elRef = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly focusTraps = inject(FocusTrapFactory);\n private readonly dir = inject(Directionality, { optional: true });\n\n /** Ends the pointer move in progress, if any: its listeners are on the document. */\n private endMove: (() => void) | null = null;\n\n constructor() {\n // A window closed in the middle of a drag (a shortcut, the app) must not\n // leave its listeners on the document, writing to a model nobody draws.\n inject(DestroyRef).onDestroy(() => this.endMove?.());\n }\n\n /** What the live region says: written by the keyboard modes only. */\n protected readonly announcement = signal('');\n\n /** The control focus was on last, so switching back to the window lands there. */\n private lastFocused: HTMLElement | null = null;\n\n protected readonly state = computed(() => this.model().state());\n protected readonly rect = computed(() => this.model().rect());\n private readonly options = computed(() => this.model().options());\n\n protected readonly displayTitle = computed(() => this.model().title() || this.untitled());\n\n /** Resolved OS — `auto` → detected platform. */\n readonly resolvedOs = computed<WrWindowResolvedOs>(() => {\n const os = this.options().os;\n return os === 'auto' ? DETECTED_OS : os;\n });\n\n /**\n * Whether each control is rendered: the option wins, the chrome decides the\n * default. Linux is close-only unless asked otherwise. Minimize does NOT hang\n * on a `<wr-window-taskbar>` being on the page: an app may list minimized\n * windows in a dock of its own from `WrWindowManager.minimized()`, and the\n * macOS chrome never drops a light.\n */\n protected readonly minimizeVisible = computed(() => this.options().showMinimize ?? this.resolvedOs() !== 'linux');\n protected readonly maximizeVisible = computed(() => this.options().showMaximize ?? this.resolvedOs() !== 'linux');\n protected readonly showClose = computed(() => this.options().showClose);\n\n /**\n * How many caption buttons are drawn. The macOS chrome centres its title on\n * the whole bar by padding it as wide as the cluster on the other side, and a\n * window without one of the lights has a narrower cluster.\n */\n protected readonly actionCount = computed(\n () => Number(this.minimizeVisible()) + Number(this.maximizeVisible()) + Number(this.showClose())\n );\n\n /** The minimize button doubles as restore, and says which it is. */\n protected readonly minimizeActionLabel = computed(() =>\n this.state() === 'minimized' ? this.restoreLabel() : this.minimizeLabel()\n );\n\n /** Same for maximize, whose restore has its own wording. */\n protected readonly maximizeActionLabel = computed(() =>\n this.state() === 'maximized' ? this.restoreDownLabel() : this.maximizeLabel()\n );\n\n protected readonly resizeHandles = computed(() => this.options().resizable && this.state() === 'normal');\n\n protected readonly classes = computed(() => {\n const model = this.model();\n const parts = [\n 'wr-window',\n `wr-window--${this.state()}`,\n `wr-window--os-${this.resolvedOs()}`,\n `wr-window--chrome-${this.options().chromeSize}`,\n model.isActive() ? 'wr-window--active' : 'wr-window--inactive',\n ];\n if (this.resizeHandles()) parts.push('wr-window--resizable');\n if (!this.options().animations) parts.push('wr-window--no-anim');\n const mode = model.keyboardMode();\n if (mode) parts.push(mode === 'move' ? 'wr-window--keyboard-moving' : 'wr-window--keyboard-resizing');\n return parts.join(' ');\n });\n\n protected readonly titleExtraTemplate = computed(() => asTemplate(this.titleExtra()));\n protected readonly titleExtraComponent = computed(() => asComponent(this.titleExtra()));\n protected readonly statusBarTemplate = computed(() => asTemplate(this.statusBar()));\n protected readonly statusBarComponent = computed(() => asComponent(this.statusBar()));\n protected readonly slotContext = computed<WrWindowSlotContext | null>(() => {\n const ref = this.windowRef();\n return ref ? { $implicit: ref } : null;\n });\n\n ngOnInit(): void {\n this.model().element = this.elRef.nativeElement;\n }\n\n // Chrome actions\n\n protected close(): void {\n this.closed.emit();\n }\n\n protected minimize(): void {\n this.model().minimize();\n }\n\n protected maximize(): void {\n this.model().maximize();\n }\n\n // Focus\n\n /**\n * Move focus into the window: to `[cdkFocusInitial]` or the first control in\n * its body — the CDK's rule, the one `WrDialog` and `WrDrawer` follow — else\n * to the window itself. The chrome buttons are not candidates: landing on\n * Close, the first of them on macOS, is the one place a window must not open\n * onto. Called after a render, by the container.\n *\n * @internal\n */\n focusInitial(): void {\n const host = this.elRef.nativeElement;\n if (!host.isConnected || this.state() === 'minimized') return;\n const body = host.querySelector<HTMLElement>('.wr-window__body');\n if (body) {\n // `deferAnchors`: no anchors go into the page, and nothing is trapped.\n const finder = this.focusTraps.create(body, true);\n const moved = finder.focusInitialElement({ preventScroll: true });\n finder.destroy();\n if (moved) return;\n }\n host.focus({ preventScroll: true });\n }\n\n /**\n * Move focus back to the control the window had last, the way a desktop\n * returns to a window — its first control when it never had one, or when that\n * one is gone or disabled.\n *\n * @internal\n */\n focusLast(): void {\n const host = this.elRef.nativeElement;\n if (!host.isConnected || this.state() === 'minimized') return;\n const last = this.lastFocused;\n if (last?.isConnected && host.contains(last)) {\n last.focus({ preventScroll: true });\n if (host.ownerDocument.activeElement === last) return;\n }\n this.focusInitial();\n }\n\n protected onFocusIn(event: FocusEvent): void {\n const target = event.target;\n if (!(target instanceof HTMLElement) || target === this.elRef.nativeElement) return;\n // Not the chrome buttons: a click on minimize focuses it, and coming back\n // from the taskbar onto the minimize button is not coming back to the window.\n if (target.closest('.wr-window__chrome-action')) return;\n this.lastFocused = target;\n }\n\n protected onFocusOut(event: FocusEvent): void {\n const next = event.relatedTarget;\n // Focus leaving the window ends keyboard move or resize where it is, the\n // same as Enter: a mode that outlived its focus would steal the arrow keys\n // the next time the user came back.\n if (this.model().keyboardMode() && !(next instanceof Node && this.elRef.nativeElement.contains(next))) {\n this.commitKeyboard();\n }\n }\n\n // Pointer\n\n /**\n * Every press inside the window activates it. A press on a grab area — the\n * title bar, or a `dragHandle` — also starts a move, and moves focus into the\n * window itself: the move's `preventDefault()` stops the browser doing it, and\n * left alone the window the user just clicked to the front was not the one\n * that had the keyboard, so Escape closed the window behind it.\n */\n protected onPointerDown(event: PointerEvent): void {\n const model = this.model();\n if (model.keyboardMode()) this.commitKeyboard();\n const target = event.target instanceof Element ? event.target : null;\n const primary = event.button === 0;\n const grab = primary && !!target && this.isGrabArea(target);\n // A minimized window is `display: none`, so a press cannot reach it in a\n // browser; a synthetic one must not bring it back either.\n if (model.state() === 'minimized') return;\n const ref = this.windowRef();\n if (ref) this.manager._activate(ref, { focus: grab });\n if (grab) this.startMove(event);\n }\n\n /** Whether a press on `target` should start a move. */\n private isGrabArea(target: Element): boolean {\n const host = this.elRef.nativeElement;\n if (target.closest('.wr-window__chrome-action, .wr-window__handle')) return false;\n const control = target.closest(INTERACTIVE);\n if (control && host.contains(control)) return false;\n const handle = this.options().dragHandle;\n if (handle) {\n const match = target.closest(handle);\n return !!match && host.contains(match);\n }\n return !!target.closest('.wr-window__chrome');\n }\n\n /**\n * Where a double-click toggles maximize: the title bar, whatever `dragHandle`\n * says — on every desktop the bar maximizes even where it does not drag — and\n * any other grab area. Never a control or a caption button.\n */\n private isDblClickArea(target: Element): boolean {\n const host = this.elRef.nativeElement;\n if (target.closest('.wr-window__chrome-action, .wr-window__handle')) return false;\n const control = target.closest(INTERACTIVE);\n if (control && host.contains(control)) return false;\n const chrome = target.closest('.wr-window__chrome');\n return (!!chrome && host.contains(chrome)) || this.isGrabArea(target);\n }\n\n /**\n * Move the window with the pointer. The listeners go on the DOCUMENT and\n * pointer capture is taken only once the press has travelled past the drag\n * threshold, and then on the element that was pressed, never on the window.\n * Chromium sends `click` and `dblclick` to the capturing element, so a\n * capture taken on the window at press time sent every click in the title\n * bar to the window instead: the double-click that maximizes stopped\n * working, and a clickable badge in `titleExtra` never heard its click. A\n * press that stays put now keeps both, and a real drag swallows the click it\n * would otherwise end in, so dragging by a badge does not also press it.\n */\n private startMove(event: PointerEvent): void {\n const model = this.model();\n const o = model.options();\n const state = model.state();\n if (!o.movable || state === 'minimized') return;\n if (state === 'maximized' && !o.restoreOnDrag) return;\n event.preventDefault();\n this.endMove?.();\n const host = this.elRef.nativeElement;\n const doc = host.ownerDocument;\n const pressed = event.target instanceof Element ? event.target : host;\n const pointerId = event.pointerId;\n\n const originX = event.clientX;\n const originY = event.clientY;\n const start = model.rect();\n // A maximized or snapped window does not move until the drag has gone\n // somewhere: a click or a double-click on its title bar must not restore it.\n let detached = state === 'normal' && !model.snap();\n if (!detached && !o.restoreOnDrag) {\n model.unsnapInPlace();\n detached = true;\n }\n let startX = model.x();\n let startY = model.y();\n /** Past the threshold: a drag rather than a click, from here on. */\n let dragging = false;\n\n const move = (e: PointerEvent): void => {\n if (e.pointerId !== pointerId) return;\n const dx = e.clientX - originX;\n const dy = e.clientY - originY;\n if (!dragging && Math.hypot(dx, dy) >= DRAG_THRESHOLD) {\n dragging = true;\n // Keeps the moves coming over an iframe in the body. Optional, since\n // jsdom implements no pointer capture, and guarded, since a synthetic\n // pointer the browser never saw is refused with a `NotFoundError`.\n try {\n pressed.setPointerCapture?.(pointerId);\n } catch {\n // The document listeners carry the drag without it.\n }\n }\n if (!detached) {\n if (!dragging) return;\n // Restore the window's own size under the pointer, keeping the grab\n // point at the same fraction of the bar — what Windows, macOS and GNOME\n // all do. The snapped or maximized size was never the window's own.\n const fraction = start.width > 0 ? (originX - start.left) / start.width : 0.5;\n model.restore();\n startX = originX - fraction * model.width();\n startY = start.top;\n detached = true;\n }\n model.setRaw({ x: startX + dx, y: startY + dy });\n model.clamp();\n model.dragTarget.set(this.detectSnapTarget(e.clientX, e.clientY));\n };\n const stop = (): void => {\n doc.removeEventListener('pointermove', move);\n doc.removeEventListener('pointerup', end);\n doc.removeEventListener('pointercancel', end);\n if (dragging && pressed.hasPointerCapture?.(pointerId)) pressed.releasePointerCapture?.(pointerId);\n model.dragTarget.set(null);\n this.endMove = null;\n };\n const end = (e: PointerEvent): void => {\n if (e.pointerId !== pointerId) return;\n const snap = model.dragTarget();\n stop();\n if (dragging) this.swallowClick(doc, pressed);\n if (!detached) return;\n if (snap) {\n model.snapTo(snap);\n if (snap !== 'top') model.resized.next({ width: model.rect().width, height: model.rect().height });\n }\n // `moved` is where the USER put the window, so a press that never moved\n // it — a click, either half of a double-click — says nothing.\n const r = model.rect();\n if (snap || r.left !== start.left || r.top !== start.top) model.moved.next({ x: r.left, y: r.top });\n };\n\n doc.addEventListener('pointermove', move);\n doc.addEventListener('pointerup', end);\n // `pointercancel` is never followed by a `pointerup` (a pen leaving range, a\n // long-press menu, an OS gesture taking over), so without this the move\n // listener outlived the drag: every later hover dragged the window. The\n // cancelled gesture's geometry is kept rather than rolled back.\n doc.addEventListener('pointercancel', end);\n this.endMove = stop;\n }\n\n /**\n * Eat the `click` a drag ends in. The browser dispatches it straight after the\n * `pointerup`, in the same task, at the element holding capture — the one the\n * drag started on — so the listener takes only a click there, and is taken\n * away at the next task rather than left to eat a real one.\n */\n private swallowClick(doc: Document, pressed: Element): void {\n const swallow = (e: Event): void => {\n if (e.target !== pressed) return;\n doc.removeEventListener('click', swallow, true);\n e.stopPropagation();\n e.preventDefault();\n };\n doc.addEventListener('click', swallow, true);\n setTimeout(() => doc.removeEventListener('click', swallow, true));\n }\n\n /** Map a pointer position to a snap target, honouring the `snap` option and the work area. */\n private detectSnapTarget(clientX: number, clientY: number): WrWindowSnapTarget | null {\n const model = this.model();\n const mode = model.options().snap;\n if (mode === 'none') return null;\n const wa = model.workArea();\n const nearLeft = clientX <= wa.left + SNAP_HOT_ZONE;\n const nearRight = clientX >= wa.left + wa.width - SNAP_HOT_ZONE;\n const nearTop = clientY <= wa.top + SNAP_HOT_ZONE;\n const nearBottom = clientY >= wa.top + wa.height - SNAP_HOT_ZONE;\n if (mode === 'all') {\n if (nearTop && nearLeft) return 'top-left';\n if (nearTop && nearRight) return 'top-right';\n if (nearBottom && nearLeft) return 'bottom-left';\n if (nearBottom && nearRight) return 'bottom-right';\n }\n if (nearTop) return 'top'; // top edge → maximise\n if (nearLeft) return 'left';\n if (nearRight) return 'right';\n return null;\n }\n\n /**\n * A double-click on the title bar maximizes, or restores a maximized or\n * snapped window. Bound on the bar itself rather than only on the host, so a\n * `dblclick` that does not bubble — which is what a harness dispatches — still\n * reaches it.\n *\n * The gate is `showMaximize !== false`, NOT `maximizeVisible()`, and the\n * difference is a window nobody can get out of: the Linux preset hides the\n * maximize BUTTON, but the gesture is how GNOME maximizes, and `maximized` is\n * reachable there with no button at all (a snap to the top edge,\n * `ref.maximize()`, a restored layout). An explicit `showMaximize: false`\n * still turns the gesture off everywhere.\n */\n protected onChromeDblClick(event: MouseEvent): void {\n this.toggleFromDblClick(event.target);\n }\n\n /**\n * The same gesture on a body `dragHandle`, which answers it the way the title\n * bar does. A double-click in the bar bubbles here too and is the bar's.\n */\n protected onBodyDblClick(event: MouseEvent): void {\n const target = event.target;\n if (target instanceof Element && target.closest('.wr-window__chrome')) return;\n this.toggleFromDblClick(target);\n }\n\n private toggleFromDblClick(target: EventTarget | null): void {\n // Double-clicking the maximize BUTTON is two clicks on it already; the\n // chrome toggling a third time left the window maximized. A button in\n // `titleExtra` is the same: two presses of it, not a gesture on the bar.\n if (!(target instanceof Element) || !this.isDblClickArea(target)) return;\n const model = this.model();\n if (model.state() === 'minimized') return;\n if (model.state() === 'normal' && model.snap()) {\n model.restore();\n return;\n }\n if (model.options().showMaximize !== false) model.maximize();\n }\n\n protected startResize(event: PointerEvent, edges: Edges): void {\n const model = this.model();\n if (!model.options().resizable || model.state() !== 'normal') return;\n event.preventDefault();\n event.stopPropagation();\n if (model.keyboardMode()) this.commitKeyboard();\n const ref = this.windowRef();\n if (ref) this.manager._activate(ref, { focus: true });\n model.unsnapInPlace();\n const target = event.currentTarget as HTMLElement;\n target.setPointerCapture?.(event.pointerId);\n\n const startX = model.x();\n const startY = model.y();\n const startW = model.width();\n const startH = model.height();\n const originX = event.clientX;\n const originY = event.clientY;\n\n const move = (e: PointerEvent): void => {\n const o = model.options();\n const dx = e.clientX - originX;\n const dy = e.clientY - originY;\n\n let nextX = startX;\n let nextY = startY;\n let nextW = startW;\n let nextH = startH;\n\n if (edges.r) nextW = startW + dx;\n if (edges.b) nextH = startH + dy;\n if (edges.l) {\n nextW = startW - dx;\n nextX = startX + dx;\n }\n if (edges.t) {\n nextH = startH - dy;\n nextY = startY + dy;\n }\n\n // Enforce min/max — when shrinking from left/top we have to fix the position too.\n const clampedW = Math.min(o.maxWidth, Math.max(o.minWidth, nextW));\n const clampedH = Math.min(o.maxHeight, Math.max(o.minHeight, nextH));\n if (edges.l) nextX += nextW - clampedW;\n if (edges.t) nextY += nextH - clampedH;\n\n model.setRaw({ x: nextX, y: nextY, width: clampedW, height: clampedH });\n model.clamp();\n };\n const cleanup = (e: PointerEvent): void => {\n target.releasePointerCapture?.(e.pointerId);\n target.removeEventListener('pointermove', move);\n target.removeEventListener('pointerup', cleanup);\n target.removeEventListener('pointercancel', cleanup);\n model.resized.next({ width: model.width(), height: model.height() });\n };\n\n target.addEventListener('pointermove', move);\n target.addEventListener('pointerup', cleanup);\n // Same cancelled-gesture leak as `startMove` — a resize handle that is\n // still listening for `pointermove` resizes the window on a bare hover.\n target.addEventListener('pointercancel', cleanup);\n }\n\n // Bound resize handlers for the template — avoids inline object literals\n // re-creating on every change-detection tick.\n protected resizeTL = (e: PointerEvent): void => this.startResize(e, { t: true, l: true });\n protected resizeT = (e: PointerEvent): void => this.startResize(e, { t: true });\n protected resizeTR = (e: PointerEvent): void => this.startResize(e, { t: true, r: true });\n protected resizeR = (e: PointerEvent): void => this.startResize(e, { r: true });\n protected resizeBR = (e: PointerEvent): void => this.startResize(e, { b: true, r: true });\n protected resizeB = (e: PointerEvent): void => this.startResize(e, { b: true });\n protected resizeBL = (e: PointerEvent): void => this.startResize(e, { b: true, l: true });\n protected resizeL = (e: PointerEvent): void => this.startResize(e, { l: true });\n\n // Keyboard move and resize\n\n /**\n * Alt+F7 moves and Alt+F8 resizes — the keys Windows has used for both since\n * Windows 3, and what GNOME and KDE bind too. Move and resize used to be\n * drag-only, which is a WCAG 2.1.1 failure on its own.\n */\n protected onKeydown(event: KeyboardEvent): void {\n if (this.model().keyboardMode()) {\n this.onModeKey(event);\n return;\n }\n if (event.defaultPrevented || !event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;\n if (event.key !== 'F7' && event.key !== 'F8') return;\n if (this.startKeyboard(event.key === 'F7' ? 'move' : 'resize')) event.preventDefault();\n }\n\n /**\n * Enter keyboard move or resize, with focus in the window so the keys arrive.\n * Returns `false` when the window may not be moved or resized.\n *\n * @internal\n */\n startKeyboard(mode: WrWindowKeyboardMode): boolean {\n const model = this.model();\n const ref = this.windowRef();\n if (ref) this.manager._activate(ref, { focus: false });\n if (!model.startKeyboard(mode)) return false;\n // Onto the window itself for the length of the mode, the way a desktop\n // does it: left on a button in the body, the Enter that ends the mode\n // pressed the button as well — and \"Close\" closed the window.\n this.elRef.nativeElement.focus({ preventScroll: true });\n this.announce(mode === 'move' ? this.moveModeText() : this.resizeModeText());\n return true;\n }\n\n private onModeKey(event: KeyboardEvent): void {\n const model = this.model();\n const step = event.shiftKey ? 1 : model.options().keyboardStep;\n const arrows: Record<string, readonly [number, number]> = {\n ArrowLeft: [-step, 0],\n ArrowRight: [step, 0],\n ArrowUp: [0, -step],\n ArrowDown: [0, step],\n };\n const delta = arrows[event.key];\n if (delta) {\n event.preventDefault();\n if (model.keyboardMode() === 'move') {\n model.nudge(delta[0], delta[1]);\n } else {\n // The inline end edge moves: in a right-to-left page that is the left\n // one, so the arrow pointing away from the window still grows it.\n const rtl = this.dir?.value === 'rtl';\n model.grow(rtl ? -delta[0] : delta[0], delta[1], rtl);\n }\n return;\n }\n if (event.key === 'Enter') {\n event.preventDefault();\n this.commitKeyboard();\n this.focusLast();\n } else if (event.key === 'Escape') {\n // Claimed, so the manager's Escape does not close the window as well.\n event.preventDefault();\n const mode = model.cancelKeyboard();\n if (mode) this.announceGeometry(mode);\n this.focusLast();\n } else if (event.key === 'Tab') {\n this.commitKeyboard();\n }\n }\n\n /** Keep what the keyboard mode did, and say so. Focus is the caller's business. */\n private commitKeyboard(): void {\n const mode = this.model().commitKeyboard();\n if (mode) this.announceGeometry(mode);\n }\n\n private announceGeometry(mode: WrWindowKeyboardMode): void {\n const r = this.model().rect();\n this.announce(\n mode === 'move' ? this.movedText({ x: r.left, y: r.top }) : this.resizedText({ width: r.width, height: r.height })\n );\n }\n\n private announce(text: string): void {\n this.announcement.set(text);\n }\n}\n","<!--\n No pointerdown here: the host takes every press, so a `dragHandle` in the body\n can start a move as well as the title bar, and a press anywhere activates the\n window. The double-click is bound here and on the host; see `onChromeDblClick`.\n The action count is for the macOS chrome, which pads its title as wide as the\n cluster so the title centres on the whole bar.\n-->\n<div\n class=\"wr-window__chrome\"\n [style.--wr-window-chrome-action-count]=\"actionCount()\"\n (dblclick)=\"onChromeDblClick($event)\"\n>\n <div class=\"wr-window__title\" [attr.id]=\"titleId\">{{ displayTitle() }}</div>\n <div class=\"wr-window__title-extra\">\n @if (titleExtraTemplate(); as template) {\n <ng-container *ngTemplateOutlet=\"template; context: slotContext(); injector: injector()\" />\n } @else if (titleExtraComponent(); as component) {\n <ng-container *ngComponentOutlet=\"component; injector: injector()\" />\n }\n </div>\n\n <div class=\"wr-window__chrome-actions\">\n @if (resolvedOs() === 'macos') {\n <!--\n macOS traffic lights: close, minimize, zoom, in that order from the frame\n edge. The button is the hit target and the coloured dot is its\n `::before`, so the box can be big enough to press while the dot stays\n the platform's size. The glyphs sit on an 8px grid and appear only while\n the cluster is hovered or holds keyboard focus, as they do on macOS.\n Zoom draws the full-screen arrows of Big Sur and later: pointing out to\n maximize, pointing in to restore. Every straight edge of both sits on a\n whole pixel, so the filled triangles stay hard at 1x.\n -->\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--close\"\n [attr.aria-label]=\"closeLabel()\"\n (click)=\"close()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" aria-hidden=\"true\">\n <path d=\"M1.5 1.5l5 5m0-5l-5 5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n @if (minimizeVisible()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--minimize\"\n [attr.aria-label]=\"minimizeActionLabel()\"\n (click)=\"minimize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" aria-hidden=\"true\">\n <path d=\"M1.5 3.5h5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n @if (maximizeVisible()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--maximize\"\n [attr.aria-label]=\"maximizeActionLabel()\"\n (click)=\"maximize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" aria-hidden=\"true\">\n @if (state() === 'maximized') {\n <path d=\"M3 3V.5L.5 3zM5 5v2.5L7.5 5z\" fill=\"currentColor\" />\n } @else {\n <path d=\"M1 1h4L1 5zm6 6H3l4-4z\" fill=\"currentColor\" />\n }\n </svg>\n </button>\n }\n } @else if (resolvedOs() === 'linux') {\n <!--\n GNOME (libadwaita) window controls: round buttons with Adwaita's 16px\n symbolic glyphs, 2px strokes on whole pixels. Restore is the SMALLER\n square, the way Adwaita draws it, not a second overlapping one. Close-only\n is the DEFAULT here, not a rule: `minimizeVisible()` resolves the input\n first, so `[showMinimize]=\"true\"` puts the button back, which is the only\n way a user on Linux can reach `<wr-window-taskbar>` at all.\n -->\n @if (minimizeVisible()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--minimize\"\n [attr.aria-label]=\"minimizeActionLabel()\"\n (click)=\"minimize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M4 11h8\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" />\n </svg>\n </button>\n }\n @if (maximizeVisible()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--maximize\"\n [attr.aria-label]=\"maximizeActionLabel()\"\n (click)=\"maximize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n @if (state() === 'maximized') {\n <rect x=\"6\" y=\"6\" width=\"4\" height=\"4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" />\n } @else {\n <rect x=\"5\" y=\"5\" width=\"6\" height=\"6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" />\n }\n </svg>\n </button>\n }\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--close\"\n [attr.aria-label]=\"closeLabel()\"\n (click)=\"close()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M5 5l6 6m0-6l-6 6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n } @else {\n <!--\n Windows 11 caption buttons: 10px glyphs in the full-height, 46px-wide\n buttons, drawn the way Segoe Fluent Icons draws them. 1px strokes on half\n pixels, so they land on whole device pixels at 1x and 2x, and the corners\n of maximize and restore are rounded by 1px.\n -->\n @if (minimizeVisible()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--minimize\"\n [attr.aria-label]=\"minimizeActionLabel()\"\n (click)=\"minimize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M0 4.5h10\" fill=\"none\" stroke=\"currentColor\" />\n </svg>\n </button>\n }\n @if (maximizeVisible()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--maximize\"\n [attr.aria-label]=\"maximizeActionLabel()\"\n (click)=\"maximize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n @if (state() === 'maximized') {\n <g fill=\"none\" stroke=\"currentColor\">\n <rect x=\".5\" y=\"2.5\" width=\"7\" height=\"7\" rx=\"1\" />\n <path d=\"M2.5 2.5v-1a1 1 0 0 1 1-1h5a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-1\" />\n </g>\n } @else {\n <rect x=\".5\" y=\".5\" width=\"9\" height=\"9\" rx=\"1\" fill=\"none\" stroke=\"currentColor\" />\n }\n </svg>\n </button>\n }\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--close\"\n [attr.aria-label]=\"closeLabel()\"\n (click)=\"close()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M.5.5l9 9m0-9l-9 9\" fill=\"none\" stroke=\"currentColor\" />\n </svg>\n </button>\n }\n }\n </div>\n</div>\n\n<div class=\"wr-window__body\">\n <ng-content />\n</div>\n\n<div class=\"wr-window__status-bar\">\n @if (statusBarTemplate(); as template) {\n <ng-container *ngTemplateOutlet=\"template; context: slotContext(); injector: injector()\" />\n } @else if (statusBarComponent(); as component) {\n <ng-container *ngComponentOutlet=\"component; injector: injector()\" />\n }\n</div>\n\n<!--\n Keyboard move and resize say what they did here: the mode on entry, the\n landing on Enter or Escape. Not each step — that would flood the region.\n-->\n<p class=\"wr-window__sr-only\" role=\"status\">{{ announcement() }}</p>\n\n@if (resizeHandles()) {\n <span class=\"wr-window__handle wr-window__handle--t\" (pointerdown)=\"resizeT($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--r\" (pointerdown)=\"resizeR($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--b\" (pointerdown)=\"resizeB($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--l\" (pointerdown)=\"resizeL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--tl\" (pointerdown)=\"resizeTL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--tr\" (pointerdown)=\"resizeTR($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--bl\" (pointerdown)=\"resizeBL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--br\" (pointerdown)=\"resizeBR($event)\"></span>\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type ComponentType } from '@angular/cdk/portal';\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n Injector,\n ViewContainerRef,\n ViewEncapsulation,\n afterNextRender,\n effect,\n inject,\n runInInjectionContext,\n untracked,\n viewChild,\n} from '@angular/core';\n\nimport { WrStorage } from 'ngwr/storage';\n\nimport { WrWindowManager } from './services/window-manager';\nimport { storageKey } from './storage-key';\nimport type { WrWindowConfig } from './types';\nimport { WrWindow } from './window';\nimport type { WrWindowRef } from './window-ref';\n\n/** Coalesce live position/size writes — drag/resize fires every move. */\nconst PERSIST_DEBOUNCE_MS = 200;\n\n/** What `storage` keeps — the geometry the user chose, never what a state imposes. @internal */\nexport interface PersistedGeometry {\n readonly x?: number;\n readonly y?: number;\n readonly width?: number;\n readonly height?: number;\n}\n\n/**\n * Internal host attached by `WrWindowManager.open()`. Draws a `<wr-window>` for\n * the ref's model, creates the consumer's component inside its body, and wires\n * the DOM-only parts of the ref — focus and keyboard mode — once it is on the\n * page. State and geometry need no wiring: the ref reads the model directly.\n *\n * @internal\n */\n@Component({\n selector: 'wr-window-container',\n templateUrl: './window-container.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [WrWindow],\n})\nexport class WrWindowContainer<C> {\n /** Set by the manager before view init. */\n config!: WrWindowConfig;\n /** Set by the manager before view init. */\n ref!: WrWindowRef<C, unknown>;\n /** Set by the manager before view init. */\n componentType!: ComponentType<C>;\n /** Custom injector with `WR_WINDOW_REF` / `WR_WINDOW_DATA` populated. */\n childInjector!: Injector;\n /** Set by the manager: move focus into the window once it has rendered. */\n autoFocus = true;\n\n private readonly hostInjector = inject(Injector);\n private readonly manager = inject(WrWindowManager);\n private readonly storage = inject(WrStorage);\n private readonly destroyRef = inject(DestroyRef);\n private persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n private readonly contentVcr = viewChild.required('content', { read: ViewContainerRef });\n private readonly wrWindow = viewChild.required(WrWindow);\n\n constructor() {\n afterNextRender(() => this.attach());\n\n // Re-clamp when the WORK AREA changes — a resized viewport, a taskbar\n // appearing — and only then. It used to re-run on every geometry write,\n // repeating the clamp the drag handler had just done on each pointer move.\n effect(() => {\n const model = this.ref._model;\n model.workArea();\n untracked(() => model.clamp());\n });\n\n this.destroyRef.onDestroy(() => {\n if (this.persistTimer !== null) clearTimeout(this.persistTimer);\n });\n }\n\n private attach(): void {\n // 1. Create the consumer's component inside the body slot.\n const componentRef = this.contentVcr().createComponent(this.componentType, {\n injector: this.childInjector,\n });\n this.ref.componentRef = componentRef;\n\n // 2. The DOM-only bridges. After a render, not now: the consumer's\n // component was created a line above and has not drawn its template yet,\n // and a window coming back from the taskbar is still `display: none`\n // until its class updates.\n const w = this.wrWindow();\n const model = this.ref._model;\n this.ref._focusWindow = mode =>\n afterNextRender(\n () => {\n if (mode === 'initial') {\n w.focusInitial();\n return;\n }\n // Only for the window that is STILL the one switched to: two\n // activations in one tick each queue a focus, and the earlier one,\n // landing last, took the keyboard back from the window the user\n // actually ended on.\n if (this.manager.active() === (this.ref as WrWindowRef<unknown, unknown>)) w.focusLast();\n },\n { injector: this.hostInjector }\n );\n this.ref._startKeyboard = mode => {\n if (model.state() !== 'minimized') {\n w.startKeyboard(mode);\n return;\n }\n model.unminimize();\n afterNextRender(() => w.startKeyboard(mode), { injector: this.hostInjector });\n };\n model.onMinimizedWithFocus = () => this.onMinimizedWithFocus();\n // A ref outlives its window; a render hook must not be registered on an\n // injector that is gone.\n this.destroyRef.onDestroy(() => {\n this.ref._focusWindow = null;\n this.ref._startKeyboard = null;\n model.onMinimizedWithFocus = null;\n });\n\n // 3. Storage — hydration happened at open, as the initial geometry; from\n // here on, save as the geometry changes.\n if (this.config.storage) this.installAutosave();\n\n // 4. Focus — never into a window that opened straight into the taskbar.\n if (this.autoFocus && model.state() !== 'minimized') this.ref._focusWindow('initial');\n\n // 5. A keyboard mode asked for before the window was on the page.\n const pending = this.ref._pendingKeyboard;\n if (pending) {\n this.ref._pendingKeyboard = null;\n this.ref._startKeyboard(pending);\n }\n }\n\n /** The window was minimized while it held focus: hand focus to its taskbar tab. */\n private onMinimizedWithFocus(): void {\n // After the render that lists the window in the taskbar.\n afterNextRender(() => this.manager._focusAfterMinimize(this.ref as WrWindowRef<unknown, unknown>), {\n injector: this.hostInjector,\n });\n }\n\n /** Persist geometry whenever it changes, debounced. */\n private installAutosave(): void {\n const cfg = this.config.storage;\n if (!cfg) return;\n const persist = cfg.persist ?? 'all';\n const key = storageKey(cfg);\n const model = this.ref._model;\n\n runInInjectionContext(this.hostInjector, () => {\n effect(() => {\n // The raw geometry: what a maximized or snapped window goes back to,\n // and so what the user chose.\n const x = model.x();\n const y = model.y();\n const width = model.width();\n const height = model.height();\n\n if (this.persistTimer !== null) clearTimeout(this.persistTimer);\n this.persistTimer = setTimeout(() => {\n this.persistTimer = null;\n const payload: PersistedGeometry = {\n ...(persist !== 'size' ? { x, y } : {}),\n ...(persist !== 'position' ? { width, height } : {}),\n };\n this.storage.set(key, payload);\n }, PERSIST_DEBOUNCE_MS);\n });\n });\n }\n}\n","<wr-window\n [model]=\"ref._model\"\n [windowRef]=\"ref\"\n [injector]=\"childInjector\"\n [titleExtra]=\"config.titleExtra ?? null\"\n [statusBar]=\"config.statusBar ?? null\"\n (closed)=\"ref.close()\"\n #window\n>\n <ng-container #content />\n</wr-window>\n\n<!--\n The snap hint lives here, not inside `<wr-window>`: `.wr-window` clips, and a\n fixed child is clipped with it while the open animation's transform is on.\n It takes the exact box the drop will give the window, from the same model\n arithmetic, so the hint and the landing cannot disagree — they did when the\n hint was a CSS 50% of the layout viewport and the snap was half of\n `innerWidth`, 7.5px apart with a classic scrollbar showing.\n-->\n@if (ref._model.previewRect(); as box) {\n <div\n class=\"wr-window__snap-hint\"\n [attr.data-target]=\"ref._model.dragTarget()\"\n [style.left.px]=\"box.left\"\n [style.top.px]=\"box.top\"\n [style.width.px]=\"box.width\"\n [style.height.px]=\"box.height\"\n [style.z-index]=\"ref._model.z() + 1\"\n aria-hidden=\"true\"\n ></div>\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type Signal, type WritableSignal, computed, signal } from '@angular/core';\n\nimport { Subject } from 'rxjs';\n\nimport { clamp } from 'ngwr/utils';\n\nimport type {\n WrWindowChromeSize,\n WrWindowConfig,\n WrWindowOs,\n WrWindowSize,\n WrWindowSnap,\n WrWindowSnapTarget,\n WrWindowState,\n WrWindowUpdate,\n} from './types';\n\n/** What a minimized window reports as its height. It is `display: none`, so this is only a number. */\nconst MINIMIZED_HEIGHT = 40;\n\n/** A finite number, or the fallback — a `NaN` from a bad config must not reach the geometry. */\nfunction num(value: number | undefined, fallback: number): number {\n return typeof value === 'number' && !Number.isNaN(value) ? value : fallback;\n}\n\n/**\n * A rectangle in viewport pixels — the work area, a snap region, a window's box.\n *\n * @internal\n */\nexport interface WrWindowRect {\n readonly left: number;\n readonly top: number;\n readonly width: number;\n readonly height: number;\n}\n\n/** @internal A window's free-floating geometry: where it is when it is neither maximized nor snapped. */\nexport interface WrWindowGeometry {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Every option a window reads after it opens, with its default applied. The\n * ones `WrWindowRef.update()` may change are signals of this object, so an\n * update reaches the chrome and the drag code alike.\n *\n * @internal\n */\nexport interface WrWindowOptions {\n readonly os: WrWindowOs;\n readonly chromeSize: WrWindowChromeSize;\n readonly animations: boolean;\n readonly minWidth: number;\n readonly minHeight: number;\n readonly maxWidth: number;\n readonly maxHeight: number;\n readonly movable: boolean;\n readonly resizable: boolean;\n readonly keepInViewport: boolean;\n readonly snap: WrWindowSnap;\n readonly restoreOnDrag: boolean;\n readonly dragHandle: string | null;\n readonly showMinimize: boolean | null;\n readonly showMaximize: boolean | null;\n readonly showClose: boolean;\n readonly closeOnEscape: boolean;\n readonly keyboard: boolean;\n readonly keyboardStep: number;\n}\n\n/** @internal */\nexport const SIZE_PRESETS: Readonly<Record<WrWindowSize, { readonly width: number; readonly height: number }>> = {\n sm: { width: 320, height: 200 },\n md: { width: 480, height: 320 },\n lg: { width: 720, height: 480 },\n};\n\n/** Keep at least this many px of a window inside the work area, so it can be grabbed again. @internal */\nexport const MIN_ON_SCREEN = 24;\n\n/** @internal `WrWindowConfig` with every default applied. */\nexport function resolveOptions(config: WrWindowConfig): WrWindowOptions {\n return {\n os: config.os ?? 'auto',\n chromeSize: config.chromeSize ?? 'md',\n animations: config.animations ?? true,\n minWidth: num(config.minWidth, 220),\n minHeight: num(config.minHeight, 140),\n maxWidth: num(config.maxWidth, Number.POSITIVE_INFINITY),\n maxHeight: num(config.maxHeight, Number.POSITIVE_INFINITY),\n movable: config.movable ?? true,\n resizable: config.resizable ?? true,\n keepInViewport: config.keepInViewport ?? true,\n snap: config.snap ?? 'none',\n restoreOnDrag: config.restoreOnDrag ?? true,\n dragHandle: config.dragHandle ?? null,\n showMinimize: config.showMinimize ?? null,\n showMaximize: config.showMaximize ?? null,\n showClose: config.showClose ?? true,\n closeOnEscape: config.closeOnEscape ?? true,\n keyboard: config.keyboard ?? true,\n keyboardStep: Math.max(1, num(config.keyboardStep, 10)),\n };\n}\n\n/** @internal The viewport, or a stand-in on the server. */\nexport function readViewport(): { readonly width: number; readonly height: number } {\n if (typeof window === 'undefined' || typeof document === 'undefined') return { width: 1024, height: 768 };\n // `clientWidth`, not `innerWidth`: a `position: fixed` box is laid out\n // against the viewport WITHOUT its scrollbar, so with a classic 15px\n // scrollbar a window maximized to `innerWidth` ran under it, and a snap to\n // the right half started 7.5px right of the hint that promised it. jsdom\n // lays nothing out and reports 0, which is what the fallback is for.\n const root = document.documentElement;\n return { width: root.clientWidth || window.innerWidth, height: root.clientHeight || window.innerHeight };\n}\n\n/** @internal Start offset `index` windows into a cascade: 30px a step, and every ten a lap 15px along. */\nexport function cascadeOffset(index: number): { readonly x: number; readonly y: number } {\n // Ten steps then back to the start, so a cascade never walks off the\n // screen — and each lap shifted 15px ALONG ONLY, so window eleven no longer\n // opens exactly on top of window one. Shifting both axes put lap three's\n // windows exactly on lap one's, one step down the diagonal; with `x - y`\n // different for each lap, no two of the first fifty windows coincide.\n const step = 50 + (index % 10) * 30;\n return { x: step + (Math.floor(index / 10) % 5) * 15, y: step };\n}\n\n/** @internal What `seedGeometry` needs to place a window that is about to open. */\nexport interface WrWindowSeed {\n readonly options: WrWindowOptions;\n readonly workArea: WrWindowRect;\n readonly size: WrWindowSize | undefined;\n readonly x?: number;\n readonly y?: number;\n readonly width?: number;\n readonly height?: number;\n /**\n * The position came back from storage or a saved layout rather than from the\n * consumer: it is moved wholly into the work area when the window fits, the\n * way a cascade position is. A desktop's geometry restored on a phone\n * otherwise opened 1100px wide with its close button off the glass.\n */\n readonly restored?: boolean;\n /** The next cascade offset, asked for only when a coordinate is missing. */\n readonly cascade: () => { readonly x: number; readonly y: number };\n readonly rtl: boolean;\n}\n\n/**\n * Where a window opens. A window OPENS on screen when it can: the size is\n * capped at the work area (the minimum still wins, since it is the consumer's\n * floor), and a cascade or restored position is moved in until the whole box\n * fits. A coordinate the consumer passed is theirs, held only to the reach a\n * drag is held to.\n *\n * @internal\n */\nexport function seedGeometry(seed: WrWindowSeed): WrWindowGeometry {\n const { options: o, workArea: wa } = seed;\n const preset = SIZE_PRESETS[seed.size ?? 'md'];\n const keep = o.keepInViewport;\n const fit = (size: number, room: number): number => (keep ? Math.min(size, room) : size);\n const width = Math.round(clamp(fit(seed.width ?? preset.width, wa.width), o.minWidth, o.maxWidth));\n const height = Math.round(clamp(fit(seed.height ?? preset.height, wa.height), o.minHeight, o.maxHeight));\n\n let x = seed.x;\n let y = seed.y;\n let cascaded = false;\n if (x == null || y == null) {\n const offset = seed.cascade();\n cascaded = true;\n // From the START edge of the work area: the right edge in a right-to-left\n // page, where the cascade used to begin at the inline end.\n x ??= seed.rtl ? wa.left + wa.width - width - offset.x : wa.left + offset.x;\n y ??= wa.top + offset.y;\n }\n const into = cascaded || !!seed.restored;\n if (keep && (into || seed.x == null)) x = clamp(x, wa.left, Math.max(wa.left, wa.left + wa.width - width));\n if (keep && (into || seed.y == null)) y = clamp(y, wa.top, Math.max(wa.top, wa.top + wa.height - height));\n return { x: Math.round(x), y: Math.round(y), width, height };\n}\n\n/** @internal How a window was set up when it opened. */\nexport interface WrWindowModelInit {\n readonly options: WrWindowOptions;\n readonly title?: string;\n readonly geometry?: WrWindowGeometry;\n readonly state?: WrWindowState;\n readonly snap?: WrWindowSnapTarget | null;\n readonly z?: number;\n readonly workArea: Signal<WrWindowRect>;\n}\n\n/** @internal A half or a quarter: what `snap` can hold. `top` is the maximized state instead. */\nexport type WrWindowSnapRegion = Exclude<WrWindowSnapTarget, 'top'>;\n\n/** @internal What `startKeyboard` hands back for the announcement. */\nexport type WrWindowKeyboardMode = 'move' | 'resize';\n\n/**\n * One window's state and geometry, and the rules for changing them.\n *\n * Created by `WrWindowManager.open()` before anything renders, so the ref's\n * signals are right from the first read and a call made before the first render\n * — `ref.maximize()` in the same tick as `open()`, `ref.setTitle()` from the\n * body's constructor — lands instead of being dropped. The component only draws\n * it and turns pointer and key events into calls on it.\n *\n * The raw `x` / `y` / `width` / `height` are the geometry the USER chose. A\n * maximized or snapped window shows something else (`rect`), and goes back to\n * the raw geometry when it leaves that state; nothing has to be saved on the\n * way in, so a `moveTo()` made while maximized is where restore lands.\n *\n * @internal\n */\nexport class WrWindowModel {\n readonly options: WritableSignal<WrWindowOptions>;\n readonly title: WritableSignal<string>;\n readonly state: WritableSignal<WrWindowState>;\n /** The half or quarter the window occupies while `normal`. `top` is never stored: it is `maximized`. */\n readonly snap: WritableSignal<WrWindowSnapRegion | null>;\n readonly x: WritableSignal<number>;\n readonly y: WritableSignal<number>;\n readonly width: WritableSignal<number>;\n readonly height: WritableSignal<number>;\n readonly z: WritableSignal<number>;\n /** Written by the manager: whether this is the window that has the keyboard. */\n readonly isActive = signal(false);\n readonly keyboardMode = signal<WrWindowKeyboardMode | null>(null);\n /** The snap region a drag in progress would land in, for the hint. */\n readonly dragTarget = signal<WrWindowSnapTarget | null>(null);\n readonly workArea: Signal<WrWindowRect>;\n\n readonly moved = new Subject<{ readonly x: number; readonly y: number }>();\n readonly resized = new Subject<{ readonly width: number; readonly height: number }>();\n readonly stateChanges = new Subject<WrWindowState>();\n\n /** Set by the component: the `<wr-window>` element, for the focus checks. */\n element: HTMLElement | null = null;\n /** Set by the container: the window was minimized while it held focus. */\n onMinimizedWithFocus: (() => void) | null = null;\n\n /** What leaving `minimized` goes back to — a window minimized while maximized comes back maximized. */\n private restoreTo: 'normal' | 'maximized' = 'normal';\n /** The geometry keyboard mode started from, after it restored the window: what a commit compares against. */\n private keyboardStart: WrWindowGeometry | null = null;\n /** Everything keyboard mode changed on entry, so Escape can put back a maximized or snapped window too. */\n private keyboardOrigin: {\n readonly geometry: WrWindowGeometry;\n readonly state: WrWindowState;\n readonly snap: WrWindowSnapRegion | null;\n } | null = null;\n\n /** The box on screen: the raw geometry, or what the state imposes on it. */\n readonly rect: Signal<WrWindowRect> = computed(() => {\n const state = this.state();\n if (state === 'maximized') return this.maximizedRect();\n const raw = { left: this.x(), top: this.y(), width: this.width(), height: this.height() };\n if (state === 'minimized') return { ...raw, height: MINIMIZED_HEIGHT };\n const snap = this.snap();\n return snap ? this.snapRect(snap) : raw;\n });\n\n /** Where the drag in progress would land, for the snap hint. */\n readonly previewRect: Signal<WrWindowRect | null> = computed(() => {\n const target = this.dragTarget();\n return target ? this.targetRect(target) : null;\n });\n\n constructor(init: WrWindowModelInit) {\n this.options = signal(init.options);\n this.title = signal(init.title ?? '');\n this.state = signal(init.state ?? 'normal');\n this.snap = signal<WrWindowSnapRegion | null>(init.snap && init.snap !== 'top' ? init.snap : null);\n const g = init.geometry ?? { x: 0, y: 0, width: SIZE_PRESETS.md.width, height: SIZE_PRESETS.md.height };\n this.x = signal(g.x);\n this.y = signal(g.y);\n this.width = signal(g.width);\n this.height = signal(g.height);\n this.z = signal(init.z ?? 0);\n this.workArea = init.workArea;\n this.clamp();\n }\n\n // State\n\n /** The one place a state is written, so `stateChanges` hears every change and only real ones. */\n setState(next: WrWindowState): void {\n const current = this.state();\n if (current === next) return;\n if (next === 'minimized') this.restoreTo = current === 'maximized' ? 'maximized' : 'normal';\n this.state.set(next);\n this.stateChanges.next(next);\n }\n\n /** Toggle: minimize, or come back to the state it was minimized from. */\n minimize(): void {\n if (this.state() === 'minimized') {\n this.unminimize();\n return;\n }\n // Read before the state flips: once the class lands, nothing inside has a\n // box and the browser has already dropped focus on `<body>`.\n const hadFocus = this.hasFocus();\n this.setState('minimized');\n if (hadFocus) this.onMinimizedWithFocus?.();\n }\n\n /** Leave `minimized` for the state the window was minimized from. A no-op otherwise. */\n unminimize(): void {\n if (this.state() === 'minimized') this.setState(this.restoreTo);\n }\n\n /** Toggle: maximize, or restore down to where it was — a snapped half included. */\n maximize(): void {\n this.setState(this.state() === 'maximized' ? 'normal' : 'maximized');\n }\n\n /** Back to the free-floating geometry: not minimized, not maximized, not snapped. */\n restore(): void {\n this.snap.set(null);\n this.setState('normal');\n }\n\n /** Snap to a region of the work area; `top` maximizes, `null` un-snaps. */\n snapTo(target: WrWindowSnapTarget | null): void {\n if (target === 'top') {\n this.setState('maximized');\n return;\n }\n this.snap.set(target);\n this.setState('normal');\n }\n\n // Geometry\n\n /** Write the raw geometry, in whole pixels — a touch drag hands out fractions. */\n setRaw(g: Partial<WrWindowGeometry>): void {\n if (g.x !== undefined) this.x.set(Math.round(g.x));\n if (g.y !== undefined) this.y.set(Math.round(g.y));\n if (g.width !== undefined) this.width.set(Math.round(g.width));\n if (g.height !== undefined) this.height.set(Math.round(g.height));\n }\n\n /**\n * A snapped window that is moved or resized by hand leaves the snap and\n * keeps the box it had, the way a desktop does — otherwise the write would\n * land in the raw geometry and nothing would visibly move.\n */\n unsnapInPlace(): void {\n if (!this.snap()) return;\n if (this.state() === 'normal') {\n const r = this.rect();\n this.setRaw({ x: r.left, y: r.top, width: r.width, height: r.height });\n }\n this.snap.set(null);\n }\n\n moveTo(x: number, y: number): void {\n this.unsnapInPlace();\n this.setRaw({ x, y });\n this.clamp();\n }\n\n resizeTo(width: number, height: number): void {\n this.unsnapInPlace();\n const o = this.options();\n this.setRaw({ width: clamp(width, o.minWidth, o.maxWidth), height: clamp(height, o.minHeight, o.maxHeight) });\n this.clamp();\n }\n\n center(): void {\n this.unsnapInPlace();\n const wa = this.workArea();\n this.setRaw({\n x: wa.left + Math.max(0, (wa.width - this.width()) / 2),\n y: wa.top + Math.max(0, (wa.height - this.height()) / 2),\n });\n }\n\n /**\n * Keep enough of the window inside the work area to grab it again. Reads the\n * work area, so a resized viewport pulls a window back into reach.\n */\n clamp(): void {\n if (!this.options().keepInViewport) return;\n const wa = this.workArea();\n const w = this.width();\n this.x.set(Math.round(clamp(this.x(), wa.left + MIN_ON_SCREEN - w, wa.left + wa.width - MIN_ON_SCREEN)));\n this.y.set(Math.round(clamp(this.y(), wa.top, wa.top + wa.height - MIN_ON_SCREEN)));\n }\n\n /** Change options on an open window. New bounds re-clamp the size the window has now. */\n update(patch: WrWindowUpdate): void {\n const { title, ...rest } = patch;\n if (title !== undefined) this.title.set(title);\n const defined: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(rest)) if (value !== undefined) defined[key] = value;\n if (Object.keys(defined).length === 0) return;\n this.options.update(o => ({ ...o, ...defined }));\n if (['minWidth', 'minHeight', 'maxWidth', 'maxHeight'].some(key => key in defined)) {\n const o = this.options();\n this.setRaw({\n width: clamp(this.width(), o.minWidth, o.maxWidth),\n height: clamp(this.height(), o.minHeight, o.maxHeight),\n });\n this.clamp();\n }\n }\n\n /** The box a maximized window takes: the work area, capped at the maximum size and centred in it. */\n maximizedRect(): WrWindowRect {\n const wa = this.workArea();\n const o = this.options();\n const width = Math.min(wa.width, o.maxWidth);\n const height = Math.min(wa.height, o.maxHeight);\n return {\n left: wa.left + Math.round((wa.width - width) / 2),\n top: wa.top + Math.round((wa.height - height) / 2),\n width,\n height,\n };\n }\n\n /**\n * The box a half or a quarter takes, held to the window's own bounds: a\n * window that cannot be that narrow keeps its minimum and stays against the\n * edge it was snapped to, and the box is kept inside the work area.\n */\n snapRect(target: WrWindowSnapRegion): WrWindowRect {\n const wa = this.workArea();\n const o = this.options();\n const halfW = Math.floor(wa.width / 2);\n const halfH = Math.floor(wa.height / 2);\n const right = target === 'right' || target === 'top-right' || target === 'bottom-right';\n const bottom = target === 'bottom-left' || target === 'bottom-right';\n const quarter = target !== 'left' && target !== 'right';\n // The far half carries the odd pixel, so the two halves meet with no gap.\n const regionW = right ? wa.width - halfW : halfW;\n const regionH = quarter ? (bottom ? wa.height - halfH : halfH) : wa.height;\n const regionL = wa.left + (right ? halfW : 0);\n const regionT = wa.top + (bottom ? halfH : 0);\n const width = clamp(regionW, o.minWidth, o.maxWidth);\n const height = clamp(regionH, o.minHeight, o.maxHeight);\n const left = right ? regionL + regionW - width : regionL;\n const top = bottom ? regionT + regionH - height : regionT;\n return {\n left: clamp(left, wa.left, Math.max(wa.left, wa.left + wa.width - width)),\n top: clamp(top, wa.top, Math.max(wa.top, wa.top + wa.height - height)),\n width,\n height,\n };\n }\n\n /** Where a snap target puts the window. */\n targetRect(target: WrWindowSnapTarget): WrWindowRect {\n return target === 'top' ? this.maximizedRect() : this.snapRect(target);\n }\n\n // Keyboard move and resize\n\n /**\n * Enter keyboard move or resize. A maximized window is restored down first\n * and a snapped one keeps its box, so the arrows move what the user sees.\n * Returns `false` when the option forbids it.\n */\n startKeyboard(mode: WrWindowKeyboardMode): boolean {\n const o = this.options();\n if (!o.keyboard || this.state() === 'minimized') return false;\n if (mode === 'move' ? !o.movable : !o.resizable) return false;\n this.keyboardOrigin = {\n geometry: { x: this.x(), y: this.y(), width: this.width(), height: this.height() },\n state: this.state(),\n snap: this.snap(),\n };\n if (this.state() === 'maximized') this.setState('normal');\n this.unsnapInPlace();\n this.keyboardStart = { x: this.x(), y: this.y(), width: this.width(), height: this.height() };\n this.keyboardMode.set(mode);\n return true;\n }\n\n /** One arrow key in keyboard move. */\n nudge(dx: number, dy: number): void {\n this.setRaw({ x: this.x() + dx, y: this.y() + dy });\n this.clamp();\n }\n\n /**\n * One arrow key in keyboard resize. The edge that moves is the inline END —\n * the left one in a right-to-left page — so growing never moves the edge the\n * window reads from.\n */\n grow(dw: number, dh: number, rtl: boolean): void {\n const o = this.options();\n const width = clamp(this.width() + dw, o.minWidth, o.maxWidth);\n const height = clamp(this.height() + dh, o.minHeight, o.maxHeight);\n const x = rtl ? this.x() - (width - this.width()) : this.x();\n this.setRaw({ x, width, height });\n this.clamp();\n }\n\n /** Keep what keyboard mode did. Returns the mode it ended, for the announcement and the stream. */\n commitKeyboard(): WrWindowKeyboardMode | null {\n const mode = this.keyboardMode();\n if (!mode) return null;\n this.keyboardMode.set(null);\n const start = this.keyboardStart;\n this.keyboardStart = null;\n this.keyboardOrigin = null;\n if (mode === 'move' && (start?.x !== this.x() || start?.y !== this.y())) {\n this.moved.next({ x: this.x(), y: this.y() });\n }\n if (mode === 'resize' && (start?.width !== this.width() || start?.height !== this.height())) {\n this.resized.next({ width: this.width(), height: this.height() });\n }\n return mode;\n }\n\n /**\n * Put the window back the way keyboard mode found it: the geometry, and the\n * maximized state or the snapped half it restored on entry. Without the last\n * two, Escape on a maximized window left it restored down.\n */\n cancelKeyboard(): WrWindowKeyboardMode | null {\n const mode = this.keyboardMode();\n if (!mode) return null;\n const origin = this.keyboardOrigin;\n this.keyboardStart = null;\n this.keyboardOrigin = null;\n this.keyboardMode.set(null);\n if (origin) {\n this.setRaw(origin.geometry);\n this.snap.set(origin.snap);\n this.setState(origin.state);\n }\n return mode;\n }\n\n /** Whether focus is inside the window. */\n hasFocus(): boolean {\n const el = this.element;\n return !!el && el.contains(el.ownerDocument.activeElement);\n }\n\n /** The window closed: no stream may outlive it. */\n complete(): void {\n this.moved.complete();\n this.resized.complete();\n this.stateChanges.complete();\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { OverlayRef } from '@angular/cdk/overlay';\nimport { type ComponentRef, type Signal, computed, signal } from '@angular/core';\n\nimport { type Observable, ReplaySubject, type Subject } from 'rxjs';\n\nimport type { WrWindowBeforeCloseHook, WrWindowSnapTarget, WrWindowState, WrWindowUpdate } from './types';\nimport { type WrWindowKeyboardMode, WrWindowModel, readViewport, resolveOptions } from './window-model';\n\n/**\n * What a ref needs from the manager that opened it.\n *\n * @internal\n */\nexport interface WrWindowRefHost {\n /** Raise the window, mark it active and, unless told otherwise, move focus into it. */\n _activate(ref: WrWindowRef<unknown, unknown>, options?: { readonly focus?: boolean }): void;\n /** Raise the window without touching focus. */\n _raise(ref: WrWindowRef<unknown, unknown>): void;\n}\n\n/**\n * Handle returned by `WrWindowManager.open()`.\n *\n * Wraps the underlying overlay, exposes signals for the live geometry,\n * and gives the consumer programmatic control over the window\n * (focus, move, resize, minimize, maximize, close).\n *\n * Every signal is right from the moment `open()` returns, and every call works\n * from then on too — including from the body component's constructor.\n *\n * @example\n * ```ts\n * const ref = manager.open(EditorComponent, {\n * title: 'Untitled.md',\n * storage: { key: 'editor', prefix: 'app' },\n * });\n *\n * ref.beforeClose(async () => {\n * if (!isDirty) return true;\n * return await confirmDiscard();\n * });\n *\n * const saved = await ref.afterClosed(); // resolves with whatever the\n * // component passed to ref.close(value)\n * ```\n */\nexport class WrWindowRef<C, R = unknown> {\n /** Stable id — used by the taskbar, workspace save, and DI. */\n readonly id: string;\n\n /**\n * @internal — emits the close result once and completes.\n *\n * A `ReplaySubject`, not a plain `Subject`, so the result survives a late\n * subscriber — the same reasoning `WrDialogRef` already carries. A caller\n * that holds the ref and awaits `afterClosed()` after any intervening\n * `await` subscribes to an already-completed stream, and a plain Subject\n * hands it nothing but `complete`: the promise resolved `undefined` and a\n * saved result was indistinguishable from a dismissal.\n */\n readonly _closed = new ReplaySubject<R | undefined>(1);\n\n /** @internal — the window's state and geometry; the signals below read through it. */\n readonly _model: WrWindowModel;\n\n /** @internal — emits whenever the state changes; `stateChanges` is its public face. */\n readonly _stateChanged: Subject<WrWindowState>;\n\n /** @internal — set by the container right after attach. */\n componentRef: ComponentRef<C> | null = null;\n\n /** @internal — whether this window opts into the taskbar list. */\n taskbarVisible = true;\n\n /** @internal — the manager that opened the window. */\n _host: WrWindowRefHost | null = null;\n\n /** @internal — close the overlay and settle the result; wired by the manager. */\n _doClose: ((result: R | undefined) => void) | null = null;\n\n /**\n * @internal — move focus into the window after the next render: to the control\n * it had last (`'last'`, falling back to the first one) or to the first one.\n * Wired by the container once the window is on the page.\n */\n _focusWindow: ((mode: 'initial' | 'last') => void) | null = null;\n\n /** @internal — enter keyboard move / resize; wired by the container. */\n _startKeyboard: ((mode: WrWindowKeyboardMode) => void) | null = null;\n\n /** @internal — a keyboard mode asked for before the window was on the page. */\n _pendingKeyboard: WrWindowKeyboardMode | null = null;\n\n /**\n * @internal — what had focus when `open()` was called, and where closing the\n * window sends it back. `null` when focus was on nothing.\n */\n _returnFocus: HTMLElement | null = null;\n\n /** Window state. A snapped window is `normal`; read {@link snap} for which half. */\n readonly state: Signal<WrWindowState>;\n /** Left edge on screen, in px — the work area's while maximized. */\n readonly x: Signal<number>;\n /** Top edge on screen, in px. */\n readonly y: Signal<number>;\n /** Width on screen, in px. */\n readonly width: Signal<number>;\n /** Height on screen, in px. */\n readonly height: Signal<number>;\n /** Stack z-index. */\n readonly z: Signal<number>;\n /** Live title. */\n readonly title: Signal<string>;\n /** The half or quarter the window is snapped to, or `null` (since v15.1). Maximized reads `null`. */\n readonly snap: Signal<WrWindowSnapTarget | null>;\n /** Whether this is the active window — the one that has the keyboard (since v15.1). */\n readonly isActive: Signal<boolean>;\n\n /** Emits the close result once, then completes — the stream `WrDialogRef.closed` is (since v15.1). */\n readonly closed: Observable<R | undefined>;\n /**\n * Emits where the user moved the window: once when a title-bar drag or a\n * keyboard move ends, and when a drag snaps it. Calls from code are silent —\n * the caller knows where it put the window (since v15.1).\n */\n readonly moved: Observable<{ readonly x: number; readonly y: number }>;\n /**\n * Emits the size the user gave the window: once when an edge drag or a\n * keyboard resize ends, and when a drag snaps it to a half or a quarter.\n * Calls from code are silent (since v15.1).\n */\n readonly resized: Observable<{ readonly width: number; readonly height: number }>;\n /** Emits every state change, from the user or from code (since v15.1). */\n readonly stateChanges: Observable<WrWindowState>;\n\n // Hooks\n private _beforeCloseHook: WrWindowBeforeCloseHook<R> | null = null;\n\n /**\n * A ref built by hand — a test double for `WR_WINDOW_REF`. It answers every\n * call with a window of its own that nothing renders.\n */\n constructor(id: string, _overlayRef: OverlayRef);\n /** @internal The manager's form: the window's model, built before anything renders. */\n constructor(id: string, _overlayRef: OverlayRef, model: WrWindowModel);\n constructor(\n id: string,\n public readonly _overlayRef: OverlayRef,\n model?: WrWindowModel\n ) {\n this.id = id;\n // A ref built by hand — a test double for `WR_WINDOW_REF` — still answers.\n const m =\n model ??\n new WrWindowModel({\n options: resolveOptions({}),\n workArea: signal({ left: 0, top: 0, ...readViewport() }),\n });\n this._model = m;\n this._stateChanged = m.stateChanges;\n this.state = m.state.asReadonly();\n this.x = computed(() => m.rect().left);\n this.y = computed(() => m.rect().top);\n this.width = computed(() => m.rect().width);\n this.height = computed(() => m.rect().height);\n this.z = m.z.asReadonly();\n this.title = m.title.asReadonly();\n this.snap = m.snap.asReadonly();\n this.isActive = m.isActive.asReadonly();\n this.closed = this._closed.asObservable();\n this.moved = m.moved.asObservable();\n this.resized = m.resized.asObservable();\n this.stateChanges = m.stateChanges.asObservable();\n }\n\n /** Resolved instance of the projected component. */\n get componentInstance(): C {\n if (!this.componentRef) {\n throw new Error('WrWindowRef: component not yet attached');\n }\n return this.componentRef.instance;\n }\n\n // Lifecycle\n\n private isClosed = false;\n\n /**\n * Close the window, optionally returning a result. If a `beforeClose`\n * hook is registered it is consulted first — a falsy resolution\n * cancels the close.\n */\n async close(result?: R): Promise<void> {\n // `WrDialogRef` / `WrDrawerRef` latch the same way on their own `isClosed`,\n // but theirs are synchronous: this is the only one of the three that AWAITS,\n // so it is the\n // only one a second call can enter mid-flight and run the hook again. Two\n // Escapes in a row do it, and so does `manager.closeAll()` while a hook is\n // pending — `_doClose` is what removes the ref from the manager's list, and\n // it has not run yet.\n if (this.isClosed) return;\n this.isClosed = true;\n\n let proceed = false;\n try {\n proceed = this._beforeCloseHook ? !!(await this._beforeCloseHook(result)) : true;\n } finally {\n // A veto is not a close, and neither is a hook that threw — release the\n // latch in both cases, or a declined close would disable the window for\n // good.\n if (!proceed) this.isClosed = false;\n }\n\n if (proceed) this._doClose?.(result);\n }\n\n /** Toggle the minimized state. Leaving it returns to the state it was minimized from. */\n minimize(): void {\n this._model.minimize();\n }\n\n /** Toggle the maximized state. Restoring down returns to where the window was, a snapped half included. */\n maximize(): void {\n this._model.maximize();\n }\n\n /** Back to `normal` at the window's own geometry — from minimized, maximized or snapped. */\n restore(): void {\n this._model.restore();\n }\n\n /**\n * Bring this window to the top of the stack. Only RAISES it: focus stays\n * where it is. Use {@link activate} to switch to the window.\n */\n focus(): void {\n this._host?._raise(this as WrWindowRef<unknown, unknown>);\n }\n\n /**\n * Switch to the window: bring it back from the taskbar if it is minimized,\n * raise it, make it the active window, and move focus to the control it had\n * last (its first control when it never had one) (since v15.1).\n */\n activate(): void {\n if (this._host) this._host._activate(this as WrWindowRef<unknown, unknown>);\n else this._model.unminimize();\n }\n\n // Programmatic geometry\n\n /**\n * Move the window to `(x, y)`, held to the work area while `keepInViewport`.\n * While maximized it moves the geometry restore lands on; a snapped window\n * leaves the snap.\n */\n moveTo(x: number, y: number): void {\n this._model.moveTo(x, y);\n }\n\n /** Resize the window, held to `minWidth`…`maxWidth` and `minHeight`…`maxHeight`. */\n resizeTo(width: number, height: number): void {\n this._model.resizeTo(width, height);\n }\n\n /** Re-position the window so it sits centered in its work area. */\n center(): void {\n this._model.center();\n }\n\n /** Snap to a half or a quarter of the work area; `'top'` maximizes, `null` un-snaps (since v15.1). */\n snapTo(target: WrWindowSnapTarget | null): void {\n this._model.snapTo(target);\n }\n\n /** Update the title-bar text, and with it the window's accessible name. */\n setTitle(title: string): void {\n this._model.title.set(title);\n }\n\n /**\n * Change options on an open window — lock it while it saves, take its close\n * button away while a task runs. New bounds re-clamp its current size\n * (since v15.1).\n */\n update(patch: WrWindowUpdate): void {\n this._model.update(patch);\n }\n\n /**\n * Move the window from the keyboard: the arrow keys step it, Shift by one\n * pixel, Enter keeps the result and Escape puts it back. Moves focus into the\n * window so the keys arrive. Bind it to a menu item or a button to offer\n * moving without a drag (since v15.1).\n */\n startMove(): void {\n this.startKeyboard('move');\n }\n\n /** Resize the window from the keyboard, the same way as {@link startMove} (since v15.1). */\n startResize(): void {\n this.startKeyboard('resize');\n }\n\n private startKeyboard(mode: WrWindowKeyboardMode): void {\n if (this._startKeyboard) this._startKeyboard(mode);\n else this._pendingKeyboard = mode;\n }\n\n // Hooks\n\n /**\n * Register a guard that runs before `close()`. Return `false` (or a\n * Promise resolving to false) to veto. Only one hook per ref —\n * subsequent calls replace the previous.\n */\n beforeClose(hook: WrWindowBeforeCloseHook<R>): void {\n this._beforeCloseHook = hook;\n }\n\n /** Resolves with the result passed to `close()` (or `undefined`). */\n afterClosed(): Promise<R | undefined> {\n return new Promise(resolve => {\n this._closed.subscribe({\n next: value => resolve(value),\n complete: () => resolve(undefined),\n });\n });\n }\n\n /** The same promise as {@link afterClosed}, under the name `WrDialogRef` uses (since v15.1). */\n awaitClose(): Promise<R | undefined> {\n return this.afterClosed();\n }\n\n /** Escape hatch — the underlying CDK overlay ref. */\n get overlayRef(): OverlayRef {\n return this._overlayRef;\n }\n}\n\nexport type { WrWindowBeforeCloseHook } from './types';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directionality } from '@angular/cdk/bidi';\nimport { type OverlayRef } from '@angular/cdk/overlay';\nimport { ComponentPortal, type ComponentType } from '@angular/cdk/portal';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n DestroyRef,\n ElementRef,\n EnvironmentInjector,\n Injector,\n PLATFORM_ID,\n Service,\n type Signal,\n afterNextRender,\n computed,\n inject,\n signal,\n untracked,\n} from '@angular/core';\n\nimport { WR_OVERLAY, wrFollowDirection } from 'ngwr/overlay';\nimport { WrStorage } from 'ngwr/storage';\nimport { clamp, randomId, toClassList } from 'ngwr/utils';\n\nimport { storageKey } from '../storage-key';\nimport { WR_WINDOW_DATA, WR_WINDOW_DEFAULTS, WR_WINDOW_REF } from '../tokens';\nimport type {\n WrWindowBounds,\n WrWindowConfig,\n WrWindowInsets,\n WrWindowLayoutSnapshot,\n WrWindowStorageConfig,\n} from '../types';\nimport { type PersistedGeometry, WrWindowContainer } from '../window-container';\nimport {\n type WrWindowRect,\n WrWindowModel,\n cascadeOffset,\n readViewport,\n resolveOptions,\n seedGeometry,\n} from '../window-model';\nimport { type WrWindowRefHost, WrWindowRef } from '../window-ref';\n\ntype AnyRef = WrWindowRef<unknown, unknown>;\n\nconst NO_RESERVE = { top: 0, bottom: 0 } as const;\n\nfunction sameRect(a: WrWindowRect, b: WrWindowRect): boolean {\n return a.left === b.left && a.top === b.top && a.width === b.width && a.height === b.height;\n}\n\n/**\n * What `WrWindowManager` needs from a `<wr-window-taskbar>` on the page: the\n * row a window's tab sits in, so focus can land on it when the window is\n * minimized and be recognised there when the window is closed from it, and\n * the strip it covers, so maximized windows stop short of it.\n *\n * @internal\n */\nexport interface WrWindowTaskbarTabs {\n /**\n * The `.wr-window-taskbar__tab` row for `ref`, the \"+N\" button when its tab is\n * folded under one, or `null` when this taskbar does not list it.\n */\n tabFor(ref: AnyRef): HTMLElement | null;\n /**\n * Whether `ref`'s place in the rail is still moving: its tab has not been\n * measured yet, or the render that folds or unfolds it has not happened. Focus\n * waits for it rather than landing on a tab about to hide or a \"+N\" not drawn.\n */\n settling(ref: AnyRef): boolean;\n /** Whether `node` is inside this taskbar. */\n contains(node: Node): boolean;\n /** The strip of the viewport this taskbar covers while it shows tabs, in px from each edge. */\n readonly reserve: Signal<{ readonly top: number; readonly bottom: number }>;\n}\n\n/**\n * Owns the open window stack, hands out z-indexes, tracks the active window,\n * cascades the default spawn position, and opens windows that wrap a consumer\n * component.\n *\n * Inject the singleton and call `open(component, config)` for a\n * dialog-style flow:\n *\n * ```ts\n * const manager = inject(WrWindowManager);\n *\n * const ref = manager.open(EditorComponent, {\n * title: 'Untitled.md',\n * size: 'lg',\n * storage: { key: 'editor', prefix: 'my-app' },\n * });\n *\n * const saved = await ref.afterClosed();\n * ```\n *\n * There is no declarative `<wr-window>`: `open()` is the only way in, so every\n * window shares this one stack.\n */\n@Service()\nexport class WrWindowManager implements WrWindowRefHost {\n private readonly overlay = inject(WR_OVERLAY);\n private readonly parentInjector = inject(EnvironmentInjector);\n private readonly storage = inject(WrStorage);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly dir = inject(Directionality, { optional: true });\n private readonly defaults = inject(WR_WINDOW_DEFAULTS, { optional: true });\n private readonly destroyRef = inject(DestroyRef);\n\n private readonly baseZ = 1000;\n private topZ = this.baseZ;\n private openCount = 0;\n\n /** All open windows, in the order they opened. */\n private readonly _windows = signal<readonly AnyRef[]>([]);\n\n /** The window that has the keyboard, or `null`. */\n private readonly _active = signal<AnyRef | null>(null);\n\n /**\n * Filled by `restoreLayout` right before it invokes the consumer's\n * opener callback. The next `open()` call with a matching `config.id`\n * pops the entry and uses it as the initial geometry and state.\n */\n private readonly pendingRestores = new Map<string, WrWindowLayoutSnapshot>();\n\n /** The taskbars on the page, registered by each `<wr-window-taskbar>` for its lifetime. */\n private readonly taskbars = signal<readonly WrWindowTaskbarTabs[]>([]);\n\n /**\n * ONE viewport for every window, kept by one `resize` listener. Each window\n * used to add its own — twenty listeners for twenty windows, each writing its\n * own copy of the same two numbers.\n */\n private readonly viewport = signal(readViewport(), {\n equal: (a, b) => a.width === b.width && a.height === b.height,\n });\n /** Bumped when an element used as `bounds` may have moved: it resized, or something scrolled. */\n private readonly layoutTick = signal(0);\n private listening = false;\n private boundsObserver: ResizeObserver | null = null;\n private readonly boundElements = new Map<HTMLElement, number>();\n private readonly bumpLayout = (): void => this.layoutTick.update(n => n + 1);\n\n /** The strip the taskbars cover, edge by edge. */\n private readonly reserve = computed(() => {\n let top = 0;\n let bottom = 0;\n for (const taskbar of this.taskbars()) {\n const r = taskbar.reserve();\n top = Math.max(top, r.top);\n bottom = Math.max(bottom, r.bottom);\n }\n return top === 0 && bottom === 0 ? NO_RESERVE : { top, bottom };\n });\n\n /** All currently-open windows, in the order they opened. */\n // Spelled out rather than `AnyRef` on every public member: the alias is not\n // exported, so the published typings would name `AnyRef$1` to a consumer.\n readonly windows: Signal<readonly WrWindowRef<unknown, unknown>[]> = this._windows.asReadonly();\n\n /**\n * The active window — the one that has the keyboard: the last one focused,\n * clicked, opened with focus or switched to (since v15.1). `null` once focus\n * moves to something on the page outside every window, and while the active\n * window is minimized.\n */\n readonly active: Signal<WrWindowRef<unknown, unknown> | null> = this._active.asReadonly();\n\n /** Windows that are minimized AND opted into the taskbar. */\n readonly minimized: Signal<WrWindowRef<unknown, unknown>[]> = computed(() =>\n this._windows().filter(w => w.taskbarVisible && w.state() === 'minimized')\n );\n\n /** Reserve the next z-index. Strictly increasing across the app's lifetime. */\n bringToFront(): number {\n this.topZ += 1;\n return this.topZ;\n }\n\n /**\n * Cascade offset for new windows, so two opens don't perfectly overlap: 30px\n * a step from the work area's start edge, back to the start after ten, and\n * each lap of ten shifted 15px along so window eleven does not land exactly\n * on window one.\n */\n nextStartOffset(): { readonly x: number; readonly y: number } {\n const offset = cascadeOffset(this.openCount);\n this.openCount += 1;\n return offset;\n }\n\n /**\n * Open a window with `component` rendered as its body. Returns a ref\n * the caller can use to drive the window programmatically and await\n * its result.\n *\n * **Singleton by id** — if `config.id` is set and a window with that\n * id is already open, that window is switched to (back from the taskbar,\n * raised, focused) and its ref returned. No duplicate window is\n * created. Use this to coalesce repeated open() calls (e.g. a\n * \"Settings\" menu item that should always re-focus the same window).\n */\n open<C, R = unknown, D = unknown>(component: ComponentType<C>, config: WrWindowConfig<D> = {}): WrWindowRef<C, R> {\n // Where focus goes back to when the window closes — read before anything\n // here moves it.\n const opener = this.focusedElement();\n\n if (config.id) {\n const existing = this.findById(config.id);\n if (existing) {\n // A second open is still an open: focus goes to the window, and back to\n // whatever asked for it this time — unless that was the window itself.\n if (config.autoFocus !== false) {\n if (opener && !existing._overlayRef.overlayElement?.contains(opener)) existing._returnFocus = opener;\n this._activate(existing);\n } else {\n existing._model.unminimize();\n this._raise(existing);\n }\n return existing as WrWindowRef<C, R>;\n }\n }\n\n // Honour a pending restore — `restoreLayout` populates this Map\n // right before invoking the consumer's opener so the new window\n // seeds at the saved geometry instead of the cascade default.\n const pending = config.id ? this.pendingRestores.get(config.id) : undefined;\n if (pending) this.pendingRestores.delete(config.id!);\n\n this.listen();\n\n const options = resolveOptions(config);\n const bounds = this.boundsElement(config.bounds ?? this.defaults?.bounds);\n const workArea = this.workAreaFor(config.bounds ?? this.defaults?.bounds, bounds);\n const releaseBounds = bounds ? this.observeBounds(bounds) : null;\n\n // Saved geometry is the INITIAL geometry, through the same fit as a\n // cascade: it used to be written over the window after it had sized\n // itself, skipping the fit and the min / max clamps, so a desktop's\n // 1100px window reopened on a phone with 24px of it on the glass.\n const saved = !pending && config.storage ? this.storage.get<PersistedGeometry>(storageKey(config.storage)) : null;\n const persist = config.storage?.persist ?? 'all';\n const isNum = (v: unknown): v is number => typeof v === 'number' && !Number.isNaN(v);\n const savedPos = saved && persist !== 'size' && isNum(saved.x) && isNum(saved.y) ? saved : null;\n const savedSize = saved && persist !== 'position' && isNum(saved.width) && isNum(saved.height) ? saved : null;\n\n const geometry = untracked(() =>\n seedGeometry({\n options,\n workArea: workArea(),\n size: config.size,\n x: pending?.x ?? savedPos?.x ?? config.x,\n y: pending?.y ?? savedPos?.y ?? config.y,\n width: pending?.width ?? savedSize?.width ?? config.width,\n height: pending?.height ?? savedSize?.height ?? config.height,\n restored: !!pending || !!savedPos,\n cascade: () => this.nextStartOffset(),\n rtl: this.dir?.value === 'rtl',\n })\n );\n\n const taskbarOptIn = config.taskbar !== false;\n const model = new WrWindowModel({\n options,\n // A saved title, else the config's — an empty saved title is not one.\n title: [pending?.title, config.title].find(t => !!t) ?? '',\n geometry,\n state: pending?.state,\n snap: pending?.snap ?? null,\n z: this.bringToFront(),\n workArea,\n });\n\n // Assigned right after the ref exists; the predicate below only ever runs\n // from a keydown, long after.\n let self: AnyRef | null = null;\n\n // Each window gets its own CDK overlay pane positioned `static` —\n // <wr-window> itself uses `position: fixed`, so the pane is only a\n // mount point. Windows are never modal — reach for `WrDialog` when\n // you need a backdrop + focus trap + scroll block.\n const overlayRef: OverlayRef = this.overlay.create({\n positionStrategy: this.overlay.position().global(),\n panelClass: toClassList('wr-window-overlay', config.panelClass),\n hasBackdrop: false,\n // Which window an Escape belongs to is a question the CDK cannot answer\n // here. Its keyboard dispatcher walks the attached overlays newest-first\n // and hands the key to the first one willing to take it — and attach order\n // is frozen at OPEN order, because raising re-stacks with a z-index and\n // never re-attaches. Declining here is what makes it recoverable: a\n // rejected event walks on down the stack instead of being eaten, so the\n // window that does own it still gets its Escape.\n eventPredicate: () => self === null || this.ownsKeyboard(self),\n // OUT of the top layer, deliberately. The CDK puts overlay hosts there by\n // default (`popover=\"manual\"`), and the top layer orders strictly by\n // ENTRY: whatever opened last paints on top and no z-index can change it.\n // That is right for a menu or a modal and exactly wrong for a window\n // manager, whose whole job is letting the user decide which window is in\n // front. It also fixes the ordering against modals: a dialog stays in the\n // top layer, so it now sits above every window instead of below whichever\n // window happened to open after it.\n usePopover: false,\n });\n\n // The z-index has to land on the OVERLAY HOST, not only on `.wr-window`.\n // Each window sits in its own CDK global wrapper, and that wrapper is\n // `position: fixed` with a numeric `z-index` — which makes it a stacking\n // context, so a z-index written inside it only orders things against its\n // own siblings, never against another window.\n overlayRef.hostElement.style.zIndex = String(model.z());\n\n // Windows are long-lived — a session can leave one open across any number\n // of direction changes — and while `x` / `y` are physical by design (as are\n // the resize grips, deliberately), the chrome is not: the macOS title bar\n // parks its button cluster with `row-reverse`, which resolves against `dir`,\n // so a stale attribute leaves the dots and the gutter that counterbalances\n // them on opposite edges. Each `open()` has its own ref, and `_doClose`\n // disposes it, which is what ends this follower.\n wrFollowDirection(overlayRef, this.dir, this.parentInjector);\n\n const id = config.id ?? randomId('wr-window');\n const ref = new WrWindowRef<C, R>(id, overlayRef, model);\n const any = ref as unknown as AnyRef;\n self = any;\n ref._host = this;\n ref.taskbarVisible = taskbarOptIn;\n\n // A minimized window is not the one with the keyboard: focus has gone to\n // its taskbar tab, or back to where the window was opened from.\n model.stateChanges.subscribe(state => {\n if (state === 'minimized' && this._active() === any) this.setActive(null);\n });\n\n // Provide WR_WINDOW_REF + WR_WINDOW_DATA inside the projected\n // component's subtree so it can `inject(WR_WINDOW_REF)` etc.\n const childInjector = Injector.create({\n parent: this.parentInjector,\n providers: [\n { provide: WR_WINDOW_REF, useValue: ref },\n { provide: WR_WINDOW_DATA, useValue: config.data ?? null },\n ],\n });\n\n const portal = new ComponentPortal<WrWindowContainer<C>>(WrWindowContainer);\n const containerRef = overlayRef.attach(portal);\n const container = containerRef.instance;\n container.config = config;\n container.ref = ref as WrWindowRef<C, unknown>;\n container.componentType = component;\n container.childInjector = childInjector;\n // A window `restoreLayout()` re-opens stays out of focus's way unless its\n // opener says otherwise: a workspace of five windows coming back must not\n // pull focus through each of them and leave it in whichever came last.\n container.autoFocus = config.autoFocus ?? !pending;\n ref._returnFocus = opener;\n\n // No role on the pane: `<wr-window>` inside it is the named `role=\"dialog\"`,\n // and a second, unnamed one around it read as \"dialog > dialog\" and tripped\n // axe's `aria-dialog-name` on every open window.\n\n // Always subscribed, and the option read when the key arrives, so\n // `update({ closeOnEscape })` reaches an open window. A key claimed below\n // it — Escape cancelling keyboard move — is not a close.\n overlayRef.keydownEvents().subscribe(event => {\n if (event.key !== 'Escape' || event.defaultPrevented || !model.options().closeOnEscape) return;\n event.preventDefault();\n void ref.close();\n });\n\n // Wire close → disposal + completion of the result subject. The\n // ref's `close()` already runs the beforeClose hook before reaching\n // this bridge.\n ref._doClose = result => {\n // Read before disposal takes the focused element out of the page. Focus\n // goes back only when it was the window's to give: inside it, on its\n // taskbar tab, or already lost. A window closed by code while the reader\n // works elsewhere leaves them there.\n const back = this.holdsFocus(any) ? ref._returnFocus : null;\n ref._returnFocus = null;\n overlayRef.dispose();\n releaseBounds?.();\n ref._closed.next(result);\n ref._closed.complete();\n model.complete();\n this._windows.update(list => list.filter(r => r !== any));\n if (this._active() === any) this.setActive(null);\n if (back?.isConnected) back.focus();\n };\n\n this._windows.update(list => [...list, any]);\n\n return ref;\n }\n\n /**\n * Switch to `ref`: back from the taskbar, raised, active, and — unless told\n * otherwise — focused on the control it had last.\n *\n * @internal\n */\n _activate(ref: AnyRef, options: { readonly focus?: boolean } = {}): void {\n if (!this._windows().includes(ref)) return;\n ref._model.unminimize();\n this._raise(ref);\n this.setActive(ref);\n if (options.focus !== false && !ref._model.hasFocus()) ref._focusWindow?.('last');\n }\n\n /**\n * Put `ref` on top of the stack. A window already on top keeps its z: every\n * click in a window used to take a new one, so the number climbed with each\n * press and every press re-wrote the host's style.\n *\n * @internal\n */\n _raise(ref: AnyRef): void {\n if (ref.z() >= this.topZ) return;\n const z = this.bringToFront();\n ref._model.z.set(z);\n const host = ref._overlayRef.hostElement;\n if (host) host.style.zIndex = String(z);\n }\n\n private setActive(ref: AnyRef | null): void {\n const previous = this._active();\n if (previous === ref) return;\n previous?._model.isActive.set(false);\n ref?._model.isActive.set(true);\n this._active.set(ref);\n }\n\n /**\n * Focus decides the active window wherever it comes from: Tab into a window,\n * a click on a field in it, a script calling `focus()`. A window that gains\n * focus is raised too — a focused window hidden behind another is a window\n * the user is typing into blind. Focus on a taskbar, or in another overlay,\n * leaves the active window as it was; focus anywhere else on the page means\n * none is.\n */\n private readonly onFocusIn = (event: FocusEvent): void => {\n const target = event.target;\n if (!(target instanceof Node)) return;\n const ref = this._windows().find(w => w._overlayRef.overlayElement?.contains(target));\n if (ref) {\n this._raise(ref);\n this.setActive(ref);\n return;\n }\n if (this.taskbars().some(t => t.contains(target))) return;\n // Focus that went into another overlay — a menu or a listbox opened from\n // inside a window, a dialog over it — is not focus that left for the page:\n // the window it came from keeps the keyboard, the way a desktop keeps a\n // window active while its menu is open.\n if (target instanceof Element && target.closest('.wr-overlay-container, .cdk-overlay-container')) return;\n this.setActive(null);\n };\n\n /** Install the shared listeners, once, on the first open in a browser. */\n private listen(): void {\n if (this.listening || !this.isBrowser) return;\n this.listening = true;\n const measure = (): void => this.viewport.set(readViewport());\n measure();\n window.addEventListener('resize', measure, { passive: true });\n document.addEventListener('focusin', this.onFocusIn, true);\n this.destroyRef.onDestroy(() => {\n window.removeEventListener('resize', measure);\n document.removeEventListener('focusin', this.onFocusIn, true);\n document.removeEventListener('scroll', this.bumpLayout, true);\n this.boundsObserver?.disconnect();\n });\n }\n\n private boundsElement(bounds: WrWindowBounds | undefined): HTMLElement | null {\n if (!bounds || bounds === 'viewport') return null;\n if (bounds instanceof ElementRef) return bounds.nativeElement;\n return typeof (bounds as HTMLElement).getBoundingClientRect === 'function' ? (bounds as HTMLElement) : null;\n }\n\n /**\n * The work area for one window: its bounds, cut to the viewport, minus the\n * strip a taskbar covers.\n */\n private workAreaFor(bounds: WrWindowBounds | undefined, element: HTMLElement | null): Signal<WrWindowRect> {\n const insets = !element && bounds && bounds !== 'viewport' ? (bounds as WrWindowInsets) : null;\n return computed(\n () => {\n const vp = this.viewport();\n const reserve = this.reserve();\n let left = 0;\n let top = 0;\n let right = vp.width;\n let bottom = vp.height;\n if (element && this.isBrowser) {\n this.layoutTick();\n const r = element.getBoundingClientRect();\n left = Math.max(0, r.left);\n top = Math.max(0, r.top);\n right = Math.min(vp.width, r.right);\n bottom = Math.min(vp.height, r.bottom);\n } else if (insets) {\n left = insets.left ?? 0;\n top = insets.top ?? 0;\n right = vp.width - (insets.right ?? 0);\n bottom = vp.height - (insets.bottom ?? 0);\n }\n top = Math.max(top, reserve.top);\n bottom = Math.min(bottom, vp.height - reserve.bottom);\n return {\n left: Math.round(left),\n top: Math.round(top),\n width: Math.max(0, Math.round(right - left)),\n height: Math.max(0, Math.round(bottom - top)),\n };\n },\n { equal: sameRect }\n );\n }\n\n /** Keep an element used as `bounds` measured while a window uses it. Returns the release. */\n private observeBounds(element: HTMLElement): () => void {\n if (!this.isBrowser) return () => undefined;\n const count = this.boundElements.get(element) ?? 0;\n this.boundElements.set(element, count + 1);\n if (count === 0) {\n if (typeof ResizeObserver !== 'undefined') {\n this.boundsObserver ??= new ResizeObserver(this.bumpLayout);\n this.boundsObserver.observe(element);\n }\n if (this.boundElements.size === 1) {\n document.addEventListener('scroll', this.bumpLayout, { capture: true, passive: true });\n }\n }\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const left = (this.boundElements.get(element) ?? 1) - 1;\n if (left > 0) {\n this.boundElements.set(element, left);\n return;\n }\n this.boundElements.delete(element);\n this.boundsObserver?.unobserve(element);\n if (this.boundElements.size === 0) document.removeEventListener('scroll', this.bumpLayout, true);\n };\n }\n\n /**\n * Whether a keyboard event routed to `ref`'s overlay is actually meant for it.\n *\n * The window holding real DOM focus owns the key. When focus is on NOTHING —\n * `<body>`, which is where a click on a window's own text used to leave it —\n * the active window owns it if it is on screen, else the front-most window on\n * screen. When focus is anywhere else on the page, no window owns it: an\n * Escape pressed in the page's own search field closed a window the reader\n * was not in. That is the rule the non-modal drawer has always followed.\n *\n * A MINIMIZED window never owns a key it did not receive through focus, and\n * never counts as being in front: it is `display: none`. Focus on a taskbar\n * tab is on the page, so no window owns that key either.\n */\n private ownsKeyboard(ref: AnyRef): boolean {\n if (!this.isBrowser) return false;\n const open = this._windows();\n const active = document.activeElement;\n const focused = active ? open.find(w => w._overlayRef.overlayElement?.contains(active)) : undefined;\n if (focused) return focused === ref;\n if (active && active !== document.body) return false;\n const current = this._active();\n if (current && current.state() !== 'minimized') return current === ref;\n let front: AnyRef | null = null;\n for (const w of open) {\n if (w.state() !== 'minimized' && (!front || w.z() > front.z())) front = w;\n }\n return front === ref;\n }\n\n /**\n * Register a taskbar for as long as it is on the page. Returns the\n * unregister call.\n *\n * @internal\n */\n _registerTaskbar(taskbar: WrWindowTaskbarTabs): () => void {\n this.taskbars.update(list => [...list, taskbar]);\n return () => this.taskbars.update(list => list.filter(t => t !== taskbar));\n }\n\n /**\n * A window was minimized while it held focus, and the render that lists it\n * in the taskbar has happened: put focus on its tab's restore button. With no\n * taskbar listing it (none on the page, or `taskbar: false`), focus goes back\n * to where the window was opened from rather than being left on `<body>`.\n *\n * @internal\n */\n _focusAfterMinimize(ref: AnyRef, attempt = 0): void {\n // A tab the rail has not measured yet can fold on the next pass, and its\n // \"+N\" is not drawn until the pass after. Wait for those, a few at most,\n // rather than focus what is about to hide or fall back to the opener.\n if (attempt < 3 && this.taskbars().some(taskbar => taskbar.settling(ref))) {\n const active = this.focusedElement();\n if (active && ref._overlayRef.overlayElement?.contains(active)) active.blur();\n afterNextRender(() => this._focusAfterMinimize(ref, attempt + 1), { injector: this.parentInjector });\n return;\n }\n // The restore button is the row's first: the close button sits after it. A\n // folded window's place is the \"+N\" button, which is a button itself.\n const tab = this.taskbarTab(ref);\n const restore = tab?.matches('button') ? tab : tab?.querySelector<HTMLElement>('button');\n if (restore) restore.focus();\n else if (ref._returnFocus?.isConnected) ref._returnFocus.focus();\n // Nowhere to go: at least never leave focus parked inside a window that is\n // `display: none`, where it would keep claiming every Escape. Browsers\n // that run the focus fixup rule have already done this.\n const active = this.focusedElement();\n if (active && ref._overlayRef.overlayElement?.contains(active)) active.blur();\n }\n\n private taskbarTab(ref: AnyRef): HTMLElement | null {\n for (const taskbar of this.taskbars()) {\n const tab = taskbar.tabFor(ref);\n if (tab) return tab;\n }\n return null;\n }\n\n /** The focused element, or `null` when that is `<body>` or nothing. */\n private focusedElement(): HTMLElement | null {\n if (!this.isBrowser) return null;\n const active = document.activeElement;\n return active instanceof HTMLElement && active !== document.body ? active : null;\n }\n\n /** Whether focus is `ref`'s to hand back: inside it, on its taskbar tab, or nowhere. */\n private holdsFocus(ref: AnyRef): boolean {\n if (!this.isBrowser) return false;\n const active = this.focusedElement();\n if (!active) return true;\n return !!ref._overlayRef.overlayElement?.contains(active) || !!this.taskbarTab(ref)?.contains(active);\n }\n\n // Arranging\n\n /** Windows on screen — not minimized. */\n private onScreen(): AnyRef[] {\n return this._windows().filter(w => w.state() !== 'minimized');\n }\n\n /**\n * Restore every window on screen and stack them down from the start edge of\n * their work area, 30px apart, keeping each one's size and their order front\n * to back (since v15.1).\n */\n cascade(): void {\n const rtl = this.dir?.value === 'rtl';\n const list = this.onScreen().sort((a, b) => a.z() - b.z());\n list.forEach((ref, index) => {\n const m = ref._model;\n m.restore();\n const wa = m.workArea();\n const o = m.options();\n const fit = (size: number, room: number): number => (o.keepInViewport ? Math.min(size, room) : size);\n const width = clamp(fit(m.width(), wa.width), o.minWidth, o.maxWidth);\n const height = clamp(fit(m.height(), wa.height), o.minHeight, o.maxHeight);\n const offset = cascadeOffset(index);\n const x = rtl ? wa.left + wa.width - width - offset.x : wa.left + offset.x;\n const y = wa.top + offset.y;\n m.setRaw({\n x: clamp(x, wa.left, Math.max(wa.left, wa.left + wa.width - width)),\n y: clamp(y, wa.top, Math.max(wa.top, wa.top + wa.height - height)),\n width,\n height,\n });\n this._raise(ref);\n });\n }\n\n /**\n * Restore every window on screen and share the work area between them, in\n * the order they opened: a grid (the default), side by side in columns, or\n * stacked in rows. A row of a grid with fewer windows spreads them across its\n * whole width. In a right-to-left page the first window takes the right\n * (since v15.1).\n */\n tile(mode: 'grid' | 'columns' | 'rows' = 'grid'): void {\n const list = this.onScreen();\n const n = list.length;\n if (n === 0) return;\n const rtl = this.dir?.value === 'rtl';\n const cols = mode === 'columns' ? n : mode === 'rows' ? 1 : Math.ceil(Math.sqrt(n));\n const rows = Math.ceil(n / cols);\n list.forEach((ref, index) => {\n const m = ref._model;\n m.restore();\n const wa = m.workArea();\n const o = m.options();\n const row = Math.floor(index / cols);\n const inRow = Math.min(cols, n - row * cols);\n let col = index % cols;\n if (rtl) col = inRow - 1 - col;\n const x0 = wa.left + Math.floor((wa.width * col) / inRow);\n const x1 = wa.left + Math.floor((wa.width * (col + 1)) / inRow);\n const y0 = wa.top + Math.floor((wa.height * row) / rows);\n const y1 = wa.top + Math.floor((wa.height * (row + 1)) / rows);\n m.setRaw({\n x: x0,\n y: y0,\n width: clamp(x1 - x0, o.minWidth, o.maxWidth),\n height: clamp(y1 - y0, o.minHeight, o.maxHeight),\n });\n m.clamp();\n });\n }\n\n /** Minimize every window on screen (since v15.1). */\n minimizeAll(): void {\n for (const ref of this.onScreen()) ref._model.minimize();\n }\n\n /** Bring every minimized window back, each to the state it was minimized from (since v15.1). */\n restoreAll(): void {\n for (const ref of this._windows()) ref._model.unminimize();\n }\n\n /**\n * Switch to the next window, in the order they opened, wrapping at the end —\n * minimized windows included, which come back. Bind it to a hotkey from\n * `ngwr/hotkey`, such as Ctrl+F6 (since v15.1).\n */\n activateNext(): void {\n this.cycle(1);\n }\n\n /** Switch to the previous window, the other way round from {@link activateNext} (since v15.1). */\n activatePrevious(): void {\n this.cycle(-1);\n }\n\n private cycle(step: 1 | -1): void {\n const list = this._windows();\n if (list.length === 0) return;\n const current = this._active();\n const index = current ? list.indexOf(current) : -1;\n const next = index < 0 ? list[step > 0 ? 0 : list.length - 1] : list[(index + step + list.length) % list.length];\n this._activate(next);\n }\n\n /** Close every programmatically-opened window. */\n closeAll(): void {\n for (const ref of [...this._windows()]) {\n void ref.close();\n }\n }\n\n /** Look up an open window by its `config.id`. Returns `null` when no match. */\n findById(id: string): WrWindowRef<unknown, unknown> | null {\n return this._windows().find(r => r.id === id) ?? null;\n }\n\n /**\n * Drop the persisted geometry for a window so the next open uses the\n * config defaults again. Matches `WrWindowConfig.storage` exactly.\n */\n clearPersistedPosition(cfg: WrWindowStorageConfig): void {\n this.storage.remove(storageKey(cfg));\n }\n\n // Workspace save/restore\n //\n // A workspace is a snapshot of every open window's id + state +\n // geometry. Reopening is the consumer's job (component identities\n // aren't serialisable), so `restoreLayout` returns the captured\n // snapshots and a helper that re-applies geometry once the windows\n // have been opened again.\n\n /** Snapshot of one window — what `saveLayout` writes / `restoreLayout` returns. */\n private layoutKey(name: string): string {\n return `wr:window-layout:${name}`;\n }\n\n /**\n * Persist the geometry + state of every open programmatic window\n * under `name`. Pair with `restoreLayout(name)` after re-opening the\n * matching components.\n */\n saveLayout(name: string): void {\n // The RAW geometry, not the live one. `ref.x()` / `ref.width()` report what\n // is on screen — a maximized window measures the viewport, a minimized one\n // measures its collapsed header — so saving those threw away the size the\n // user actually chose. Restoring then re-maximized over viewport-sized\n // \"restore\" geometry, and \"Restore down\" left the window filling the screen\n // with no way back; a minimized window came back from the taskbar as a stub\n // clamped to `minHeight`. The window knows the real numbers all along.\n const snapshot: WrWindowLayoutSnapshot[] = this._windows().map(ref => ({\n id: ref.id,\n state: ref.state(),\n x: ref._model.x(),\n y: ref._model.y(),\n width: ref._model.width(),\n height: ref._model.height(),\n title: ref.title(),\n snap: ref._model.snap(),\n }));\n this.storage.set(this.layoutKey(name), snapshot);\n }\n\n /** Read a saved workspace. Returns `null` when no snapshot is found. */\n readLayout(name: string): readonly WrWindowLayoutSnapshot[] | null {\n return this.storage.get(this.layoutKey(name));\n }\n\n /**\n * Apply a saved workspace.\n *\n * Each saved entry is matched to a currently-open window by `id`. For\n * matches, the geometry / state / title is re-applied immediately.\n * For misses, the optional `open` callback is invoked so the consumer\n * can re-open the right component for that id — the freshly-opened\n * window opens straight at the saved geometry and in the saved state, with\n * no cascade flicker — fitted into the work area when this viewport is\n * smaller than the one the layout was saved on.\n *\n * ```ts\n * manager.restoreLayout('default', (id, snap) => {\n * if (id.startsWith('editor:')) {\n * manager.open(EditorComponent, { id, title: snap.title, data: ... });\n * }\n * });\n * ```\n */\n restoreLayout(name: string, open?: (id: string, snapshot: { readonly title: string }) => void): void {\n const snapshot = this.readLayout(name);\n if (!snapshot) return;\n\n for (const snap of snapshot) {\n const existing = this.findById(snap.id);\n if (existing) {\n this.applyRestore(existing, snap);\n continue;\n }\n if (!open) continue;\n // Stash the geometry so the next `open()` call with this id\n // consumes it as the seed instead of cascading.\n this.pendingRestores.set(snap.id, snap);\n open(snap.id, { title: snap.title });\n // Belt + braces: if the opener didn't actually open a window (or\n // opened with a different id), drop the stale pending entry so it\n // doesn't ambush a future open.\n if (!this.findById(snap.id)) this.pendingRestores.delete(snap.id);\n }\n }\n\n private applyRestore(ref: AnyRef, snap: WrWindowLayoutSnapshot): void {\n // Back to a known 'normal' baseline first, then the geometry, the snap and\n // the state, each written once — the toggles would un-minimize a window\n // that was already minimized.\n const m = ref._model;\n m.restore();\n if (snap.title) m.title.set(snap.title);\n m.resizeTo(snap.width, snap.height);\n m.moveTo(snap.x, snap.y);\n if (snap.snap && snap.snap !== 'top') m.snap.set(snap.snap);\n if (snap.state !== 'normal') m.setState(snap.state);\n }\n\n /** Drop a saved workspace. */\n clearLayout(name: string): void {\n this.storage.remove(this.layoutKey(name));\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directionality } from '@angular/cdk/bidi';\nimport { coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n ViewEncapsulation,\n afterNextRender,\n afterRenderEffect,\n computed,\n inject,\n input,\n signal,\n viewChild,\n viewChildren,\n} from '@angular/core';\n\nimport { WrDropdown, WrDropdownItem, WrDropdownMenu } from 'ngwr/dropdown';\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\n\nimport { WrWindowManager } from './services/window-manager';\nimport type { WrWindowTaskbarShow } from './types';\nimport type { WrWindowRef } from './window-ref';\n\ntype AnyRef = WrWindowRef<unknown, unknown>;\n\n/**\n * Stands in for the consumer input `useI18nText` expects — the taskbar exposes no\n * label inputs. Read reactively rather than once at construction: the rail is as\n * long-lived as the app, so a catalog that arrives later, or a locale switch, has to\n * reach it.\n */\nconst NO_OVERRIDE = signal<string | null>(null).asReadonly();\n\nconst NO_RESERVE = { top: 0, bottom: 0 } as const;\n\n/**\n * What the rail has to fit its tabs into, in px: the width inside its padding and\n * border, the gap between two buttons, the width of the \"+N\" button and the width\n * each window's tab takes at its own title, by window id. `null` where nothing is\n * laid out — on the server, in a hidden taskbar, under jsdom — and then only\n * `maxTabs` folds.\n */\ninterface Room {\n readonly width: number;\n readonly gap: number;\n readonly more: number;\n readonly tabs: ReadonlyMap<string, number>;\n}\n\nconst sameTabs = (a: ReadonlyMap<string, number>, b: ReadonlyMap<string, number>): boolean =>\n a.size === b.size && [...a].every(([id, width]) => b.get(id) === width);\n\nconst sameRoom = (a: Room | null, b: Room | null): boolean =>\n a === b || (!!a && !!b && a.width === b.width && a.gap === b.gap && a.more === b.more && sameTabs(a.tabs, b.tabs));\n\n/** `null` and an empty attribute leave the width to decide; any number keeps at least one tab. */\nconst maxTabsAttr = (value: unknown): number | null =>\n value === null || value === undefined || value === ''\n ? null\n : Math.max(1, Math.trunc(coerceNumberProperty(value, 1)));\n\n/**\n * OS-style window taskbar. Drop one anywhere in the app — typically\n * fixed to the bottom of the viewport — and it lists the windows\n * `WrWindowManager.open()` has handed out: the minimized ones by default,\n * every open one with `show=\"all\"`. Clicking a tab switches to its window;\n * with `show=\"all\"`, clicking the active window's tab minimizes it. The close\n * glyph dismisses a window without restoring it.\n *\n * The rail is one Tab stop, a toolbar: the arrow keys move between its\n * buttons, Home and End jump to the ends.\n *\n * Focus follows the window in and out of the rail: minimizing a window\n * that holds focus puts focus on its tab here, and restoring it from the\n * tab moves focus into the window.\n *\n * While it shows tabs, the rail reserves its strip of the viewport, so a\n * maximized or snapped window stops short of it.\n *\n * The rail stays one row. A tab is as wide as its title, up to\n * `--wr-window-taskbar-tab-max-width`, and the tabs that do not fit — or every\n * one past `maxTabs` — fold under a \"+N\" button at the end, which opens them as\n * a menu. In `show=\"all\"` the active window's tab is never folded.\n *\n * Windows opted out via `config.taskbar = false` never show up here.\n *\n * @example\n * ```html\n * <wr-window-taskbar />\n * <wr-window-taskbar position=\"top\" />\n * <wr-window-taskbar show=\"all\" />\n * <wr-window-taskbar show=\"all\" [maxTabs]=\"6\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/window\n */\n@Component({\n selector: 'wr-window-taskbar',\n templateUrl: './window-taskbar.html',\n imports: [WrDropdown, WrDropdownMenu, WrDropdownItem],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'classes()',\n role: 'toolbar',\n '[attr.aria-label]': 'railLabel()',\n '(keydown)': 'onKeydown($event)',\n '(focusin)': 'onFocusIn($event)',\n },\n})\nexport class WrWindowTaskbar {\n // Four English literals lived in this component's markup, next to a catalog that\n // already carried `window.close`. A `toolbar` with no name and tabs announced in\n // the wrong language are both invisible on screen.\n private readonly minimizedLabel = useI18nText(NO_OVERRIDE, 'window.taskbar', 'Minimized windows');\n private readonly allLabel = useI18nText(NO_OVERRIDE, 'window.taskbarAll', 'Open windows');\n /** @internal */ protected readonly closeLabel = useI18nText(NO_OVERRIDE, 'window.closeWindow', 'Close window');\n /** @internal */ protected readonly untitled = useI18nText(NO_OVERRIDE, 'window.untitled', 'Untitled');\n /** @internal */ protected readonly restoreLabel = useI18nFormatter('window.restoreWindow', 'Restore {{title}}');\n /** @internal */ protected readonly moreLabel = useI18nFormatter('window.taskbarMore', 'More windows: {{count}}');\n\n /** Edge the taskbar pins itself to. @default 'bottom' */\n readonly position = input<'top' | 'bottom'>('bottom');\n\n /**\n * Which windows the rail lists: the minimized ones, or every open one with\n * the active window marked (since v15.1). @default 'minimized'\n */\n readonly show = input<WrWindowTaskbarShow>('minimized');\n\n /**\n * The most tabs the rail shows; the rest fold under a \"+N\" button that opens\n * them as a menu (since v15.1). The width folds tabs too, whatever this says:\n * the tabs that do not fit beside the button at their own width go under it.\n * `null` leaves it to the width alone.\n * @default null\n */\n readonly maxTabs = input<number | null, unknown>(null, { transform: maxTabsAttr });\n\n private readonly manager = inject(WrWindowManager);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n private readonly dir = inject(Directionality, { optional: true });\n\n /** @internal */ protected readonly railLabel = computed(() =>\n this.show() === 'all' ? this.allLabel() : this.minimizedLabel()\n );\n\n /** @internal — the windows the rail lists, in the order they opened. */\n protected readonly items = computed(() =>\n this.show() === 'all' ? this.manager.windows().filter(w => w.taskbarVisible) : this.manager.minimized()\n );\n\n /** What the rail has to fit its tabs into — see {@link Room}. */\n private readonly room = signal<Room | null>(null, { equal: sameRoom });\n\n /**\n * The tabs the rail draws, in opening order: all of them while they fit and\n * `maxTabs` allows it, otherwise the most that fit beside the \"+N\" button,\n * never more than `maxTabs` and never fewer than one. The active window's tab\n * takes the last place when it would otherwise fold, so the one tab\n * `show=\"all\"` marks is always in reach. A tab not measured yet counts as\n * nothing, and the pass after its first render corrects that.\n */\n protected readonly visible = computed(() => {\n const items = this.items();\n const max = this.maxTabs() ?? Infinity;\n const room = this.room();\n const fits = (shown: readonly AnyRef[], more: boolean): boolean => {\n if (room === null) return true;\n let need = Math.max(0, shown.length - 1) * room.gap + (more ? room.gap + room.more : 0);\n for (const ref of shown) need += room.tabs.get(ref.id) ?? 0;\n // No slack beyond float noise: a row the rail accepts must not overflow,\n // or its tabs squeeze and read differently the next pass.\n return need <= room.width + 0.01;\n };\n if (items.length <= max && fits(items, false)) return items;\n const current = items.find(ref => this.isCurrent(ref));\n const first = (count: number): AnyRef[] => {\n const shown = items.slice(0, count);\n if (current && !shown.includes(current)) shown[count - 1] = current;\n return shown;\n };\n for (let count = Math.min(max, items.length - 1); count > 1; count--) {\n const shown = first(count);\n if (fits(shown, true)) return shown;\n }\n return first(1);\n });\n\n /** @internal — each listed window's place among the drawn tabs, absent while it is folded. */\n protected readonly slots = computed(() => new Map(this.visible().map((ref, index) => [ref, index])));\n\n /** @internal — the windows under the \"+N\" button, in opening order. */\n protected readonly folded = computed(() => {\n const visible = this.visible();\n return this.items().filter(ref => !visible.includes(ref));\n });\n\n /** The \"+N\" menu opens away from the edge the rail is pinned to. */\n protected readonly menuPosition = computed(() => (this.position() === 'top' ? 'bottom-end' : 'top-end'));\n\n protected readonly classes = computed(() => `wr-window-taskbar wr-window-taskbar--${this.position()}`);\n\n /**\n * One row per entry of `items()`, in the same order. A folded window keeps its\n * tab, laid out but hidden, which is how the rail knows its width.\n */\n private readonly tabs = viewChildren<ElementRef<HTMLElement>>('tab');\n private readonly more = viewChild<ElementRef<HTMLButtonElement>>('more');\n\n /**\n * The rail's one Tab stop, as an index into its buttons: two per drawn tab,\n * restore then close, and the \"+N\" button last.\n */\n private readonly rovingIndex = signal(0);\n private readonly stop = computed(() => {\n const buttons = this.visible().length * 2 + (this.folded().length > 0 ? 1 : 0);\n return Math.max(0, Math.min(this.rovingIndex(), buttons - 1));\n });\n\n /** The strip of the viewport the rail covers while it shows tabs. */\n private readonly reserve = signal<{ readonly top: number; readonly bottom: number }>(NO_RESERVE, {\n equal: (a, b) => a.top === b.top && a.bottom === b.bottom,\n });\n\n constructor() {\n // So a window minimized with focus inside can hand it to its tab here, a\n // window closed from its tab knows the focus there was its own, and a\n // maximized window stops short of the rail.\n const unregister = this.manager._registerTaskbar({\n // A folded window's place in the rail is the \"+N\" button it sits under.\n tabFor: ref => {\n if (this.folded().includes(ref)) return this.more()?.nativeElement ?? null;\n const index = this.items().indexOf(ref);\n return index >= 0 ? (this.tabs()[index]?.nativeElement ?? null) : null;\n },\n settling: ref => {\n const room = this.room();\n const index = this.items().indexOf(ref);\n if (room === null || index < 0) return false;\n if (!room.tabs.has(ref.id)) return true;\n if (this.folded().includes(ref)) return !this.more();\n return !!this.tabs()[index]?.nativeElement.classList.contains('wr-window-taskbar__tab--folded');\n },\n contains: node => this.host.contains(node),\n reserve: this.reserve.asReadonly(),\n });\n const destroyRef = inject(DestroyRef);\n destroyRef.onDestroy(unregister);\n\n // After the render that adds or removes the rail or a tab, retitles a tab\n // or moves the rail to the other edge — and again whenever the host, the\n // rail or the viewport changes size, which is also how a late web font\n // reaches the widths.\n let observer: ResizeObserver | null = null;\n let observedRail: HTMLElement | null = null;\n afterRenderEffect(() => {\n for (const ref of this.items()) this.tabTitle(ref);\n void this.folded().length;\n this.position();\n const rail = this.host.querySelector<HTMLElement>('.wr-window-taskbar__rail');\n if (observer && rail !== observedRail) {\n if (observedRail) observer.unobserve(observedRail);\n if (rail) observer.observe(rail);\n }\n observedRail = rail;\n this.measure();\n });\n afterNextRender(() => {\n const measure = (): void => this.measure();\n observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(measure);\n observer?.observe(this.host);\n if (observedRail) observer?.observe(observedRail);\n window.addEventListener('resize', measure, { passive: true });\n destroyRef.onDestroy(() => {\n observer?.disconnect();\n window.removeEventListener('resize', measure);\n });\n });\n }\n\n /** A window with no title still needs a name in the rail. */\n protected tabTitle(ref: AnyRef): string {\n return ref.title() || this.untitled();\n }\n\n /** Whether `ref` is the active window and on screen — what `show=\"all\"` marks. */\n protected isCurrent(ref: AnyRef): boolean {\n return ref.isActive() && ref.state() !== 'minimized';\n }\n\n /** A minimized window's tab restores it; in `show=\"all\"` the others' tabs switch to their window. */\n protected tabLabel(ref: AnyRef): string {\n const title = this.tabTitle(ref);\n return this.show() === 'all' && ref.state() !== 'minimized' ? title : this.restoreLabel({ title });\n }\n\n protected tabIndex(button: number): number {\n return button >= 0 && button === this.stop() ? 0 : -1;\n }\n\n protected press(ref: AnyRef): void {\n // The active window's own tab minimizes it, as on every desktop taskbar.\n // Focus is on this tab, not in the window, so it stays here.\n if (this.show() === 'all' && this.isCurrent(ref)) {\n ref.minimize();\n return;\n }\n // Back from the taskbar in the state it was minimized from, raised, and\n // focused on the control it had last — the tab this was pressed on may be\n // about to leave the rail, which would drop focus on `<body>`.\n ref.activate();\n }\n\n /** A window picked from the \"+N\" menu: the menu closes and the window comes forward, as from its tab. */\n protected pick(ref: AnyRef, menu: WrDropdown): void {\n menu.close();\n this.press(ref);\n }\n\n protected close(ref: AnyRef, event: Event): void {\n event.stopPropagation();\n void ref.close();\n }\n\n /** The toolbar pattern: arrows between buttons, Home and End to the ends, mirrored in RTL. */\n protected onKeydown(event: KeyboardEvent): void {\n const buttons = this.buttons();\n if (buttons.length === 0) return;\n const current = buttons.indexOf(event.target as HTMLButtonElement);\n if (current < 0) return;\n const rtl = this.dir?.value === 'rtl';\n let next: number;\n switch (event.key) {\n case 'ArrowRight':\n next = current + (rtl ? -1 : 1);\n break;\n case 'ArrowLeft':\n next = current + (rtl ? 1 : -1);\n break;\n case 'Home':\n next = 0;\n break;\n case 'End':\n next = buttons.length - 1;\n break;\n default:\n return;\n }\n event.preventDefault();\n next = (next + buttons.length) % buttons.length;\n this.rovingIndex.set(next);\n buttons[next].focus();\n }\n\n /** A click or a script that focuses a button moves the Tab stop with it. */\n protected onFocusIn(event: FocusEvent): void {\n const index = this.buttons().indexOf(event.target as HTMLButtonElement);\n if (index >= 0) this.rovingIndex.set(index);\n }\n\n /** The drawn buttons in order — a folded tab's are hidden and out of the toolbar. */\n private buttons(): HTMLButtonElement[] {\n return [\n ...this.host.querySelectorAll<HTMLButtonElement>(\n '.wr-window-taskbar__tab:not(.wr-window-taskbar__tab--folded) button, .wr-window-taskbar__more'\n ),\n ];\n }\n\n private measure(): void {\n if (typeof window === 'undefined') return;\n this.measureRoom();\n const rect = this.host.getBoundingClientRect();\n if (rect.height <= 0) {\n this.reserve.set(NO_RESERVE);\n return;\n }\n const vh = document.documentElement.clientHeight || window.innerHeight;\n this.reserve.set(\n this.position() === 'top'\n ? { top: Math.ceil(rect.bottom), bottom: 0 }\n : { top: 0, bottom: Math.max(0, Math.ceil(vh - rect.top)) }\n );\n }\n\n /**\n * Read what the rail has to fit into. The host spans the viewport between its\n * insets, so its width is the most the rail can take, and the gap comes from\n * the stylesheet, so a consumer's hook is what the arithmetic uses.\n *\n * A tab's width is the one its title asks for, capped by its `max-width`. Every\n * tab is laid out, a folded one too, so each can be read — and a tab drawn\n * narrower than its title, squeezed as the only one left, is as wide as it is\n * plus the part of the title it clips. That keeps the reading the same however\n * the row is drawn, so a pass never feeds the next one a different answer.\n *\n * The \"+N\" button is measured once it is drawn — until then a tab's height\n * stands in for its width, and the next pass corrects it. That converges: a\n * wider button folds more, which can only keep its count's digits or add one.\n */\n private measureRoom(): void {\n const rail = this.host.querySelector<HTMLElement>('.wr-window-taskbar__rail');\n const items = this.items();\n const tabs = this.tabs().map(tab => tab.nativeElement);\n const width = this.host.clientWidth;\n if (!rail || tabs.length === 0 || width <= 0) {\n this.room.set(null);\n return;\n }\n // A render is on its way that will draw the tabs `items()` lists; measure that one.\n if (tabs.length !== items.length) return;\n const railStyle = getComputedStyle(rail);\n const px = (value: string): number => parseFloat(value) || 0;\n const inner =\n width -\n px(railStyle.paddingInlineStart) -\n px(railStyle.paddingInlineEnd) -\n px(railStyle.borderInlineStartWidth) -\n px(railStyle.borderInlineEndWidth);\n const widths = new Map<string, number>();\n tabs.forEach((tab, index) => {\n const width = tab.getBoundingClientRect().width;\n const cap = getComputedStyle(tab).maxWidth;\n // A cap that depends on the box it sits in — a percentage, a calc() with\n // one — resolves against the rail for a drawn tab and the host for a folded\n // one, so there is no width of the tab's own to recover: take it as drawn.\n const fixed = cap.endsWith('px');\n if (!fixed && cap !== 'none' && cap !== '') {\n widths.set(items[index].id, width);\n return;\n }\n // Scroll and client widths are whole pixels, so a clip of one is rounding,\n // not a title the tab is too narrow for.\n const title = tab.querySelector<HTMLElement>('.wr-window-taskbar__tab-title');\n const clipped = title ? title.scrollWidth - title.clientWidth : 0;\n const natural = width + (clipped > 1 ? clipped : 0);\n widths.set(items[index].id, fixed ? Math.min(natural, parseFloat(cap)) : natural);\n });\n const more = this.more()?.nativeElement.getBoundingClientRect().width ?? tabs[0].getBoundingClientRect().height;\n this.room.set({ width: inner, gap: px(railStyle.columnGap), more, tabs: widths });\n }\n}\n","@if (items().length > 0) {\n <div class=\"wr-window-taskbar__rail\">\n @for (ref of items(); track ref.id) {\n @let slot = slots().get(ref) ?? -1;\n <!--\n Two SIBLING buttons in a plain container, not a close button nested\n inside the tab. The close used to be a `role=\"button\"` span with\n `tabindex=\"0\"` inside the tab's own `<button>` — interactive content\n inside interactive content, which the HTML parser and `nested-interactive`\n both object to. Nothing caught it: a taskbar tab exists only while a\n window is minimized, and the a11y sweep reads prerendered HTML, where the\n rail is not rendered at all.\n -->\n <!--\n A folded window keeps its tab, hidden and out of the row but laid out,\n so the rail can read the width it would take to draw it again.\n -->\n <div\n #tab\n class=\"wr-window-taskbar__tab\"\n [class.wr-window-taskbar__tab--active]=\"isCurrent(ref)\"\n [class.wr-window-taskbar__tab--minimized]=\"ref.state() === 'minimized'\"\n [class.wr-window-taskbar__tab--folded]=\"slot < 0\"\n [attr.inert]=\"slot < 0 ? '' : null\"\n >\n <button\n type=\"button\"\n class=\"wr-window-taskbar__tab-restore\"\n [attr.aria-label]=\"tabLabel(ref)\"\n [attr.aria-pressed]=\"show() === 'all' ? isCurrent(ref) : null\"\n [attr.tabindex]=\"tabIndex(slot < 0 ? -1 : slot * 2)\"\n (click)=\"press(ref)\"\n >\n <span class=\"wr-window-taskbar__tab-title\">{{ tabTitle(ref) }}</span>\n </button>\n <button\n type=\"button\"\n class=\"wr-window-taskbar__tab-close\"\n [attr.aria-label]=\"closeLabel()\"\n [attr.tabindex]=\"tabIndex(slot < 0 ? -1 : slot * 2 + 1)\"\n (click)=\"close(ref, $event)\"\n >\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M1 1 L9 9 M9 1 L1 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </button>\n </div>\n }\n @if (folded().length > 0) {\n <button\n #more\n #fold=\"wrDropdown\"\n type=\"button\"\n class=\"wr-window-taskbar__more\"\n [wrDropdown]=\"foldMenu\"\n [position]=\"menuPosition()\"\n [attr.aria-label]=\"moreLabel({ count: folded().length })\"\n [attr.tabindex]=\"tabIndex(visible().length * 2)\"\n >\n +{{ folded().length }}\n </button>\n <wr-dropdown-menu #foldMenu>\n @for (ref of folded(); track ref.id) {\n <wr-dropdown-item\n class=\"wr-window-taskbar__fold-item\"\n [class.wr-window-taskbar__fold-item--minimized]=\"ref.state() === 'minimized'\"\n [attr.aria-label]=\"tabLabel(ref)\"\n (click)=\"pick(ref, fold)\"\n >\n {{ tabTitle(ref) }}\n </wr-dropdown-item>\n }\n </wr-dropdown-menu>\n }\n </div>\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type WrFeature, wrFeature } from 'ngwr/utils';\n\nimport { WR_WINDOW_DEFAULTS } from './tokens';\nimport type { WrWindowDefaults } from './types';\n\n/**\n * App-wide window defaults, as a feature of `provideWr()` — today the work area\n * every window keeps inside, so maximized windows stop short of an app header.\n * A window's own `WrWindowConfig.bounds` still wins.\n *\n * Bootstrap only: `WrWindowManager` is root-provided and reads it once, from\n * the root injector, so in a route's `providers` it changes nothing.\n *\n * @example\n * ```ts\n * import { provideWr } from 'ngwr';\n * import { withWindows } from 'ngwr/window';\n *\n * bootstrapApplication(App, {\n * providers: [provideWr(withWindows({ bounds: { top: 64 } }))],\n * });\n * ```\n */\nexport function withWindows(defaults: WrWindowDefaults): WrFeature<'windows'> {\n return wrFeature('windows', [{ provide: WR_WINDOW_DEFAULTS, useValue: defaults }]);\n}\n"],"mappings":"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"}
|