@bitstack/ng-boundary 14.0.1-alpha.2 → 14.0.1-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,63 +1,217 @@
1
- # MyLib
1
+ # @bitstack/ng-boundary
2
2
 
3
- This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.3.0.
3
+ A responsive boundary component for Angular applications with built-in orientation support and SCSS utilities for pixel-perfect responsive design.
4
4
 
5
- ## Code scaffolding
5
+ ## Features
6
6
 
7
- Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
7
+ - Responsive boundary container with automatic aspect ratio management
8
+ - Portrait and landscape orientation support with auto-detection
9
+ - CSS custom properties for responsive sizing
10
+ - Comprehensive SCSS utilities for responsive design
11
+ - Standalone component architecture (Angular 14+)
12
+
13
+ ## Installation
8
14
 
9
15
  ```bash
10
- ng generate component component-name
16
+ npm install @bitstack/ng-boundary
11
17
  ```
12
18
 
13
- For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
14
-
15
- ```bash
16
- ng generate --help
19
+ ## Usage
20
+
21
+ ### 1. Using the Component
22
+
23
+ Import and use the `BsBoundary` component in your Angular application:
24
+
25
+ ```typescript
26
+ import { Component } from '@angular/core';
27
+ import { BsBoundary } from '@bitstack/ng-boundary';
28
+
29
+ @Component({
30
+ selector: 'app-root',
31
+ standalone: true,
32
+ imports: [BsBoundary],
33
+ template: `
34
+ <bs-boundary
35
+ [isDebug]="false"
36
+ [bgColor]="'transparent'"
37
+ [contentClickable]="true"
38
+ [orientationMode]="'auto'"
39
+ (afterBoundaryInit)="onBoundaryInit($event)"
40
+ (orientationChange)="onOrientationChange($event)">
41
+ <!-- Your content here -->
42
+ <div class="my-content">
43
+ Hello World
44
+ </div>
45
+ </bs-boundary>
46
+ `
47
+ })
48
+ export class AppComponent {
49
+ onBoundaryInit(boundary: ElementRef<HTMLDivElement>) {
50
+ console.log('Boundary initialized:', boundary);
51
+ }
52
+
53
+ onOrientationChange(mode: 'portrait' | 'landscape') {
54
+ console.log('Orientation changed to:', mode);
55
+ }
56
+ }
17
57
  ```
18
58
 
19
- ## Building
59
+ #### Component Inputs
20
60
 
21
- To build the library, run:
61
+ - `isDebug`: (boolean) Enable debug mode with background color - default: `false`
62
+ - `bgColor`: (string) Background color for the boundary
63
+ - `contentClickable`: (boolean) Whether content is clickable - default: `true`
64
+ - `orientationMode`: ('auto' | 'portrait' | 'landscape') Orientation mode - default: `'auto'`
65
+ - `injectStyle`: (IInjectStyle) Custom styles to inject
22
66
 
23
- ```bash
24
- ng build bitstack-ng-boundary
25
- ```
67
+ #### Component Outputs
26
68
 
27
- This command will compile your project, and the build artifacts will be placed in the `dist/` directory.
69
+ - `afterBoundaryInit`: Emits after boundary initialization with ElementRef
70
+ - `orientationChange`: Emits when orientation changes
28
71
 
29
- ### Publishing the Library
72
+ ### 2. Using SCSS Utilities
30
73
 
31
- Once the project is built, you can publish your library by following these steps:
74
+ The boundary component provides CSS custom properties that you can use with the included SCSS utilities:
32
75
 
33
- 1. Navigate to the `dist` directory:
34
- ```bash
35
- cd dist/bitstack-ng-boundary
36
- ```
76
+ #### Import SCSS Utilities
37
77
 
38
- 2. Run the `npm publish` command to publish your library to the npm registry:
39
- ```bash
40
- npm publish
41
- ```
78
+ In your component SCSS file or global styles:
42
79
 
43
- ## Running unit tests
80
+ ```scss
81
+ @use '@bitstack/ng-boundary/styles' as boundary;
44
82
 
45
- To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
83
+ .my-component {
84
+ // Use the px2vw function for responsive sizing
85
+ // This automatically adapts to portrait/landscape mode
86
+ width: boundary.px2vw(100);
87
+ height: boundary.px2vw(200);
88
+ padding: boundary.px2vw(20);
46
89
 
47
- ```bash
48
- ng test
90
+ // Or use mixins for specific properties
91
+ @include boundary.width(100);
92
+ @include boundary.height(200);
93
+ @include boundary.padding-left(20);
94
+ }
49
95
  ```
50
96
 
51
- ## Running end-to-end tests
97
+ #### Available SCSS Functions
98
+
99
+ - `px2vw($px)` - Converts px to responsive units based on boundary
100
+ - `px2vw-unbounded($px)` - Converts px to viewport units (not bounded)
101
+ - `vw($w)` - Returns viewport width unit (dvw or vw)
102
+ - `vh($h)` - Returns viewport height unit (dvh or vh)
103
+
104
+ #### Available SCSS Mixins
105
+
106
+ **Responsive sizing mixins:**
107
+ - `@include width($px)` - Set responsive width
108
+ - `@include height($px)` - Set responsive height
109
+ - `@include padding-left($px)` - Set responsive left padding
110
+ - `@include padding-right($px)` - Set responsive right padding
111
+ - `@include padding-top($px)` - Set responsive top padding
112
+ - `@include padding-bottom($px)` - Set responsive bottom padding
113
+ - `@include px2vw($property, $px)` - Set any property with responsive value
114
+
115
+ **Utility mixins:**
116
+ - `@include flexCenter` - Flex center alignment
117
+ - `@include hideScrollbar` - Hide scrollbars
118
+ - `@include bg-contain` - Background contain
119
+ - `@include bg-cover` - Background cover
120
+ - `@include text-center` - Center text
121
+ - `@include text-shadow($color)` - Text shadow
122
+ - `@include size($w, $h: $w)` - Set width and height
123
+
124
+ **Responsive breakpoint mixins:**
125
+ - `@include s { ... }` - Small devices and up
126
+ - `@include landscape { ... }` - Mobile landscape
127
+ - `@include portrait { ... }` - Mobile portrait
128
+ - `@include pc_landscape { ... }` - PC landscape
129
+ - `@include pc_portrait { ... }` - PC portrait
130
+
131
+ #### CSS Custom Properties
132
+
133
+ The boundary component sets these CSS variables that the SCSS utilities use:
134
+
135
+ - `--boundary-width` - Current boundary width
136
+ - `--boundary-height` - Current boundary height
137
+ - `--design-base-width` - Design base width (portrait: 540, landscape: 960)
138
+ - `--design-base-height` - Design base height (portrait: 960, landscape: 540)
139
+ - `--px2vw-ratio` - Ratio for px to responsive unit conversion
140
+
141
+ ### 3. Complete Example
142
+
143
+ ```typescript
144
+ // app.component.ts
145
+ import { Component } from '@angular/core';
146
+ import { BsBoundary } from '@bitstack/ng-boundary';
147
+
148
+ @Component({
149
+ selector: 'app-root',
150
+ standalone: true,
151
+ imports: [BsBoundary],
152
+ templateUrl: './app.component.html',
153
+ styleUrls: ['./app.component.scss']
154
+ })
155
+ export class AppComponent {}
156
+ ```
52
157
 
53
- For end-to-end (e2e) testing, run:
158
+ ```html
159
+ <!-- app.component.html -->
160
+ <bs-boundary [orientationMode]="'auto'">
161
+ <div class="game-container">
162
+ <h1 class="title">My Game</h1>
163
+ <button class="play-button">Play</button>
164
+ </div>
165
+ </bs-boundary>
166
+ ```
54
167
 
55
- ```bash
56
- ng e2e
168
+ ```scss
169
+ // app.component.scss
170
+ @use '@bitstack/ng-boundary/styles' as boundary;
171
+
172
+ .game-container {
173
+ @include boundary.flexCenter;
174
+ flex-direction: column;
175
+ width: 100%;
176
+ height: 100%;
177
+ gap: boundary.px2vw(20);
178
+ }
179
+
180
+ .title {
181
+ font-size: boundary.px2vw(48);
182
+ @include boundary.padding-top(40);
183
+ }
184
+
185
+ .play-button {
186
+ @include boundary.width(200);
187
+ @include boundary.height(60);
188
+ font-size: boundary.px2vw(24);
189
+ border-radius: boundary.px2vw(12);
190
+ }
57
191
  ```
58
192
 
59
- Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
193
+ ## Design System
194
+
195
+ The component is designed with these base dimensions:
196
+ - Portrait mode: 540px × 960px
197
+ - Landscape mode: 960px × 540px
198
+
199
+ The `px2vw()` function automatically scales your design to fit within the boundary while maintaining aspect ratio.
200
+
201
+ ## Requirements
202
+
203
+ - Angular 14.0.0 or higher
204
+ - @angular/cdk 14.0.0 or higher
205
+ - SCSS support in your Angular project
206
+
207
+ ## Building
208
+
209
+ To build the library:
210
+
211
+ ```bash
212
+ ng build bitstack-ng-boundary
213
+ ```
60
214
 
61
- ## Additional Resources
215
+ ## License
62
216
 
63
- For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
217
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitstack/ng-boundary",
3
- "version": "14.0.1-alpha.2",
3
+ "version": "14.0.1-alpha.3",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^14.0.0",
6
6
  "@angular/core": "^14.0.0",
@@ -29,4 +29,4 @@
29
29
  "default": "./fesm2020/bitstack-ng-boundary.mjs"
30
30
  }
31
31
  }
32
- }
32
+ }
@@ -0,0 +1,109 @@
1
+ // check support device-vh
2
+ @use "sass:math";
3
+ @use "variables";
4
+ @use "responsive";
5
+
6
+ // Import required mixins from responsive
7
+ @mixin supports-dv {
8
+ @supports (width: 100dvh) {
9
+ @content;
10
+ }
11
+ }
12
+ @mixin not-supports-dv {
13
+ @supports not (width: 100dvh) {
14
+ @content;
15
+ }
16
+ }
17
+
18
+ // Import and re-export functions from responsive
19
+ @function responsive-size-by-px($px, $unit: 'v', $isLandscape: false, $isMax: false) {
20
+ $w: math.div($px, 5.4);
21
+ @return responsive.responsive-size-by-vw($w, $unit, $isLandscape, $isMax);
22
+ }
23
+
24
+ // Note: responsive-size-by-vw is provided by the responsive module
25
+ // and should be accessed via @use "responsive"
26
+
27
+
28
+
29
+ // use vw, vh or dvw, dvh
30
+ @function vw($w) {
31
+ @return #{$w}#{variables.$vw-unit};
32
+ }
33
+ @function vh($h) {
34
+ @return #{$h}#{variables.$vh-unit};
35
+ }
36
+
37
+
38
+
39
+ @mixin setProperty($property, $value) {
40
+ @include supports-dv {
41
+ #{$property}: responsive-size-by-px($value, 'dv');
42
+ }
43
+ @include not-supports-dv {
44
+ #{$property}: responsive-size-by-px($value, 'v');
45
+ }
46
+ }
47
+
48
+ // 響應式尺寸 mixin 版本 (包含 supports-dv 判斷)
49
+ @mixin px2vw($property, $px) {
50
+ $layout-width-num: variables.$design-width; // 375
51
+ $layout-height-num: variables.$design-height; // 667
52
+
53
+ $vw-value: math.div($px, $layout-width-num) * 100; // 70/375*100
54
+ $vh-value: math.div($px, $layout-height-num) * 100; // 70/667*100
55
+
56
+ @include supports-dv {
57
+ #{$property}: min(#{$vw-value}dvw, #{$vh-value}dvh);
58
+ }
59
+ @include not-supports-dv {
60
+ #{$property}: min(#{$vw-value}vw, #{$vh-value}vh);
61
+ }
62
+ }
63
+
64
+ // 單一屬性響應式 mixin (你想要的語法)
65
+ @mixin height($px) {
66
+ @include px2vw(height, $px);
67
+ }
68
+
69
+ @mixin width($px) {
70
+ @include px2vw(width, $px);
71
+ }
72
+
73
+ @mixin padding-left($px) {
74
+ @include px2vw(padding-left, $px);
75
+ }
76
+
77
+ @mixin padding-right($px) {
78
+ @include px2vw(padding-right, $px);
79
+ }
80
+
81
+ @mixin padding-top($px) {
82
+ @include px2vw(padding-top, $px);
83
+ }
84
+
85
+ @mixin padding-bottom($px) {
86
+ @include px2vw(padding-bottom, $px);
87
+ }
88
+
89
+ // 響應式尺寸函數 (自動適應直式/橫式)
90
+ // 使用 CSS 變數來獲取當前模式下的設計基準寬度
91
+ // Portrait: --design-base-width = 375
92
+ // Landscape: --design-base-width = 667
93
+ @function px2vw($px) {
94
+ @return calc(#{$px} * var(--px2vw-ratio));
95
+ }
96
+
97
+ // 原始的 px2vw 函數 (不受 boundary 限制,直接基於 viewport)
98
+ @function px2vw-unbounded($px) {
99
+ $layout-width-num: variables.$design-width; // 375
100
+ $layout-height-num: variables.$design-height; // 667
101
+
102
+ $vw-value: math.div($px, $layout-width-num) * 100; // 70/375*100 = 18.666667
103
+ $vh-value: math.div($px, $layout-height-num) * 100; // 70/667*100 = 10.494948
104
+
105
+ @return unquote("min(#{$vw-value}#{variables.$vw-unit}, #{$vh-value}#{variables.$vw-unit})");
106
+ }
107
+
108
+
109
+
@@ -0,0 +1,33 @@
1
+ /* 字體定義 */
2
+ @font-face {
3
+ font-family: 'MicrosoftYaHei';
4
+ src: url('/assets/fonts/msyh.woff2') format('woff2');
5
+ font-weight: normal;
6
+ font-style: normal;
7
+ font-display: swap;
8
+ }
9
+
10
+ @font-face {
11
+ font-family: 'Myanmar MN';
12
+ src: url('/assets/fonts/myanmar-mn.woff2') format('woff2');
13
+ font-weight: normal;
14
+ font-style: normal;
15
+ font-display: swap;
16
+ }
17
+
18
+ @font-face {
19
+ font-family: 'Myanmar MN';
20
+ src: url('/assets/fonts/myanmar-mn-bold.woff2') format('woff2');
21
+ font-weight: bold;
22
+ font-style: normal;
23
+ font-display: swap;
24
+ }
25
+
26
+ @font-face {
27
+ font-family: 'Prompt';
28
+ src: url('/assets/fonts/prompt-regular.woff2') format('woff2');
29
+ font-weight: normal;
30
+ font-style: normal;
31
+ font-display: swap;
32
+ }
33
+
@@ -0,0 +1,107 @@
1
+ @use "responsive";
2
+
3
+
4
+ /* Small devices (portrait tablets and large phones, 376px and up) */
5
+ @mixin s {
6
+ @media only screen and (min-width: 481px) and (min-height: 746px) {
7
+ @content;
8
+ }
9
+ }
10
+
11
+ // only mobile
12
+ @mixin landscape {
13
+ @media only screen and (orientation: landscape) and (any-pointer: coarse) {
14
+ @content;
15
+ }
16
+ }
17
+
18
+ @mixin portrait {
19
+ @media only screen and (orientation: portrait) and (any-pointer: coarse) {
20
+ @content;
21
+ }
22
+ }
23
+
24
+ @mixin pc_landscape {
25
+ @media only screen and (orientation: landscape) {
26
+ @content;
27
+ }
28
+ }
29
+
30
+ @mixin pc_portrait {
31
+ @media only screen and (orientation: portrait) {
32
+ @content;
33
+ }
34
+ }
35
+
36
+
37
+ @mixin text-center {
38
+ text-align: center;
39
+ }
40
+
41
+ @mixin text-shadow($color) {
42
+ text-shadow: -1px 0 $color, 0 1px $color, 1px 0 $color, 0 -1px $color;
43
+ }
44
+
45
+ @mixin size($w, $h: $w) {
46
+ width: $w;
47
+ height: $h;
48
+ }
49
+
50
+ @mixin hideScrollbar {
51
+ -ms-overflow-style: -ms-autohiding-scrollbar;
52
+ scrollbar-width: none;
53
+ &::-webkit-scrollbar {
54
+ display: none;
55
+ }
56
+ }
57
+
58
+ @mixin flexCenter {
59
+ display: flex;
60
+ justify-content: center;
61
+ align-items: center;
62
+ }
63
+
64
+ @mixin bg-contain {
65
+ background: center / contain no-repeat;
66
+ }
67
+
68
+ @mixin bg-cover {
69
+ background: center / cover no-repeat;
70
+ }
71
+
72
+ @mixin devBorder($color: aqua) {
73
+ box-shadow: inset 0 0 0 1px $color;
74
+ }
75
+
76
+ // WebP 圖片支持 mixin - 自動生成 WebP fallback
77
+ // 使用方法: @include bg-image-webp("/assets/images/_common/img-support/img.png");
78
+ @mixin bg-image-webp($png-path) {
79
+ $webp-path: str-replace($png-path, '.png', '.webp');
80
+
81
+ @supports (background-image: image-set(url("x.webp") type("image/webp"))){
82
+ background-image: image-set(
83
+ url($webp-path) type("image/webp"),
84
+ url($png-path) type("image/png")
85
+ );
86
+ }
87
+ @supports not (background-image: image-set(url("x.webp") type("image/webp"))){
88
+ background-image: url($png-path);
89
+ }
90
+ }
91
+
92
+ // 辅助函数:字符串替换
93
+ @function str-replace($string, $search, $replace: '') {
94
+ $index: str-index($string, $search);
95
+ @if $index {
96
+ @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
97
+ }
98
+ @return $string;
99
+ }
100
+
101
+ .scale-btn {
102
+ cursor: pointer;
103
+ transition: transform 0.1s;
104
+ &:active {
105
+ transform: scale(0.9);
106
+ }
107
+ }
@@ -0,0 +1,698 @@
1
+ // check support device-vh
2
+ @use "sass:math";
3
+ @use "variables";
4
+
5
+
6
+
7
+ @mixin supports-dv {
8
+ @supports (width: 100dvh) {
9
+ @content;
10
+ }
11
+ }
12
+ @mixin not-supports-dv {
13
+ @supports not (width: 100dvh) {
14
+ @content;
15
+ }
16
+ }
17
+
18
+
19
+
20
+ /**
21
+ * 主要尺寸轉換方法
22
+ * 將設計稿的 px 轉為AWD的 vw
23
+ */
24
+ @function responsive-size-by-vw($w, $unit: 'v', $isLandscape: false, $isMax: false) {
25
+ @if ($isLandscape) {
26
+ @if ($isMax) {
27
+ @return max(vw($w, $unit), vh($w, $unit) * variables.$design-height / variables.$design-width);
28
+ } @else {
29
+ @return min(vw($w, $unit), vh($w, $unit) * variables.$design-height / variables.$design-width);
30
+ }
31
+ } @else {
32
+ @if ($isMax) {
33
+ @return max(vw($w, $unit), vh($w, $unit) * variables.$design-width / variables.$design-height);
34
+ } @else {
35
+ @return min(vw($w, $unit), vh($w, $unit) * variables.$design-width / variables.$design-height);
36
+ }
37
+ }
38
+ }
39
+ @function responsive-size-by-vh($h, $unit: 'v', $isLandscape: false, $isMax: false) {
40
+ @if ($isLandscape) {
41
+ @if ($isMax) {
42
+ @return max(vw($h, $unit) * variables.$design-width / variables.$design-height, vh($h, $unit));
43
+ } @else {
44
+ @return min(vw($h, $unit) * variables.$design-width / variables.$design-height, vh($h, $unit));
45
+ }
46
+ } @else {
47
+ @if ($isMax) {
48
+ @return max(vw($h, $unit) * variables.$design-height / variables.$design-width, vh($h, $unit));
49
+ } @else {
50
+ @return min(vw($h, $unit) * variables.$design-height / variables.$design-width, vh($h, $unit));
51
+ }
52
+ }
53
+ }
54
+ @function responsive-size-by-px($px, $unit: 'v', $isLandscape: false, $isMax: false) {
55
+ $w: math.div($px, 5.4);
56
+ @return responsive-size-by-vw($w, $unit, $isLandscape, $isMax);
57
+ }
58
+
59
+ // responsive width/height by vw
60
+ @mixin width-by-vw($w, $isLandscape: false, $isMax: false) {
61
+ @include supports-dv {
62
+ width: responsive-size-by-vw($w, 'dv', $isLandscape, $isMax);
63
+ }
64
+ @include not-supports-dv {
65
+ width: responsive-size-by-vw($w, 'v', $isLandscape, $isMax);
66
+ }
67
+ }
68
+ @mixin height-by-vw($h, $isLandscape: false, $isMax: false) {
69
+ @include supports-dv {
70
+ height: responsive-size-by-vw($h, 'dv', $isLandscape, $isMax);
71
+ }
72
+ @include not-supports-dv {
73
+ height: responsive-size-by-vw($h, 'v', $isLandscape, $isMax);
74
+ }
75
+ }
76
+ @mixin size-by-vw($w, $h: $w, $isLandscape: false, $isMax: false) {
77
+ @include width-by-vw($w, $isLandscape, $isMax);
78
+ @include height-by-vw($h, $isLandscape, $isMax);
79
+ }
80
+ // responsive width/height by vh
81
+ @mixin width-by-vh($w, $isLandscape: false, $isMax: false) {
82
+ @include supports-dv {
83
+ width: responsive-size-by-vh($w, 'dv', $isLandscape, $isMax);
84
+ }
85
+ @include not-supports-dv {
86
+ width: responsive-size-by-vh($w, 'v', $isLandscape, $isMax);
87
+ }
88
+ }
89
+ @mixin height-by-vh($h, $isLandscape: false, $isMax: false) {
90
+ @include supports-dv {
91
+ height: responsive-size-by-vh($h, 'dv', $isLandscape, $isMax);
92
+ }
93
+ @include not-supports-dv {
94
+ height: responsive-size-by-vh($h, 'v', $isLandscape, $isMax);
95
+ }
96
+ }
97
+ @mixin size-by-vh($w, $h: $w, $isLandscape: false, $isMax: false) {
98
+ @include width-by-vh($w, $isLandscape, $isMax);
99
+ @include height-by-vh($h, $isLandscape, $isMax);
100
+ }
101
+ // responsive width/height by px
102
+ @mixin width-by-px($w, $isLandscape: false, $isMax: false) {
103
+ @include supports-dv {
104
+ width: responsive-size-by-px($w, 'dv', $isLandscape, $isMax);
105
+ }
106
+ @include not-supports-dv {
107
+ width: responsive-size-by-px($w, 'v', $isLandscape, $isMax);
108
+ }
109
+ }
110
+ @mixin height-by-px($h, $isLandscape: false, $isMax: false) {
111
+ @include supports-dv {
112
+ height: responsive-size-by-px($h, 'dv', $isLandscape, $isMax);
113
+ }
114
+ @include not-supports-dv {
115
+ height: responsive-size-by-px($h, 'v', $isLandscape, $isMax);
116
+ }
117
+ }
118
+ @mixin size-by-px($w, $h: $w, $isLandscape: false, $isMax: false) {
119
+ @include width-by-px($w, $isLandscape, $isMax);
120
+ @include height-by-px($h, $isLandscape, $isMax);
121
+ }
122
+
123
+ @mixin responsive-min-height-by-px($px, $isLandscape: false, $isMax: false) {
124
+ @include supports-dv {
125
+ min-height: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
126
+ }
127
+ @include not-supports-dv {
128
+ min-height: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
129
+ }
130
+ }
131
+
132
+ @mixin responsive-max-height-by-px($px, $isLandscape: false, $isMax: false) {
133
+ @include supports-dv {
134
+ max-height: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
135
+ }
136
+ @include not-supports-dv {
137
+ max-height: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
138
+ }
139
+ }
140
+
141
+ // responsive font-size
142
+ @mixin responsive-font-size($w, $isLandscape: false, $isMax: false) {
143
+ @include supports-dv {
144
+ font-size: responsive-size-by-vw($w, 'dv', $isLandscape, $isMax);
145
+ }
146
+ @include not-supports-dv {
147
+ font-size: responsive-size-by-vw($w, 'v', $isLandscape, $isMax);
148
+ }
149
+ }
150
+ @mixin responsive-font-size-by-vh($w, $isLandscape: false) {
151
+ @include supports-dv {
152
+ font-size: responsive-size-by-vh($w, 'dv', $isLandscape);
153
+ }
154
+ @include not-supports-dv {
155
+ font-size: responsive-size-by-vh($w, 'v', $isLandscape);
156
+ }
157
+ }
158
+ @mixin responsive-font-size-by-px($px, $isLandscape: false, $isMax: false) {
159
+ @include supports-dv {
160
+ font-size: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
161
+ }
162
+ @include not-supports-dv {
163
+ font-size: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
164
+ }
165
+ }
166
+
167
+ // responsive line-height
168
+ @mixin responsive-line-height($w) {
169
+ @include supports-dv {
170
+ line-height: responsive-size-by-vw($w, 'dv');
171
+ }
172
+ @include not-supports-dv {
173
+ line-height: responsive-size-by-vw($w, 'v');
174
+ }
175
+ }
176
+ @mixin responsive-line-height-by-vh($h) {
177
+ @include supports-dv {
178
+ line-height: responsive-size-by-vh($h, 'dv');
179
+ }
180
+ @include not-supports-dv {
181
+ line-height: responsive-size-by-vh($h, 'v');
182
+ }
183
+ }
184
+ @mixin responsive-line-height-by-px($px) {
185
+ @include supports-dv {
186
+ line-height: responsive-size-by-px($px, 'dv');
187
+ }
188
+ @include not-supports-dv {
189
+ line-height: responsive-size-by-px($px, 'v');
190
+ }
191
+ }
192
+
193
+ // responsive letter-spacing
194
+ @mixin responsive-letter-spacing($w) {
195
+ @include supports-dv() {
196
+ letter-spacing: responsive-size-by-vw($w, 'dv');
197
+ }
198
+ @include not-supports-dv() {
199
+ letter-spacing: responsive-size-by-vw($w, 'v');
200
+ }
201
+ }
202
+ @mixin responsive-letter-spacing-by-vh($h) {
203
+ @include supports-dv() {
204
+ letter-spacing: responsive-size-by-vh($h, 'dv');
205
+ }
206
+ @include not-supports-dv() {
207
+ letter-spacing: responsive-size-by-vh($h, 'v');
208
+ }
209
+ }
210
+ @mixin responsive-letter-spacing-by-px($px) {
211
+ @include supports-dv() {
212
+ letter-spacing: responsive-size-by-px($px, 'dv');
213
+ }
214
+ @include not-supports-dv() {
215
+ letter-spacing: responsive-size-by-px($px, 'v');
216
+ }
217
+ }
218
+
219
+ // responsive stroke width
220
+ @mixin responsive-stroke-width-by-vw($w) {
221
+ @include supports-dv {
222
+ stroke-width: responsive-size-by-vw($w, 'dv');
223
+ }
224
+ @include not-supports-dv {
225
+ stroke-width: responsive-size-by-vw($w, 'v');
226
+ }
227
+ }
228
+ @mixin responsive-stroke-width-by-vh($h) {
229
+ @include supports-dv {
230
+ stroke-width: responsive-size-by-vh($h, 'dv');
231
+ }
232
+ @include not-supports-dv {
233
+ stroke-width: responsive-size-by-vh($h, 'v');
234
+ }
235
+ }
236
+ @mixin responsive-stroke-width-by-px($px) {
237
+ @include supports-dv {
238
+ stroke-width: responsive-size-by-px($px, 'dv');
239
+ }
240
+ @include not-supports-dv {
241
+ stroke-width: responsive-size-by-px($px, 'v');
242
+ }
243
+ }
244
+
245
+ // responsive text stroke
246
+ @mixin responsive-text-stroke-by-vw($w, $color) {
247
+ @include supports-dv {
248
+ -webkit-text-stroke: responsive-size-by-vw($w, 'dv') $color;
249
+ }
250
+ @include not-supports-dv {
251
+ -webkit-text-stroke: responsive-size-by-vw($w, 'v') $color;
252
+ }
253
+ }
254
+ @mixin responsive-text-stroke-by-vh($w, $color) {
255
+ @include supports-dv {
256
+ -webkit-text-stroke: responsive-size-by-vh($w, 'dv') $color;
257
+ }
258
+ @include not-supports-dv {
259
+ -webkit-text-stroke: responsive-size-by-vh($w, 'v') $color;
260
+ }
261
+ }
262
+ @mixin responsive-text-stroke-by-px($px, $color) {
263
+ @include supports-dv {
264
+ -webkit-text-stroke: responsive-size-by-px($px, 'dv') $color;
265
+ }
266
+ @include not-supports-dv {
267
+ -webkit-text-stroke: responsive-size-by-px($px, 'v') $color;
268
+ }
269
+ }
270
+
271
+ // responsive border-radius
272
+ @mixin responsive-border-radius-by-vw($w, $isLandscape: false, $isMax: false) {
273
+ @include supports-dv {
274
+ border-radius: responsive-size-by-vw($w, 'dv', $isLandscape, $isMax);
275
+ }
276
+ @include not-supports-dv {
277
+ border-radius: responsive-size-by-vw($w, 'v', $isLandscape, $isMax);
278
+ }
279
+ }
280
+ @mixin responsive-border-radius-by-vh($h, $isLandscape: false, $isMax: false) {
281
+ @include supports-dv {
282
+ border-radius: responsive-size-by-vh($h, 'dv', $isLandscape, $isMax);
283
+ }
284
+ @include not-supports-dv {
285
+ border-radius: responsive-size-by-vh($h, 'v', $isLandscape, $isMax);
286
+ }
287
+ }
288
+ @mixin responsive-border-radius-by-px($px, $isLandscape: false, $isMax: false) {
289
+ @include supports-dv {
290
+ border-radius: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
291
+ }
292
+ @include not-supports-dv {
293
+ border-radius: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
294
+ }
295
+ }
296
+
297
+ // responsive margin
298
+ @mixin responsive-margin-top-by-vw($w, $isLandscape: false, $isMax: false) {
299
+ @include supports-dv {
300
+ margin-top: responsive-size-by-vw($w, 'dv', $isLandscape, $isMax);
301
+ }
302
+ @include not-supports-dv {
303
+ margin-top: responsive-size-by-vw($w, 'v', $isLandscape, $isMax);
304
+ }
305
+ }
306
+ @mixin responsive-margin-bottom-by-vw($w, $isLandscape: false, $isMax: false) {
307
+ @include supports-dv {
308
+ margin-bottom: responsive-size-by-vw($w, 'dv', $isLandscape, $isMax);
309
+ }
310
+ @include not-supports-dv {
311
+ margin-bottom: responsive-size-by-vw($w, 'v', $isLandscape, $isMax);
312
+ }
313
+ }
314
+ @mixin responsive-margin-left-by-vw($w, $isLandscape: false, $isMax: false) {
315
+ @include supports-dv {
316
+ margin-left: responsive-size-by-vw($w, 'dv', $isLandscape, $isMax);
317
+ }
318
+ @include not-supports-dv {
319
+ margin-left: responsive-size-by-vw($w, 'v', $isLandscape, $isMax);
320
+ }
321
+ }
322
+ @mixin responsive-margin-right-by-vw($w, $isLandscape: false, $isMax: false) {
323
+ @include supports-dv {
324
+ margin-right: responsive-size-by-vw($w, 'dv', $isLandscape, $isMax);
325
+ }
326
+ @include not-supports-dv {
327
+ margin-right: responsive-size-by-vw($w, 'v', $isLandscape, $isMax);
328
+ }
329
+ }
330
+ @mixin responsive-margin-by-vw($w, $isLandscape: false, $isMax: false) {
331
+ @include responsive-margin-top-by-vw($w, $isLandscape, $isMax);
332
+ @include responsive-margin-bottom-by-vw($w, $isLandscape, $isMax);
333
+ @include responsive-margin-left-by-vw($w, $isLandscape, $isMax);
334
+ @include responsive-margin-right-by-vw($w, $isLandscape, $isMax);
335
+ }
336
+
337
+ @mixin responsive-margin-top-by-vh($h, $isLandscape: false, $isMax: false) {
338
+ @include supports-dv {
339
+ margin-top: responsive-size-by-vh($h, 'dv', $isLandscape, $isMax);
340
+ }
341
+ @include not-supports-dv {
342
+ margin-top: responsive-size-by-vh($h, 'v', $isLandscape, $isMax);
343
+ }
344
+ }
345
+ @mixin responsive-margin-bottom-by-vh($h, $isLandscape: false, $isMax: false) {
346
+ @include supports-dv {
347
+ margin-bottom: responsive-size-by-vh($h, 'dv', $isLandscape, $isMax);
348
+ }
349
+ @include not-supports-dv {
350
+ margin-bottom: responsive-size-by-vh($h, 'v', $isLandscape, $isMax);
351
+ }
352
+ }
353
+ @mixin responsive-margin-left-by-vh($h, $isLandscape: false, $isMax: false) {
354
+ @include supports-dv {
355
+ margin-left: responsive-size-by-vh($h, 'dv', $isLandscape, $isMax);
356
+ }
357
+ @include not-supports-dv {
358
+ margin-left: responsive-size-by-vh($h, 'v', $isLandscape, $isMax);
359
+ }
360
+ }
361
+ @mixin responsive-margin-right-by-vh($h, $isLandscape: false, $isMax: false) {
362
+ @include supports-dv {
363
+ margin-right: responsive-size-by-vh($h, 'dv', $isLandscape, $isMax);
364
+ }
365
+ @include not-supports-dv {
366
+ margin-right: responsive-size-by-vh($h, 'v', $isLandscape, $isMax);
367
+ }
368
+ }
369
+ @mixin responsive-margin-by-vh($h, $isLandscape: false, $isMax: false) {
370
+ @include responsive-margin-top-by-vh($h, $isLandscape, $isMax);
371
+ @include responsive-margin-bottom-by-vh($h, $isLandscape, $isMax);
372
+ @include responsive-margin-left-by-vh($h, $isLandscape, $isMax);
373
+ @include responsive-margin-right-by-vh($h, $isLandscape, $isMax);
374
+ }
375
+
376
+ @mixin responsive-margin-top-by-px($px, $isLandscape: false, $isMax: false) {
377
+ @include supports-dv {
378
+ margin-top: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
379
+ }
380
+ @include not-supports-dv {
381
+ margin-top: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
382
+ }
383
+ }
384
+ @mixin responsive-margin-bottom-by-px($px, $isLandscape: false, $isMax: false) {
385
+ @include supports-dv {
386
+ margin-bottom: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
387
+ }
388
+ @include not-supports-dv {
389
+ margin-bottom: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
390
+ }
391
+ }
392
+ @mixin responsive-margin-left-by-px($px, $isLandscape: false, $isMax: false) {
393
+ @include supports-dv {
394
+ margin-left: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
395
+ }
396
+ @include not-supports-dv {
397
+ margin-left: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
398
+ }
399
+ }
400
+ @mixin responsive-margin-right-by-px($px, $isLandscape: false, $isMax: false) {
401
+ @include supports-dv {
402
+ margin-right: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
403
+ }
404
+ @include not-supports-dv {
405
+ right: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
406
+ }
407
+ }
408
+ @mixin responsive-margin-by-px($px, $isLandscape: false, $isMax: false) {
409
+ @include responsive-margin-top-by-px($px, $isLandscape, $isMax);
410
+ @include responsive-margin-bottom-by-px($px, $isLandscape, $isMax);
411
+ @include responsive-margin-left-by-px($px, $isLandscape, $isMax);
412
+ @include responsive-margin-right-by-px($px, $isLandscape, $isMax);
413
+ }
414
+
415
+ // responsive padding
416
+ @mixin responsive-padding-top-by-vw($w, $isLandscape: false, $isMax: false) {
417
+ @include supports-dv {
418
+ padding-top: responsive-size-by-vw($w, 'dv', $isLandscape, $isMax);
419
+ }
420
+ @include not-supports-dv {
421
+ padding-top: responsive-size-by-vw($w, 'v', $isLandscape, $isMax);
422
+ }
423
+ }
424
+ @mixin responsive-padding-bottom-by-vw($w, $isLandscape: false, $isMax: false) {
425
+ @include supports-dv {
426
+ padding-bottom: responsive-size-by-vw($w, 'dv', $isLandscape, $isMax);
427
+ }
428
+ @include not-supports-dv {
429
+ padding-bottom: responsive-size-by-vw($w, 'v', $isLandscape, $isMax);
430
+ }
431
+ }
432
+ @mixin responsive-padding-left-by-vw($w, $isLandscape: false, $isMax: false) {
433
+ @include supports-dv {
434
+ padding-left: responsive-size-by-vw($w, 'dv', $isLandscape, $isMax);
435
+ }
436
+ @include not-supports-dv {
437
+ padding-left: responsive-size-by-vw($w, 'v', $isLandscape, $isMax);
438
+ }
439
+ }
440
+ @mixin responsive-padding-right-by-vw($w, $isLandscape: false, $isMax: false) {
441
+ @include supports-dv {
442
+ padding-right: responsive-size-by-vw($w, 'dv', $isLandscape, $isMax);
443
+ }
444
+ @include not-supports-dv {
445
+ padding-right: responsive-size-by-vw($w, 'v', $isLandscape, $isMax);
446
+ }
447
+ }
448
+ @mixin responsive-padding-by-vw($w, $isLandscape: false, $isMax: false) {
449
+ @include responsive-padding-top-by-vw($w, $isLandscape, $isMax);
450
+ @include responsive-padding-bottom-by-vw($w, $isLandscape, $isMax);
451
+ @include responsive-padding-left-by-vw($w, $isLandscape, $isMax);
452
+ @include responsive-padding-right-by-vw($w, $isLandscape, $isMax);
453
+ }
454
+
455
+ @mixin responsive-padding-top-by-vh($h, $isLandscape: false, $isMax: false) {
456
+ @include supports-dv {
457
+ padding-top: responsive-size-by-vh($h, 'dv', $isLandscape, $isMax);
458
+ }
459
+ @include not-supports-dv {
460
+ padding-top: responsive-size-by-vh($h, 'v', $isLandscape, $isMax);
461
+ }
462
+ }
463
+ @mixin responsive-padding-bottom-by-vh($h, $isLandscape: false, $isMax: false) {
464
+ @include supports-dv {
465
+ padding-bottom: responsive-size-by-vh($h, 'dv', $isLandscape, $isMax);
466
+ }
467
+ @include not-supports-dv {
468
+ padding-bottom: responsive-size-by-vh($h, 'v', $isLandscape, $isMax);
469
+ }
470
+ }
471
+ @mixin responsive-padding-left-by-vh($h, $isLandscape: false, $isMax: false) {
472
+ @include supports-dv {
473
+ padding-left: responsive-size-by-vh($h, 'dv', $isLandscape, $isMax);
474
+ }
475
+ @include not-supports-dv {
476
+ padding-left: responsive-size-by-vh($h, 'v', $isLandscape, $isMax);
477
+ }
478
+ }
479
+ @mixin responsive-padding-right-by-vh($h, $isLandscape: false, $isMax: false) {
480
+ @include supports-dv {
481
+ padding-right: responsive-size-by-vh($h, 'dv', $isLandscape, $isMax);
482
+ }
483
+ @include not-supports-dv {
484
+ padding-right: responsive-size-by-vh($h, 'v', $isLandscape, $isMax);
485
+ }
486
+ }
487
+ @mixin responsive-padding-by-vh($h, $isLandscape: false, $isMax: false) {
488
+ @include responsive-padding-top-by-vh($h, $isLandscape, $isMax);
489
+ @include responsive-padding-bottom-by-vh($h, $isLandscape, $isMax);
490
+ @include responsive-padding-left-by-vh($h, $isLandscape, $isMax);
491
+ @include responsive-padding-right-by-vh($h, $isLandscape, $isMax);
492
+ }
493
+
494
+ @mixin responsive-padding-top-by-px($px, $isLandscape: false, $isMax: false) {
495
+ @include supports-dv {
496
+ padding-top: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
497
+ }
498
+ @include not-supports-dv {
499
+ padding-top: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
500
+ }
501
+ }
502
+ @mixin responsive-padding-bottom-by-px($px, $isLandscape: false, $isMax: false) {
503
+ @include supports-dv {
504
+ padding-bottom: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
505
+ }
506
+ @include not-supports-dv {
507
+ padding-bottom: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
508
+ }
509
+ }
510
+ @mixin responsive-padding-left-by-px($px, $isLandscape: false, $isMax: false) {
511
+ @include supports-dv {
512
+ padding-left: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
513
+ }
514
+ @include not-supports-dv {
515
+ padding-left: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
516
+ }
517
+ }
518
+ @mixin responsive-padding-right-by-px($px, $isLandscape: false, $isMax: false) {
519
+ @include supports-dv {
520
+ padding-right: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
521
+ }
522
+ @include not-supports-dv {
523
+ padding-right: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
524
+ }
525
+ }
526
+ @mixin responsive-padding-by-px($px, $isLandscape: false, $isMax: false) {
527
+ @include responsive-padding-top-by-px($px, $isLandscape, $isMax);
528
+ @include responsive-padding-bottom-by-px($px, $isLandscape, $isMax);
529
+ @include responsive-padding-left-by-px($px, $isLandscape, $isMax);
530
+ @include responsive-padding-right-by-px($px, $isLandscape, $isMax);
531
+ }
532
+
533
+ // responsive position
534
+ @mixin responsive-position-by-vw($vw: (top: "", right: "", bottom: "", left: ""), $isLandscape: false, $isMax: false) {
535
+ $top: if(map-has-key($vw, top), map-get($vw, top), "");
536
+ $right: if(map-has-key($vw, right), map-get($vw, right), "");
537
+ $bottom: if(map-has-key($vw, bottom), map-get($vw, bottom), "");
538
+ $left: if(map-has-key($vw, left), map-get($vw, left), "");
539
+
540
+ @include supports-dv {
541
+ @if ($top != "") {
542
+ top: responsive-size-by-vw($top, 'dv', $isLandscape, $isMax);
543
+ }
544
+ @if ($right != "") {
545
+ right: responsive-size-by-vw($right, 'dv', $isLandscape, $isMax);
546
+ }
547
+ @if ($bottom != "") {
548
+ bottom: responsive-size-by-vw($bottom, 'dv', $isLandscape, $isMax);
549
+ }
550
+ @if ($left != "") {
551
+ left: responsive-size-by-vw($left, 'dv', $isLandscape, $isMax);
552
+ }
553
+ }
554
+ @include not-supports-dv {
555
+ @if ($top != "") {
556
+ top: responsive-size-by-vw($top, 'v', $isLandscape, $isMax);
557
+ }
558
+ @if ($right != "") {
559
+ right: responsive-size-by-vw($right, 'v', $isLandscape, $isMax);
560
+ }
561
+ @if ($bottom != "") {
562
+ bottom: responsive-size-by-vw($bottom, 'v', $isLandscape, $isMax);
563
+ }
564
+ @if ($left != "") {
565
+ left: responsive-size-by-vw($left, 'v', $isLandscape, $isMax);
566
+ }
567
+ }
568
+ }
569
+ @mixin responsive-position-by-vh($vh: (top: "", right: "", bottom: "", left: ""), $isLandscape: false, $isMax: false) {
570
+ $top: if(map-has-key($vh, top), map-get($vh, top), "");
571
+ $right: if(map-has-key($vh, right), map-get($vh, right), "");
572
+ $bottom: if(map-has-key($vh, bottom), map-get($vh, bottom), "");
573
+ $left: if(map-has-key($vh, left), map-get($vh, left), "");
574
+ @include supports-dv {
575
+ @if ($top != "") {
576
+ top: responsive-size-by-vh($top, 'dv', $isLandscape, $isMax);
577
+ }
578
+ @if ($right != "") {
579
+ right: responsive-size-by-vh($right, 'dv', $isLandscape, $isMax);
580
+ }
581
+ @if ($bottom != "") {
582
+ bottom: responsive-size-by-vh($bottom, 'dv', $isLandscape, $isMax);
583
+ }
584
+ @if ($left != "") {
585
+ left: responsive-size-by-vh($left, 'dv', $isLandscape, $isMax);
586
+ }
587
+ }
588
+ @include not-supports-dv {
589
+ @if ($top != "") {
590
+ top: responsive-size-by-vh($top, 'v', $isLandscape, $isMax);
591
+ }
592
+ @if ($right != "") {
593
+ right: responsive-size-by-vh($right, 'v', $isLandscape, $isMax);
594
+ }
595
+ @if ($bottom != "") {
596
+ bottom: responsive-size-by-vh($bottom, 'v', $isLandscape, $isMax);
597
+ }
598
+ @if ($left != "") {
599
+ left: responsive-size-by-vh($left, 'v', $isLandscape, $isMax);
600
+ }
601
+ }
602
+ }
603
+ @mixin responsive-position-by-px($px: (top: "", right: "", bottom: "", left: ""), $isLandscape: false, $isMax: false) {
604
+ $top: if(map-has-key($px, top), map-get($px, top), "");
605
+ $right: if(map-has-key($px, right), map-get($px, right), "");
606
+ $bottom: if(map-has-key($px, bottom), map-get($px, bottom), "");
607
+ $left: if(map-has-key($px, left), map-get($px, left), "");
608
+ @include supports-dv {
609
+ @if ($top != "") {
610
+ top: responsive-size-by-px($top, 'dv', $isLandscape, $isMax);
611
+ }
612
+ @if ($right != "") {
613
+ right: responsive-size-by-px($right, 'dv', $isLandscape, $isMax);
614
+ }
615
+ @if ($bottom != "") {
616
+ bottom: responsive-size-by-px($bottom, 'dv', $isLandscape, $isMax);
617
+ }
618
+ @if ($left != "") {
619
+ left: responsive-size-by-px($left, 'dv', $isLandscape, $isMax);
620
+ }
621
+ }
622
+ @include not-supports-dv {
623
+ @if ($top != "") {
624
+ top: responsive-size-by-px($top, 'v', $isLandscape, $isMax);
625
+ }
626
+ @if ($right != "") {
627
+ right: responsive-size-by-px($right, 'v', $isLandscape, $isMax);
628
+ }
629
+ @if ($bottom != "") {
630
+ bottom: responsive-size-by-px($bottom, 'v', $isLandscape, $isMax);
631
+ }
632
+ @if ($left != "") {
633
+ left: responsive-size-by-px($left, 'v', $isLandscape, $isMax);
634
+ }
635
+ }
636
+ }
637
+
638
+ @mixin responsive-letter-border($color, $w, $h: $w) {
639
+ $vw: $w + 'vw';
640
+ $vh: $h + 'vh';
641
+ $unit: min(#{$vw}, #{$vh} * variables.$design-width / variables.$design-height);
642
+ $minusUnit: calc(-1 * $unit);
643
+
644
+ text-shadow:
645
+ $unit 0 $color, /* 筆畫顏色,水平偏移 */
646
+ $minusUnit 0 $color, /* 筆畫顏色,水平偏移 */
647
+ 0 $unit $color, /* 筆畫顏色,垂直偏移 */
648
+ 0 $minusUnit $color, /* 筆畫顏色,垂直偏移 */
649
+ $unit $unit $color, /* 斜向右下 */
650
+ $minusUnit $minusUnit $color, /* 斜向左上 */
651
+ $unit $minusUnit $color, /* 斜向右上 */
652
+ $minusUnit $unit $color; /* 斜向左下 */
653
+ }
654
+
655
+ @mixin responsive-letter-shadow($color, $w, $h: $w) {
656
+ $vw: $w + 'vw';
657
+ $vh: $h + 'vh';
658
+ $unit: min(#{$vw}, #{$vh} * variables.$design-width / variables.$design-height);
659
+
660
+ text-shadow: $unit $unit $unit $color; /* 陰影顏色 */
661
+ }
662
+
663
+ @mixin responsive-letter-border-shadow($colorBorder, $colorShadow, $w, $h: $w) {
664
+ $vw: $w + 'vw';
665
+ $vh: $h + 'vh';
666
+ $unit: min(#{$vw}, #{$vh} * variables.$design-width / variables.$design-height);
667
+ $minusUnit: calc(-1 * $unit);
668
+ $shadow: calc(2 * $unit);
669
+
670
+ text-shadow:
671
+ $unit 0 $colorBorder, /* 筆畫顏色,水平偏移 */
672
+ $minusUnit 0 $colorBorder, /* 筆畫顏色,水平偏移 */
673
+ 0 $unit $colorBorder, /* 筆畫顏色,垂直偏移 */
674
+ 0 $minusUnit $colorBorder, /* 筆畫顏色,垂直偏移 */
675
+ $unit $unit $colorBorder, /* 斜向右下 */
676
+ $minusUnit $minusUnit $colorBorder, /* 斜向左上 */
677
+ $unit $minusUnit $colorBorder, /* 斜向右上 */
678
+ $minusUnit $unit $colorBorder, /* 斜向左下 */
679
+ $shadow $shadow $shadow $colorShadow; /* 陰影顏色 */
680
+ }
681
+
682
+ @mixin responsive-border-by-px($px, $color, $isLandscape: false, $isMax: false) {
683
+ @include supports-dv {
684
+ border: responsive-size-by-px($px, 'dv', $isLandscape, $isMax) solid $color;
685
+ }
686
+ @include not-supports-dv {
687
+ border: responsive-size-by-px($px, 'v', $isLandscape, $isMax) solid $color;
688
+ }
689
+ }
690
+
691
+ @mixin responsive-padding-inline-start-by-px($px, $isLandscape: false, $isMax: false) {
692
+ @include supports-dv {
693
+ padding-inline-start: responsive-size-by-px($px, 'dv', $isLandscape, $isMax);
694
+ }
695
+ @include not-supports-dv {
696
+ padding-inline-start: responsive-size-by-px($px, 'v', $isLandscape, $isMax);
697
+ }
698
+ }
@@ -0,0 +1,29 @@
1
+ @use "sass:math";
2
+
3
+ // 基礎尺寸 (無單位數值)
4
+ $design-width: 540;
5
+ $design-height: 960;
6
+
7
+ // 帶單位的版本 (當需要 px 單位時使用)
8
+ $design-width-px: #{$design-width}px;
9
+ $design-height-px: #{$design-height}px;
10
+
11
+ $landscape-ratio: math.div($design-width, $design-height);
12
+ $portrait-ratio: math.div($design-height, $design-width);
13
+
14
+ // Portrait 模式的設計基準
15
+ $layout-portrait-width: $design-width; // 375
16
+ $layout-portrait-height: $design-height; // 667
17
+
18
+ // Landscape 模式的設計基準
19
+ $layout-landscape-width: $design-height; // 667
20
+ $layout-landscape-height: $design-width; // 375
21
+
22
+ $vw-unit: dvw !default;
23
+ $vh-unit: dvh !default;
24
+
25
+ @supports not (width: 100dvh) {
26
+ $vw-unit: vw;
27
+ $vh-unit: vh;
28
+ }
29
+
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Public SCSS API for @bitstack/ng-boundary
3
+ *
4
+ * This file exports all SCSS utilities, functions, and mixins
5
+ * for use in consumer projects.
6
+ *
7
+ * Usage:
8
+ * @use '@bitstack/ng-boundary/styles' as boundary;
9
+ *
10
+ * .my-component {
11
+ * width: boundary.px2vw(100);
12
+ * height: boundary.px2vw(200);
13
+ * }
14
+ */
15
+
16
+ // Export all utilities
17
+ // Note: _awd already includes _responsive internally, so we don't need to forward _responsive separately
18
+ @forward '../lib/_/_variables';
19
+ @forward '../lib/_/_awd';
20
+ @forward '../lib/_/_mixin';
package/styles.scss ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Main entry point for @bitstack/ng-boundary styles
3
+ *
4
+ * Usage:
5
+ * @use '@bitstack/ng-boundary/styles' as boundary;
6
+ */
7
+
8
+ @forward 'src/styles/index';