@nopon-web/styles 0.1.0 → 0.2.0

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/_variables.scss CHANGED
@@ -1,42 +1,98 @@
1
- // 尺寸模式(rem/vw)
2
- $size-mode: rem !default;
1
+ @use 'sass:map';
3
2
 
4
- // 尺寸基准(16 = 1rem 基准)
5
- $size-root: 16 !default;
3
+ @use "./helper/expression" as expr;
6
4
 
7
- // 字号基准(md 等级)
8
- $text-base: 16 !default;
9
-
10
- // 字号比例阶梯(基于 md = 1)
11
- // lv < 0: small
12
- // lv = 0: medium
13
- // lv > 0: large
14
- //
5
+ // Size System
6
+ // --size-root : 设计基准(px)
7
+ // --size-unit : 等效 1px 抽象单位
15
8
  // 设计参考: https://tailwindcss.com/docs/font-size
16
9
  // 参考标准: 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)
10
+ // ============================================
11
+ //
12
+ // rem 模式:
13
+ // 基于 root font-size(等价 Flexible)
14
+ //
15
+ // vw 模式:
16
+ // 基于视口宽度比例
17
+ // 需通过 JS 动态设置 size-root = 当前视口宽度(px)
18
+ //
19
+ // ============================================
20
+ $size: () !default;
21
+ $size: map.deep-merge(
22
+ (
23
+ root: 16, // 尺寸基准(16 = 1rem 基准)
24
+ mode: 1rem, // Flexible 模式: 1rem; Viewport 模式: 100vw;
25
+ unit: expr.math(1, "/", expr.ref(size, root), "*", expr.ref(size, mode))
26
+ ),
27
+ $size
28
+ );
29
+
30
+ $text-base: expr.math(16, "*", expr.ref(size, unit)) !default; // 字号基准(md 等级)
31
+ $text: () !default; // 字号比例阶梯(基于 md = 1)
32
+ $text: map.deep-merge(
33
+ (
34
+ 6xs: expr.math(expr.ref(text-base), "*", 0.125),
35
+ 5xs: expr.math(expr.ref(text-base), "*", 0.25),
36
+ 4xs: expr.math(expr.ref(text-base), "*", 0.375),
37
+ 3xs: expr.math(expr.ref(text-base), "*", 0.5),
38
+ 2xs: expr.math(expr.ref(text-base), "*", 0.625),
39
+ xs: expr.math(expr.ref(text-base), "*", 0.75),
40
+ sm: expr.math(expr.ref(text-base), "*", 0.875),
41
+ md: expr.math(expr.ref(text-base), "*", 1),
42
+ lg: expr.math(expr.ref(text-base), "*", 1.125),
43
+ xl: expr.math(expr.ref(text-base), "*", 1.25),
44
+ 2xl: expr.math(expr.ref(text-base), "*", 1.5),
45
+ 3xl: expr.math(expr.ref(text-base), "*", 1.875),
46
+ 4xl: expr.math(expr.ref(text-base), "*", 2.25),
47
+ 5xl: expr.math(expr.ref(text-base), "*", 3),
48
+ 6xl: expr.math(expr.ref(text-base), "*", 3.75),
49
+ 7xl: expr.math(expr.ref(text-base), "*", 4.5),
50
+ 8xl: expr.math(expr.ref(text-base), "*", 6),
51
+ 9xl: expr.math(expr.ref(text-base), "*", 8)
52
+ ),
53
+ $text
36
54
  );
37
55
 
38
- // 判断是否应用了主题包, 从而确定是否注册了 theme-vars
39
- $theme-applied: false !default;
56
+ // ============================================
57
+ // Color
58
+ // 设计参考: https://tailwindcss.com/docs/colors
59
+ // ============================================
60
+ // 命名: $<name>-<scale>
61
+ // scale: 50(浅) → 950(深),500 为主色
62
+ // 可映射为 CSS 变量支持主题切换
63
+ // ============================================
64
+ $color: () !default;
65
+ $color: map.deep-merge(
66
+ (
67
+ theme: (
68
+ 50: #ede6ff,
69
+ 500: #6e64c8,
70
+ ),
71
+ base: (
72
+ 50: #fff,
73
+ 250: #f5f6f7,
74
+ 500: #eee,
75
+ inverse: (
76
+ 50: #777777,
77
+ 250: #333333,
78
+ 500: #000000,
79
+ ),
80
+ ),
81
+ danger: (
82
+ 500: #ff7b7b,
83
+ ),
84
+ text: (
85
+ 500: expr.ref(color, base, inverse, 500),
86
+ inverse: (
87
+ 500: expr.ref(color, base, 50)
88
+ )
89
+ ),
90
+ icon: (
91
+ 500: expr.ref(color, base, inverse, 50)
92
+ )
93
+ ),
94
+ $color
95
+ );
40
96
 
41
97
  // 层级
42
- $z-index-base: 1000;
98
+ $z-index-base: 1000;
@@ -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
  }
@@ -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,204 @@
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" 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
+ // 递归解析
69
+ @if var-value-is-ref($value) {
70
+ @return var-get-ref($value, cfg.$var-runtime-mode);
71
+ }
72
+
73
+ @if var-value-is-calc($value) {
74
+ @return var-get-calc($value, cfg.$var-runtime-mode);
75
+ }
76
+
77
+ @return $value;
78
+ }
79
+
80
+ /* ===================================================== */
81
+ /* 4️⃣ 解析 ref(统一模式) */
82
+ /* ===================================================== */
83
+
84
+ @function var-get-ref($ref-value, $mode: value) {
85
+ $path: map.get($ref-value, ref);
86
+
87
+ // 先拿真实值(永远可用)
88
+ $fallback: var-get-value($path...);
89
+
90
+ @if $fallback == null {
91
+ @error "Ref path not found: #{$path}";
92
+ }
93
+
94
+ /* =========================
95
+ 未注册 CSS 变量
96
+ 强制返回真实值
97
+ ========================= */
98
+
99
+ @if cfg.$var-css-registered == false {
100
+ @return $fallback;
101
+ }
102
+
103
+ /* =========================
104
+ CSS 模式
105
+ ========================= */
106
+
107
+ @if $mode == css {
108
+ $name: var-get-name($path...);
109
+ @return string.unquote("var(--#{$name}, #{$fallback})");
110
+ }
111
+
112
+ /* =========================
113
+ value 模式
114
+ ========================= */
115
+
116
+ @return $fallback;
117
+ }
118
+
119
+ /* ===================================================== */
120
+ /* 5️⃣ 解析 calc(统一模式) */
121
+ /* ===================================================== */
122
+
123
+ @function var-get-calc($value, $mode: value) {
124
+ $parts: map.get($value, calc);
125
+
126
+ /* =========================
127
+ CSS 模式
128
+ ========================= */
129
+
130
+ @if $mode == css {
131
+ $string: "";
132
+
133
+ @each $item in $parts {
134
+ @if $item == "+" or $item == "-" or $item == "*" or $item == "/" {
135
+ $string: "#{$string} #{$item} ";
136
+ } @else {
137
+ $current: $item;
138
+
139
+ @if var-value-is-ref($item) {
140
+ $current: var-get-ref($item, css);
141
+ }
142
+
143
+ $string: "#{$string}#{$current}";
144
+ }
145
+ }
146
+
147
+ @return string.unquote("calc(#{$string})");
148
+ }
149
+
150
+ /* =========================
151
+ value 模式(编译期计算)
152
+ ========================= */
153
+
154
+ $result: null;
155
+ $operator: null;
156
+
157
+ @each $item in $parts {
158
+ @if $item == "+" or $item == "-" or $item == "*" or $item == "/" {
159
+ $operator: $item;
160
+ } @else {
161
+ $current: if(var-value-is-ref($item), var-get-ref($item, value), $item);
162
+
163
+ @if $result == null {
164
+ $result: $current;
165
+ } @else {
166
+ @if $operator == "+" {
167
+ $result: $result + $current;
168
+ } @else if $operator == "-" {
169
+ $result: $result - $current;
170
+ } @else if $operator == "*" {
171
+ $result: $result * $current;
172
+ } @else if $operator == "/" {
173
+ $result: math.div($result, $current);
174
+ }
175
+ }
176
+ }
177
+ }
178
+
179
+ @return $result;
180
+ }
181
+
182
+ /* ===================================================== */
183
+ /* 6️⃣ 最终出口 */
184
+ /* 始终返回 var(--xxx, fallback) */
185
+ /* ===================================================== */
186
+
187
+ @function var-get($path...) {
188
+ $name: var-get-name($path...);
189
+ $fallback: var-get-value($path...);
190
+
191
+ // 如果未注册 CSS 变量 → 直接返回真实值
192
+ @if cfg.$var-css-registered == false {
193
+ @if $fallback == null {
194
+ @return null;
195
+ }
196
+ @return $fallback;
197
+ }
198
+
199
+ @if $fallback == null {
200
+ @return string.unquote("var(--#{$name})");
201
+ }
202
+
203
+ @return string.unquote("var(--#{$name}, #{$fallback})");
204
+ }
@@ -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
+ }
@@ -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,49 @@
1
+ @use "sass:map";
2
+ @use "sass:meta";
3
+
4
+ @use "../variables" as vars;
5
+ @use "../function/index" as fn;
6
+
7
+ /* ===================================================== */
8
+ /* 递归输出 CSS 变量 */
9
+ /* ===================================================== */
10
+
11
+ @mixin var-emit($name, $value) {
12
+ // 如果是普通嵌套 map(不是 ref / calc)
13
+ @if meta.type-of($value) == "map" and not fn.var-value-is-ref($value) and not fn.var-value-is-calc($value) {
14
+ @each $k, $v in $value {
15
+ @include var-emit("#{$name}-#{$k}", $v);
16
+ }
17
+ } @else {
18
+ $final-value: null;
19
+
20
+ // ref
21
+ @if fn.var-value-is-ref($value) {
22
+ $final-value: fn.var-get-ref($value, css);
23
+ }
24
+
25
+ // calc
26
+ @else if fn.var-value-is-calc($value) {
27
+ $final-value: fn.var-get-calc($value, css);
28
+ }
29
+
30
+ // 普通值
31
+ @else {
32
+ $final-value: $value;
33
+ }
34
+
35
+ --#{$name}: #{$final-value};
36
+ }
37
+ }
38
+
39
+ /* ===================================================== */
40
+ /* 注册所有变量 */
41
+ /* ===================================================== */
42
+
43
+ @mixin var-register() {
44
+ $all: meta.module-variables("vars");
45
+
46
+ @each $name, $value in $all {
47
+ @include var-emit($name, $value);
48
+ }
49
+ }
package/mixin/index.scss CHANGED
@@ -6,9 +6,11 @@
6
6
 
7
7
  @use "./_atomic" as *;
8
8
  @use "./_namespace" as *;
9
+ @use "./_variables" as *;
9
10
 
10
11
  @forward "../_config";
11
12
  @forward "./_namespace";
13
+ @forward "./_variables";
12
14
 
13
15
  @mixin absolute-center($x: true, $y: true) {
14
16
  $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.00",
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
- // ============================================
14
-
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);
4
+ @mixin vars() {
5
+ font-size: calc(#{fn.var-get(size, root)} * 1px);
6
+ @include mx.var-register();
50
7
 
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);
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)};
89
16
  }
90
17
  }
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});
104
- }
105
- }
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
- }