@nopon-web/styles 0.0.2 → 0.0.5

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/_config.scss ADDED
@@ -0,0 +1,7 @@
1
+ $namespace: "s" !default;
2
+ $common-separator: "-" !default;
3
+ $element-separator: "__" !default;
4
+ $modifier-separator: "--" !default;
5
+ $state-prefix: "is" !default;
6
+ $theme-prefix: "theme" !default;
7
+ $theme-name: "" !default;
package/_function.scss CHANGED
@@ -1,18 +1,61 @@
1
- @use 'sass:string';
2
- @use './_variables' as var;
1
+ @use "sass:string";
2
+ @use "./_variables" as var;
3
+ @use "_config" as config;
4
+
5
+ // bem("block", "element", "modifier") => "s_block__element--modifier"
6
+ @function bem($block, $element: "", $modifier: "") {
7
+ $name: config.$namespace + config.$common-separator + $block;
8
+
9
+ @if $element != "" {
10
+ $name: $name + config.$element-separator + $element;
11
+ }
12
+
13
+ @if $modifier != "" {
14
+ $name: $name + config.$modifier-separator + $modifier;
15
+ }
16
+
17
+ @return $name;
18
+ }
19
+
20
+ @function when($state) {
21
+ $state-selector: config.$state-prefix + config.$common-separator + $state;
22
+
23
+ @return ".#{$state-selector}";
24
+ }
25
+
26
+ @function join-class($parts...) {
27
+ $result: "";
28
+
29
+ @each $part in $parts {
30
+ @if $part != null and $part != "" {
31
+ @if $result == "" {
32
+ $result: $part;
33
+ } @else {
34
+ $result: $result + config.$common-separator + $part;
35
+ }
36
+ }
37
+ }
38
+
39
+ @return $result;
40
+ }
41
+
42
+ // 最小尺寸单位转换
43
+ @function u($value) {
44
+ @return calc(#{$value} * var(--size-unit));
45
+ }
3
46
 
4
47
  @function get-image($image) {
5
48
  // 已经是合法CSS值的情况
6
- @if string.index($image, 'url(') or
7
- string.index($image, 'gradient(') or
8
- string.index($image, 'var(') or
9
- string.index($image, 'data:')
49
+ @if string.index($image, "url(") or
50
+ string.index($image, "gradient(") or
51
+ string.index($image, "var(") or
52
+ string.index($image, "data:")
10
53
  {
11
54
  @return $image;
12
55
  }
13
56
 
14
57
  // 空值或none
15
- @if $image == none or $image == null {
58
+ @if $image ==none or $image ==null {
16
59
  @return none;
17
60
  }
18
61
 
package/_mixin.scss CHANGED
@@ -1,6 +1,92 @@
1
- @use './_variables' as var;
2
- @use './_function' as func;
3
- @use 'sass:map';
1
+ @use "sass:map";
2
+
3
+ @use "_config" as *;
4
+ @use "_variables" as var;
5
+ @use "_function" as func;
6
+
7
+ @forward "_config";
8
+ @forward "_variables";
9
+ @forward "_function";
10
+
11
+ // BEM
12
+ $B: null;
13
+ $__bem-context: null;
14
+
15
+ @mixin b($block) {
16
+ $B: $namespace + $common-separator + $block !global;
17
+
18
+ .#{$B} {
19
+ $__bem-context: "block" !global;
20
+ @content;
21
+ $__bem-context: null !global;
22
+ }
23
+ }
24
+
25
+ @mixin e($element) {
26
+ @if $__bem-context != "block" {
27
+ @error "e() can only be used inside b()";
28
+ }
29
+
30
+ @each $E in $element {
31
+ .#{$B + $element-separator + $E} {
32
+ $__bem-context: "element" !global;
33
+ @content;
34
+ $__bem-context: "block" !global;
35
+ }
36
+ }
37
+ }
38
+
39
+ @mixin m($modifier) {
40
+ @if $__bem-context != "block" and $__bem-context != "element" {
41
+ @error "m() can only be used inside b() or e()";
42
+ }
43
+
44
+ @each $M in $modifier {
45
+ &#{$modifier-separator + $M} {
46
+ @content;
47
+ }
48
+ }
49
+ }
50
+
51
+ @mixin t($names: null) {
52
+ @if $__bem-context != "block" {
53
+ @error "t() can only be used inside b()";
54
+ }
55
+
56
+ // 解析 themes 列表
57
+ $themes: ();
58
+ @if $names == null {
59
+ @if $theme-name == null or $theme-name == "" {
60
+ @error "$theme-name must be set globally or passed to @include t().";
61
+ }
62
+ $themes: ($theme-name);
63
+ } @else {
64
+ $themes: $names;
65
+ }
66
+
67
+ // 逐个生成 theme 选择器
68
+ @each $theme in $themes {
69
+ @if $theme == null or $theme == "" {
70
+ @error "Invalid theme name in @include t().";
71
+ }
72
+
73
+ $T: $theme-prefix + $common-separator + $theme;
74
+
75
+ &.#{$B + $modifier-separator + $T} {
76
+ @content;
77
+ }
78
+ }
79
+ }
80
+
81
+ @mixin when($state) {
82
+ $state-selector: $state-prefix + $common-separator + $state;
83
+
84
+ @at-root {
85
+ #{if(&, "&.#{$state-selector}", ".#{$state-selector}")} {
86
+ @content;
87
+ }
88
+ }
89
+ }
4
90
 
5
91
  @mixin absolute-center($x: true, $y: true) {
6
92
  position: absolute;
@@ -13,7 +99,7 @@
13
99
  left: 50%;
14
100
  }
15
101
 
16
- transform: translate(#{if($x, '-50%', '0')}, #{if($y, '-50%', '0')});
102
+ transform: translate(#{if($x, "-50%", "0")}, #{if($y, "-50%", "0")});
17
103
  }
18
104
 
19
105
  @mixin set-z-index($number) {
@@ -30,19 +116,6 @@
30
116
  background-image: func.get-image($image);
31
117
  }
32
118
 
33
- @mixin bg-border($width, $height, $image, $border: ('width': 0, 'image-slice': 0), $fill: true) {
34
- $border-width: map.get($border, 'width');
35
- $border-image-slice: map.get($border, 'image-slice');
36
-
37
- width: $width;
38
- height: $height;
39
- border-image-source: func.get-image($image);
40
- border-style: solid;
41
- box-sizing: border-box;
42
- border-width: $border-width;
43
- border-image-slice: #{$border-image-slice}#{if($fill, ' fill', '')};
44
- }
45
-
46
119
  @mixin bg-text($image) {
47
120
  background-clip: text;
48
121
  -webkit-background-clip: text;
@@ -51,167 +124,54 @@
51
124
  background-image: func.get-image($image);
52
125
  }
53
126
 
54
- @mixin text-stroke($size: 1px, $color: #000, $blur: 0) {
55
- text-shadow: #{$size} #{$size} #{$blur} #{$color}, -#{$size} #{$size} #{$blur} #{$color},
56
- #{$size} -#{$size} #{$blur} #{$color}, -#{$size} -#{$size} #{$blur} #{$color};
57
- }
58
-
59
- /// 通用列表布局封装
60
- /// 支持 grid / flex 两种布局
61
- /// @param $options - 可选配置
62
- /// ------------------------------------------------------------------------
63
- /// HTML 模板示例:
64
- // <ul class="b-e--list">
65
- // <li class="b-e--item">
66
- // <div class="b-e--media">
67
- // <div class="b-e--picture">
68
- // <div class="b-e--picture_bg picture">
69
- // <img src="">
70
- // </div>
71
- // <div class="b-e--picture_wrapper picture">
72
- // <img class="b-e--picture_content"
73
- // src="">
74
- // </div>
75
- // <div class="b-e--picture_decoration picture">
76
- // <img src="">
77
- // </div>
78
- // <div class="b-e--picture_cover picture">
79
- // <img src="">
80
- // </div>
81
- // </div>
82
- // </div>
83
- // <div class="b-e--content">
84
- // <div class="b-e--content_text">
85
- // <span class="text"></span>
86
- // </div>
87
- // </div>
88
- // </li>
89
- // </ul>
90
- /// ------------------------------------------------------------------------
91
- @mixin extend-list($options: ()) {
92
- // --- 默认参数 ---
93
- $defaults: (
94
- 'namespace-block': 'b',
95
- 'namespace-element': 'e',
96
- // 布局模式
97
- 'display': grid,
98
- // 是否换行
99
- 'wrap': false,
100
- // 列数
101
- 'col': 4,
102
- // 间距
103
- 'gap': 10px,
104
- // 图片宽高比
105
- 'picture-ratio': 100%,
106
- // 图片宽度
107
- 'picture-width': 100%,
108
- // 图片高度
109
- 'picture-height': 100%,
110
- );
111
-
112
- // 合并配置
113
- $config: map.merge($defaults, $options);
114
-
115
- // 变量定义
116
- $block: map.get($config, 'namespace-block');
117
- $element: map.get($config, 'namespace-element');
118
- $display: map.get($config, 'display');
119
- $wrap: map.get($config, 'wrap');
120
- $col: map.get($config, 'col');
121
- $gap: map.get($config, 'gap');
122
- $picture-ratio: map.get($config, 'picture-ratio');
123
- $picture-width: map.get($config, 'picture-width');
124
- $picture-height: map.get($config, 'picture-height');
125
-
126
- // --- 列表容器 ---
127
- .#{$block}-#{$element}--list {
128
- --col: #{$col};
129
- --gap: #{$gap};
130
- --picture-ratio: #{$picture-ratio};
131
- --picture-width: #{$picture-width};
132
- --picture-height: #{$picture-height};
133
- display: $display;
134
-
135
- // flex 布局
136
- @if $display == flex {
137
- margin: 0 calc(var(--gap) / -2);
138
-
139
- // 换行
140
- @if $wrap {
141
- flex-wrap: wrap;
142
- }
143
- }
144
-
145
- // grid 布局(默认)
146
- @if $display == grid {
147
- gap: var(--gap);
148
-
149
- // 换行
150
- @if $wrap {
151
- grid-template-columns: repeat(var(--col), minmax(0, 1fr));
152
- } @else {
153
- grid-auto-flow: column;
154
- grid-auto-columns: calc((100% - (var(--col) - 1) * var(--gap)) / var(--col));
155
- }
156
- }
127
+ @mixin frame-border($frame) {
128
+ $image: map.get($frame, image);
129
+ $inset: map.get($frame, inset);
130
+ $slice: map.get($frame, slice);
131
+ $fill: map.get($frame, fill);
132
+ $repeat: map.get($frame, repeat, stretch);
157
133
 
158
- @if $wrap == false {
159
- overflow-x: scroll;
160
- }
134
+ @if not $image or not $inset or not $slice {
135
+ @error "frame-border: image / inset / slice are required";
161
136
  }
162
137
 
163
- // --- 列表项 ---
164
- .#{$block}-#{$element}--item {
165
- position: relative;
166
- font-size: 0;
167
-
168
- @if $display == flex {
169
- flex-shrink: 0;
170
- width: calc(100% / var(--col));
171
- padding: calc(var(--gap) / 2);
172
- }
173
- }
174
-
175
- // --- 图片 ---
176
- .#{$block}-#{$element}--picture {
177
- position: relative;
178
-
179
- &_bg {
180
- width: 100%;
181
- height: 100%;
182
- @include absolute-center(true, true);
183
- z-index: 0;
184
- }
185
-
186
- &_wrapper {
187
- position: relative;
188
- height: 0;
189
- padding-bottom: var(--picture-ratio);
190
- }
138
+ box-sizing: border-box;
139
+ border-style: solid;
140
+ border-width: $inset;
141
+ border-image-source: func.get-image($image);
142
+ border-image-slice: #{$slice}#{if($fill, " fill", "")};
143
+ border-image-repeat: $repeat;
144
+ }
191
145
 
192
- &_content {
193
- max-width: var(--picture-width);
194
- max-height: var(--picture-height);
195
- @include absolute-center(true, true);
196
- }
146
+ @mixin text-stroke($size, $color: #000, $blur: 0) {
147
+ text-shadow:
148
+ #{$size} #{$size} #{$blur} #{$color},
149
+ -#{$size} #{$size} #{$blur} #{$color},
150
+ #{$size} -#{$size} #{$blur} #{$color},
151
+ -#{$size} -#{$size} #{$blur} #{$color};
152
+ }
197
153
 
198
- &_decoration {
199
- position: absolute;
200
- top: 0;
201
- right: 0;
202
- z-index: 1;
203
- }
154
+ @mixin text-shadow($size, $color: #000, $offset-x: func.u(2), $offset-y: #{u(2)}) {
155
+ position: relative;
156
+ z-index: 0;
157
+ font-size: 0;
158
+ line-height: 1;
159
+ font-size: #{func.u(10)};
204
160
 
205
- &_cover {
206
- @include absolute-center(true, true);
207
- z-index: 2;
208
- width: 100%;
209
- height: 100%;
210
- }
161
+ > * {
162
+ font-size: $size;
211
163
  }
212
164
 
213
- // --- 内容区 ---
214
- .#{$block}-#{$element}--content {
215
- text-align: center;
165
+ &::before {
166
+ content: attr(data-text);
167
+ position: absolute;
168
+ top: 50%;
169
+ left: 50%;
170
+ z-index: -1;
171
+ color: $color;
172
+ font-size: $size;
173
+ white-space: nowrap;
174
+ // 偏移量
175
+ transform: translate(calc(-50% + #{$offset-x}), calc(-50% + #{$offset-y}));
216
176
  }
217
177
  }
package/_variables.scss CHANGED
@@ -1,2 +1,9 @@
1
+ // 🔤 尺寸基准值,控制设计稿与真实页面的缩放比例
2
+ $size-root: 16 !default;
3
+ // 🔤 最小单位:等效于 1px:
4
+ // - 当使用 rem 方案:1px = calc(1 / var(--size-root) * 1rem)
5
+ // - 当使用 vw 方案:1px = calc(1 / var(--size-root) * 100vw)
6
+ $size-unit: calc(1 / var(--size-root) * 1rem) !default;
7
+
1
8
  // 层级
2
9
  $z-index-base: 1000;
@@ -1,3 +1,5 @@
1
+ @use "../mixin" as *;
2
+
1
3
  @keyframes like-floating {
2
4
  from {
3
5
  transform: translateY(0) scale(0.5);
@@ -8,8 +10,8 @@
8
10
  }
9
11
  }
10
12
 
11
- .animation {
12
- &-like_floating {
13
+ @include b(animation) {
14
+ &.#{join-class("like", "floating")} {
13
15
  animation-name: like-floating;
14
16
  animation-duration: 1s;
15
17
  animation-timing-function: ease-out;
@@ -0,0 +1,32 @@
1
+ @use "../mixin" as *;
2
+
3
+ @include b(popup) {
4
+ &.#{bem(dialog)} {
5
+ --popup-padding: 0;
6
+ --popup-width: var(--dialog-width, 50%);
7
+ }
8
+ }
9
+
10
+ @include b(dialog) {
11
+ --dialog-width: 30%;
12
+ --dialog-padding-header: #{u(10)};
13
+ --dialog-padding-body: #{u(15)};
14
+ --dialog-padding-footer: #{u(10)};
15
+
16
+ @include e(header) {
17
+ padding: var(--dialog-padding-header);
18
+
19
+ @include m(title) {
20
+ font-size: var(--text-lg);
21
+ }
22
+ }
23
+
24
+ @include e(body) {
25
+ padding: var(--dialog-padding-body);
26
+ overflow: hidden;
27
+ }
28
+
29
+ @include e(footer) {
30
+ padding: var(--dialog-padding-footer);
31
+ }
32
+ }
@@ -0,0 +1,59 @@
1
+ @use "../mixin" as *;
2
+
3
+ /*!
4
+ Example HTML:
5
+
6
+ <div class="frame-box">
7
+ <div class="frame-box__bg"></div>
8
+ <div class="frame-box__wrapper">
9
+ <div class="frame-box__body">
10
+ Content
11
+ </div>
12
+ </div>
13
+ <div class="frame-box__frame"></div>
14
+ <div class="frame-box__header">
15
+ <span class="frame-box__header--title">Title</span>
16
+ </div>
17
+ </div>
18
+ */
19
+
20
+ @include b(join-class("frame", "box")) {
21
+ position: relative;
22
+ box-sizing: border-box;
23
+ font-size: 0;
24
+
25
+ @include e(bg) {
26
+ width: 100%;
27
+ height: 100%;
28
+ @include absolute-center(true, true);
29
+ z-index: 0;
30
+ pointer-events: none;
31
+ }
32
+
33
+ @include e(wrapper) {
34
+ position: relative;
35
+ z-index: 1;
36
+ margin: 0 auto;
37
+ }
38
+
39
+ @include e(frame) {
40
+ width: 100%;
41
+ height: 100%;
42
+ @include absolute-center(true, true);
43
+ z-index: 2;
44
+ pointer-events: none;
45
+ }
46
+
47
+ @include e(header) {
48
+ @include absolute-center(true, false);
49
+ top: 0;
50
+ z-index: 3;
51
+ display: flex;
52
+ justify-content: center;
53
+ align-items: center;
54
+
55
+ @include m(title) {
56
+ white-space: nowrap;
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,64 @@
1
+ // 布局网格
2
+ @use "../mixin" as *;
3
+
4
+ @include b("grid") {
5
+ --col: 4;
6
+ --gap: #{u(0)};
7
+ --display: grid;
8
+ display: var(--display);
9
+
10
+ /* ========= grid 布局 ========= */
11
+ @include when("grid") {
12
+ --display: grid;
13
+ gap: var(--gap);
14
+
15
+ // 换行
16
+ @include when("wrap") {
17
+ grid-template-columns: repeat(var(--col), minmax(0, 1fr));
18
+ }
19
+
20
+ &:not(#{when("wrap")}) {
21
+ grid-auto-flow: column;
22
+ grid-auto-columns: calc((100% - (var(--col) - 1) * var(--gap)) / var(--col));
23
+ overflow-x: scroll;
24
+ }
25
+ }
26
+
27
+ /* ========= flex布局 ========= */
28
+ @include when("flex") {
29
+ --display: flex;
30
+ gap: var(--gap);
31
+
32
+ // 自动宽度
33
+ &:not(#{when("auto")}) {
34
+ > {
35
+ @include b("cell") {
36
+ flex-shrink: 0;
37
+ width: calc((100% - (var(--col) - 1) * var(--gap)) / var(--col));
38
+ }
39
+ }
40
+ }
41
+
42
+ // 换行
43
+ @include when("wrap") {
44
+ flex-wrap: wrap;
45
+ }
46
+
47
+ &:not(#{when("wrap")}) {
48
+ overflow-x: scroll;
49
+ }
50
+ }
51
+
52
+ /* ========= 单个 cell 居中 ========= */
53
+ @include when(join-class("only", "center")) {
54
+ > {
55
+ @include b("cell") {
56
+ &:only-child {
57
+ grid-column: 1 / calc(var(--col) + 1);
58
+ width: calc(100% / var(--col));
59
+ margin: 0 auto;
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
@@ -1,9 +1,7 @@
1
- // 图标
2
- .icon {
3
- display: inline-block;
4
- vertical-align: middle;
1
+ @use "../mixin" as *;
5
2
 
6
- &.picture {
7
- font-size: 0;
8
- }
9
- }
3
+ @include b("icon") {
4
+ display: inline-block;
5
+ vertical-align: middle;
6
+ color: inherit;
7
+ }
@@ -0,0 +1,49 @@
1
+ @use "../mixin" as *;
2
+
3
+ @include b("image") {
4
+ --aspect-ratio: 1;
5
+ position: relative;
6
+
7
+ // 背景
8
+ @include e("bg") {
9
+ @include absolute-center(true, true);
10
+ z-index: 0;
11
+ width: 100%;
12
+ height: 100%;
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ }
17
+
18
+ // 图片内容
19
+ @include e("content") {
20
+ position: relative;
21
+ z-index: 1;
22
+ width: 100%;
23
+ height: 100%;
24
+ object-fit: contain;
25
+ }
26
+
27
+ // 遮罩
28
+ @include e("overlay") {
29
+ @include absolute-center(true, true);
30
+ z-index: 3;
31
+ width: 100%;
32
+ height: 100%;
33
+ }
34
+
35
+ // 装饰
36
+ @include e("decoration") {
37
+ position: absolute;
38
+ z-index: 2;
39
+ top: 0;
40
+ right: 0;
41
+ }
42
+
43
+ @include when("ratio") {
44
+ @include e("content") {
45
+ aspect-ratio: var(--aspect-ratio);
46
+ object-fit: cover;
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,11 @@
1
+ @use "./animation.scss";
2
+ @use "./dialog.scss";
3
+ @use "./frame-box.scss";
4
+ @use "./grid.scss";
5
+ @use "./icon.scss";
6
+ @use "./image.scss";
7
+ @use "./popup.scss";
8
+ @use "./progress.scss";
9
+ @use "./scroll-bar.scss";
10
+ @use "./table.scss";
11
+ @use "./text.scss";
@@ -1,48 +1,63 @@
1
- .popup {
2
- overflow: hidden;
3
-
4
- &.no-scroll {
5
- .popup-wrapper {
6
- display: flex;
7
- flex-direction: column;
8
- }
1
+ @use "../mixin" as *;
2
+
3
+ @include b(popup) {
4
+ --popup-width: 30%;
5
+ --popup-height: auto;
6
+ --popup-padding: calc(20 * var(--size-unit));
7
+ --popup-bg: linear-gradient(0deg, var(--color-base-50), var(--color-base-50));
8
+ --popup-z-index: 1;
9
+ --popup-close-inset: #{u(4)} #{u(4)} auto auto;
10
+
11
+ position: fixed;
12
+ top: 0;
13
+ left: 0;
14
+ width: 100%;
15
+ height: 100%;
16
+ pointer-events: none;
17
+ @include set-z-index(var(--popup-z-index));
18
+
19
+ @include e(wrapper) {
20
+ @include bg(var(--popup-width), var(--popup-height), var(--popup-bg));
21
+ position: relative;
22
+ padding: var(--popup-padding);
23
+ pointer-events: auto;
24
+ }
9
25
 
10
- .popup-body {
11
- flex: 1;
12
- }
26
+ @include e(close) {
27
+ position: absolute;
28
+ inset: var(--popup-close-inset);
29
+ z-index: 1;
13
30
  }
14
- }
15
31
 
16
- .popup-wrapper {
17
- height: 100%;
18
- }
32
+ // 默认居中
33
+ &:not(#{when(ttb)}, #{when(rtl)}, #{when(btt)}, #{when(ltr)}) {
34
+ display: flex;
35
+ align-items: center;
36
+ justify-content: center;
37
+ }
19
38
 
20
- .popup-header--title {
21
- width: 100%;
22
- display: flex;
23
- align-items: center;
24
- justify-content: center;
25
- }
39
+ @include when(ttb) {
40
+ --popup-width: 100%;
41
+ }
26
42
 
27
- .popup-body {
28
- position: relative;
29
- overflow-y: scroll;
30
- }
43
+ @include when(rtl) {
44
+ display: flex;
45
+ justify-content: flex-end;
31
46
 
32
- .popup-footer {
33
- text-align: center;
34
- }
47
+ @include e(wrapper) {
48
+ height: 100%;
49
+ }
50
+ }
35
51
 
36
- .popup-footer--button_list {
37
- display: flex;
38
- justify-content: space-around;
39
- margin: 0 auto;
40
- }
52
+ @include when(btt) {
53
+ --popup-width: 100%;
54
+ display: flex;
55
+ align-items: flex-end;
56
+ }
41
57
 
42
- // 自定义
43
- .footer-custom {
44
- position: sticky;
45
- left: 0;
46
- bottom: 0;
47
- width: 100%;
58
+ @include when(ltr) {
59
+ @include e(wrapper) {
60
+ height: 100%;
61
+ }
62
+ }
48
63
  }
@@ -0,0 +1,115 @@
1
+ @use "../mixin" as *;
2
+
3
+ /*!
4
+ Example HTML:
5
+
6
+ <div class="s-progress">
7
+ <div class="s-progress__wrapper">
8
+ <div class="s-progress__segments">
9
+ <div class="s-progress__segment is-active" style="--progress-segment-width: calc(100% - 0%)">
10
+ <div class="s-progress__segment--wrapper">
11
+ <div class="s-progress__segment--point"></div>
12
+ <div class="s-progress__segment--content"><span class="s-text">100%</span></div>
13
+ </div>
14
+ </div>
15
+ </div>
16
+ <div class="s-progress__bar">
17
+ <div class="s-progress__bar--outer"><div class="s-progress__bar--inner"></div></div>
18
+ </div>
19
+ </div>
20
+ </div>
21
+
22
+ */
23
+
24
+ @include b(progress) {
25
+ --progress-width: 100%;
26
+ --progress-value: 0%; // 进度值
27
+ --progress-segment-point-width: #{u(30)}; // 节点大小
28
+ --progress-segment-point-transform: translateX(50%); // 节点中心偏移
29
+ --progress-segment-point-bg: linear-gradient(0deg, var(--color-base-500), var(--color-base-500)); // 节点背景
30
+ --progress-segment-point-bg-active: linear-gradient(0deg, var(--theme-color-500), var(--theme-color-500)); // 节点背景
31
+ --progress-segment-content-transform: translateX(50%); // 内容中心偏移
32
+
33
+ --progress-bar-height: #{u(20)}; // 进度条高度
34
+ --progress-bar-radius: #{u(10)}; // 进度条(内外)圆角
35
+ --progress-bar-outer-bg: linear-gradient(0deg, var(--color-base-250), var(--color-base-250)); // 外背景
36
+ --progress-bar-outer-padding: 0; // 外边距
37
+ --progress-bar-inner-bg: linear-gradient(0deg, var(--theme-color-500), var(--theme-color-500)); // 内背景
38
+ overflow-x: scroll;
39
+
40
+ @include e(wrapper) {
41
+ width: var(--progress-width);
42
+ position: relative;
43
+ min-height: var(--progress-segment-point-width);
44
+ }
45
+
46
+ // 片段
47
+ @include e(segments) {
48
+ display: flex;
49
+ justify-content: flex-start;
50
+ }
51
+
52
+ @include e(segment) {
53
+ position: relative;
54
+ z-index: 1;
55
+ width: var(--progress-segment-width, 0%);
56
+
57
+ @include m(wrapper) {
58
+ display: flex;
59
+ flex-direction: column;
60
+ align-items: flex-end;
61
+ }
62
+
63
+ @include m(point) {
64
+ border-radius: 100%;
65
+ @include bg(
66
+ var(--progress-segment-point-width),
67
+ var(--progress-segment-point-width),
68
+ var(--progress-segment-point-bg)
69
+ );
70
+ transform: var(--progress-segment-point-transform);
71
+ }
72
+
73
+ @include m(content) {
74
+ transform: var(--progress-segment-content-transform);
75
+ }
76
+
77
+ @include when("active") {
78
+ .#{bem("progress", "segment", "point")} {
79
+ @include bg(
80
+ var(--progress-segment-point-width),
81
+ var(--progress-segment-point-width),
82
+ var(--progress-segment-point-bg-active)
83
+ );
84
+ }
85
+ }
86
+ }
87
+
88
+ // 进度条
89
+ @include e(bar) {
90
+ width: 100%;
91
+ position: absolute;
92
+ top: calc(var(--progress-segment-point-width) / 2);
93
+ left: 0;
94
+ z-index: 0;
95
+ transform: translateY(-50%);
96
+
97
+ @include m(outer) {
98
+ width: 100%;
99
+ padding: var(--progress-bar-outer-padding);
100
+ border-radius: var(--progress-bar-radius);
101
+ @include bg(100%, var(--progress-bar-height), var(--progress-bar-outer-bg));
102
+ }
103
+
104
+ @include m(inner) {
105
+ height: 100%;
106
+ border-radius: var(--progress-bar-radius);
107
+ @include bg(var(--progress-value, 0%), 100%, var(--progress-bar-inner-bg));
108
+ }
109
+ }
110
+
111
+ @include when(rtl) {
112
+ --progress-segment-point-transform: translateX(-50%);
113
+ --progress-segment-content-transform: translateX(-50%);
114
+ }
115
+ }
@@ -1,30 +1,23 @@
1
1
  .table {
2
- --grid-padding: 0.2rem 0;
2
+ --grid-padding: #{u(2)} 0;
3
3
  --grid-width: auto;
4
4
  --bg-thead: rgba(0, 0, 0, 0.2);
5
- --color-border: rgba(255, 255, 255, 0.2);
5
+ --color-border: #ffffff33;
6
6
  width: 100%;
7
7
  font-size: 0;
8
8
  border-spacing: 0;
9
9
  border-collapse: separate;
10
- border: 0.02rem solid var(--color-border);
10
+ border: #{u(2)} solid var(--color-border);
11
11
  overflow: hidden;
12
12
 
13
13
  thead {
14
14
  background-color: var(--bg-thead);
15
15
 
16
16
  .text {
17
- font-size: 0.3rem;
18
17
  font-weight: bold;
19
18
  }
20
19
  }
21
20
 
22
- tbody {
23
- .text {
24
- font-size: 0.28rem;
25
- }
26
- }
27
-
28
21
  tr {
29
22
  width: 100%;
30
23
  display: flex;
@@ -38,10 +31,11 @@
38
31
  flex: 1 0 var(--grid-width);
39
32
  padding: var(--grid-padding);
40
33
  border: solid var(--color-border);
41
- border-width: 0 0.02rem 0.02rem 0;
34
+ border-width: 0 #{u(2)} #{u(2)} 0;
42
35
  }
43
36
 
44
37
  .text {
38
+ text-align: center;
45
39
  vertical-align: middle;
46
40
  }
47
41
  }
@@ -1,15 +1,43 @@
1
- .text {
1
+ @use "../mixin" as *;
2
+
3
+ @include b("text") {
2
4
  display: inline-block;
3
5
  line-height: 1;
4
6
  vertical-align: middle;
5
7
 
6
- &.paragraph {
7
- line-height: 1.5;
8
- }
9
-
10
- &.ellipsis {
8
+ @include when("ellipsis") {
9
+ width: 100%;
11
10
  white-space: nowrap;
12
11
  text-overflow: ellipsis;
13
12
  overflow: hidden;
14
13
  }
14
+
15
+ @include when("h1") {
16
+ font-size: var(--text-3xl);
17
+ }
18
+
19
+ @include when("h2") {
20
+ font-size: var(--text-2xl);
21
+ }
22
+
23
+ @include when("h3") {
24
+ font-size: var(--text-xl);
25
+ }
26
+
27
+ @include when("h4") {
28
+ font-size: var(--text-lg);
29
+ }
30
+
31
+ @include when("h5") {
32
+ font-size: var(--text-base);
33
+ }
34
+
35
+ @include when("h6") {
36
+ font-size: var(--text-sm);
37
+ }
38
+
39
+ @include when("p") {
40
+ display: block;
41
+ line-height: 1.5;
42
+ }
15
43
  }
package/index.scss CHANGED
@@ -1,2 +1,2 @@
1
- @use './normalize.css';
2
- @use './base.scss';
1
+ @use "./normalize.css";
2
+ @use "./base.scss";
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
- {
2
- "name": "@nopon-web/styles",
3
- "version": "0.0.2",
4
- "main": "index.js",
5
- "scripts": {
6
- "test": "echo \"Error: no test specified\" && exit 1"
7
- },
8
- "keywords": [],
9
- "author": "",
10
- "license": "ISC",
11
- "description": "",
12
- "publishConfig": {
13
- "access": "public"
14
- }
15
- }
1
+ {
2
+ "name": "@nopon-web/styles",
3
+ "version": "0.0.5",
4
+ "main": "index.js",
5
+ "scripts": {
6
+ "test": "echo \"Error: no test specified\" && exit 1"
7
+ },
8
+ "keywords": [],
9
+ "author": "",
10
+ "license": "ISC",
11
+ "description": "",
12
+ "publishConfig": {
13
+ "access": "public"
14
+ }
15
+ }
package/theme.scss CHANGED
@@ -1,5 +1,5 @@
1
- @use 'sass:map';
2
- @use './_variables' as var;
1
+ @use "sass:map";
2
+ @use "./_variables" as var;
3
3
 
4
4
  // -----------------------------
5
5
  // 🎨 颜色设计变量命名规范
@@ -40,8 +40,6 @@ $color-danger-500: #ff7b7b;
40
40
  // 参考标准: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size#values
41
41
  // xx-small、x-small、small、medium、large、x-large、xx-large、xxx-large(基于用户默认字体大小(medium)的绝对大小关键字)
42
42
 
43
- $size-root: 16; // 🔤 尺寸基准值,控制设计稿与真实页面的缩放比例
44
-
45
43
  $text-small-map: (
46
44
  // 14px
47
45
  0: 0.875,
@@ -107,7 +105,7 @@ $text-large-map: (
107
105
  --color-danger-500: #{$color-danger-500};
108
106
 
109
107
  // 🔤 尺寸基准值,控制设计稿与真实页面的缩放比例
110
- --size-root: #{$size-root};
108
+ --size-root: #{var.$size-root};
111
109
 
112
110
  // 🔤 最小单位:等效于 1px:
113
111
  // - 当使用 rem 方案:1px = calc(1 / var(--size-root) * 1rem)
@@ -1,41 +0,0 @@
1
- /*!
2
- Example HTML:
3
-
4
- <div class="box-card">
5
- <div class="box-wrapper">
6
- <div class="box-header">
7
- <span class="box-title">Title</span>
8
- </div>
9
- <div class="box-body">Content</div>
10
- </div>
11
- </div>
12
- */
13
-
14
- @use '../mixin' as mixin;
15
-
16
- .box-card {
17
- position: relative;
18
- font-size: 0;
19
- }
20
-
21
- .box-wrapper {
22
- margin: 0 auto;
23
- }
24
-
25
- .box-header {
26
- @include mixin.absolute-center(true, false);
27
- top: 0;
28
- display: flex;
29
- align-items: center;
30
- }
31
-
32
- .box-title {
33
- white-space: nowrap;
34
- }
35
-
36
- .box-body--bg {
37
- width: 100%;
38
- @include mixin.absolute-center(true, false);
39
- top: 0;
40
- z-index: -1;
41
- }
@@ -1,45 +0,0 @@
1
- @use '../mixin' as mixin;
2
-
3
- .picture {
4
- > img {
5
- width: 100%;
6
- height: 100%;
7
- object-fit: contain;
8
- }
9
-
10
- &:has(.picture-content, .picture-frame) {
11
- position: relative;
12
- }
13
-
14
- // 图片内容
15
- .picture-content {
16
- &--center {
17
- @include mixin.absolute-center(true, true);
18
- }
19
-
20
- &--bottom {
21
- @include mixin.absolute-center(true, false);
22
- bottom: 0;
23
- }
24
- }
25
-
26
- // 图片边框
27
- .picture-frame {
28
- width: 100%;
29
- height: 100%;
30
- @include mixin.absolute-center(true, true);
31
- z-index: 0;
32
- }
33
-
34
- &:has(.picture-frame) {
35
- --frame-width: 0.02rem;
36
-
37
- > img {
38
- position: relative;
39
- width: calc(100% - var(--frame-width) * 2);
40
- height: calc(100% - var(--frame-width) * 2);
41
- margin: var(--frame-width);
42
- z-index: 0;
43
- }
44
- }
45
- }
package/components.scss DELETED
@@ -1,3 +0,0 @@
1
- @use './components/icon.scss';
2
- @use './components/picture.scss';
3
- @use './components/text.scss';