@mezzanine-ui/system 0.16.0 → 1.0.0-beta.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.
Files changed (58) hide show
  1. package/_system.scss +46 -7
  2. package/effect/_effect.scss +78 -0
  3. package/effect/_index.scss +1 -0
  4. package/effect/constants.d.ts +1 -0
  5. package/effect/constants.js +3 -0
  6. package/effect/index.d.ts +2 -0
  7. package/effect/index.js +1 -0
  8. package/effect/typings.d.ts +32 -0
  9. package/motion/_motion.scss +47 -11
  10. package/motion/duration.d.ts +1 -1
  11. package/motion/duration.js +6 -5
  12. package/motion/easing.d.ts +1 -1
  13. package/motion/easing.js +3 -4
  14. package/package.json +1 -1
  15. package/palette/_index.scss +3 -1
  16. package/palette/_palette.scss +3 -203
  17. package/palette/_primitives.scss +269 -0
  18. package/palette/_semantic.scss +549 -0
  19. package/palette/constants.d.ts +1 -1
  20. package/palette/constants.js +2 -2
  21. package/palette/index.js +1 -1
  22. package/palette/typings.d.ts +86 -0
  23. package/radius/_index.scss +1 -0
  24. package/radius/_radius.scss +71 -0
  25. package/radius/constants.d.ts +1 -0
  26. package/radius/constants.js +3 -0
  27. package/radius/index.d.ts +3 -0
  28. package/radius/index.js +2 -0
  29. package/radius/radius.d.ts +18 -0
  30. package/radius/radius.js +32 -0
  31. package/size/_size.scss +6 -1
  32. package/size/size.d.ts +2 -0
  33. package/spacing/_index.scss +3 -1
  34. package/spacing/_primitives.scss +155 -0
  35. package/spacing/_semantic.scss +663 -0
  36. package/spacing/_spacing.scss +2 -18
  37. package/spacing/constants.d.ts +1 -0
  38. package/spacing/constants.js +2 -1
  39. package/spacing/index.js +1 -1
  40. package/spacing/toSpacingCssVar.d.ts +1 -0
  41. package/spacing/toSpacingCssVar.js +1 -0
  42. package/spacing/typings.d.ts +81 -0
  43. package/transition/_transition.scss +25 -9
  44. package/typography/SF-Mono/SFMonoMedium.woff +0 -0
  45. package/typography/SF-Mono/SFMonoRegular.woff +0 -0
  46. package/typography/SF-Mono/SFMonoSemibold.woff +0 -0
  47. package/typography/_index.scss +4 -1
  48. package/typography/_primitives.scss +318 -0
  49. package/typography/_semantic.scss +237 -0
  50. package/typography/_sf-mono.scss +34 -0
  51. package/typography/_typography.scss +4 -248
  52. package/typography/_utils.scss +4 -0
  53. package/typography/index.js +1 -0
  54. package/typography/typings.d.ts +9 -1
  55. package/typography/typings.js +4 -0
  56. package/z-index/_z-index.scss +1 -1
  57. package/palette/_constants.scss +0 -267
  58. package/palette/_utils.scss +0 -47
@@ -1 +1,82 @@
1
+ /** @deprecated */
1
2
  export type SpacingLevel = number;
3
+ /**
4
+ * Spacing primitive scales - 間距原始級距(對應 px 值)
5
+ */
6
+ export type SpacingScale = 0 | 1 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 24 | 28 | 32 | 36 | 40 | 48 | 52 | 56 | 60 | 64 | 80 | 160 | 240 | 320 | 360 | 400 | 480 | 560 | 640 | 720 | 960 | 1140;
7
+ /**
8
+ * Spacing primitives configuration
9
+ */
10
+ export type SpacingPrimitives = Partial<Record<SpacingScale, string | number>>;
11
+ /**
12
+ * Spacing semantic contexts - 語意化間距的使用情境
13
+ */
14
+ export type SpacingContext = 'size' | 'gap' | 'padding';
15
+ /**
16
+ * Spacing mode - 間距模式
17
+ */
18
+ export type SpacingMode = 'default' | 'compact';
19
+ /**
20
+ * Size categories - 尺寸分類
21
+ */
22
+ export type SizeCategory = 'element' | 'container';
23
+ /**
24
+ * Padding categories - 內邊距分類
25
+ */
26
+ export type PaddingCategory = 'horizontal' | 'vertical';
27
+ /**
28
+ * Element size tones - 元素尺寸調性
29
+ */
30
+ export type ElementTone = 'hairline' | 'tiny' | 'tight' | 'compact' | 'slim' | 'narrow' | 'base' | 'base-fixed' | 'gentle' | 'relaxed' | 'airy' | 'roomy' | 'loose' | 'extra-wide' | 'extra-wide-condense' | 'expansive' | 'extra' | 'max';
31
+ /**
32
+ * Container size tones - 容器尺寸調性
33
+ */
34
+ export type ContainerTone = 'collapsed' | 'tiny' | 'tight' | 'slim' | 'narrow' | 'compact' | 'standard' | 'balanced' | 'broad' | 'wide' | 'expanded' | 'max';
35
+ /**
36
+ * Gap tones - 間隙調性
37
+ */
38
+ export type GapTone = 'none' | 'micro' | 'tiny' | 'tight' | 'compact' | 'base' | 'base-fixed' | 'comfortable' | 'roomy' | 'spacious' | 'relaxed' | 'airy' | 'generous' | 'breath' | 'wide';
39
+ /**
40
+ * Horizontal padding tones - 水平內邊距調性
41
+ */
42
+ export type HorizontalPaddingTone = 'none' | 'micro' | 'tiny' | 'tiny-fixed' | 'tight' | 'tight-fixed' | 'base' | 'base-fixed' | 'calm' | 'comfort' | 'comfort-fixed' | 'roomy' | 'spacious' | 'relaxed' | 'airy' | 'breath' | 'wide' | 'max';
43
+ /**
44
+ * Vertical padding tones - 垂直內邊距調性
45
+ */
46
+ export type VerticalPaddingTone = 'none' | 'micro' | 'tiny' | 'tight' | 'base' | 'calm' | 'comfort' | 'roomy' | 'spacious' | 'generous' | 'relaxed';
47
+ /**
48
+ * Category 與對應 Tone 的映射型別
49
+ */
50
+ export type SpacingToneMap = {
51
+ size: {
52
+ element: ElementTone;
53
+ container: ContainerTone;
54
+ };
55
+ gap: GapTone;
56
+ padding: {
57
+ horizontal: HorizontalPaddingTone;
58
+ vertical: VerticalPaddingTone;
59
+ };
60
+ };
61
+ /**
62
+ * 取得特定 context 的 tone 型別
63
+ * @example
64
+ * type GapT = SpacingToneFor<'gap'>; // GapTone
65
+ */
66
+ export type SpacingToneFor<C extends SpacingContext> = SpacingToneMap[C] extends infer T ? T extends {
67
+ element: any;
68
+ } ? never : T : never;
69
+ /**
70
+ * 取得特定 context + category 的 tone 型別
71
+ * @example
72
+ * type EleTone = SpacingCategoryToneFor<'size', 'element'>; // ElementTone
73
+ */
74
+ export type SpacingCategoryToneFor<C extends SpacingContext, Cat extends C extends 'size' ? SizeCategory : C extends 'padding' ? PaddingCategory : never> = C extends 'size' ? Cat extends SizeCategory ? SpacingToneMap['size'][Cat] : never : C extends 'padding' ? Cat extends PaddingCategory ? SpacingToneMap['padding'][Cat] : never : never;
75
+ /**
76
+ * Semantic spacing 完整型別 - context + category + tone 組合
77
+ * @example
78
+ * const spacing1: SemanticSpacing = 'size-element-base';
79
+ * const spacing2: SemanticSpacing = 'gap-comfortable';
80
+ * const spacing3: SemanticSpacing = 'padding-horizontal-calm';
81
+ */
82
+ export type SemanticSpacing = `size-element-${ElementTone}` | `size-container-${ContainerTone}` | `gap-${GapTone}` | `padding-horizontal-${HorizontalPaddingTone}` | `padding-vertical-${VerticalPaddingTone}`;
@@ -1,17 +1,33 @@
1
+ @use 'sass:meta';
2
+ @use 'sass:string';
1
3
  @use '../motion';
2
4
 
3
- @function enter($property, $duration: motion.duration(short), $delay: 0ms) {
4
- @return $property $duration motion.easing(decelerated) $delay;
5
- }
5
+ @function entrance($property, $duration: moderate, $delay: 0ms) {
6
+ $duration-value: if(
7
+ meta.type-of($duration) == number or string.index(meta.inspect($duration), 'calc') != null,
8
+ $duration,
9
+ motion.duration($duration)
10
+ );
6
11
 
7
- @function exit($property, $duration: motion.duration(shorter), $delay: 0ms) {
8
- @return $property $duration motion.easing(accelerated) $delay;
12
+ @return $property $duration-value motion.easing(entrance) $delay;
9
13
  }
10
14
 
11
- @function emphasized($property, $duration: motion.duration(short), $delay: 0ms) {
12
- @return $property $duration motion.easing(emphasized) $delay;
15
+ @function exit($property, $duration: moderate, $delay: 0ms) {
16
+ $duration-value: if(
17
+ meta.type-of($duration) == number or string.index(meta.inspect($duration), 'calc') != null,
18
+ $duration,
19
+ motion.duration($duration)
20
+ );
21
+
22
+ @return $property $duration-value motion.easing(exit) $delay;
13
23
  }
14
24
 
15
- @function standard($property, $duration: motion.duration(short), $delay: 0ms) {
16
- @return $property $duration motion.easing(standard) $delay;
25
+ @function standard($property, $duration: moderate, $delay: 0ms) {
26
+ $duration-value: if(
27
+ meta.type-of($duration) == number or string.index(meta.inspect($duration), 'calc') != null,
28
+ $duration,
29
+ motion.duration($duration)
30
+ );
31
+
32
+ @return $property $duration-value motion.easing(standard) $delay;
17
33
  }
@@ -1,2 +1,5 @@
1
1
  @forward './utils';
2
- @forward './typography';
2
+ @forward './typography'; // @deprecated - will be removed in next major version
3
+ @forward './primitives' as primitive-*;
4
+ @forward './semantic' as semantic-*;
5
+ @forward './sf-mono';
@@ -0,0 +1,318 @@
1
+ @use 'sass:meta';
2
+ @use '../utils/list';
3
+ @use '../utils/map';
4
+ @use './utils' as typography-utils;
5
+
6
+ // ==========================================
7
+ // Font Family Primitives
8
+ // ==========================================
9
+
10
+ // 定義所有可用的 font-family 類型
11
+ $primitive-font-family-types: (
12
+ pingfangtc,
13
+ notosans,
14
+ sfmono
15
+ );
16
+
17
+ // CSS 變數前綴
18
+ $primitive-prefix: mzn-typography-primitive;
19
+
20
+ // 預設 font-family 定義
21
+ $default-font-families: (
22
+ pingfangtc: 'PingFang TC',
23
+ notosans: 'Noto Sans TC',
24
+ sfmono: 'SF Mono',
25
+ );
26
+
27
+ // ==========================================
28
+ // Font Weight Primitives
29
+ // ==========================================
30
+
31
+ // 定義所有可用的 font-weight 類型
32
+ $primitive-font-weight-types: (
33
+ regular,
34
+ medium,
35
+ semibold
36
+ );
37
+
38
+ // 預設 font-weight 定義
39
+ $default-font-weights: (
40
+ regular: 400,
41
+ medium: 500,
42
+ semibold: 600,
43
+ );
44
+
45
+ // ==========================================
46
+ // Font Size Primitives
47
+ // ==========================================
48
+
49
+ // 定義所有可用的 font-size 級距
50
+ $primitive-font-size-scales: (24, 18, 16, 14, 12, 10);
51
+
52
+ // 預設 font-size 定義
53
+ $default-font-sizes: (
54
+ 24: typography-utils.px-to-rem(24px),
55
+ 18: typography-utils.px-to-rem(18px),
56
+ 16: typography-utils.px-to-rem(16px),
57
+ 14: typography-utils.px-to-rem(14px),
58
+ 12: typography-utils.px-to-rem(12px),
59
+ 10: typography-utils.px-to-rem(10px),
60
+ );
61
+
62
+ // ==========================================
63
+ // Line Height Primitives
64
+ // ==========================================
65
+
66
+ // 定義所有可用的 line-height 類型
67
+ $primitive-line-height-types: (
68
+ h1,
69
+ h2,
70
+ h3,
71
+ body,
72
+ caption,
73
+ annotation,
74
+ functional
75
+ );
76
+
77
+ // 預設 line-height 定義
78
+ $default-line-heights: (
79
+ h1: 28px,
80
+ h2: 24px,
81
+ h3: 22px,
82
+ body: 20px,
83
+ caption: 16px,
84
+ annotation: 14px,
85
+ functional: 16px,
86
+ );
87
+
88
+ // ==========================================
89
+ // Letter Spacing Primitives
90
+ // ==========================================
91
+
92
+ // 定義所有可用的 letter-spacing 類型
93
+ $primitive-letter-spacing-types: (
94
+ 0
95
+ );
96
+
97
+ // 預設 letter-spacing 定義
98
+ $default-letter-spacings: (
99
+ 0: 0em,
100
+ );
101
+
102
+ // ==========================================
103
+ // Validation Functions
104
+ // ==========================================
105
+
106
+ @function is-font-family-type-valid($type) {
107
+ @return list.includes($primitive-font-family-types, $type);
108
+ }
109
+
110
+ @function is-font-weight-type-valid($type) {
111
+ @return list.includes($primitive-font-weight-types, $type);
112
+ }
113
+
114
+ @function is-font-size-scale-valid($scale) {
115
+ @return list.includes($primitive-font-size-scales, $scale);
116
+ }
117
+
118
+ @function is-line-height-type-valid($type) {
119
+ @return list.includes($primitive-line-height-types, $type);
120
+ }
121
+
122
+ @function is-letter-spacing-type-valid($type) {
123
+ @return list.includes($primitive-letter-spacing-types, $type);
124
+ }
125
+
126
+ // ==========================================
127
+ // CSS Variable Functions
128
+ // ==========================================
129
+
130
+ // Get font-family CSS variable
131
+ @function font-family-variable($type, $fallback: null) {
132
+ @if not is-font-family-type-valid($type) {
133
+ @error 'Invalid font-family type #{$type}. Please choose one of #{$primitive-font-family-types}';
134
+ }
135
+
136
+ $varname: --#{$primitive-prefix}-font-family-#{$type};
137
+
138
+ @if not $fallback {
139
+ @return var(#{$varname});
140
+ }
141
+
142
+ @return var(#{$varname}, $fallback);
143
+ }
144
+
145
+ // Get font-weight CSS variable
146
+ @function font-weight-variable($type, $fallback: null) {
147
+ @if not is-font-weight-type-valid($type) {
148
+ @error 'Invalid font-weight type #{$type}. Please choose one of #{$primitive-font-weight-types}';
149
+ }
150
+
151
+ $varname: --#{$primitive-prefix}-font-weight-#{$type};
152
+
153
+ @if not $fallback {
154
+ @return var(#{$varname});
155
+ }
156
+
157
+ @return var(#{$varname}, $fallback);
158
+ }
159
+
160
+ // Get font-size CSS variable
161
+ @function font-size-variable($scale, $fallback: null) {
162
+ @if not is-font-size-scale-valid($scale) {
163
+ @error 'Invalid font-size scale #{$scale}. Please choose one of #{$primitive-font-size-scales}';
164
+ }
165
+
166
+ $varname: --#{$primitive-prefix}-font-size-#{$scale};
167
+
168
+ @if not $fallback {
169
+ @return var(#{$varname});
170
+ }
171
+
172
+ @return var(#{$varname}, $fallback);
173
+ }
174
+
175
+ // Get line-height CSS variable
176
+ @function line-height-variable($type, $fallback: null) {
177
+ @if not is-line-height-type-valid($type) {
178
+ @error 'Invalid line-height type #{$type}. Please choose one of #{$primitive-line-height-types}';
179
+ }
180
+
181
+ $varname: --#{$primitive-prefix}-line-height-#{$type};
182
+
183
+ @if not $fallback {
184
+ @return var(#{$varname});
185
+ }
186
+
187
+ @return var(#{$varname}, $fallback);
188
+ }
189
+
190
+ // Get letter-spacing CSS variable
191
+ @function letter-spacing-variable($type, $fallback: null) {
192
+ @if not is-letter-spacing-type-valid($type) {
193
+ @error 'Invalid letter-spacing type #{$type}. Please choose one of #{$primitive-letter-spacing-types}';
194
+ }
195
+
196
+ $varname: --#{$primitive-prefix}-letter-spacing-#{$type};
197
+
198
+ @if not $fallback {
199
+ @return var(#{$varname});
200
+ }
201
+
202
+ @return var(#{$varname}, $fallback);
203
+ }
204
+
205
+ // Get default font-family list from primitives
206
+ @function get-font-family-list($font-families: ()) {
207
+ $merged-font-families: map.merge($default-font-families, $font-families);
208
+ $result: ();
209
+
210
+ // 按照指定順序:PingFang TC, Noto Sans TC, SF Mono, sans-serif
211
+ @if map.has-key($merged-font-families, pingfangtc) {
212
+ $result: list.append($result, map.get($merged-font-families, pingfangtc), comma);
213
+ }
214
+
215
+ @if map.has-key($merged-font-families, notosans) {
216
+ $result: list.append($result, map.get($merged-font-families, notosans), comma);
217
+ }
218
+
219
+ @if map.has-key($merged-font-families, sfmono) {
220
+ $result: list.append($result, map.get($merged-font-families, sfmono), comma);
221
+ }
222
+
223
+ // 添加 sans-serif 作為最終回退
224
+ $result: list.append($result, sans-serif, comma);
225
+
226
+ @return $result;
227
+ }
228
+
229
+ // ==========================================
230
+ // Generate CSS Variables Mixin
231
+ // ==========================================
232
+
233
+ // Generate partial font-family CSS variables
234
+ @mixin partial-font-family-variables($font-families: ()) {
235
+ @each $type, $value in $font-families {
236
+ @if not is-font-family-type-valid($type) {
237
+ @error 'Invalid font-family type #{$type}. Please choose one of #{$primitive-font-family-types}';
238
+ }
239
+
240
+ @if $value {
241
+ --#{$primitive-prefix}-font-family-#{$type}: #{meta.inspect($value)};
242
+ }
243
+ }
244
+ }
245
+
246
+ // Generate partial font-weight CSS variables
247
+ @mixin partial-font-weight-variables($font-weights: ()) {
248
+ @each $type, $value in $font-weights {
249
+ @if not is-font-weight-type-valid($type) {
250
+ @error 'Invalid font-weight type #{$type}. Please choose one of #{$primitive-font-weight-types}';
251
+ }
252
+
253
+ @if $value {
254
+ --#{$primitive-prefix}-font-weight-#{$type}: #{$value};
255
+ }
256
+ }
257
+ }
258
+
259
+ // Generate partial font-size CSS variables
260
+ @mixin partial-font-size-variables($font-sizes: ()) {
261
+ @each $scale, $value in $font-sizes {
262
+ @if not is-font-size-scale-valid($scale) {
263
+ @error 'Invalid font-size scale #{$scale}. Please choose one of #{$primitive-font-size-scales}';
264
+ }
265
+
266
+ @if $value {
267
+ --#{$primitive-prefix}-font-size-#{$scale}: #{$value};
268
+ }
269
+ }
270
+ }
271
+
272
+ // Generate partial line-height CSS variables
273
+ @mixin partial-line-height-variables($line-heights: ()) {
274
+ @each $type, $value in $line-heights {
275
+ @if not is-line-height-type-valid($type) {
276
+ @error 'Invalid line-height type #{$type}. Please choose one of #{$primitive-line-height-types}';
277
+ }
278
+
279
+ @if $value {
280
+ --#{$primitive-prefix}-line-height-#{$type}: #{$value};
281
+ }
282
+ }
283
+ }
284
+
285
+ // Generate partial letter-spacing CSS variables
286
+ @mixin partial-letter-spacing-variables($letter-spacings: ()) {
287
+ @each $type, $value in $letter-spacings {
288
+ @if not is-letter-spacing-type-valid($type) {
289
+ @error 'Invalid letter-spacing type #{$type}. Please choose one of #{$primitive-letter-spacing-types}';
290
+ }
291
+
292
+ @if $value {
293
+ --#{$primitive-prefix}-letter-spacing-#{$type}: #{$value};
294
+ }
295
+ }
296
+ }
297
+
298
+ // Generate all typography primitive CSS variables
299
+ @mixin variables(
300
+ $font-families: (),
301
+ $font-weights: (),
302
+ $font-sizes: (),
303
+ $line-heights: (),
304
+ $letter-spacings: ()
305
+ ) {
306
+ // Merge user values with defaults
307
+ $merged-font-families: map.merge($default-font-families, $font-families);
308
+ $merged-font-weights: map.merge($default-font-weights, $font-weights);
309
+ $merged-font-sizes: map.merge($default-font-sizes, $font-sizes);
310
+ $merged-line-heights: map.merge($default-line-heights, $line-heights);
311
+ $merged-letter-spacings: map.merge($default-letter-spacings, $letter-spacings);
312
+
313
+ @include partial-font-family-variables($merged-font-families);
314
+ @include partial-font-weight-variables($merged-font-weights);
315
+ @include partial-font-size-variables($merged-font-sizes);
316
+ @include partial-line-height-variables($merged-line-heights);
317
+ @include partial-letter-spacing-variables($merged-letter-spacings);
318
+ }
@@ -0,0 +1,237 @@
1
+ @use '../utils/list';
2
+ @use '../utils/map';
3
+ @use './primitives' as primitive;
4
+
5
+ $prefix: mzn-typography;
6
+
7
+ // 定義所有 semantic 類型
8
+ $semantic-types: (
9
+ h1,
10
+ h2,
11
+ h3,
12
+ body,
13
+ body-highlight,
14
+ body-mono,
15
+ body-mono-highlight,
16
+ text-link-body,
17
+ text-link-caption,
18
+ caption,
19
+ caption-highlight,
20
+ annotation,
21
+ annotation-highlight,
22
+ button,
23
+ button-highlight,
24
+ input,
25
+ input-mono,
26
+ label-primary,
27
+ label-primary-highlight,
28
+ label-secondary
29
+ );
30
+
31
+ // 定義所有 typography 屬性
32
+ $semantic-props: (
33
+ font-family,
34
+ font-size,
35
+ font-weight,
36
+ line-height,
37
+ letter-spacing
38
+ );
39
+
40
+ // Semantic Typography 定義
41
+ $semantic-typographies: (
42
+ h1: (
43
+ font-size: primitive.font-size-variable(24),
44
+ font-weight: primitive.font-weight-variable(semibold),
45
+ line-height: primitive.line-height-variable(h1),
46
+ letter-spacing: primitive.letter-spacing-variable(0),
47
+ ),
48
+ h2: (
49
+ font-size: primitive.font-size-variable(18),
50
+ font-weight: primitive.font-weight-variable(semibold),
51
+ line-height: primitive.line-height-variable(h2),
52
+ letter-spacing: primitive.letter-spacing-variable(0),
53
+ ),
54
+ h3: (
55
+ font-size: primitive.font-size-variable(16),
56
+ font-weight: primitive.font-weight-variable(semibold),
57
+ line-height: primitive.line-height-variable(h3),
58
+ letter-spacing: primitive.letter-spacing-variable(0),
59
+ ),
60
+ body: (
61
+ font-size: primitive.font-size-variable(14),
62
+ font-weight: primitive.font-weight-variable(regular),
63
+ line-height: primitive.line-height-variable(body),
64
+ letter-spacing: primitive.letter-spacing-variable(0),
65
+ ),
66
+ body-highlight: (
67
+ font-size: primitive.font-size-variable(14),
68
+ font-weight: primitive.font-weight-variable(medium),
69
+ line-height: primitive.line-height-variable(body),
70
+ letter-spacing: primitive.letter-spacing-variable(0),
71
+ ),
72
+ body-mono: (
73
+ font-family: primitive.font-family-variable(sfmono),
74
+ font-size: primitive.font-size-variable(14),
75
+ font-weight: primitive.font-weight-variable(regular),
76
+ line-height: primitive.line-height-variable(body),
77
+ letter-spacing: primitive.letter-spacing-variable(0),
78
+ ),
79
+ body-mono-highlight: (
80
+ font-family: primitive.font-family-variable(sfmono),
81
+ font-size: primitive.font-size-variable(14),
82
+ font-weight: primitive.font-weight-variable(medium),
83
+ line-height: primitive.line-height-variable(body),
84
+ letter-spacing: primitive.letter-spacing-variable(0),
85
+ ),
86
+ text-link-body: (
87
+ font-size: primitive.font-size-variable(14),
88
+ font-weight: primitive.font-weight-variable(regular),
89
+ line-height: primitive.line-height-variable(body),
90
+ letter-spacing: primitive.letter-spacing-variable(0),
91
+ ),
92
+ text-link-caption: (
93
+ font-size: primitive.font-size-variable(12),
94
+ font-weight: primitive.font-weight-variable(regular),
95
+ line-height: primitive.line-height-variable(caption),
96
+ letter-spacing: primitive.letter-spacing-variable(0),
97
+ ),
98
+ caption: (
99
+ font-size: primitive.font-size-variable(12),
100
+ font-weight: primitive.font-weight-variable(regular),
101
+ line-height: primitive.line-height-variable(caption),
102
+ letter-spacing: primitive.letter-spacing-variable(0),
103
+ ),
104
+ caption-highlight: (
105
+ font-size: primitive.font-size-variable(12),
106
+ font-weight: primitive.font-weight-variable(semibold),
107
+ line-height: primitive.line-height-variable(caption),
108
+ letter-spacing: primitive.letter-spacing-variable(0),
109
+ ),
110
+ annotation: (
111
+ font-size: primitive.font-size-variable(10),
112
+ font-weight: primitive.font-weight-variable(regular),
113
+ line-height: primitive.line-height-variable(annotation),
114
+ letter-spacing: primitive.letter-spacing-variable(0),
115
+ ),
116
+ annotation-highlight: (
117
+ font-size: primitive.font-size-variable(10),
118
+ font-weight: primitive.font-weight-variable(semibold),
119
+ line-height: primitive.line-height-variable(annotation),
120
+ letter-spacing: primitive.letter-spacing-variable(0),
121
+ ),
122
+ button: (
123
+ font-size: primitive.font-size-variable(14),
124
+ font-weight: primitive.font-weight-variable(regular),
125
+ line-height: primitive.line-height-variable(functional),
126
+ letter-spacing: primitive.letter-spacing-variable(0),
127
+ ),
128
+ button-highlight: (
129
+ font-size: primitive.font-size-variable(14),
130
+ font-weight: primitive.font-weight-variable(medium),
131
+ line-height: primitive.line-height-variable(functional),
132
+ letter-spacing: primitive.letter-spacing-variable(0),
133
+ ),
134
+ input: (
135
+ font-size: primitive.font-size-variable(14),
136
+ font-weight: primitive.font-weight-variable(regular),
137
+ line-height: primitive.line-height-variable(functional),
138
+ letter-spacing: primitive.letter-spacing-variable(0),
139
+ ),
140
+ input-mono: (
141
+ font-family: primitive.font-family-variable(sfmono),
142
+ font-size: primitive.font-size-variable(14),
143
+ font-weight: primitive.font-weight-variable(regular),
144
+ line-height: primitive.line-height-variable(functional),
145
+ letter-spacing: primitive.letter-spacing-variable(0),
146
+ ),
147
+ label-primary: (
148
+ font-size: primitive.font-size-variable(14),
149
+ font-weight: primitive.font-weight-variable(regular),
150
+ line-height: primitive.line-height-variable(functional),
151
+ letter-spacing: primitive.letter-spacing-variable(0),
152
+ ),
153
+ label-primary-highlight: (
154
+ font-size: primitive.font-size-variable(14),
155
+ font-weight: primitive.font-weight-variable(medium),
156
+ line-height: primitive.line-height-variable(functional),
157
+ letter-spacing: primitive.letter-spacing-variable(0),
158
+ ),
159
+ label-secondary: (
160
+ font-size: primitive.font-size-variable(12),
161
+ font-weight: primitive.font-weight-variable(regular),
162
+ line-height: primitive.line-height-variable(functional),
163
+ letter-spacing: primitive.letter-spacing-variable(0),
164
+ ),
165
+ );
166
+
167
+ @function is-semantic-type-valid($type) {
168
+ @return list.includes($semantic-types, $type);
169
+ }
170
+
171
+ @function is-semantic-prop-valid($prop) {
172
+ @return list.includes($semantic-props, $prop);
173
+ }
174
+
175
+ // Get semantic typography CSS variable name
176
+ @function get-semantic-var-name($type, $prop) {
177
+ @return --#{$prefix}-#{$type}-#{$prop};
178
+ }
179
+
180
+ // Get semantic typography property value as CSS variable
181
+ @function prop($type, $prop) {
182
+ @if not is-semantic-type-valid($type) {
183
+ @error 'Invalid semantic type #{$type}. Please choose one of #{$semantic-types}';
184
+ }
185
+
186
+ @if not is-semantic-prop-valid($prop) {
187
+ @error 'Invalid property #{$prop}. Please choose one of #{$semantic-props}';
188
+ }
189
+
190
+ @return var(#{get-semantic-var-name($type, $prop)});
191
+ }
192
+
193
+ // Generate all semantic typography CSS variables
194
+ @mixin variables($typographies: ()) {
195
+ // Merge user typographies with default typographies
196
+ $merged-typographies: map.deep-merge($semantic-typographies, $typographies);
197
+
198
+ @each $type, $props in $merged-typographies {
199
+ @if not is-semantic-type-valid($type) {
200
+ @error 'Invalid semantic type #{$type}. Please choose one of #{$semantic-types}';
201
+ }
202
+
203
+ @each $prop, $value in $props {
204
+ @if not is-semantic-prop-valid($prop) {
205
+ @error 'Invalid property #{$prop}. Please choose one of #{$semantic-props}';
206
+ }
207
+
208
+ @if $value {
209
+ #{get-semantic-var-name($type, $prop)}: #{$value};
210
+ }
211
+ }
212
+ }
213
+ }
214
+
215
+ // Apply Semantic Typography Mixin
216
+ @mixin variable($type, $exclude-props: ()) {
217
+ @if not is-semantic-type-valid($type) {
218
+ @error 'Invalid semantic type #{$type}. Please choose one of #{$semantic-types}';
219
+ }
220
+
221
+ // Validate exclude props
222
+ @each $prop in $exclude-props {
223
+ @if not is-semantic-prop-valid($prop) {
224
+ @error 'Invalid property #{$prop}. Please choose one of #{$semantic-props}';
225
+ }
226
+ }
227
+
228
+ $typography: map.get($semantic-typographies, $type);
229
+
230
+ @each $prop in $semantic-props {
231
+ @if not list.includes($exclude-props, $prop) {
232
+ @if map.has-key($typography, $prop) {
233
+ #{$prop}: var(--#{$prefix}-#{$type}-#{$prop});
234
+ }
235
+ }
236
+ }
237
+ }