@nopon-web/styles 0.1.0 → 0.2.1

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 CHANGED
@@ -1,9 +1,12 @@
1
+ // bem
1
2
  $namespace: "s" !default;
2
3
  $common-separator: "-" !default;
3
4
  $element-separator: "__" !default;
4
5
  $modifier-separator: "--" !default;
5
6
  $state-prefix: "is" !default;
6
-
7
7
  $theme-prefix: "theme" !default;
8
8
  $theme-name: "" !default;
9
- $theme-font-prefix: "text" !default;
9
+
10
+ // vars
11
+ $var-css-registered: true !default; // 是否已经注册 CSS Variables
12
+ $var-runtime-mode: value !default; // var运行时模式, value = 编译期计算, css = 运行时 calc + var
package/atomic/_flex.scss CHANGED
@@ -1,35 +1,85 @@
1
1
  @use "../mixin/index" as mx;
2
2
 
3
3
  $flex: (
4
- 1: 1 1 0%,
5
- auto: 1 1 auto,
6
- initial: 0 1 auto,
7
- none: none,
4
+ 1: (
5
+ flex: 1 1 0%,
6
+ ),
7
+ auto: (
8
+ flex: 1 1 auto,
9
+ ),
10
+ initial: (
11
+ flex: 0 1 auto,
12
+ ),
13
+ none: (
14
+ flex: none,
15
+ ),
8
16
  );
9
17
 
10
18
  $flex-justify: (
11
- normal: normal,
12
- start: flex-start,
13
- end: flex-end,
14
- center: center,
15
- between: space-between,
16
- around: space-around,
17
- evenly: space-evenly,
18
- stretch: stretch,
19
+ normal: (
20
+ justify-content: normal,
21
+ ),
22
+ start: (
23
+ justify-content: flex-start,
24
+ ),
25
+ end: (
26
+ justify-content: flex-end,
27
+ ),
28
+ center: (
29
+ justify-content: center,
30
+ ),
31
+ between: (
32
+ justify-content: space-between,
33
+ ),
34
+ around: (
35
+ justify-content: space-around,
36
+ ),
37
+ evenly: (
38
+ justify-content: space-evenly,
39
+ ),
40
+ stretch: (
41
+ justify-content: stretch,
42
+ ),
19
43
  );
20
44
 
21
45
  $flex-align: (
22
- start: flex-start,
23
- end: flex-end,
24
- center: center,
25
- baseline: baseline,
26
- stretch: stretch,
46
+ start: (
47
+ align-items: flex-start,
48
+ ),
49
+ end: (
50
+ align-items: flex-end,
51
+ ),
52
+ center: (
53
+ align-items: center,
54
+ ),
55
+ baseline: (
56
+ align-items: baseline,
57
+ ),
58
+ stretch: (
59
+ align-items: stretch,
60
+ ),
61
+ );
62
+
63
+ $flex-direction: (
64
+ row: (
65
+ flex-direction: row,
66
+ ),
67
+ row-reverse: (
68
+ flex-direction: row-reverse,
69
+ ),
70
+ col: (
71
+ flex-direction: column,
72
+ ),
73
+ col-reverse: (
74
+ flex-direction: column-reverse,
75
+ ),
27
76
  );
28
77
 
29
78
  .flex {
30
- display: flex;
79
+ display: flex;
31
80
  }
32
81
 
33
- @include mx.generate-atomic("flex", flex, $flex);
34
- @include mx.generate-atomic("justify", justify-content, $flex-justify);
35
- @include mx.generate-atomic("items", align-items, $flex-align);
82
+ @include mx.generate-atomic("flex", $flex);
83
+ @include mx.generate-atomic("justify", $flex-justify);
84
+ @include mx.generate-atomic("items", $flex-align);
85
+ @include mx.generate-atomic("flex", $flex-direction);
@@ -0,0 +1,13 @@
1
+ @use "../mixin/index" as mx;
2
+
3
+ $font-weight: (
4
+ thin: (font-weight: 100),
5
+ extralight: (font-weight: 200),
6
+ light: (font-weight: 300),
7
+ normal: (font-weight: 400),
8
+ medium: (font-weight: 500),
9
+ semibold: (font-weight: 600),
10
+ bold: (font-weight: 700),
11
+ );
12
+
13
+ @include mx.generate-atomic("font", $font-weight);
@@ -0,0 +1,10 @@
1
+ @use "../mixin/index" as mx;
2
+
3
+ $text-decoration-line: (
4
+ underline: (text-decoration-line: underline),
5
+ overline: (text-decoration-line: overline),
6
+ line-through: (text-decoration-line: line-through),
7
+ no-underline: (text-decoration-line: none),
8
+ );
9
+
10
+ @include mx.generate-atomic(null, $text-decoration-line);
package/atomic/index.scss CHANGED
@@ -1 +1,3 @@
1
- @use "./flex";
1
+ @use "./flex";
2
+ @use "./font";
3
+ @use "./text";
@@ -0,0 +1,134 @@
1
+ @use '../function/index' as fn;
2
+ @use '../mixin/index' as mx;
3
+
4
+ @include mx.b(button) {
5
+ @include mx.var-register(button);
6
+ position: relative;
7
+ display: inline-block;
8
+ padding: fn.var-get(button, padding);
9
+ line-height: 1;
10
+ border: none;
11
+ border-radius: fn.var-get(button, radius, base);
12
+ font-size: fn.var-get(button, size, text);
13
+ color: fn.var-get(button, color, text, base);
14
+ background-color: transparent;
15
+ box-sizing: border-box;
16
+ overflow: hidden;
17
+ cursor: pointer;
18
+
19
+ + .#{fn.bem(button)} {
20
+ margin-left: fn.var-get(button, gap);
21
+ }
22
+
23
+ &::after {
24
+ content: '';
25
+ position: absolute;
26
+ top: 0;
27
+ left: 0;
28
+ z-index: 0;
29
+ display: block;
30
+ width: 100%;
31
+ height: 100%;
32
+ background-color: fn.var-get(button, color, bg, base);
33
+ }
34
+
35
+ // 内容
36
+ @include mx.e(content) {
37
+ position: relative;
38
+ z-index: 1;
39
+ }
40
+
41
+ &:hover,
42
+ &:active,
43
+ &:focus {
44
+ color: fn.var-get(button, color, text, hover);
45
+
46
+ &::after {
47
+ background-color: fn.var-get(button, color, bg, hover);
48
+ }
49
+ }
50
+
51
+ // 类型
52
+ @include mx.m(primary) {
53
+ --#{fn.var-get-name(button, color, text, base)}: #{fn.var-get(color, text, inverse, 500)};
54
+ --#{fn.var-get-name(button, color, bg, base)}: #{fn.var-get(button, color, theme, 500)};
55
+
56
+ &:active,
57
+ &:focus {
58
+ --#{fn.var-get-name(button, color, text,hover)}: #{fn.var-get(color, text, inverse, 500)};
59
+ --#{fn.var-get-name(button, color, bg, hover)}: #{fn.var-get(button, color, theme, 500)};
60
+ }
61
+ }
62
+
63
+ // 大小
64
+ @include mx.m(small) {
65
+ --#{fn.var-get-name(button, size, base)}: #{fn.var-get(text, 2xl)};
66
+ --#{fn.var-get-name(button, size, text)}: #{fn.var-get(text, xs)};
67
+ --#{fn.var-get-name(button, padding)}: #{fn.var-get(text, 4xs)} #{fn.var-get(text, xs)};
68
+ }
69
+
70
+ @include mx.m(large) {
71
+ --#{fn.var-get-name(button, size, base)}: #{fn.var-get(text, 4xl)};
72
+ --#{fn.var-get-name(button, padding)}: #{fn.var-get(text, sm)} #{fn.var-get(text, lg)};
73
+ }
74
+
75
+ // 朴素
76
+ @include mx.when(plain) {
77
+ --#{fn.var-get-name(button, color, bg, base)}: transparent;
78
+ --#{fn.var-get-name(button, color, bg, hover)}: transparent;
79
+ border-width: fn.var-get(button, border, width);
80
+ border-style: fn.var-get(button, border, style);
81
+ border-color: fn.var-get(button, border, color, base);
82
+
83
+ &:hover,
84
+ &:active,
85
+ &:focus {
86
+ border-color: fn.var-get(button, border, color, hover);
87
+ }
88
+
89
+ &.#{fn.bem(button, '', primary)} {
90
+ --#{fn.var-get-name(button, color, text, base)}: #{fn.var-get(button, color, theme, 500)};
91
+ --#{fn.var-get-name(button, border, color, base)}: #{fn.var-get(button, color, theme, 500)};
92
+
93
+ &:hover,
94
+ &:active,
95
+ &:focus {
96
+ --#{fn.var-get-name(button, color, text, hover)}: #{fn.var-get(button, color, theme, 500)};
97
+ --#{fn.var-get-name(button, color, bg, hover)}: #{fn.var-get(button, color, theme, 50)};
98
+ }
99
+ }
100
+ }
101
+
102
+ // 椭圆
103
+ @include mx.when(round) {
104
+ border-radius: fn.var-get(button, radius, round);
105
+ }
106
+
107
+ // 圆型
108
+ @include mx.when(circle) {
109
+ width: #{fn.var-get(button, size, base)};
110
+ height: #{fn.var-get(button, size, base)};
111
+ border-radius: fn.var-get(button, radius, circle);
112
+ padding: 0;
113
+ }
114
+
115
+ // 文本
116
+ @include mx.when(text) {
117
+ --#{fn.var-get-name(button, color, bg, base)}: transparent;
118
+
119
+ &.#{fn.bem(button, '', primary)} {
120
+ --#{fn.var-get-name(button, color, text, base)}: #{fn.var-get(button, color, theme, 500)};
121
+ }
122
+ }
123
+
124
+ // 背景
125
+ @include mx.when(no-bg) {
126
+ --#{fn.var-get-name(button, color, bg, base)}: transparent;
127
+ --#{fn.var-get-name(button, color, bg, hover)}: transparent;
128
+ --#{fn.var-get-name(button, color, text, hover)}: #{fn.var-get(button, color, theme, 500)};
129
+
130
+ &.#{fn.bem(button, '', primary)} {
131
+ --#{fn.var-get-name(button, color, text, base)}: #{fn.var-get(button, color, theme, 500)};
132
+ }
133
+ }
134
+ }
@@ -1,7 +1,14 @@
1
+ @use "../function/index" as fn;
1
2
  @use "../mixin/index" as mx;
2
3
 
3
4
  @include mx.b("icon") {
4
- display: inline-block;
5
- vertical-align: middle;
6
- color: inherit;
7
- }
5
+ display: inline-block;
6
+ vertical-align: middle;
7
+ color: inherit;
8
+
9
+ &.#{fn.bem(image)} {
10
+ .#{fn.bem(image, content)} {
11
+ display: block;
12
+ }
13
+ }
14
+ }
@@ -28,14 +28,14 @@ Example HTML:
28
28
  --progress-segment-point-width: #{fn.u(30)}; // 节点大小
29
29
  --progress-segment-point-transform: translateX(50%); // 节点中心偏移
30
30
  --progress-segment-point-bg: linear-gradient(0deg, var(--color-base-500), var(--color-base-500)); // 节点背景
31
- --progress-segment-point-bg-active: linear-gradient(0deg, var(--theme-color-500), var(--theme-color-500)); // 节点背景
31
+ --progress-segment-point-bg-active: linear-gradient(0deg, var(--color-theme-500), var(--color-theme-500)); // 节点背景
32
32
  --progress-segment-content-transform: translateX(50%); // 内容中心偏移
33
33
 
34
34
  --progress-bar-height: #{fn.u(20)}; // 进度条高度
35
35
  --progress-bar-radius: #{fn.u(10)}; // 进度条(内外)圆角
36
36
  --progress-bar-outer-bg: linear-gradient(0deg, var(--color-base-250), var(--color-base-250)); // 外背景
37
37
  --progress-bar-outer-padding: 0; // 外边距
38
- --progress-bar-inner-bg: linear-gradient(0deg, var(--theme-color-500), var(--theme-color-500)); // 内背景
38
+ --progress-bar-inner-bg: linear-gradient(0deg, var(--color-theme-500), var(--color-theme-500)); // 内背景
39
39
  overflow-x: scroll;
40
40
 
41
41
  @include mx.e(wrapper) {
@@ -27,7 +27,7 @@
27
27
  }
28
28
 
29
29
  &_thumb {
30
- background-color: var(--theme-color);
30
+ background-color: var(--color-theme);
31
31
  }
32
32
  }
33
33
  }
@@ -1,6 +1,6 @@
1
1
  @use "sass:map";
2
2
  @use "../_config"as cfg;
3
- @use "../_variables" as vars;
3
+ @use "../variables/index" as vars;
4
4
  @use "../function/index" as fn;
5
5
  @use "../mixin/index" as mx;
6
6
 
@@ -8,6 +8,7 @@
8
8
  display: inline-block;
9
9
  line-height: 1;
10
10
  vertical-align: middle;
11
+ color: #{fn.var-get(color, text, 500)};
11
12
 
12
13
  @include mx.when("ellipsis") {
13
14
  width: 100%;
@@ -16,13 +17,10 @@
16
17
  overflow: hidden;
17
18
  }
18
19
 
19
- @each $step, $data in vars.$text-scale {
20
- $ratio: map.get($data, ratio);
21
- $token: map.get($data, token);
22
-
20
+ @each $k, $v in vars.$text {
23
21
  // 生成字体尺寸
24
- @include mx.m($token) {
25
- font-size: var(#{fn.css-var-name(cfg.$theme-font-prefix, $token)});
22
+ @include mx.m($k) {
23
+ font-size: #{fn.var-get(text, $k)};
26
24
  }
27
25
  }
28
26
 
@@ -0,0 +1,226 @@
1
+ @use "sass:map";
2
+ @use "sass:meta";
3
+ @use "sass:list";
4
+ @use "sass:math";
5
+ @use "sass:string";
6
+
7
+ @use "../_config" as cfg;
8
+ @use "../variables/index" as vars;
9
+
10
+ /* ===================================================== */
11
+ /* 1️⃣ 类型判断 */
12
+ /* ===================================================== */
13
+
14
+ @function var-value-is-ref($value) {
15
+ @return meta.type-of($value) == "map" and map.has-key($value, ref);
16
+ }
17
+
18
+ @function var-value-is-calc($value) {
19
+ @return meta.type-of($value) == "map" and map.has-key($value, calc);
20
+ }
21
+
22
+ /* ===================================================== */
23
+ /* 2️⃣ 变量名生成 */
24
+ /* ===================================================== */
25
+
26
+ @function var-get-name($path...) {
27
+ $name: "";
28
+
29
+ @for $i from 1 through list.length($path) {
30
+ $part: list.nth($path, $i);
31
+
32
+ @if $i == 1 {
33
+ $name: "#{$part}";
34
+ } @else {
35
+ $name: "#{$name}-#{$part}";
36
+ }
37
+ }
38
+
39
+ @return $name;
40
+ }
41
+
42
+ /* ===================================================== */
43
+ /* 3️⃣ 读取嵌套 map */
44
+ /* ===================================================== */
45
+
46
+ @function var-get-value($path...) {
47
+ $modules: meta.module-variables("vars");
48
+ $root: list.nth($path, 1);
49
+
50
+ @if not map.has-key($modules, $root) {
51
+ @return null;
52
+ }
53
+
54
+ $value: map.get($modules, $root);
55
+
56
+ @if list.length($path) > 1 {
57
+ @for $i from 2 through list.length($path) {
58
+ $key: list.nth($path, $i);
59
+
60
+ @if meta.type-of($value) != "map" or not map.has-key($value, $key) {
61
+ @return null;
62
+ }
63
+
64
+ $value: map.get($value, $key);
65
+ }
66
+ }
67
+
68
+ $result: $value;
69
+
70
+ // ref
71
+ @if var-value-is-ref($value) {
72
+ $result: var-get-ref($value, cfg.$var-runtime-mode);
73
+ }
74
+
75
+ // calc
76
+ @else if var-value-is-calc($value) {
77
+ $result: var-get-calc($value, cfg.$var-runtime-mode);
78
+ }
79
+
80
+ // list
81
+ @else if meta.type-of($value) == "list" {
82
+ $list-result: ();
83
+
84
+ @each $item in $value {
85
+ $resolved: $item;
86
+
87
+ @if var-value-is-ref($item) {
88
+ $resolved: var-get-ref($item, cfg.$var-runtime-mode);
89
+ } @else if var-value-is-calc($item) {
90
+ $resolved: var-get-calc($item, cfg.$var-runtime-mode);
91
+ }
92
+
93
+ $list-result: list.append($list-result, $resolved, space);
94
+ }
95
+
96
+ $result: $list-result;
97
+ }
98
+
99
+ @return $result;
100
+ }
101
+
102
+ /* ===================================================== */
103
+ /* 4️⃣ 解析 ref(统一模式) */
104
+ /* ===================================================== */
105
+
106
+ @function var-get-ref($ref-value, $mode: value) {
107
+ $path: map.get($ref-value, ref);
108
+
109
+ // 先拿真实值(永远可用)
110
+ $fallback: var-get-value($path...);
111
+
112
+ @if $fallback == null {
113
+ @error "Ref path not found: #{$path}";
114
+ }
115
+
116
+ /* =========================
117
+ 未注册 CSS 变量
118
+ 强制返回真实值
119
+ ========================= */
120
+
121
+ @if cfg.$var-css-registered == false {
122
+ @return $fallback;
123
+ }
124
+
125
+ /* =========================
126
+ CSS 模式
127
+ ========================= */
128
+
129
+ @if $mode == css {
130
+ $name: var-get-name($path...);
131
+ @return string.unquote("var(--#{$name}, #{$fallback})");
132
+ }
133
+
134
+ /* =========================
135
+ value 模式
136
+ ========================= */
137
+
138
+ @return $fallback;
139
+ }
140
+
141
+ /* ===================================================== */
142
+ /* 5️⃣ 解析 calc(统一模式) */
143
+ /* ===================================================== */
144
+
145
+ @function var-get-calc($value, $mode: value) {
146
+ $parts: map.get($value, calc);
147
+
148
+ /* =========================
149
+ CSS 模式
150
+ ========================= */
151
+
152
+ @if $mode == css {
153
+ $string: "";
154
+
155
+ @each $item in $parts {
156
+ @if $item == "+" or $item == "-" or $item == "*" or $item == "/" {
157
+ $string: "#{$string} #{$item} ";
158
+ } @else {
159
+ $current: $item;
160
+
161
+ @if var-value-is-ref($item) {
162
+ $current: var-get-ref($item, css);
163
+ }
164
+
165
+ $string: "#{$string}#{$current}";
166
+ }
167
+ }
168
+
169
+ @return string.unquote("calc(#{$string})");
170
+ }
171
+
172
+ /* =========================
173
+ value 模式(编译期计算)
174
+ ========================= */
175
+
176
+ $result: null;
177
+ $operator: null;
178
+
179
+ @each $item in $parts {
180
+ @if $item == "+" or $item == "-" or $item == "*" or $item == "/" {
181
+ $operator: $item;
182
+ } @else {
183
+ $current: if(var-value-is-ref($item), var-get-ref($item, value), $item);
184
+
185
+ @if $result == null {
186
+ $result: $current;
187
+ } @else {
188
+ @if $operator == "+" {
189
+ $result: $result + $current;
190
+ } @else if $operator == "-" {
191
+ $result: $result - $current;
192
+ } @else if $operator == "*" {
193
+ $result: $result * $current;
194
+ } @else if $operator == "/" {
195
+ $result: math.div($result, $current);
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+ @return $result;
202
+ }
203
+
204
+ /* ===================================================== */
205
+ /* 6️⃣ 最终出口 */
206
+ /* 始终返回 var(--xxx, fallback) */
207
+ /* ===================================================== */
208
+
209
+ @function var-get($path...) {
210
+ $name: var-get-name($path...);
211
+ $fallback: var-get-value($path...);
212
+
213
+ // 如果未注册 CSS 变量 → 直接返回真实值
214
+ @if cfg.$var-css-registered == false {
215
+ @if $fallback == null {
216
+ @return null;
217
+ }
218
+ @return $fallback;
219
+ }
220
+
221
+ @if $fallback == null {
222
+ @return string.unquote("var(--#{$name})");
223
+ }
224
+
225
+ @return string.unquote("var(--#{$name}, #{$fallback})");
226
+ }
@@ -1,18 +1,16 @@
1
1
  @use "sass:string";
2
2
 
3
- @use "./namespace" as *;
3
+ @use "./_namespace" as *;
4
+ @use "./_variables" as *;
4
5
 
5
6
  @forward "./_namespace";
7
+ @forward "./_variables";
6
8
 
7
9
  // 尺寸最小单位
8
10
  @function u($value) {
9
11
  @return calc(#{$value} * var(--size-unit));
10
12
  }
11
13
 
12
- @function css-var-name($category, $token) {
13
- @return "--#{$category}-#{$token}";
14
- }
15
-
16
14
  @function get-image($image) {
17
15
  // 已经是合法CSS值的情况
18
16
  @if string.index($image, "url(") or
@@ -0,0 +1,7 @@
1
+ @function ref($path...) {
2
+ @return (ref: $path);
3
+ }
4
+
5
+ @function math($parts...) {
6
+ @return (calc: $parts);
7
+ }
@@ -1,9 +1,13 @@
1
1
 
2
2
  // atomic
3
- @mixin generate-atomic($prefix, $property, $map) {
4
- @each $key, $value in $map {
5
- .#{$prefix}-#{$key} {
6
- #{$property}: $value;
7
- }
8
- }
3
+ @mixin generate-atomic($prefix, $map) {
4
+ @each $key, $declarations in $map {
5
+ $class-name: if($prefix ==null, $key, "#{$prefix}-#{$key}");
6
+
7
+ .#{$class-name} {
8
+ @each $prop, $val in $declarations {
9
+ #{$prop}: $val;
10
+ }
11
+ }
12
+ }
9
13
  }
@@ -40,6 +40,22 @@ $__bem-context: null;
40
40
  }
41
41
  }
42
42
 
43
+ @mixin when($state) {
44
+ $state-selector: cfg.$state-prefix + cfg.$common-separator + $state;
45
+
46
+ @at-root {
47
+ @if & {
48
+ &.#{$state-selector} {
49
+ @content;
50
+ }
51
+ } @else {
52
+ .#{$state-selector} {
53
+ @content;
54
+ }
55
+ }
56
+ }
57
+ }
58
+
43
59
  @mixin t($names: null) {
44
60
  @if $__bem-context != "block" {
45
61
  @error "t() can only be used inside b()";
@@ -69,19 +85,3 @@ $__bem-context: null;
69
85
  }
70
86
  }
71
87
  }
72
-
73
- @mixin when($state) {
74
- $state-selector: cfg.$state-prefix + cfg.$common-separator + $state;
75
-
76
- @at-root {
77
- @if & {
78
- &.#{$state-selector} {
79
- @content;
80
- }
81
- } @else {
82
- .#{$state-selector} {
83
- @content;
84
- }
85
- }
86
- }
87
- }
@@ -0,0 +1,71 @@
1
+ @use 'sass:map';
2
+ @use 'sass:meta';
3
+ @use "sass:list";
4
+
5
+ @use '../variables/index' as vars;
6
+ @use '../function/index' as fn;
7
+
8
+ /* ===================================================== */
9
+ /* 递归输出 CSS 变量 */
10
+ /* ===================================================== */
11
+
12
+ @mixin var-emit($name, $value) {
13
+ // map 递归
14
+ @if meta.type-of($value) == 'map' and not fn.var-value-is-ref($value) and not fn.var-value-is-calc($value) {
15
+ @each $k, $v in $value {
16
+ @include var-emit('#{$name}-#{$k}', $v);
17
+ }
18
+ } @else {
19
+ $final-value: null;
20
+
21
+ // ref
22
+ @if fn.var-value-is-ref($value) {
23
+ $final-value: fn.var-get-ref($value, css);
24
+ }
25
+
26
+ // calc
27
+ @else if fn.var-value-is-calc($value) {
28
+ $final-value: fn.var-get-calc($value, css);
29
+ }
30
+
31
+ // list
32
+ @else if meta.type-of($value) == 'list' {
33
+ $result: ();
34
+
35
+ @each $item in $value {
36
+ $resolved: $item;
37
+
38
+ @if fn.var-value-is-ref($item) {
39
+ $resolved: fn.var-get-ref($item, css);
40
+ } @else if fn.var-value-is-calc($item) {
41
+ $resolved: fn.var-get-calc($item, css);
42
+ }
43
+
44
+ $result: list.append($result, $resolved, space);
45
+ }
46
+
47
+ $final-value: $result;
48
+ }
49
+
50
+ // 普通值
51
+ @else {
52
+ $final-value: $value;
53
+ }
54
+
55
+ --#{$name}: #{$final-value};
56
+ }
57
+ }
58
+
59
+ @mixin var-register($names...) {
60
+ $all: meta.module-variables('vars');
61
+
62
+ @each $name in $names {
63
+ @if not map.has-key($all, $name) {
64
+ @error "Variable `#{$name}` not found in vars module.";
65
+ }
66
+
67
+ $value: map.get($all, $name);
68
+
69
+ @include var-emit($name, $value);
70
+ }
71
+ }
package/mixin/index.scss CHANGED
@@ -1,14 +1,18 @@
1
1
  @use "sass:map";
2
2
 
3
3
  @use "../_config"as cfg;
4
- @use "../_variables" as vars;
4
+ @use "../variables/index" as vars;
5
5
  @use "../function/index" as fn;
6
6
 
7
7
  @use "./_atomic" as *;
8
8
  @use "./_namespace" as *;
9
+ @use "./_variables" as *;
9
10
 
10
11
  @forward "../_config";
12
+
13
+ @forward "./_atomic";
11
14
  @forward "./_namespace";
15
+ @forward "./_variables";
12
16
 
13
17
  @mixin absolute-center($x: true, $y: true) {
14
18
  $x-value: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nopon-web/styles",
3
- "version": "0.1.00",
3
+ "version": "0.2.01",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
package/theme.scss CHANGED
@@ -1,115 +1,17 @@
1
- @use "sass:map";
2
- @use "./_config"as cfg;
3
- @use "./_variables" as vars;
4
1
  @use "./function/index" as fn;
2
+ @use "./mixin/index" as mx;
5
3
 
6
- // ============================================
7
- // Color Tokens(颜色设计令牌)
8
- // 设计参考: https://tailwindcss.com/docs/colors
9
- // ============================================
10
- // 命名: $<name>-<scale>
11
- // scale: 50(浅) → 950(深),500 为主色
12
- // 可映射为 CSS 变量支持主题切换
13
- // ============================================
4
+ @mixin root-vars() {
5
+ font-size: calc(#{fn.var-get(size, root)} * 1px);
6
+ @include mx.var-register(size, text-base, text, color, z-index-base);
14
7
 
15
- // 主题色
16
- $theme-color-50: #ede6ff;
17
- $theme-color-500: #6e64c8;
18
-
19
- // 基础色(Background / Text Base)
20
- $color-base-50: #fff;
21
- $color-base-250: #f5f6f7;
22
- $color-base-500: #eee;
23
- $color-base-inverse-50: #777777;
24
- $color-base-inverse-250: #333333;
25
- $color-base-inverse-500: #000000;
26
-
27
- // 功能色(Semantic)
28
- $color-danger-500: #ff7b7b;
29
-
30
- @mixin color-vars {
31
- --theme-color-50: #{$theme-color-50};
32
- --theme-color-500: #{$theme-color-500};
33
-
34
- // Base
35
- --color-base-50: #{$color-base-50};
36
- --color-base-250: #{$color-base-250};
37
- --color-base-500: #{$color-base-500};
38
- --color-base-inverse-50: #{$color-base-inverse-50};
39
- --color-base-inverse-250: #{$color-base-inverse-250};
40
- --color-base-inverse-500: #{$color-base-inverse-500};
41
-
42
- // Semantic
43
- --color-danger-500: #{$color-danger-500};
44
-
45
- --color-text-500: var(--color-base-inverse-500);
46
- --color-text-inverse-500: var(--color-base-50);
47
- --color-icon-500: var(--color-base-inverse-500);
48
- --color-border-500: var(--color-base-500);
49
- --color-bg-500: var(--color-base-250);
50
-
51
- // Dark Mode(结构反转
52
8
  &.dark {
53
- --color-base-inverse-50: #{$color-base-50};
54
- --color-base-inverse-250: #{$color-base-250};
55
- --color-base-inverse-500: #{$color-base-500};
56
-
57
- --color-base-50: #{$color-base-inverse-500};
58
- --color-base-250: #{$color-base-inverse-250};
59
- --color-base-500: #{$color-base-inverse-50};
60
- }
61
- }
9
+ --color-base-50: #{fn.var-get-value(color, base, inverse, 500)};
10
+ --color-base-250: #{fn.var-get-value(color, base, inverse, 250)};
11
+ --color-base-500: #{fn.var-get-value(color, base, inverse, 50)};
62
12
 
63
- // ============================================
64
- // Scale Apply
65
- // --size-root : 设计基准(px)
66
- // --size-unit : 等效 1px 抽象单位
67
- // ============================================
68
- //
69
- // rem 模式:
70
- // 基于 root font-size(等价 Flexible)
71
- //
72
- // vw 模式:
73
- // 基于视口宽度比例
74
- // 需通过 JS 动态设置 --size-root = 当前视口宽度(px)
75
- //
76
- // ============================================
77
- @mixin size-apply() {
78
- font-size: calc(var(--size-root) * 1px);
79
- --size-root: #{vars.$size-root};
80
-
81
- @if vars.$size-mode ==rem {
82
- // Flexible
83
- --size-unit: calc(1 / var(--size-root) * 1rem);
84
- }
85
-
86
- @else if vars.$size-mode ==vw {
87
- // Viewport
88
- --size-unit: calc(1 / var(--size-root) * 100vw);
89
- }
90
- }
91
-
92
- // ============================================
93
- // Font Variables
94
- // text-* = base × ratio
95
- // ============================================
96
- @mixin text-vars() {
97
- #{fn.css-var-name(cfg.$theme-font-prefix, base)}: calc(#{vars.$text-base} * var(--size-unit));
98
-
99
- @each $step, $data in vars.$text-scale {
100
- $ratio: map.get($data, ratio);
101
- $token: map.get($data, token);
102
-
103
- #{fn.css-var-name(cfg.$theme-font-prefix, $token)}: calc(var(--#{cfg.$theme-font-prefix}-base) * #{$ratio});
13
+ --color-base-inverse-50: #{fn.var-get-value(color, base, 50)};
14
+ --color-base-inverse-250: #{fn.var-get-value(color, base, 250)};
15
+ --color-base-inverse-500: #{fn.var-get-value(color, base, 500)};
104
16
  }
105
17
  }
106
-
107
- // 主题变量
108
- @mixin vars() {
109
- @include size-apply();
110
- @include text-vars();
111
- @include color-vars();
112
-
113
- // 层级控制
114
- --z-index-base: #{vars.$z-index-base};
115
- }
@@ -0,0 +1,42 @@
1
+ @use 'sass:map';
2
+ @use '../helper/expression' as expr;
3
+
4
+ $button: () !default;
5
+ $button: map.deep-merge(
6
+ (
7
+ color: (
8
+ theme: (
9
+ 50: expr.ref(color, theme, 50),
10
+ 500: expr.ref(color, theme, 500),
11
+ ),
12
+ text: (
13
+ base: expr.ref(color, text, 500),
14
+ hover: expr.ref(button, color, theme, 500),
15
+ ),
16
+ bg: (
17
+ base: expr.ref(color, base, 250),
18
+ hover: expr.ref(button, color, theme, 50),
19
+ ),
20
+ ),
21
+ size: (
22
+ base: expr.math(30, '*', expr.ref(size, unit)),
23
+ text: expr.ref(text, sm),
24
+ ),
25
+ border: (
26
+ width: expr.math(1, '*', expr.ref(size, unit)),
27
+ style: solid,
28
+ color: (
29
+ base: expr.ref(color, base, 250),
30
+ hover: expr.ref(button, color, theme, 500),
31
+ ),
32
+ ),
33
+ radius: (
34
+ base: expr.math(4, '*', expr.ref(size, unit)),
35
+ round: expr.math(20, '*', expr.ref(size, unit)),
36
+ circle: 100%,
37
+ ),
38
+ padding: expr.math(12, '*', expr.ref(size, unit)) expr.math(14, '*', expr.ref(size, unit)),
39
+ gap: expr.math(10, '*', expr.ref(size, unit)),
40
+ ),
41
+ $button
42
+ );
@@ -0,0 +1,100 @@
1
+ @use "sass:map";
2
+ @use "../helper/expression" as expr;
3
+
4
+ @forward "./button.scss";
5
+
6
+ /* =======================================================
7
+ Size System
8
+ root : 设计基准(px), 需通过 JS 动态设置 size-root = 当前视口宽度(px)
9
+ context : 根尺寸表达(1rem / 100vw)
10
+ unit : 1px 折算单位
11
+ -------------------------------------------------------
12
+ rem 模式 : root = 16 → 1rem = 16px
13
+ vw 模式 : root = 设计稿宽度 → 100vw
14
+ -------------------------------------------------------
15
+ 设计参考: https://tailwindcss.com/docs/font-size
16
+ 参考标准: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size#values
17
+ ======================================================= */
18
+
19
+ $size: () !default;
20
+ $size: map.deep-merge(
21
+ (
22
+ root: 16,
23
+ // 设计基准(px)
24
+ context: 1rem,
25
+ // 尺寸上下文(1rem / 100vw)
26
+ unit: expr.math(1, "/", expr.ref(size, root), "*", expr.ref(size, context)),
27
+ ),
28
+ $size
29
+ );
30
+
31
+ /* ================= Typography ================= */
32
+ $text-base: expr.math(16, "*", expr.ref(size, unit)) !default; // 基准字号(md)
33
+ $text: () !default;
34
+ $text: map.deep-merge(
35
+ (
36
+ 6xs: expr.math(expr.ref(text-base), "*", 0.125),
37
+ 5xs: expr.math(expr.ref(text-base), "*", 0.25),
38
+ 4xs: expr.math(expr.ref(text-base), "*", 0.375),
39
+ 3xs: expr.math(expr.ref(text-base), "*", 0.5),
40
+ 2xs: expr.math(expr.ref(text-base), "*", 0.625),
41
+ xs: expr.math(expr.ref(text-base), "*", 0.75),
42
+ sm: expr.math(expr.ref(text-base), "*", 0.875),
43
+ md: expr.math(expr.ref(text-base), "*", 1),
44
+ lg: expr.math(expr.ref(text-base), "*", 1.125),
45
+ xl: expr.math(expr.ref(text-base), "*", 1.25),
46
+ 2xl: expr.math(expr.ref(text-base), "*", 1.5),
47
+ 3xl: expr.math(expr.ref(text-base), "*", 1.875),
48
+ 4xl: expr.math(expr.ref(text-base), "*", 2.25),
49
+ 5xl: expr.math(expr.ref(text-base), "*", 3),
50
+ 6xl: expr.math(expr.ref(text-base), "*", 3.75),
51
+ 7xl: expr.math(expr.ref(text-base), "*", 4.5),
52
+ 8xl: expr.math(expr.ref(text-base), "*", 6),
53
+ 9xl: expr.math(expr.ref(text-base), "*", 8),
54
+ ),
55
+ $text
56
+ );
57
+
58
+ /* =======================================================
59
+ Color System
60
+ scale: 50(浅) → 950(深),500 为主色
61
+ 500 : 主色
62
+ 支持 ref / 主题切换
63
+ -------------------------------------------------------
64
+ 设计参考: https://tailwindcss.com/docs/colors
65
+ ======================================================= */
66
+ $color: () !default;
67
+ $color: map.deep-merge(
68
+ (
69
+ theme: (
70
+ 50: #ede6ff,
71
+ 500: #6e64c8,
72
+ ),
73
+ base: (
74
+ 50: #fff,
75
+ 250: #f5f6f7,
76
+ 500: #eee,
77
+ inverse: (
78
+ 50: #777777,
79
+ 250: #333333,
80
+ 500: #000000,
81
+ ),
82
+ ),
83
+ danger: (
84
+ 500: #ff7b7b,
85
+ ),
86
+ text: (
87
+ 500: expr.ref(color, base, inverse, 500),
88
+ inverse: (
89
+ 500: expr.ref(color, base, 50),
90
+ ),
91
+ ),
92
+ icon: (
93
+ 500: expr.ref(color, base, inverse, 50),
94
+ ),
95
+ ),
96
+ $color
97
+ );
98
+
99
+ /* ================= Layer ================= */
100
+ $z-index-base: 1000;
package/_variables.scss DELETED
@@ -1,42 +0,0 @@
1
- // 尺寸模式(rem/vw)
2
- $size-mode: rem !default;
3
-
4
- // 尺寸基准(16 = 1rem 基准)
5
- $size-root: 16 !default;
6
-
7
- // 字号基准(md 等级)
8
- $text-base: 16 !default;
9
-
10
- // 字号比例阶梯(基于 md = 1)
11
- // lv < 0: small
12
- // lv = 0: medium
13
- // lv > 0: large
14
- //
15
- // 设计参考: https://tailwindcss.com/docs/font-size
16
- // 参考标准: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size#values
17
- $text-scale: (
18
- -7: (ratio: 0.125, token: 6xs),
19
- -6: (ratio: 0.25, token: 5xs),
20
- -5: (ratio: 0.375, token: 4xs),
21
- -4: (ratio: 0.5, token: 3xs),
22
- -3: (ratio: 0.625, token: 2xs),
23
- -2: (ratio: 0.75, token: xs),
24
- -1: (ratio: 0.875, token: sm),
25
- 0: (ratio: 1, token: md),
26
- 1: (ratio: 1.125, token: lg),
27
- 2: (ratio: 1.25, token: xl),
28
- 3: (ratio: 1.5, token: 2xl),
29
- 4: (ratio: 1.875, token: 3xl),
30
- 5: (ratio: 2.25, token: 4xl),
31
- 6: (ratio: 3, token: 5xl),
32
- 7: (ratio: 3.75, token: 6xl),
33
- 8: (ratio: 4.5, token: 7xl),
34
- 9: (ratio: 6, token: 8xl),
35
- 10: (ratio: 8, token: 9xl)
36
- );
37
-
38
- // 判断是否应用了主题包, 从而确定是否注册了 theme-vars
39
- $theme-applied: false !default;
40
-
41
- // 层级
42
- $z-index-base: 1000;