@nopon-web/styles 0.0.1 → 0.0.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/_config.scss ADDED
@@ -0,0 +1,5 @@
1
+ $namespace: 's' !default;
2
+ $state-prefix: 'is' !default;
3
+ $common-separator: '-' !default;
4
+ $element-separator: '__' !default;
5
+ $modifier-separator: '--' !default;
package/_function.scss CHANGED
@@ -1,5 +1,21 @@
1
1
  @use 'sass:string';
2
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
+ }
3
19
 
4
20
  @function get-image($image) {
5
21
  // 已经是合法CSS值的情况
@@ -12,7 +28,7 @@
12
28
  }
13
29
 
14
30
  // 空值或none
15
- @if $image == none or $image == null {
31
+ @if $image ==none or $image ==null {
16
32
  @return none;
17
33
  }
18
34
 
package/_mixin.scss CHANGED
@@ -1,5 +1,61 @@
1
- @use './_variables' as var;
2
- @use './_function' as func;
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
+ $__bem-context: null;
13
+
14
+ @mixin b($block) {
15
+ $B: $namespace + $common-separator + $block;
16
+
17
+ .#{$B} {
18
+ $__bem-context: 'block' !global;
19
+ @content;
20
+ $__bem-context: null !global;
21
+ }
22
+ }
23
+
24
+ @mixin e($element) {
25
+ @if $__bem-context != 'block' {
26
+ @error 'e() can only be used inside b()';
27
+ }
28
+
29
+ @each $E in $element {
30
+ &#{$element-separator + $E} {
31
+ $__bem-context: 'element' !global;
32
+ @content;
33
+ $__bem-context: 'block' !global;
34
+ }
35
+ }
36
+ }
37
+
38
+ @mixin m($modifier) {
39
+ @if $__bem-context != 'block' and $__bem-context != 'element' {
40
+ @error 'm() can only be used inside b() or e()';
41
+ }
42
+
43
+ @each $M in $modifier {
44
+ &#{$modifier-separator + $M} {
45
+ @content;
46
+ }
47
+ }
48
+ }
49
+
50
+ @mixin when($state) {
51
+ $state-selector: $state-prefix + $common-separator + $state;
52
+
53
+ @at-root {
54
+ #{if(&, '&.#{$state-selector}', '.#{$state-selector}')} {
55
+ @content;
56
+ }
57
+ }
58
+ }
3
59
 
4
60
  @mixin absolute-center($x: true, $y: true) {
5
61
  position: absolute;
@@ -29,10 +85,17 @@
29
85
  background-image: func.get-image($image);
30
86
  }
31
87
 
32
- @mixin bg-border($width, $height, $image) {
33
- min-width: $width;
88
+ @mixin bg-border($width, $height, $image, $border: ('width': 0, 'image-slice': 0), $fill: true) {
89
+ $border-width: map.get($border, 'width');
90
+ $border-image-slice: map.get($border, 'image-slice');
91
+
92
+ width: $width;
34
93
  height: $height;
35
94
  border-image-source: func.get-image($image);
95
+ border-style: solid;
96
+ box-sizing: border-box;
97
+ border-width: $border-width;
98
+ border-image-slice: #{$border-image-slice}#{if($fill, ' fill', '')};
36
99
  }
37
100
 
38
101
  @mixin bg-text($image) {
@@ -42,3 +105,198 @@
42
105
  -webkit-text-fill-color: transparent;
43
106
  background-image: func.get-image($image);
44
107
  }
108
+
109
+ @mixin text-stroke($size: 1px, $color: #000, $blur: 0) {
110
+ text-shadow: #{$size} #{$size} #{$blur} #{$color}, -#{$size} #{$size} #{$blur} #{$color},
111
+ #{$size} -#{$size} #{$blur} #{$color}, -#{$size} -#{$size} #{$blur} #{$color};
112
+ }
113
+
114
+ @mixin text-shadow($size: 14px, $color: #000, $offset-x: 2px, $offset-y: 2px) {
115
+ position: relative;
116
+ z-index: 0;
117
+ font-size: 0;
118
+ line-height: 1;
119
+
120
+ > * {
121
+ font-size: $size;
122
+ }
123
+
124
+ &::before {
125
+ content: attr(data-text);
126
+ position: absolute;
127
+ top: 50%;
128
+ left: 50%;
129
+ z-index: -1;
130
+ color: $color;
131
+ font-size: $size;
132
+ white-space: nowrap;
133
+ // 偏移量
134
+ transform: translate(calc(-50% + #{$offset-x}), calc(-50% + #{$offset-y}));
135
+ }
136
+ }
137
+
138
+ /// 通用列表布局封装
139
+ /// 支持 grid / flex 两种布局
140
+ /// @param $options - 可选配置
141
+ /// ------------------------------------------------------------------------
142
+ /// HTML 模板示例:
143
+ // <ul class="b-e--list">
144
+ // <li class="b-e--item">
145
+ // <div class="b-e--media">
146
+ // <div class="b-e--picture">
147
+ // <div class="b-e--picture_bg picture">
148
+ // <img src="">
149
+ // </div>
150
+ // <div class="b-e--picture_wrapper picture">
151
+ // <img class="b-e--picture_content"
152
+ // src="">
153
+ // </div>
154
+ // <div class="b-e--picture_decoration picture">
155
+ // <img src="">
156
+ // </div>
157
+ // <div class="b-e--picture_cover picture">
158
+ // <img src="">
159
+ // </div>
160
+ // </div>
161
+ // </div>
162
+ // <div class="b-e--content">
163
+ // <div class="b-e--content_text">
164
+ // <span class="text"></span>
165
+ // </div>
166
+ // </div>
167
+ // </li>
168
+ // </ul>
169
+ /// ------------------------------------------------------------------------
170
+ @mixin extend-list($options: ()) {
171
+ // --- 默认参数 ---
172
+ $defaults: (
173
+ 'namespace-block': 'b',
174
+ 'namespace-element': 'e',
175
+ // 布局模式
176
+ 'display': grid,
177
+ // 是否换行
178
+ 'wrap': false,
179
+ // 列数
180
+ 'col': 4,
181
+ // 间距
182
+ 'gap': 10px,
183
+ // 图片宽高比
184
+ 'picture-ratio': 100%,
185
+ // 图片宽度
186
+ 'picture-width': 100%,
187
+ // 图片高度
188
+ 'picture-height': 100%,
189
+ );
190
+
191
+ // 合并配置
192
+ $config: map.merge($defaults, $options);
193
+
194
+ // 变量定义
195
+ $block: map.get($config, 'namespace-block');
196
+ $element: map.get($config, 'namespace-element');
197
+ $display: map.get($config, 'display');
198
+ $wrap: map.get($config, 'wrap');
199
+ $col: map.get($config, 'col');
200
+ $gap: map.get($config, 'gap');
201
+ $picture-ratio: map.get($config, 'picture-ratio');
202
+ $picture-width: map.get($config, 'picture-width');
203
+ $picture-height: map.get($config, 'picture-height');
204
+
205
+ // --- 列表容器 ---
206
+ .#{$block}-#{$element}--list {
207
+ --col: #{$col};
208
+ --gap: #{$gap};
209
+ --picture-ratio: #{$picture-ratio};
210
+ --picture-width: #{$picture-width};
211
+ --picture-height: #{$picture-height};
212
+ display: $display;
213
+
214
+ // flex 布局
215
+ @if $display ==flex {
216
+ margin: 0 calc(var(--gap) / -2);
217
+
218
+ // 换行
219
+ @if $wrap {
220
+ flex-wrap: wrap;
221
+ }
222
+ }
223
+
224
+ // grid 布局(默认)
225
+ @if $display ==grid {
226
+ gap: var(--gap);
227
+
228
+ // 换行
229
+ @if $wrap {
230
+ grid-template-columns: repeat(var(--col), minmax(0, 1fr));
231
+ } @else {
232
+ grid-auto-flow: column;
233
+ grid-auto-columns: calc((100% - (var(--col) - 1) * var(--gap)) / var(--col));
234
+ }
235
+ }
236
+
237
+ @if $wrap ==false {
238
+ overflow-x: scroll;
239
+ }
240
+
241
+ .#{$block}-#{$element}--item:only-child {
242
+ grid-column: 1 / calc(var(--col) + 1);
243
+ width: calc(100% / var(--col));
244
+ margin: 0 auto;
245
+ }
246
+ }
247
+
248
+ // --- 列表项 ---
249
+ .#{$block}-#{$element}--item {
250
+ position: relative;
251
+ font-size: 0;
252
+
253
+ @if $display ==flex {
254
+ flex-shrink: 0;
255
+ width: calc(100% / var(--col));
256
+ padding: calc(var(--gap) / 2);
257
+ }
258
+ }
259
+
260
+ // --- 图片 ---
261
+ .#{$block}-#{$element}--picture {
262
+ position: relative;
263
+
264
+ &_bg {
265
+ width: 100%;
266
+ height: 100%;
267
+ @include absolute-center(true, true);
268
+ z-index: 0;
269
+ }
270
+
271
+ &_wrapper {
272
+ position: relative;
273
+ height: 0;
274
+ padding-bottom: var(--picture-ratio);
275
+ }
276
+
277
+ &_content {
278
+ max-width: var(--picture-width);
279
+ max-height: var(--picture-height);
280
+ @include absolute-center(true, true);
281
+ }
282
+
283
+ &_decoration {
284
+ position: absolute;
285
+ top: 0;
286
+ right: 0;
287
+ z-index: 1;
288
+ }
289
+
290
+ &_cover {
291
+ @include absolute-center(true, true);
292
+ z-index: 2;
293
+ width: 100%;
294
+ height: 100%;
295
+ }
296
+ }
297
+
298
+ // --- 内容区 ---
299
+ .#{$block}-#{$element}--content {
300
+ text-align: center;
301
+ }
302
+ }
@@ -0,0 +1,41 @@
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,8 +1,9 @@
1
- @use '../_variables' as var;
2
-
3
1
  // 图标
4
2
  .icon {
5
- display: inline-block;
6
- vertical-align: middle;
7
- font-size: var(--text-xs);
8
- }
3
+ display: inline-block;
4
+ vertical-align: middle;
5
+
6
+ &.picture {
7
+ font-size: 0;
8
+ }
9
+ }
@@ -0,0 +1,19 @@
1
+ @use '../mixin' as *;
2
+
3
+ @include b('image') {
4
+ --aspect-ratio: 1;
5
+
6
+ > img {
7
+ width: 100%;
8
+ height: 100%;
9
+ }
10
+
11
+ @include when('ratio') {
12
+ position: relative;
13
+ aspect-ratio: var(--aspect-ratio);
14
+
15
+ > img {
16
+ object-fit: cover;
17
+ }
18
+ }
19
+ }
@@ -1,26 +1,40 @@
1
1
  @use '../mixin' as mixin;
2
2
 
3
- // 图片
4
3
  .picture {
5
4
  position: relative;
5
+ --frame-width: 0.02rem;
6
6
 
7
- img {
7
+ > img {
8
8
  width: 100%;
9
9
  height: 100%;
10
10
  object-fit: contain;
11
11
  }
12
12
 
13
+ // 图片内容
13
14
  .picture-content {
14
15
  &--center {
15
16
  @include mixin.absolute-center(true, true);
16
17
  }
18
+
17
19
  &--bottom {
18
20
  @include mixin.absolute-center(true, false);
19
21
  bottom: 0;
20
22
  }
21
23
  }
22
24
 
23
- &:has(.picture-content) {
24
- position: relative;
25
+ // 图片边框
26
+ .picture-frame {
27
+ width: 100%;
28
+ height: 100%;
29
+ @include mixin.absolute-center(true, true);
30
+ z-index: 1;
31
+
32
+ + img {
33
+ position: relative;
34
+ width: calc(100% - var(--frame-width) * 2);
35
+ height: calc(100% - var(--frame-width) * 2);
36
+ margin: var(--frame-width);
37
+ z-index: 0;
38
+ }
25
39
  }
26
40
  }
@@ -1,5 +1,3 @@
1
- @use '../_variables' as var;
2
-
3
1
  .popup {
4
2
  overflow: hidden;
5
3
 
@@ -8,6 +6,7 @@
8
6
  display: flex;
9
7
  flex-direction: column;
10
8
  }
9
+
11
10
  .popup-body {
12
11
  flex: 1;
13
12
  }
@@ -36,7 +35,8 @@
36
35
 
37
36
  .popup-footer--button_list {
38
37
  display: flex;
39
- align-items: flex-end;
38
+ justify-content: space-around;
39
+ margin: 0 auto;
40
40
  }
41
41
 
42
42
  // 自定义
@@ -1,31 +1,33 @@
1
1
  .s-scroll {
2
- &::-webkit-scrollbar {
3
- display: none;
4
- }
2
+ &::-webkit-scrollbar {
3
+ display: none;
4
+ }
5
5
 
6
- &-bar {
7
- &_x {
8
- position: relative;
9
- .s-scroll-bar_thumb {
10
- position: absolute;
11
- bottom: 0;
12
- left: 0;
13
- height: 6px;
14
- }
15
- }
6
+ &-bar {
7
+ &_x {
8
+ position: relative;
16
9
 
17
- &_y {
18
- position: relative;
19
- .s-scroll-bar_thumb {
20
- position: absolute;
21
- top: 0;
22
- left: 0;
23
- width: 100%;
24
- }
25
- }
10
+ .s-scroll-bar_thumb {
11
+ position: absolute;
12
+ bottom: 0;
13
+ left: 0;
14
+ height: 6px;
15
+ }
16
+ }
26
17
 
27
- &_thumb {
28
- background-color: var(--theme-color);
29
- }
30
- }
31
- }
18
+ &_y {
19
+ position: relative;
20
+
21
+ .s-scroll-bar_thumb {
22
+ position: absolute;
23
+ top: 0;
24
+ left: 0;
25
+ width: 100%;
26
+ }
27
+ }
28
+
29
+ &_thumb {
30
+ background-color: var(--theme-color);
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,48 @@
1
+ .table {
2
+ --grid-padding: 0.2rem 0;
3
+ --grid-width: auto;
4
+ --bg-thead: rgba(0, 0, 0, 0.2);
5
+ --color-border: rgba(255, 255, 255, 0.2);
6
+ width: 100%;
7
+ font-size: 0;
8
+ border-spacing: 0;
9
+ border-collapse: separate;
10
+ border: 0.02rem solid var(--color-border);
11
+ overflow: hidden;
12
+
13
+ thead {
14
+ background-color: var(--bg-thead);
15
+
16
+ .text {
17
+ font-size: 0.3rem;
18
+ font-weight: bold;
19
+ }
20
+ }
21
+
22
+ tbody {
23
+ .text {
24
+ font-size: 0.28rem;
25
+ }
26
+ }
27
+
28
+ tr {
29
+ width: 100%;
30
+ display: flex;
31
+ }
32
+
33
+ th,
34
+ td {
35
+ display: inline-flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ flex: 1 0 var(--grid-width);
39
+ padding: var(--grid-padding);
40
+ border: solid var(--color-border);
41
+ border-width: 0 0.02rem 0.02rem 0;
42
+ }
43
+
44
+ .text {
45
+ text-align: center;
46
+ vertical-align: middle;
47
+ }
48
+ }
@@ -1,8 +1,15 @@
1
- @use '../_variables' as var;
2
-
3
- // 文本
4
1
  .text {
5
2
  display: inline-block;
6
- font-size: var(--text-sm);
7
3
  line-height: 1;
4
+ vertical-align: middle;
5
+
6
+ &.paragraph {
7
+ line-height: 1.5;
8
+ }
9
+
10
+ &.ellipsis {
11
+ white-space: nowrap;
12
+ text-overflow: ellipsis;
13
+ overflow: hidden;
14
+ }
8
15
  }
package/components.scss CHANGED
@@ -1,4 +1,3 @@
1
1
  @use './components/icon.scss';
2
2
  @use './components/picture.scss';
3
- @use './components/popup.scss';
4
3
  @use './components/text.scss';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nopon-web/styles",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"