@bitstack/ng-boundary 14.0.6-alpha.1 → 14.0.6-alpha.2

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.
@@ -1,6 +1,6 @@
1
- import { Component, EventEmitter, inject, Input, Output, } from '@angular/core';
1
+ import { Component, ElementRef, EventEmitter, inject, Input, Output, } from '@angular/core';
2
2
  import { BreakpointObserver } from '@angular/cdk/layout';
3
- import { Subject, takeUntil } from 'rxjs';
3
+ import { debounceTime, fromEvent, Subject, takeUntil } from 'rxjs';
4
4
  import { BsBoundaryContextService } from './bs-boundary-context.service';
5
5
  import * as i0 from "@angular/core";
6
6
  export class BsBoundary {
@@ -11,6 +11,7 @@ export class BsBoundary {
11
11
  this.orientationChange = new EventEmitter();
12
12
  this.breakpointObserver = inject(BreakpointObserver);
13
13
  this.boundaryContext = inject(BsBoundaryContextService);
14
+ this.elementRef = inject(ElementRef);
14
15
  this.destroy$ = new Subject();
15
16
  }
16
17
  get isLandscape() {
@@ -18,6 +19,9 @@ export class BsBoundary {
18
19
  }
19
20
  ngOnInit() {
20
21
  this.setupBreakpointObserver();
22
+ this.setupResizeObserver();
23
+ // 延遲執行以確保 CSS 變數已經設定
24
+ setTimeout(() => this.updateBoundaryCalculations(), 0);
21
25
  }
22
26
  ngOnDestroy() {
23
27
  this.destroy$.next();
@@ -30,11 +34,15 @@ export class BsBoundary {
30
34
  if (this.lockOrientation === 'landscape') {
31
35
  this.boundaryContext.setIsLandscape(true);
32
36
  this.orientationChange.emit(true);
37
+ // 鎖定方向後也需要更新計算
38
+ setTimeout(() => this.updateBoundaryCalculations(), 0);
33
39
  return;
34
40
  }
35
41
  if (this.lockOrientation === 'portrait') {
36
42
  this.boundaryContext.setIsLandscape(false);
37
43
  this.orientationChange.emit(false);
44
+ // 鎖定方向後也需要更新計算
45
+ setTimeout(() => this.updateBoundaryCalculations(), 0);
38
46
  return;
39
47
  }
40
48
  this.breakpointObserver
@@ -43,16 +51,62 @@ export class BsBoundary {
43
51
  .subscribe(result => {
44
52
  this.boundaryContext.setIsLandscape(result.matches);
45
53
  this.orientationChange.emit(result.matches);
54
+ this.updateBoundaryCalculations();
46
55
  });
47
56
  }
57
+ /**
58
+ * 監控視口大小變化
59
+ */
60
+ setupResizeObserver() {
61
+ fromEvent(window, 'resize')
62
+ .pipe(debounceTime(100), takeUntil(this.destroy$))
63
+ .subscribe(() => {
64
+ this.updateBoundaryCalculations();
65
+ });
66
+ }
67
+ /**
68
+ * 更新邊界計算(支援 Chrome 74,不使用 CSS min/max 函數)
69
+ */
70
+ updateBoundaryCalculations() {
71
+ const hostElement = this.elementRef.nativeElement;
72
+ const computedStyle = getComputedStyle(hostElement);
73
+ // 讀取 CSS 變數
74
+ const designWidth = parseFloat(computedStyle.getPropertyValue('--design-width') || '1920');
75
+ const designHeight = parseFloat(computedStyle.getPropertyValue('--design-height') || '1080');
76
+ const vw100 = parseFloat(computedStyle.getPropertyValue('--vw100') || `${window.innerWidth}`);
77
+ const vh100 = parseFloat(computedStyle.getPropertyValue('--vh100') || `${window.innerHeight}`);
78
+ // 計算比例
79
+ const landscapeRatio = designWidth / designHeight;
80
+ const portraitRatio = designHeight / designWidth;
81
+ // 根據方向計算邊界最大值
82
+ const isLandscape = this.isLandscape;
83
+ const boundaryMaxWidth = isLandscape
84
+ ? vh100 * portraitRatio
85
+ : vh100 * landscapeRatio;
86
+ const boundaryMaxHeight = isLandscape
87
+ ? vw100 * landscapeRatio
88
+ : vw100 * portraitRatio;
89
+ // 計算實際邊界寬高(模擬 CSS min 函數)
90
+ const boundaryWidth = Math.min(vw100, boundaryMaxWidth);
91
+ const boundaryHeight = Math.min(vh100, boundaryMaxHeight);
92
+ // 計算設計基準
93
+ const designBaseWidth = isLandscape ? designHeight : designWidth;
94
+ const designBaseHeight = isLandscape ? designWidth : designHeight;
95
+ // 計算 px2vw 比例
96
+ const px2vwRatio = boundaryWidth / designBaseWidth;
97
+ // 設定 CSS 變數到 host 元素
98
+ hostElement.style.setProperty('--boundary-width', `${boundaryWidth}px`);
99
+ hostElement.style.setProperty('--boundary-height', `${boundaryHeight}px`);
100
+ hostElement.style.setProperty('--px2vw-ratio', `${px2vwRatio}`);
101
+ }
48
102
  }
49
103
  BsBoundary.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: BsBoundary, deps: [], target: i0.ɵɵFactoryTarget.Component });
50
- BsBoundary.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: BsBoundary, isStandalone: true, selector: "bs-boundary", inputs: { isFixedCenter: "isFixedCenter", pointerEventsNone: "pointerEventsNone", lockOrientation: "lockOrientation", forwardStyle: "forwardStyle" }, outputs: { orientationChange: "orientationChange" }, host: { properties: { "class.landscape": "isLandscape" } }, providers: [BsBoundaryContextService], ngImport: i0, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: ["@charset \"UTF-8\";:host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:100%;height:100%;max-width:var(--boundary-width);max-height:var(--boundary-height)}.boundary-wrapper.pointerEventsNone{pointer-events:none}.boundary-wrapper{--active-ratio: var(--landscape-ratio);--active-inv-ratio: var(--portrait-ratio);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio));--px2vw-ratio: calc(var(--boundary-width) / var(--design-base-width));--design-base-width: var(--design-width);--design-base-height: var(--design-height)}@media (min-aspect-ratio: 16/9){.boundary-wrapper{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.boundary-wrapper.landscape{--active-ratio: var(--portrait-ratio);--active-inv-ratio: var(--landscape-ratio);--design-base-width: var(--design-height);--design-base-height: var(--design-width);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio))}@media (min-aspect-ratio: 9/16){.boundary-wrapper.landscape{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] });
104
+ BsBoundary.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: BsBoundary, isStandalone: true, selector: "bs-boundary", inputs: { isFixedCenter: "isFixedCenter", pointerEventsNone: "pointerEventsNone", lockOrientation: "lockOrientation", forwardStyle: "forwardStyle" }, outputs: { orientationChange: "orientationChange" }, host: { properties: { "class.landscape": "isLandscape" } }, providers: [BsBoundaryContextService], ngImport: i0, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: [":host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:var(--vw100);height:var(--vh100);max-width:calc(var(--vh100) * var(--landscape-ratio));max-height:calc(var(--vw100) * var(--portrait-ratio))}.boundary-wrapper.pointerEventsNone{pointer-events:none}:host.landscape .boundary-wrapper{max-width:calc(var(--vh100) * var(--portrait-ratio));max-height:calc(var(--vw100) * var(--landscape-ratio))}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] });
51
105
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: BsBoundary, decorators: [{
52
106
  type: Component,
53
107
  args: [{ selector: 'bs-boundary', standalone: true, providers: [BsBoundaryContextService], host: {
54
108
  '[class.landscape]': 'isLandscape'
55
- }, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: ["@charset \"UTF-8\";:host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:100%;height:100%;max-width:var(--boundary-width);max-height:var(--boundary-height)}.boundary-wrapper.pointerEventsNone{pointer-events:none}.boundary-wrapper{--active-ratio: var(--landscape-ratio);--active-inv-ratio: var(--portrait-ratio);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio));--px2vw-ratio: calc(var(--boundary-width) / var(--design-base-width));--design-base-width: var(--design-width);--design-base-height: var(--design-height)}@media (min-aspect-ratio: 16/9){.boundary-wrapper{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.boundary-wrapper.landscape{--active-ratio: var(--portrait-ratio);--active-inv-ratio: var(--landscape-ratio);--design-base-width: var(--design-height);--design-base-height: var(--design-width);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio))}@media (min-aspect-ratio: 9/16){.boundary-wrapper.landscape{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] }]
109
+ }, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: [":host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:var(--vw100);height:var(--vh100);max-width:calc(var(--vh100) * var(--landscape-ratio));max-height:calc(var(--vw100) * var(--portrait-ratio))}.boundary-wrapper.pointerEventsNone{pointer-events:none}:host.landscape .boundary-wrapper{max-width:calc(var(--vh100) * var(--portrait-ratio));max-height:calc(var(--vw100) * var(--landscape-ratio))}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] }]
56
110
  }], propDecorators: { isFixedCenter: [{
57
111
  type: Input
58
112
  }], pointerEventsNone: [{
@@ -64,4 +118,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
64
118
  }], orientationChange: [{
65
119
  type: Output
66
120
  }] } });
67
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnMtYm91bmRhcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9iaXRzdGFjay1uZy1ib3VuZGFyeS9zcmMvbGliL2JzLWJvdW5kYXJ5LnRzIiwiLi4vLi4vLi4vLi4vcHJvamVjdHMvYml0c3RhY2stbmctYm91bmRhcnkvc3JjL2xpYi90ZW1wbGF0ZS5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBRUwsTUFBTSxHQUNQLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBQyxPQUFPLEVBQUUsU0FBUyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQ3hDLE9BQU8sRUFBQyx3QkFBd0IsRUFBQyxNQUFNLCtCQUErQixDQUFDOztBQVl2RSxNQUFNLE9BQU8sVUFBVTtJQVZ2QjtRQVlhLGtCQUFhLEdBQWEsS0FBSyxDQUFDO1FBQ2hDLHNCQUFpQixHQUFhLEtBQUssQ0FBQztRQUNwQyxvQkFBZSxHQUFzQixNQUFNLENBQUM7UUFHM0Msc0JBQWlCLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztRQUVsRCx1QkFBa0IsR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUNoRCxvQkFBZSxHQUFHLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBQ25ELGFBQVEsR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO0tBdUMxQztJQXJDRyxJQUFJLFdBQVc7UUFDWCxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsY0FBYyxFQUFFLENBQUM7SUFDakQsQ0FBQztJQUVELFFBQVE7UUFDSixJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztJQUNuQyxDQUFDO0lBRUQsV0FBVztRQUNQLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUM3QixDQUFDO0lBRUQ7O09BRUc7SUFDSCx1QkFBdUI7UUFDbkIsSUFBSSxJQUFJLENBQUMsZUFBZSxLQUFLLFdBQVcsRUFBRTtZQUN0QyxJQUFJLENBQUMsZUFBZSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMxQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2xDLE9BQU87U0FDVjtRQUVELElBQUksSUFBSSxDQUFDLGVBQWUsS0FBSyxVQUFVLEVBQUU7WUFDckMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDM0MsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNuQyxPQUFPO1NBQ1Y7UUFFRCxJQUFJLENBQUMsa0JBQWtCO2FBQ2xCLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQzthQUNuQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUM5QixTQUFTLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDaEIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3BELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2hELENBQUMsQ0FBQyxDQUFDO0lBQ1gsQ0FBQzs7dUdBakRRLFVBQVU7MkZBQVYsVUFBVSxpVUFMUixDQUFDLHdCQUF3QixDQUFDLDBCQ2xCekMsd01BUUE7MkZEZWEsVUFBVTtrQkFWdEIsU0FBUzsrQkFDSSxhQUFhLGNBRVgsSUFBSSxhQUVMLENBQUMsd0JBQXdCLENBQUMsUUFDL0I7d0JBQ0YsbUJBQW1CLEVBQUUsYUFBYTtxQkFDckM7OEJBSVEsYUFBYTtzQkFBckIsS0FBSztnQkFDRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUVJLGlCQUFpQjtzQkFBMUIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBpbmplY3QsXG4gIElucHV0LCBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7VE9yaWVudGF0aW9uTW9kZX0gZnJvbSAnLi9tb2RlbCc7XG5pbXBvcnQge0JyZWFrcG9pbnRPYnNlcnZlcn0gZnJvbSAnQGFuZ3VsYXIvY2RrL2xheW91dCc7XG5pbXBvcnQge1N1YmplY3QsIHRha2VVbnRpbH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge0JzQm91bmRhcnlDb250ZXh0U2VydmljZX0gZnJvbSAnLi9icy1ib3VuZGFyeS1jb250ZXh0LnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2JzLWJvdW5kYXJ5JyxcbiAgICB0ZW1wbGF0ZVVybDogJ3RlbXBsYXRlLmh0bWwnLFxuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgc3R5bGVVcmxzOiBbJy4vc3R5bGVzLnNjc3MnXSxcbiAgICBwcm92aWRlcnM6IFtCc0JvdW5kYXJ5Q29udGV4dFNlcnZpY2VdLFxuICAgIGhvc3Q6IHtcbiAgICAgICAgJ1tjbGFzcy5sYW5kc2NhcGVdJzogJ2lzTGFuZHNjYXBlJ1xuICAgIH1cbn0pXG5leHBvcnQgY2xhc3MgQnNCb3VuZGFyeSBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcblxuICAgIEBJbnB1dCgpIGlzRml4ZWRDZW50ZXI/OiBib29sZWFuID0gZmFsc2U7XG4gICAgQElucHV0KCkgcG9pbnRlckV2ZW50c05vbmU/OiBib29sZWFuID0gZmFsc2U7XG4gICAgQElucHV0KCkgbG9ja09yaWVudGF0aW9uPzogVE9yaWVudGF0aW9uTW9kZSA9ICdhdXRvJztcbiAgICBASW5wdXQoKSBmb3J3YXJkU3R5bGU/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXG4gICAgQE91dHB1dCgpIG9yaWVudGF0aW9uQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuXG4gICAgcHJpdmF0ZSBicmVha3BvaW50T2JzZXJ2ZXIgPSBpbmplY3QoQnJlYWtwb2ludE9ic2VydmVyKTtcbiAgICBwcml2YXRlIGJvdW5kYXJ5Q29udGV4dCA9IGluamVjdChCc0JvdW5kYXJ5Q29udGV4dFNlcnZpY2UpO1xuICAgIHByaXZhdGUgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gICAgZ2V0IGlzTGFuZHNjYXBlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5ib3VuZGFyeUNvbnRleHQuZ2V0SXNMYW5kc2NhcGUoKTtcbiAgICB9XG5cbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXR1cEJyZWFrcG9pbnRPYnNlcnZlcigpO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRlc3Ryb3kkLm5leHQoKTtcbiAgICAgICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIOebo+aOp+aWueWQkeiuiuWMllxuICAgICAqL1xuICAgIHNldHVwQnJlYWtwb2ludE9ic2VydmVyKCkge1xuICAgICAgICBpZiAodGhpcy5sb2NrT3JpZW50YXRpb24gPT09ICdsYW5kc2NhcGUnKSB7XG4gICAgICAgICAgICB0aGlzLmJvdW5kYXJ5Q29udGV4dC5zZXRJc0xhbmRzY2FwZSh0cnVlKTtcbiAgICAgICAgICAgIHRoaXMub3JpZW50YXRpb25DaGFuZ2UuZW1pdCh0cnVlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmxvY2tPcmllbnRhdGlvbiA9PT0gJ3BvcnRyYWl0Jykge1xuICAgICAgICAgICAgdGhpcy5ib3VuZGFyeUNvbnRleHQuc2V0SXNMYW5kc2NhcGUoZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5vcmllbnRhdGlvbkNoYW5nZS5lbWl0KGZhbHNlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuYnJlYWtwb2ludE9ic2VydmVyXG4gICAgICAgICAgICAub2JzZXJ2ZSgnKG9yaWVudGF0aW9uOiBsYW5kc2NhcGUpJylcbiAgICAgICAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUocmVzdWx0ID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmJvdW5kYXJ5Q29udGV4dC5zZXRJc0xhbmRzY2FwZShyZXN1bHQubWF0Y2hlcyk7XG4gICAgICAgICAgICAgICAgdGhpcy5vcmllbnRhdGlvbkNoYW5nZS5lbWl0KHJlc3VsdC5tYXRjaGVzKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cbn1cbiIsIjxkaXZcbiAgY2xhc3M9XCJib3VuZGFyeS13cmFwcGVyXCJcbiAgW2NsYXNzLmZpeGVkLWNlbnRlcl09XCJpc0ZpeGVkQ2VudGVyXCJcbiAgW2NsYXNzLnBvaW50ZXJFdmVudHNOb25lXT1cInBvaW50ZXJFdmVudHNOb25lXCJcbiAgW3N0eWxlXT1cImZvcndhcmRTdHlsZVwiXG4+XG4gICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG48L2Rpdj5cbiJdfQ==
121
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnMtYm91bmRhcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9iaXRzdGFjay1uZy1ib3VuZGFyeS9zcmMvbGliL2JzLWJvdW5kYXJ5LnRzIiwiLi4vLi4vLi4vLi4vcHJvamVjdHMvYml0c3RhY2stbmctYm91bmRhcnkvc3JjL2xpYi90ZW1wbGF0ZS5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixNQUFNLEVBQ04sS0FBSyxFQUVMLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUN2RCxPQUFPLEVBQUMsWUFBWSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQ2pFLE9BQU8sRUFBQyx3QkFBd0IsRUFBQyxNQUFNLCtCQUErQixDQUFDOztBQVl2RSxNQUFNLE9BQU8sVUFBVTtJQVZ2QjtRQVlhLGtCQUFhLEdBQWEsS0FBSyxDQUFDO1FBQ2hDLHNCQUFpQixHQUFhLEtBQUssQ0FBQztRQUNwQyxvQkFBZSxHQUFzQixNQUFNLENBQUM7UUFHM0Msc0JBQWlCLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztRQUVsRCx1QkFBa0IsR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUNoRCxvQkFBZSxHQUFHLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBQ25ELGVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDaEMsYUFBUSxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7S0F3RzFDO0lBdEdHLElBQUksV0FBVztRQUNYLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUNqRCxDQUFDO0lBRUQsUUFBUTtRQUNKLElBQUksQ0FBQyx1QkFBdUIsRUFB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QUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ3BFLENBQUM7O3VHQW5IUSxVQUFVOzJGQUFWLFVBQVUsaVVBTFIsQ0FBQyx3QkFBd0IsQ0FBQywwQkNuQnpDLHdNQVFBOzJGRGdCYSxVQUFVO2tCQVZ0QixTQUFTOytCQUNJLGFBQWEsY0FFWCxJQUFJLGFBRUwsQ0FBQyx3QkFBd0IsQ0FBQyxRQUMvQjt3QkFDRixtQkFBbUIsRUFBRSxhQUFhO3FCQUNyQzs4QkFJUSxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBRUksaUJBQWlCO3NCQUExQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIGluamVjdCxcbiAgSW5wdXQsIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtUT3JpZW50YXRpb25Nb2RlfSBmcm9tICcuL21vZGVsJztcbmltcG9ydCB7QnJlYWtwb2ludE9ic2VydmVyfSBmcm9tICdAYW5ndWxhci9jZGsvbGF5b3V0JztcbmltcG9ydCB7ZGVib3VuY2VUaW1lLCBmcm9tRXZlbnQsIFN1YmplY3QsIHRha2VVbnRpbH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge0JzQm91bmRhcnlDb250ZXh0U2VydmljZX0gZnJvbSAnLi9icy1ib3VuZGFyeS1jb250ZXh0LnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2JzLWJvdW5kYXJ5JyxcbiAgICB0ZW1wbGF0ZVVybDogJ3RlbXBsYXRlLmh0bWwnLFxuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgc3R5bGVVcmxzOiBbJy4vc3R5bGVzLnNjc3MnXSxcbiAgICBwcm92aWRlcnM6IFtCc0JvdW5kYXJ5Q29udGV4dFNlcnZpY2VdLFxuICAgIGhvc3Q6IHtcbiAgICAgICAgJ1tjbGFzcy5sYW5kc2NhcGVdJzogJ2lzTGFuZHNjYXBlJ1xuICAgIH1cbn0pXG5leHBvcnQgY2xhc3MgQnNCb3VuZGFyeSBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcblxuICAgIEBJbnB1dCgpIGlzRml4ZWRDZW50ZXI/OiBib29sZWFuID0gZmFsc2U7XG4gICAgQElucHV0KCkgcG9pbnRlckV2ZW50c05vbmU/OiBib29sZWFuID0gZmFsc2U7XG4gICAgQElucHV0KCkgbG9ja09yaWVudGF0aW9uPzogVE9yaWVudGF0aW9uTW9kZSA9ICdhdXRvJztcbiAgICBASW5wdXQoKSBmb3J3YXJkU3R5bGU/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXG4gICAgQE91dHB1dCgpIG9yaWVudGF0aW9uQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuXG4gICAgcHJpdmF0ZSBicmVha3BvaW50T2JzZXJ2ZXIgPSBpbmplY3QoQnJlYWtwb2ludE9ic2VydmVyKTtcbiAgICBwcml2YXRlIGJvdW5kYXJ5Q29udGV4dCA9IGluamVjdChCc0JvdW5kYXJ5Q29udGV4dFNlcnZpY2UpO1xuICAgIHByaXZhdGUgZWxlbWVudFJlZiA9IGluamVjdChFbGVtZW50UmVmKTtcbiAgICBwcml2YXRlIGRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIGdldCBpc0xhbmRzY2FwZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYm91bmRhcnlDb250ZXh0LmdldElzTGFuZHNjYXBlKCk7XG4gICAgfVxuXG4gICAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2V0dXBCcmVha3BvaW50T2JzZXJ2ZXIoKTtcbiAgICAgICAgdGhpcy5zZXR1cFJlc2l6ZU9ic2VydmVyKCk7XG4gICAgICAgIC8vIOW7tumBsuWft+ihjOS7peeiuuS/nSBDU1Mg6K6K5pW45bey57aT6Kit5a6aXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy51cGRhdGVCb3VuZGFyeUNhbGN1bGF0aW9ucygpLCAwKTtcbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDnm6PmjqfmlrnlkJHororljJZcbiAgICAgKi9cbiAgICBzZXR1cEJyZWFrcG9pbnRPYnNlcnZlcigpIHtcbiAgICAgICAgaWYgKHRoaXMubG9ja09yaWVudGF0aW9uID09PSAnbGFuZHNjYXBlJykge1xuICAgICAgICAgICAgdGhpcy5ib3VuZGFyeUNvbnRleHQuc2V0SXNMYW5kc2NhcGUodHJ1ZSk7XG4gICAgICAgICAgICB0aGlzLm9yaWVudGF0aW9uQ2hhbmdlLmVtaXQodHJ1ZSk7XG4gICAgICAgICAgICAvLyDpjpblrprmlrnlkJHlvozkuZ/pnIDopoHmm7TmlrDoqIjnrpdcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy51cGRhdGVCb3VuZGFyeUNhbGN1bGF0aW9ucygpLCAwKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmxvY2tPcmllbnRhdGlvbiA9PT0gJ3BvcnRyYWl0Jykge1xuICAgICAgICAgICAgdGhpcy5ib3VuZGFyeUNvbnRleHQuc2V0SXNMYW5kc2NhcGUoZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5vcmllbnRhdGlvbkNoYW5nZS5lbWl0KGZhbHNlKTtcbiAgICAgICAgICAgIC8vIOmOluWumuaWueWQkeW+jOS5n+mcgOimgeabtOaWsOioiOeul1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLnVwZGF0ZUJvdW5kYXJ5Q2FsY3VsYXRpb25zKCksIDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5icmVha3BvaW50T2JzZXJ2ZXJcbiAgICAgICAgICAgIC5vYnNlcnZlKCcob3JpZW50YXRpb246IGxhbmRzY2FwZSknKVxuICAgICAgICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxuICAgICAgICAgICAgLnN1YnNjcmliZShyZXN1bHQgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYm91bmRhcnlDb250ZXh0LnNldElzTGFuZHNjYXBlKHJlc3VsdC5tYXRjaGVzKTtcbiAgICAgICAgICAgICAgICB0aGlzLm9yaWVudGF0aW9uQ2hhbmdlLmVtaXQocmVzdWx0Lm1hdGNoZXMpO1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlQm91bmRhcnlDYWxjdWxhdGlvbnMoKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIOebo+aOp+imluWPo+Wkp+Wwj+iuiuWMllxuICAgICAqL1xuICAgIHNldHVwUmVzaXplT2JzZXJ2ZXIoKSB7XG4gICAgICAgIGZyb21FdmVudCh3aW5kb3csICdyZXNpemUnKVxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgZGVib3VuY2VUaW1lKDEwMCksXG4gICAgICAgICAgICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUJvdW5kYXJ5Q2FsY3VsYXRpb25zKCk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDmm7TmlrDpgornlYzoqIjnrpfvvIjmlK/mj7QgQ2hyb21lIDc077yM5LiN5L2/55SoIENTUyBtaW4vbWF4IOWHveaVuO+8iVxuICAgICAqL1xuICAgIHVwZGF0ZUJvdW5kYXJ5Q2FsY3VsYXRpb25zKCkge1xuICAgICAgICBjb25zdCBob3N0RWxlbWVudCA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50O1xuICAgICAgICBjb25zdCBjb21wdXRlZFN0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZShob3N0RWxlbWVudCk7XG5cbiAgICAgICAgLy8g6K6A5Y+WIENTUyDorormlbhcbiAgICAgICAgY29uc3QgZGVzaWduV2lkdGggPSBwYXJzZUZsb2F0KGNvbXB1dGVkU3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgnLS1kZXNpZ24td2lkdGgnKSB8fCAnMTkyMCcpO1xuICAgICAgICBjb25zdCBkZXNpZ25IZWlnaHQgPSBwYXJzZUZsb2F0KGNvbXB1dGVkU3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgnLS1kZXNpZ24taGVpZ2h0JykgfHwgJzEwODAnKTtcbiAgICAgICAgY29uc3QgdncxMDAgPSBwYXJzZUZsb2F0KGNvbXB1dGVkU3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgnLS12dzEwMCcpIHx8IGAke3dpbmRvdy5pbm5lcldpZHRofWApO1xuICAgICAgICBjb25zdCB2aDEwMCA9IHBhcnNlRmxvYXQoY29tcHV0ZWRTdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCctLXZoMTAwJykgfHwgYCR7d2luZG93LmlubmVySGVpZ2h0fWApO1xuXG4gICAgICAgIC8vIOioiOeul+avlOS+i1xuICAgICAgICBjb25zdCBsYW5kc2NhcGVSYXRpbyA9IGRlc2lnbldpZHRoIC8gZGVzaWduSGVpZ2h0O1xuICAgICAgICBjb25zdCBwb3J0cmFpdFJhdGlvID0gZGVzaWduSGVpZ2h0IC8gZGVzaWduV2lkdGg7XG5cbiAgICAgICAgLy8g5qC55pOa5pa55ZCR6KiI566X6YKK55WM5pyA5aSn5YC8XG4gICAgICAgIGNvbnN0IGlzTGFuZHNjYXBlID0gdGhpcy5pc0xhbmRzY2FwZTtcbiAgICAgICAgY29uc3QgYm91bmRhcnlNYXhXaWR0aCA9IGlzTGFuZHNjYXBlXG4gICAgICAgICAgICA/IHZoMTAwICogcG9ydHJhaXRSYXRpb1xuICAgICAgICAgICAgOiB2aDEwMCAqIGxhbmRzY2FwZVJhdGlvO1xuICAgICAgICBjb25zdCBib3VuZGFyeU1heEhlaWdodCA9IGlzTGFuZHNjYXBlXG4gICAgICAgICAgICA/IHZ3MTAwICogbGFuZHNjYXBlUmF0aW9cbiAgICAgICAgICAgIDogdncxMDAgKiBwb3J0cmFpdFJhdGlvO1xuXG4gICAgICAgIC8vIOioiOeul+Wvpumam+mCiueVjOWvrOmrmO+8iOaooeaTrCBDU1MgbWluIOWHveaVuO+8iVxuICAgICAgICBjb25zdCBib3VuZGFyeVdpZHRoID0gTWF0aC5taW4odncxMDAsIGJvdW5kYXJ5TWF4V2lkdGgpO1xuICAgICAgICBjb25zdCBib3VuZGFyeUhlaWdodCA9IE1hdGgubWluKHZoMTAwLCBib3VuZGFyeU1heEhlaWdodCk7XG5cbiAgICAgICAgLy8g6KiI566X6Kit6KiI5Z+65rqWXG4gICAgICAgIGNvbnN0IGRlc2lnbkJhc2VXaWR0aCA9IGlzTGFuZHNjYXBlID8gZGVzaWduSGVpZ2h0IDogZGVzaWduV2lkdGg7XG4gICAgICAgIGNvbnN0IGRlc2lnbkJhc2VIZWlnaHQgPSBpc0xhbmRzY2FwZSA/IGRlc2lnbldpZHRoIDogZGVzaWduSGVpZ2h0O1xuXG4gICAgICAgIC8vIOioiOeulyBweDJ2dyDmr5TkvotcbiAgICAgICAgY29uc3QgcHgydndSYXRpbyA9IGJvdW5kYXJ5V2lkdGggLyBkZXNpZ25CYXNlV2lkdGg7XG5cbiAgICAgICAgLy8g6Kit5a6aIENTUyDorormlbjliLAgaG9zdCDlhYPntKBcbiAgICAgICAgaG9zdEVsZW1lbnQuc3R5bGUuc2V0UHJvcGVydHkoJy0tYm91bmRhcnktd2lkdGgnLCBgJHtib3VuZGFyeVdpZHRofXB4YCk7XG4gICAgICAgIGhvc3RFbGVtZW50LnN0eWxlLnNldFByb3BlcnR5KCctLWJvdW5kYXJ5LWhlaWdodCcsIGAke2JvdW5kYXJ5SGVpZ2h0fXB4YCk7XG4gICAgICAgIGhvc3RFbGVtZW50LnN0eWxlLnNldFByb3BlcnR5KCctLXB4MnZ3LXJhdGlvJywgYCR7cHgydndSYXRpb31gKTtcbiAgICB9XG59XG4iLCI8ZGl2XG4gIGNsYXNzPVwiYm91bmRhcnktd3JhcHBlclwiXG4gIFtjbGFzcy5maXhlZC1jZW50ZXJdPVwiaXNGaXhlZENlbnRlclwiXG4gIFtjbGFzcy5wb2ludGVyRXZlbnRzTm9uZV09XCJwb2ludGVyRXZlbnRzTm9uZVwiXG4gIFtzdHlsZV09XCJmb3J3YXJkU3R5bGVcIlxuPlxuICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuPC9kaXY+XG4iXX0=
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, EventEmitter, inject, Component, Input, Output } from '@angular/core';
2
+ import { Injectable, EventEmitter, inject, ElementRef, Component, Input, Output } from '@angular/core';
3
3
  import { BreakpointObserver } from '@angular/cdk/layout';
4
- import { BehaviorSubject, Subject, takeUntil } from 'rxjs';
4
+ import { BehaviorSubject, Subject, takeUntil, fromEvent, debounceTime } from 'rxjs';
5
5
 
6
6
  class BsBoundaryContextService {
7
7
  constructor() {
@@ -29,6 +29,7 @@ class BsBoundary {
29
29
  this.orientationChange = new EventEmitter();
30
30
  this.breakpointObserver = inject(BreakpointObserver);
31
31
  this.boundaryContext = inject(BsBoundaryContextService);
32
+ this.elementRef = inject(ElementRef);
32
33
  this.destroy$ = new Subject();
33
34
  }
34
35
  get isLandscape() {
@@ -36,6 +37,9 @@ class BsBoundary {
36
37
  }
37
38
  ngOnInit() {
38
39
  this.setupBreakpointObserver();
40
+ this.setupResizeObserver();
41
+ // 延遲執行以確保 CSS 變數已經設定
42
+ setTimeout(() => this.updateBoundaryCalculations(), 0);
39
43
  }
40
44
  ngOnDestroy() {
41
45
  this.destroy$.next();
@@ -48,11 +52,15 @@ class BsBoundary {
48
52
  if (this.lockOrientation === 'landscape') {
49
53
  this.boundaryContext.setIsLandscape(true);
50
54
  this.orientationChange.emit(true);
55
+ // 鎖定方向後也需要更新計算
56
+ setTimeout(() => this.updateBoundaryCalculations(), 0);
51
57
  return;
52
58
  }
53
59
  if (this.lockOrientation === 'portrait') {
54
60
  this.boundaryContext.setIsLandscape(false);
55
61
  this.orientationChange.emit(false);
62
+ // 鎖定方向後也需要更新計算
63
+ setTimeout(() => this.updateBoundaryCalculations(), 0);
56
64
  return;
57
65
  }
58
66
  this.breakpointObserver
@@ -61,16 +69,62 @@ class BsBoundary {
61
69
  .subscribe(result => {
62
70
  this.boundaryContext.setIsLandscape(result.matches);
63
71
  this.orientationChange.emit(result.matches);
72
+ this.updateBoundaryCalculations();
64
73
  });
65
74
  }
75
+ /**
76
+ * 監控視口大小變化
77
+ */
78
+ setupResizeObserver() {
79
+ fromEvent(window, 'resize')
80
+ .pipe(debounceTime(100), takeUntil(this.destroy$))
81
+ .subscribe(() => {
82
+ this.updateBoundaryCalculations();
83
+ });
84
+ }
85
+ /**
86
+ * 更新邊界計算(支援 Chrome 74,不使用 CSS min/max 函數)
87
+ */
88
+ updateBoundaryCalculations() {
89
+ const hostElement = this.elementRef.nativeElement;
90
+ const computedStyle = getComputedStyle(hostElement);
91
+ // 讀取 CSS 變數
92
+ const designWidth = parseFloat(computedStyle.getPropertyValue('--design-width') || '1920');
93
+ const designHeight = parseFloat(computedStyle.getPropertyValue('--design-height') || '1080');
94
+ const vw100 = parseFloat(computedStyle.getPropertyValue('--vw100') || `${window.innerWidth}`);
95
+ const vh100 = parseFloat(computedStyle.getPropertyValue('--vh100') || `${window.innerHeight}`);
96
+ // 計算比例
97
+ const landscapeRatio = designWidth / designHeight;
98
+ const portraitRatio = designHeight / designWidth;
99
+ // 根據方向計算邊界最大值
100
+ const isLandscape = this.isLandscape;
101
+ const boundaryMaxWidth = isLandscape
102
+ ? vh100 * portraitRatio
103
+ : vh100 * landscapeRatio;
104
+ const boundaryMaxHeight = isLandscape
105
+ ? vw100 * landscapeRatio
106
+ : vw100 * portraitRatio;
107
+ // 計算實際邊界寬高(模擬 CSS min 函數)
108
+ const boundaryWidth = Math.min(vw100, boundaryMaxWidth);
109
+ const boundaryHeight = Math.min(vh100, boundaryMaxHeight);
110
+ // 計算設計基準
111
+ const designBaseWidth = isLandscape ? designHeight : designWidth;
112
+ const designBaseHeight = isLandscape ? designWidth : designHeight;
113
+ // 計算 px2vw 比例
114
+ const px2vwRatio = boundaryWidth / designBaseWidth;
115
+ // 設定 CSS 變數到 host 元素
116
+ hostElement.style.setProperty('--boundary-width', `${boundaryWidth}px`);
117
+ hostElement.style.setProperty('--boundary-height', `${boundaryHeight}px`);
118
+ hostElement.style.setProperty('--px2vw-ratio', `${px2vwRatio}`);
119
+ }
66
120
  }
67
121
  BsBoundary.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: BsBoundary, deps: [], target: i0.ɵɵFactoryTarget.Component });
68
- BsBoundary.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: BsBoundary, isStandalone: true, selector: "bs-boundary", inputs: { isFixedCenter: "isFixedCenter", pointerEventsNone: "pointerEventsNone", lockOrientation: "lockOrientation", forwardStyle: "forwardStyle" }, outputs: { orientationChange: "orientationChange" }, host: { properties: { "class.landscape": "isLandscape" } }, providers: [BsBoundaryContextService], ngImport: i0, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: ["@charset \"UTF-8\";:host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:100%;height:100%;max-width:var(--boundary-width);max-height:var(--boundary-height)}.boundary-wrapper.pointerEventsNone{pointer-events:none}.boundary-wrapper{--active-ratio: var(--landscape-ratio);--active-inv-ratio: var(--portrait-ratio);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio));--px2vw-ratio: calc(var(--boundary-width) / var(--design-base-width));--design-base-width: var(--design-width);--design-base-height: var(--design-height)}@media (min-aspect-ratio: 16/9){.boundary-wrapper{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.boundary-wrapper.landscape{--active-ratio: var(--portrait-ratio);--active-inv-ratio: var(--landscape-ratio);--design-base-width: var(--design-height);--design-base-height: var(--design-width);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio))}@media (min-aspect-ratio: 9/16){.boundary-wrapper.landscape{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] });
122
+ BsBoundary.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: BsBoundary, isStandalone: true, selector: "bs-boundary", inputs: { isFixedCenter: "isFixedCenter", pointerEventsNone: "pointerEventsNone", lockOrientation: "lockOrientation", forwardStyle: "forwardStyle" }, outputs: { orientationChange: "orientationChange" }, host: { properties: { "class.landscape": "isLandscape" } }, providers: [BsBoundaryContextService], ngImport: i0, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: [":host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:var(--vw100);height:var(--vh100);max-width:calc(var(--vh100) * var(--landscape-ratio));max-height:calc(var(--vw100) * var(--portrait-ratio))}.boundary-wrapper.pointerEventsNone{pointer-events:none}:host.landscape .boundary-wrapper{max-width:calc(var(--vh100) * var(--portrait-ratio));max-height:calc(var(--vw100) * var(--landscape-ratio))}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] });
69
123
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: BsBoundary, decorators: [{
70
124
  type: Component,
71
125
  args: [{ selector: 'bs-boundary', standalone: true, providers: [BsBoundaryContextService], host: {
72
126
  '[class.landscape]': 'isLandscape'
73
- }, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: ["@charset \"UTF-8\";:host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:100%;height:100%;max-width:var(--boundary-width);max-height:var(--boundary-height)}.boundary-wrapper.pointerEventsNone{pointer-events:none}.boundary-wrapper{--active-ratio: var(--landscape-ratio);--active-inv-ratio: var(--portrait-ratio);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio));--px2vw-ratio: calc(var(--boundary-width) / var(--design-base-width));--design-base-width: var(--design-width);--design-base-height: var(--design-height)}@media (min-aspect-ratio: 16/9){.boundary-wrapper{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.boundary-wrapper.landscape{--active-ratio: var(--portrait-ratio);--active-inv-ratio: var(--landscape-ratio);--design-base-width: var(--design-height);--design-base-height: var(--design-width);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio))}@media (min-aspect-ratio: 9/16){.boundary-wrapper.landscape{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] }]
127
+ }, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: [":host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:var(--vw100);height:var(--vh100);max-width:calc(var(--vh100) * var(--landscape-ratio));max-height:calc(var(--vw100) * var(--portrait-ratio))}.boundary-wrapper.pointerEventsNone{pointer-events:none}:host.landscape .boundary-wrapper{max-width:calc(var(--vh100) * var(--portrait-ratio));max-height:calc(var(--vw100) * var(--landscape-ratio))}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] }]
74
128
  }], propDecorators: { isFixedCenter: [{
75
129
  type: Input
76
130
  }], pointerEventsNone: [{
@@ -1 +1 @@
1
- {"version":3,"file":"bitstack-ng-boundary.mjs","sources":["../../../projects/bitstack-ng-boundary/src/lib/bs-boundary-context.service.ts","../../../projects/bitstack-ng-boundary/src/lib/bs-boundary.ts","../../../projects/bitstack-ng-boundary/src/lib/template.html","../../../projects/bitstack-ng-boundary/src/public-api.ts","../../../projects/bitstack-ng-boundary/src/bitstack-ng-boundary.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\n@Injectable()\nexport class BsBoundaryContextService {\n private _isLandscape = new BehaviorSubject<boolean>(false);\n\n readonly isLandscape$ = this._isLandscape.asObservable();\n\n setIsLandscape(value: boolean): void {\n this._isLandscape.next(value);\n }\n\n getIsLandscape(): boolean {\n return this._isLandscape.value;\n }\n}\n","import {\n Component,\n EventEmitter,\n inject,\n Input, OnDestroy,\n OnInit,\n Output,\n} from '@angular/core';\nimport {TOrientationMode} from './model';\nimport {BreakpointObserver} from '@angular/cdk/layout';\nimport {Subject, takeUntil} from 'rxjs';\nimport {BsBoundaryContextService} from './bs-boundary-context.service';\n\n@Component({\n selector: 'bs-boundary',\n templateUrl: 'template.html',\n standalone: true,\n styleUrls: ['./styles.scss'],\n providers: [BsBoundaryContextService],\n host: {\n '[class.landscape]': 'isLandscape'\n }\n})\nexport class BsBoundary implements OnInit, OnDestroy {\n\n @Input() isFixedCenter?: boolean = false;\n @Input() pointerEventsNone?: boolean = false;\n @Input() lockOrientation?: TOrientationMode = 'auto';\n @Input() forwardStyle?: Record<string, string>;\n\n @Output() orientationChange = new EventEmitter<boolean>();\n\n private breakpointObserver = inject(BreakpointObserver);\n private boundaryContext = inject(BsBoundaryContextService);\n private destroy$ = new Subject<void>();\n\n get isLandscape(): boolean {\n return this.boundaryContext.getIsLandscape();\n }\n\n ngOnInit(): void {\n this.setupBreakpointObserver();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n /**\n * 監控方向變化\n */\n setupBreakpointObserver() {\n if (this.lockOrientation === 'landscape') {\n this.boundaryContext.setIsLandscape(true);\n this.orientationChange.emit(true);\n return;\n }\n\n if (this.lockOrientation === 'portrait') {\n this.boundaryContext.setIsLandscape(false);\n this.orientationChange.emit(false);\n return;\n }\n\n this.breakpointObserver\n .observe('(orientation: landscape)')\n .pipe(takeUntil(this.destroy$))\n .subscribe(result => {\n this.boundaryContext.setIsLandscape(result.matches);\n this.orientationChange.emit(result.matches);\n });\n }\n}\n","<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n","/*\n * Public API Surface of @bitstack/ng-boundary\n */\n\nexport * from './lib/bs-boundary';\nexport * from './lib/bs-boundary-context.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bitstack-ng-boundary.mjs","sources":["../../../projects/bitstack-ng-boundary/src/lib/bs-boundary-context.service.ts","../../../projects/bitstack-ng-boundary/src/lib/bs-boundary.ts","../../../projects/bitstack-ng-boundary/src/lib/template.html","../../../projects/bitstack-ng-boundary/src/public-api.ts","../../../projects/bitstack-ng-boundary/src/bitstack-ng-boundary.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\n@Injectable()\nexport class BsBoundaryContextService {\n private _isLandscape = new BehaviorSubject<boolean>(false);\n\n readonly isLandscape$ = this._isLandscape.asObservable();\n\n setIsLandscape(value: boolean): void {\n this._isLandscape.next(value);\n }\n\n getIsLandscape(): boolean {\n return this._isLandscape.value;\n }\n}\n","import {\n Component,\n ElementRef,\n EventEmitter,\n inject,\n Input, OnDestroy,\n OnInit,\n Output,\n} from '@angular/core';\nimport {TOrientationMode} from './model';\nimport {BreakpointObserver} from '@angular/cdk/layout';\nimport {debounceTime, fromEvent, Subject, takeUntil} from 'rxjs';\nimport {BsBoundaryContextService} from './bs-boundary-context.service';\n\n@Component({\n selector: 'bs-boundary',\n templateUrl: 'template.html',\n standalone: true,\n styleUrls: ['./styles.scss'],\n providers: [BsBoundaryContextService],\n host: {\n '[class.landscape]': 'isLandscape'\n }\n})\nexport class BsBoundary implements OnInit, OnDestroy {\n\n @Input() isFixedCenter?: boolean = false;\n @Input() pointerEventsNone?: boolean = false;\n @Input() lockOrientation?: TOrientationMode = 'auto';\n @Input() forwardStyle?: Record<string, string>;\n\n @Output() orientationChange = new EventEmitter<boolean>();\n\n private breakpointObserver = inject(BreakpointObserver);\n private boundaryContext = inject(BsBoundaryContextService);\n private elementRef = inject(ElementRef);\n private destroy$ = new Subject<void>();\n\n get isLandscape(): boolean {\n return this.boundaryContext.getIsLandscape();\n }\n\n ngOnInit(): void {\n this.setupBreakpointObserver();\n this.setupResizeObserver();\n // 延遲執行以確保 CSS 變數已經設定\n setTimeout(() => this.updateBoundaryCalculations(), 0);\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n /**\n * 監控方向變化\n */\n setupBreakpointObserver() {\n if (this.lockOrientation === 'landscape') {\n this.boundaryContext.setIsLandscape(true);\n this.orientationChange.emit(true);\n // 鎖定方向後也需要更新計算\n setTimeout(() => this.updateBoundaryCalculations(), 0);\n return;\n }\n\n if (this.lockOrientation === 'portrait') {\n this.boundaryContext.setIsLandscape(false);\n this.orientationChange.emit(false);\n // 鎖定方向後也需要更新計算\n setTimeout(() => this.updateBoundaryCalculations(), 0);\n return;\n }\n\n this.breakpointObserver\n .observe('(orientation: landscape)')\n .pipe(takeUntil(this.destroy$))\n .subscribe(result => {\n this.boundaryContext.setIsLandscape(result.matches);\n this.orientationChange.emit(result.matches);\n this.updateBoundaryCalculations();\n });\n }\n\n /**\n * 監控視口大小變化\n */\n setupResizeObserver() {\n fromEvent(window, 'resize')\n .pipe(\n debounceTime(100),\n takeUntil(this.destroy$)\n )\n .subscribe(() => {\n this.updateBoundaryCalculations();\n });\n }\n\n /**\n * 更新邊界計算(支援 Chrome 74,不使用 CSS min/max 函數)\n */\n updateBoundaryCalculations() {\n const hostElement = this.elementRef.nativeElement as HTMLElement;\n const computedStyle = getComputedStyle(hostElement);\n\n // 讀取 CSS 變數\n const designWidth = parseFloat(computedStyle.getPropertyValue('--design-width') || '1920');\n const designHeight = parseFloat(computedStyle.getPropertyValue('--design-height') || '1080');\n const vw100 = parseFloat(computedStyle.getPropertyValue('--vw100') || `${window.innerWidth}`);\n const vh100 = parseFloat(computedStyle.getPropertyValue('--vh100') || `${window.innerHeight}`);\n\n // 計算比例\n const landscapeRatio = designWidth / designHeight;\n const portraitRatio = designHeight / designWidth;\n\n // 根據方向計算邊界最大值\n const isLandscape = this.isLandscape;\n const boundaryMaxWidth = isLandscape\n ? vh100 * portraitRatio\n : vh100 * landscapeRatio;\n const boundaryMaxHeight = isLandscape\n ? vw100 * landscapeRatio\n : vw100 * portraitRatio;\n\n // 計算實際邊界寬高(模擬 CSS min 函數)\n const boundaryWidth = Math.min(vw100, boundaryMaxWidth);\n const boundaryHeight = Math.min(vh100, boundaryMaxHeight);\n\n // 計算設計基準\n const designBaseWidth = isLandscape ? designHeight : designWidth;\n const designBaseHeight = isLandscape ? designWidth : designHeight;\n\n // 計算 px2vw 比例\n const px2vwRatio = boundaryWidth / designBaseWidth;\n\n // 設定 CSS 變數到 host 元素\n hostElement.style.setProperty('--boundary-width', `${boundaryWidth}px`);\n hostElement.style.setProperty('--boundary-height', `${boundaryHeight}px`);\n hostElement.style.setProperty('--px2vw-ratio', `${px2vwRatio}`);\n }\n}\n","<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n","/*\n * Public API Surface of @bitstack/ng-boundary\n */\n\nexport * from './lib/bs-boundary';\nexport * from './lib/bs-boundary-context.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, EventEmitter, inject, Component, Input, Output } from '@angular/core';
2
+ import { Injectable, EventEmitter, inject, ElementRef, Component, Input, Output } from '@angular/core';
3
3
  import { BreakpointObserver } from '@angular/cdk/layout';
4
- import { BehaviorSubject, Subject, takeUntil } from 'rxjs';
4
+ import { BehaviorSubject, Subject, takeUntil, fromEvent, debounceTime } from 'rxjs';
5
5
 
6
6
  class BsBoundaryContextService {
7
7
  constructor() {
@@ -29,6 +29,7 @@ class BsBoundary {
29
29
  this.orientationChange = new EventEmitter();
30
30
  this.breakpointObserver = inject(BreakpointObserver);
31
31
  this.boundaryContext = inject(BsBoundaryContextService);
32
+ this.elementRef = inject(ElementRef);
32
33
  this.destroy$ = new Subject();
33
34
  }
34
35
  get isLandscape() {
@@ -36,6 +37,9 @@ class BsBoundary {
36
37
  }
37
38
  ngOnInit() {
38
39
  this.setupBreakpointObserver();
40
+ this.setupResizeObserver();
41
+ // 延遲執行以確保 CSS 變數已經設定
42
+ setTimeout(() => this.updateBoundaryCalculations(), 0);
39
43
  }
40
44
  ngOnDestroy() {
41
45
  this.destroy$.next();
@@ -48,11 +52,15 @@ class BsBoundary {
48
52
  if (this.lockOrientation === 'landscape') {
49
53
  this.boundaryContext.setIsLandscape(true);
50
54
  this.orientationChange.emit(true);
55
+ // 鎖定方向後也需要更新計算
56
+ setTimeout(() => this.updateBoundaryCalculations(), 0);
51
57
  return;
52
58
  }
53
59
  if (this.lockOrientation === 'portrait') {
54
60
  this.boundaryContext.setIsLandscape(false);
55
61
  this.orientationChange.emit(false);
62
+ // 鎖定方向後也需要更新計算
63
+ setTimeout(() => this.updateBoundaryCalculations(), 0);
56
64
  return;
57
65
  }
58
66
  this.breakpointObserver
@@ -61,16 +69,62 @@ class BsBoundary {
61
69
  .subscribe(result => {
62
70
  this.boundaryContext.setIsLandscape(result.matches);
63
71
  this.orientationChange.emit(result.matches);
72
+ this.updateBoundaryCalculations();
64
73
  });
65
74
  }
75
+ /**
76
+ * 監控視口大小變化
77
+ */
78
+ setupResizeObserver() {
79
+ fromEvent(window, 'resize')
80
+ .pipe(debounceTime(100), takeUntil(this.destroy$))
81
+ .subscribe(() => {
82
+ this.updateBoundaryCalculations();
83
+ });
84
+ }
85
+ /**
86
+ * 更新邊界計算(支援 Chrome 74,不使用 CSS min/max 函數)
87
+ */
88
+ updateBoundaryCalculations() {
89
+ const hostElement = this.elementRef.nativeElement;
90
+ const computedStyle = getComputedStyle(hostElement);
91
+ // 讀取 CSS 變數
92
+ const designWidth = parseFloat(computedStyle.getPropertyValue('--design-width') || '1920');
93
+ const designHeight = parseFloat(computedStyle.getPropertyValue('--design-height') || '1080');
94
+ const vw100 = parseFloat(computedStyle.getPropertyValue('--vw100') || `${window.innerWidth}`);
95
+ const vh100 = parseFloat(computedStyle.getPropertyValue('--vh100') || `${window.innerHeight}`);
96
+ // 計算比例
97
+ const landscapeRatio = designWidth / designHeight;
98
+ const portraitRatio = designHeight / designWidth;
99
+ // 根據方向計算邊界最大值
100
+ const isLandscape = this.isLandscape;
101
+ const boundaryMaxWidth = isLandscape
102
+ ? vh100 * portraitRatio
103
+ : vh100 * landscapeRatio;
104
+ const boundaryMaxHeight = isLandscape
105
+ ? vw100 * landscapeRatio
106
+ : vw100 * portraitRatio;
107
+ // 計算實際邊界寬高(模擬 CSS min 函數)
108
+ const boundaryWidth = Math.min(vw100, boundaryMaxWidth);
109
+ const boundaryHeight = Math.min(vh100, boundaryMaxHeight);
110
+ // 計算設計基準
111
+ const designBaseWidth = isLandscape ? designHeight : designWidth;
112
+ const designBaseHeight = isLandscape ? designWidth : designHeight;
113
+ // 計算 px2vw 比例
114
+ const px2vwRatio = boundaryWidth / designBaseWidth;
115
+ // 設定 CSS 變數到 host 元素
116
+ hostElement.style.setProperty('--boundary-width', `${boundaryWidth}px`);
117
+ hostElement.style.setProperty('--boundary-height', `${boundaryHeight}px`);
118
+ hostElement.style.setProperty('--px2vw-ratio', `${px2vwRatio}`);
119
+ }
66
120
  }
67
121
  BsBoundary.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: BsBoundary, deps: [], target: i0.ɵɵFactoryTarget.Component });
68
- BsBoundary.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: BsBoundary, isStandalone: true, selector: "bs-boundary", inputs: { isFixedCenter: "isFixedCenter", pointerEventsNone: "pointerEventsNone", lockOrientation: "lockOrientation", forwardStyle: "forwardStyle" }, outputs: { orientationChange: "orientationChange" }, host: { properties: { "class.landscape": "isLandscape" } }, providers: [BsBoundaryContextService], ngImport: i0, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: ["@charset \"UTF-8\";:host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:100%;height:100%;max-width:var(--boundary-width);max-height:var(--boundary-height)}.boundary-wrapper.pointerEventsNone{pointer-events:none}.boundary-wrapper{--active-ratio: var(--landscape-ratio);--active-inv-ratio: var(--portrait-ratio);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio));--px2vw-ratio: calc(var(--boundary-width) / var(--design-base-width));--design-base-width: var(--design-width);--design-base-height: var(--design-height)}@media (min-aspect-ratio: 16/9){.boundary-wrapper{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.boundary-wrapper.landscape{--active-ratio: var(--portrait-ratio);--active-inv-ratio: var(--landscape-ratio);--design-base-width: var(--design-height);--design-base-height: var(--design-width);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio))}@media (min-aspect-ratio: 9/16){.boundary-wrapper.landscape{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] });
122
+ BsBoundary.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: BsBoundary, isStandalone: true, selector: "bs-boundary", inputs: { isFixedCenter: "isFixedCenter", pointerEventsNone: "pointerEventsNone", lockOrientation: "lockOrientation", forwardStyle: "forwardStyle" }, outputs: { orientationChange: "orientationChange" }, host: { properties: { "class.landscape": "isLandscape" } }, providers: [BsBoundaryContextService], ngImport: i0, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: [":host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:var(--vw100);height:var(--vh100);max-width:calc(var(--vh100) * var(--landscape-ratio));max-height:calc(var(--vw100) * var(--portrait-ratio))}.boundary-wrapper.pointerEventsNone{pointer-events:none}:host.landscape .boundary-wrapper{max-width:calc(var(--vh100) * var(--portrait-ratio));max-height:calc(var(--vw100) * var(--landscape-ratio))}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] });
69
123
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: BsBoundary, decorators: [{
70
124
  type: Component,
71
125
  args: [{ selector: 'bs-boundary', standalone: true, providers: [BsBoundaryContextService], host: {
72
126
  '[class.landscape]': 'isLandscape'
73
- }, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: ["@charset \"UTF-8\";:host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:100%;height:100%;max-width:var(--boundary-width);max-height:var(--boundary-height)}.boundary-wrapper.pointerEventsNone{pointer-events:none}.boundary-wrapper{--active-ratio: var(--landscape-ratio);--active-inv-ratio: var(--portrait-ratio);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio));--px2vw-ratio: calc(var(--boundary-width) / var(--design-base-width));--design-base-width: var(--design-width);--design-base-height: var(--design-height)}@media (min-aspect-ratio: 16/9){.boundary-wrapper{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.boundary-wrapper.landscape{--active-ratio: var(--portrait-ratio);--active-inv-ratio: var(--landscape-ratio);--design-base-width: var(--design-height);--design-base-height: var(--design-width);--boundary-width: var(--vw100);--boundary-height: calc(var(--boundary-width) * var(--active-inv-ratio))}@media (min-aspect-ratio: 9/16){.boundary-wrapper.landscape{--boundary-height: var(--vh100);--boundary-width: calc(var(--boundary-height) * var(--active-ratio))}}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] }]
127
+ }, template: "<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n", styles: [":host{--landscape-ratio: calc(var(--design-width) / var(--design-height));--portrait-ratio: calc(var(--design-height) / var(--design-width))}.boundary-wrapper{width:var(--vw100);height:var(--vh100);max-width:calc(var(--vh100) * var(--landscape-ratio));max-height:calc(var(--vw100) * var(--portrait-ratio))}.boundary-wrapper.pointerEventsNone{pointer-events:none}:host.landscape .boundary-wrapper{max-width:calc(var(--vh100) * var(--portrait-ratio));max-height:calc(var(--vw100) * var(--landscape-ratio))}.fixed-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);transform-origin:center;z-index:99}\n"] }]
74
128
  }], propDecorators: { isFixedCenter: [{
75
129
  type: Input
76
130
  }], pointerEventsNone: [{
@@ -1 +1 @@
1
- {"version":3,"file":"bitstack-ng-boundary.mjs","sources":["../../../projects/bitstack-ng-boundary/src/lib/bs-boundary-context.service.ts","../../../projects/bitstack-ng-boundary/src/lib/bs-boundary.ts","../../../projects/bitstack-ng-boundary/src/lib/template.html","../../../projects/bitstack-ng-boundary/src/public-api.ts","../../../projects/bitstack-ng-boundary/src/bitstack-ng-boundary.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\n@Injectable()\nexport class BsBoundaryContextService {\n private _isLandscape = new BehaviorSubject<boolean>(false);\n\n readonly isLandscape$ = this._isLandscape.asObservable();\n\n setIsLandscape(value: boolean): void {\n this._isLandscape.next(value);\n }\n\n getIsLandscape(): boolean {\n return this._isLandscape.value;\n }\n}\n","import {\n Component,\n EventEmitter,\n inject,\n Input, OnDestroy,\n OnInit,\n Output,\n} from '@angular/core';\nimport {TOrientationMode} from './model';\nimport {BreakpointObserver} from '@angular/cdk/layout';\nimport {Subject, takeUntil} from 'rxjs';\nimport {BsBoundaryContextService} from './bs-boundary-context.service';\n\n@Component({\n selector: 'bs-boundary',\n templateUrl: 'template.html',\n standalone: true,\n styleUrls: ['./styles.scss'],\n providers: [BsBoundaryContextService],\n host: {\n '[class.landscape]': 'isLandscape'\n }\n})\nexport class BsBoundary implements OnInit, OnDestroy {\n\n @Input() isFixedCenter?: boolean = false;\n @Input() pointerEventsNone?: boolean = false;\n @Input() lockOrientation?: TOrientationMode = 'auto';\n @Input() forwardStyle?: Record<string, string>;\n\n @Output() orientationChange = new EventEmitter<boolean>();\n\n private breakpointObserver = inject(BreakpointObserver);\n private boundaryContext = inject(BsBoundaryContextService);\n private destroy$ = new Subject<void>();\n\n get isLandscape(): boolean {\n return this.boundaryContext.getIsLandscape();\n }\n\n ngOnInit(): void {\n this.setupBreakpointObserver();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n /**\n * 監控方向變化\n */\n setupBreakpointObserver() {\n if (this.lockOrientation === 'landscape') {\n this.boundaryContext.setIsLandscape(true);\n this.orientationChange.emit(true);\n return;\n }\n\n if (this.lockOrientation === 'portrait') {\n this.boundaryContext.setIsLandscape(false);\n this.orientationChange.emit(false);\n return;\n }\n\n this.breakpointObserver\n .observe('(orientation: landscape)')\n .pipe(takeUntil(this.destroy$))\n .subscribe(result => {\n this.boundaryContext.setIsLandscape(result.matches);\n this.orientationChange.emit(result.matches);\n });\n }\n}\n","<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n","/*\n * Public API Surface of @bitstack/ng-boundary\n */\n\nexport * from './lib/bs-boundary';\nexport * from './lib/bs-boundary-context.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bitstack-ng-boundary.mjs","sources":["../../../projects/bitstack-ng-boundary/src/lib/bs-boundary-context.service.ts","../../../projects/bitstack-ng-boundary/src/lib/bs-boundary.ts","../../../projects/bitstack-ng-boundary/src/lib/template.html","../../../projects/bitstack-ng-boundary/src/public-api.ts","../../../projects/bitstack-ng-boundary/src/bitstack-ng-boundary.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\n@Injectable()\nexport class BsBoundaryContextService {\n private _isLandscape = new BehaviorSubject<boolean>(false);\n\n readonly isLandscape$ = this._isLandscape.asObservable();\n\n setIsLandscape(value: boolean): void {\n this._isLandscape.next(value);\n }\n\n getIsLandscape(): boolean {\n return this._isLandscape.value;\n }\n}\n","import {\n Component,\n ElementRef,\n EventEmitter,\n inject,\n Input, OnDestroy,\n OnInit,\n Output,\n} from '@angular/core';\nimport {TOrientationMode} from './model';\nimport {BreakpointObserver} from '@angular/cdk/layout';\nimport {debounceTime, fromEvent, Subject, takeUntil} from 'rxjs';\nimport {BsBoundaryContextService} from './bs-boundary-context.service';\n\n@Component({\n selector: 'bs-boundary',\n templateUrl: 'template.html',\n standalone: true,\n styleUrls: ['./styles.scss'],\n providers: [BsBoundaryContextService],\n host: {\n '[class.landscape]': 'isLandscape'\n }\n})\nexport class BsBoundary implements OnInit, OnDestroy {\n\n @Input() isFixedCenter?: boolean = false;\n @Input() pointerEventsNone?: boolean = false;\n @Input() lockOrientation?: TOrientationMode = 'auto';\n @Input() forwardStyle?: Record<string, string>;\n\n @Output() orientationChange = new EventEmitter<boolean>();\n\n private breakpointObserver = inject(BreakpointObserver);\n private boundaryContext = inject(BsBoundaryContextService);\n private elementRef = inject(ElementRef);\n private destroy$ = new Subject<void>();\n\n get isLandscape(): boolean {\n return this.boundaryContext.getIsLandscape();\n }\n\n ngOnInit(): void {\n this.setupBreakpointObserver();\n this.setupResizeObserver();\n // 延遲執行以確保 CSS 變數已經設定\n setTimeout(() => this.updateBoundaryCalculations(), 0);\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n /**\n * 監控方向變化\n */\n setupBreakpointObserver() {\n if (this.lockOrientation === 'landscape') {\n this.boundaryContext.setIsLandscape(true);\n this.orientationChange.emit(true);\n // 鎖定方向後也需要更新計算\n setTimeout(() => this.updateBoundaryCalculations(), 0);\n return;\n }\n\n if (this.lockOrientation === 'portrait') {\n this.boundaryContext.setIsLandscape(false);\n this.orientationChange.emit(false);\n // 鎖定方向後也需要更新計算\n setTimeout(() => this.updateBoundaryCalculations(), 0);\n return;\n }\n\n this.breakpointObserver\n .observe('(orientation: landscape)')\n .pipe(takeUntil(this.destroy$))\n .subscribe(result => {\n this.boundaryContext.setIsLandscape(result.matches);\n this.orientationChange.emit(result.matches);\n this.updateBoundaryCalculations();\n });\n }\n\n /**\n * 監控視口大小變化\n */\n setupResizeObserver() {\n fromEvent(window, 'resize')\n .pipe(\n debounceTime(100),\n takeUntil(this.destroy$)\n )\n .subscribe(() => {\n this.updateBoundaryCalculations();\n });\n }\n\n /**\n * 更新邊界計算(支援 Chrome 74,不使用 CSS min/max 函數)\n */\n updateBoundaryCalculations() {\n const hostElement = this.elementRef.nativeElement as HTMLElement;\n const computedStyle = getComputedStyle(hostElement);\n\n // 讀取 CSS 變數\n const designWidth = parseFloat(computedStyle.getPropertyValue('--design-width') || '1920');\n const designHeight = parseFloat(computedStyle.getPropertyValue('--design-height') || '1080');\n const vw100 = parseFloat(computedStyle.getPropertyValue('--vw100') || `${window.innerWidth}`);\n const vh100 = parseFloat(computedStyle.getPropertyValue('--vh100') || `${window.innerHeight}`);\n\n // 計算比例\n const landscapeRatio = designWidth / designHeight;\n const portraitRatio = designHeight / designWidth;\n\n // 根據方向計算邊界最大值\n const isLandscape = this.isLandscape;\n const boundaryMaxWidth = isLandscape\n ? vh100 * portraitRatio\n : vh100 * landscapeRatio;\n const boundaryMaxHeight = isLandscape\n ? vw100 * landscapeRatio\n : vw100 * portraitRatio;\n\n // 計算實際邊界寬高(模擬 CSS min 函數)\n const boundaryWidth = Math.min(vw100, boundaryMaxWidth);\n const boundaryHeight = Math.min(vh100, boundaryMaxHeight);\n\n // 計算設計基準\n const designBaseWidth = isLandscape ? designHeight : designWidth;\n const designBaseHeight = isLandscape ? designWidth : designHeight;\n\n // 計算 px2vw 比例\n const px2vwRatio = boundaryWidth / designBaseWidth;\n\n // 設定 CSS 變數到 host 元素\n hostElement.style.setProperty('--boundary-width', `${boundaryWidth}px`);\n hostElement.style.setProperty('--boundary-height', `${boundaryHeight}px`);\n hostElement.style.setProperty('--px2vw-ratio', `${px2vwRatio}`);\n }\n}\n","<div\n class=\"boundary-wrapper\"\n [class.fixed-center]=\"isFixedCenter\"\n [class.pointerEventsNone]=\"pointerEventsNone\"\n [style]=\"forwardStyle\"\n>\n <ng-content></ng-content>\n</div>\n","/*\n * Public API Surface of @bitstack/ng-boundary\n */\n\nexport * from './lib/bs-boundary';\nexport * from './lib/bs-boundary-context.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -9,6 +9,7 @@ export declare class BsBoundary implements OnInit, OnDestroy {
9
9
  orientationChange: EventEmitter<boolean>;
10
10
  private breakpointObserver;
11
11
  private boundaryContext;
12
+ private elementRef;
12
13
  private destroy$;
13
14
  get isLandscape(): boolean;
14
15
  ngOnInit(): void;
@@ -17,6 +18,14 @@ export declare class BsBoundary implements OnInit, OnDestroy {
17
18
  * 監控方向變化
18
19
  */
19
20
  setupBreakpointObserver(): void;
21
+ /**
22
+ * 監控視口大小變化
23
+ */
24
+ setupResizeObserver(): void;
25
+ /**
26
+ * 更新邊界計算(支援 Chrome 74,不使用 CSS min/max 函數)
27
+ */
28
+ updateBoundaryCalculations(): void;
20
29
  static ɵfac: i0.ɵɵFactoryDeclaration<BsBoundary, never>;
21
30
  static ɵcmp: i0.ɵɵComponentDeclaration<BsBoundary, "bs-boundary", never, { "isFixedCenter": "isFixedCenter"; "pointerEventsNone": "pointerEventsNone"; "lockOrientation": "lockOrientation"; "forwardStyle": "forwardStyle"; }, { "orientationChange": "orientationChange"; }, never, ["*"], true>;
22
31
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitstack/ng-boundary",
3
- "version": "14.0.6-alpha.1",
3
+ "version": "14.0.6-alpha.2",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=14 <16",
6
6
  "@angular/core": ">=14 <16",
@@ -25,7 +25,7 @@
25
25
  // --design-height: 667;
26
26
  // }
27
27
  @function px2vw($px) {
28
- @return calc(#{$px} * var(--px2vw-ratio));
28
+ @return calc(#{$px}px * var(--px2vw-ratio));
29
29
  }
30
30
 
31
31