@zhang_jifan/fanui 2.1.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 (127) hide show
  1. package/ACCESSIBILITY.md +61 -0
  2. package/CHANGELOG.md +112 -0
  3. package/COMMERCIAL-LICENSE.md +71 -0
  4. package/DESIGN-SYSTEM.md +294 -0
  5. package/LICENSE +661 -0
  6. package/README.md +348 -0
  7. package/USAGE.md +1926 -0
  8. package/_index.scss +20 -0
  9. package/dist/fanui.cjs +15 -0
  10. package/dist/fanui.css +28209 -0
  11. package/dist/fanui.d.ts +353 -0
  12. package/dist/fanui.esm.js +71 -0
  13. package/dist/fanui.js +4782 -0
  14. package/dist/fanui.min.css +1 -0
  15. package/dist/fanui.mjs +71 -0
  16. package/dist/modules/fanui-advanced.css +830 -0
  17. package/dist/modules/fanui-advanced.min.css +129 -0
  18. package/dist/modules/fanui-alert.css +575 -0
  19. package/dist/modules/fanui-alert.min.css +122 -0
  20. package/dist/modules/fanui-badge.css +426 -0
  21. package/dist/modules/fanui-badge.min.css +77 -0
  22. package/dist/modules/fanui-base.css +1394 -0
  23. package/dist/modules/fanui-base.min.css +236 -0
  24. package/dist/modules/fanui-blog.css +762 -0
  25. package/dist/modules/fanui-blog.min.css +108 -0
  26. package/dist/modules/fanui-button.css +526 -0
  27. package/dist/modules/fanui-button.min.css +56 -0
  28. package/dist/modules/fanui-card.css +291 -0
  29. package/dist/modules/fanui-card.min.css +52 -0
  30. package/dist/modules/fanui-choice.css +539 -0
  31. package/dist/modules/fanui-choice.min.css +83 -0
  32. package/dist/modules/fanui-dashboard.css +1057 -0
  33. package/dist/modules/fanui-dashboard.min.css +160 -0
  34. package/dist/modules/fanui-data.css +687 -0
  35. package/dist/modules/fanui-data.min.css +125 -0
  36. package/dist/modules/fanui-feedback.css +432 -0
  37. package/dist/modules/fanui-feedback.min.css +79 -0
  38. package/dist/modules/fanui-form.css +779 -0
  39. package/dist/modules/fanui-form.min.css +123 -0
  40. package/dist/modules/fanui-glass.css +497 -0
  41. package/dist/modules/fanui-glass.min.css +46 -0
  42. package/dist/modules/fanui-input-plus.css +799 -0
  43. package/dist/modules/fanui-input-plus.min.css +124 -0
  44. package/dist/modules/fanui-interactive.css +960 -0
  45. package/dist/modules/fanui-interactive.min.css +138 -0
  46. package/dist/modules/fanui-layout.css +4399 -0
  47. package/dist/modules/fanui-layout.min.css +1172 -0
  48. package/dist/modules/fanui-marketing.css +1125 -0
  49. package/dist/modules/fanui-marketing.min.css +144 -0
  50. package/dist/modules/fanui-nav.css +458 -0
  51. package/dist/modules/fanui-nav.min.css +76 -0
  52. package/dist/modules/fanui-overlay.css +547 -0
  53. package/dist/modules/fanui-overlay.min.css +91 -0
  54. package/dist/modules/fanui-table.css +290 -0
  55. package/dist/modules/fanui-table.min.css +62 -0
  56. package/dist/modules/fanui-tabs.css +333 -0
  57. package/dist/modules/fanui-tabs.min.css +58 -0
  58. package/dist/modules/fanui-themes.css +2728 -0
  59. package/dist/modules/fanui-themes.min.css +40 -0
  60. package/dist/modules/fanui-tokens.css +587 -0
  61. package/dist/modules/fanui-tokens.min.css +3 -0
  62. package/dist/modules/fanui-utilities.css +6557 -0
  63. package/dist/modules/fanui-utilities.min.css +1762 -0
  64. package/dist/modules/sizes.json +103 -0
  65. package/docs/MIGRATION-v2.md +179 -0
  66. package/examples/01-script-tag.html +149 -0
  67. package/examples/02-react/README.md +39 -0
  68. package/examples/02-react/index.html +12 -0
  69. package/examples/02-react/package.json +20 -0
  70. package/examples/02-react/src/App.jsx +108 -0
  71. package/examples/02-react/src/main.jsx +13 -0
  72. package/examples/02-react/src/useFanUI.js +87 -0
  73. package/examples/02-react/vite.config.js +6 -0
  74. package/examples/03-vue3/README.md +67 -0
  75. package/examples/03-vue3/index.html +12 -0
  76. package/examples/03-vue3/package.json +19 -0
  77. package/examples/03-vue3/src/App.vue +93 -0
  78. package/examples/03-vue3/src/main.js +8 -0
  79. package/examples/03-vue3/src/useFanUI.js +85 -0
  80. package/examples/03-vue3/vite.config.js +6 -0
  81. package/examples/04-vue2-cdn.html +93 -0
  82. package/examples/README.md +34 -0
  83. package/package.json +127 -0
  84. package/src/_functions.scss +319 -0
  85. package/src/_mixins.scss +1202 -0
  86. package/src/_tokens.scss +180 -0
  87. package/src/_variables.scss +491 -0
  88. package/src/base/_animations.scss +210 -0
  89. package/src/base/_reset.scss +359 -0
  90. package/src/base/_rtl.scss +133 -0
  91. package/src/base/_typography.scss +353 -0
  92. package/src/components/_advanced.scss +763 -0
  93. package/src/components/_alert.scss +322 -0
  94. package/src/components/_badge.scss +279 -0
  95. package/src/components/_blog.scss +693 -0
  96. package/src/components/_button.scss +351 -0
  97. package/src/components/_capabilities.scss +463 -0
  98. package/src/components/_card.scss +281 -0
  99. package/src/components/_choice.scss +444 -0
  100. package/src/components/_dashboard.scss +950 -0
  101. package/src/components/_data.scss +618 -0
  102. package/src/components/_feedback.scss +403 -0
  103. package/src/components/_form.scss +408 -0
  104. package/src/components/_glass.scss +374 -0
  105. package/src/components/_input-plus.scss +730 -0
  106. package/src/components/_interactive.scss +885 -0
  107. package/src/components/_marketing.scss +982 -0
  108. package/src/components/_nav.scss +480 -0
  109. package/src/components/_overlay.scss +517 -0
  110. package/src/components/_table.scss +276 -0
  111. package/src/components/_tabs.scss +338 -0
  112. package/src/fanui.d.ts +353 -0
  113. package/src/fanui.js +4782 -0
  114. package/src/fanui.scss +79 -0
  115. package/src/glass/_switches.scss +36 -0
  116. package/src/glass/_tokens.scss +259 -0
  117. package/src/layout/_container.scss +111 -0
  118. package/src/layout/_flex.scss +164 -0
  119. package/src/layout/_grid.scss +180 -0
  120. package/src/themes/_accents.scss +201 -0
  121. package/src/themes/_palettes.scss +180 -0
  122. package/src/utilities/_borders.scss +104 -0
  123. package/src/utilities/_display.scss +145 -0
  124. package/src/utilities/_effects.scss +210 -0
  125. package/src/utilities/_sizing.scss +123 -0
  126. package/src/utilities/_spacing.scss +118 -0
  127. package/src/utilities/_texture.scss +323 -0
@@ -0,0 +1,403 @@
1
+ // =============================================================================
2
+ // fanUI · 反馈类组件:进度条 / 加载 / 骨架屏 / 空状态
3
+ // =============================================================================
4
+
5
+ @use "sass:map";
6
+ @use "../functions" as fn;
7
+ @use "../variables" as v;
8
+ @use "../mixins" as mx;
9
+
10
+ // -----------------------------------------------------------------------------
11
+ // 1. 进度条 Progress
12
+ // -----------------------------------------------------------------------------
13
+
14
+ .fanui-progress {
15
+ --fanui-progress-h: 8px;
16
+ --fanui-progress-radius: var(--fanui-radius-full);
17
+ --fanui-progress-track: #{fn.fanui-var("color-surface-sunken")};
18
+ --fanui-progress-bar: #{fn.fanui-var("primary")};
19
+
20
+ position: relative;
21
+ display: flex;
22
+ width: 100%;
23
+ height: var(--fanui-progress-h);
24
+ overflow: hidden;
25
+ background-color: var(--fanui-progress-track);
26
+ border-radius: var(--fanui-progress-radius);
27
+ box-sizing: border-box;
28
+
29
+ &__bar {
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: flex-end;
33
+ width: 0;
34
+ height: 100%;
35
+ background-color: var(--fanui-progress-bar);
36
+ border-radius: inherit;
37
+ @include mx.fanui-transition(width, v.$fanui-duration-slow, v.$fanui-ease-out);
38
+ }
39
+
40
+ &__label {
41
+ padding: 0 6px;
42
+ font-size: 10px;
43
+ font-weight: 600;
44
+ line-height: 1;
45
+ color: fn.fanui-var("color-text-inverse");
46
+ white-space: nowrap;
47
+ }
48
+
49
+ // 尺寸
50
+ &--xs { --fanui-progress-h: 3px; }
51
+ &--sm { --fanui-progress-h: 5px; }
52
+ &--lg { --fanui-progress-h: 12px; }
53
+ &--xl { --fanui-progress-h: 18px; }
54
+
55
+ // 条纹 / 动画
56
+ &--striped .fanui-progress__bar {
57
+ background-image: linear-gradient(
58
+ 45deg,
59
+ rgba(255, 255, 255, 0.2) 25%, transparent 25%,
60
+ transparent 50%, rgba(255, 255, 255, 0.2) 50%,
61
+ rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent
62
+ );
63
+ background-size: 1rem 1rem;
64
+ }
65
+
66
+ &--animated .fanui-progress__bar {
67
+ animation: fanui-progress-stripes 1s linear infinite;
68
+ }
69
+
70
+ // 不确定进度
71
+ &--indeterminate .fanui-progress__bar {
72
+ position: absolute;
73
+ top: 0;
74
+ bottom: 0;
75
+ width: 35%;
76
+ animation: fanui-progress-indeterminate 1.6s v.$fanui-ease-in-out infinite;
77
+ }
78
+
79
+ // 语义色
80
+ @each $name, $color in v.$fanui-theme-colors {
81
+ &--#{$name} { --fanui-progress-bar: #{fn.fanui-var("#{$name}", $color)}; }
82
+ }
83
+
84
+ &--neutral { --fanui-progress-bar: #{fn.fanui-var("color-text-muted")}; }
85
+ }
86
+
87
+ // 带文字的进度行
88
+ .fanui-progress-line {
89
+ display: flex;
90
+ align-items: center;
91
+ gap: fn.fanui-var("space-3");
92
+
93
+ .fanui-progress { flex: 1 1 auto; }
94
+
95
+ &__text {
96
+ flex: 0 0 auto;
97
+ min-width: 40px;
98
+ font-size: fn.fanui-var("font-size-sm");
99
+ color: fn.fanui-var("color-text-muted");
100
+ text-align: end;
101
+ font-variant-numeric: tabular-nums;
102
+ }
103
+ }
104
+
105
+ // 环形进度(基于 conic-gradient)
106
+ .fanui-progress-ring {
107
+ --fanui-ring-size: 56px;
108
+ --fanui-ring-width: 6px;
109
+ --fanui-ring-value: 0;
110
+ --fanui-ring-color: #{fn.fanui-var("primary")};
111
+
112
+ position: relative;
113
+ display: inline-flex;
114
+ align-items: center;
115
+ justify-content: center;
116
+ width: var(--fanui-ring-size);
117
+ height: var(--fanui-ring-size);
118
+ border-radius: 50%;
119
+ background: conic-gradient(
120
+ var(--fanui-ring-color) calc(var(--fanui-ring-value) * 1%),
121
+ fn.fanui-var("color-surface-sunken") 0
122
+ );
123
+
124
+ &::before {
125
+ content: "";
126
+ position: absolute;
127
+ inset: var(--fanui-ring-width);
128
+ border-radius: 50%;
129
+ background-color: fn.fanui-var("color-surface");
130
+ }
131
+
132
+ &__text {
133
+ position: relative;
134
+ font-size: fn.fanui-var("font-size-sm");
135
+ font-weight: 600;
136
+ color: fn.fanui-var("color-text-strong");
137
+ font-variant-numeric: tabular-nums;
138
+ }
139
+
140
+ &--sm { --fanui-ring-size: 40px; --fanui-ring-width: 4px; }
141
+ &--lg { --fanui-ring-size: 80px; --fanui-ring-width: 8px; }
142
+ }
143
+
144
+ // -----------------------------------------------------------------------------
145
+ // 2. 加载指示器 Spinner / Loading
146
+ // -----------------------------------------------------------------------------
147
+
148
+ .fanui-spinner {
149
+ --fanui-spinner-size: 20px;
150
+ --fanui-spinner-width: 2px;
151
+ --fanui-spinner-color: currentColor;
152
+
153
+ display: inline-block;
154
+ width: var(--fanui-spinner-size);
155
+ height: var(--fanui-spinner-size);
156
+ border: var(--fanui-spinner-width) solid fn.fanui-alpha(#64748b, 0.25);
157
+ border-top-color: var(--fanui-spinner-color);
158
+ border-radius: 50%;
159
+ animation: fanui-spin 720ms linear infinite;
160
+ box-sizing: border-box;
161
+ flex: 0 0 auto;
162
+
163
+ @each $name, $color in v.$fanui-theme-colors {
164
+ &--#{$name} { --fanui-spinner-color: #{fn.fanui-var("#{$name}", $color)}; }
165
+ }
166
+
167
+ &--xs { --fanui-spinner-size: 12px; --fanui-spinner-width: 2px; }
168
+ &--sm { --fanui-spinner-size: 16px; --fanui-spinner-width: 2px; }
169
+ &--lg { --fanui-spinner-size: 28px; --fanui-spinner-width: 3px; }
170
+ &--xl { --fanui-spinner-size: 40px; --fanui-spinner-width: 4px; }
171
+
172
+ // 点状加载
173
+ &--dots {
174
+ width: auto;
175
+ height: auto;
176
+ border: 0;
177
+ animation: none;
178
+ display: inline-flex;
179
+ gap: 5px;
180
+
181
+ &::before,
182
+ &::after,
183
+ > i {
184
+ content: "";
185
+ display: block;
186
+ width: 6px;
187
+ height: 6px;
188
+ border-radius: 50%;
189
+ background-color: var(--fanui-spinner-color);
190
+ animation: fanui-bounce 1.2s v.$fanui-ease-in-out infinite;
191
+ }
192
+
193
+ &::after { animation-delay: 0.15s; }
194
+ > i { animation-delay: 0.3s; }
195
+ }
196
+
197
+ // 三段脉冲
198
+ &--pulse {
199
+ border: 0;
200
+ animation: fanui-pulse 1.4s v.$fanui-ease-in-out infinite;
201
+ background-color: var(--fanui-spinner-color);
202
+ border-radius: 50%;
203
+ }
204
+ }
205
+
206
+ // 加载遮罩(局部区域)
207
+ .fanui-loading {
208
+ position: relative;
209
+
210
+ &__mask {
211
+ position: absolute;
212
+ inset: 0;
213
+ z-index: 10;
214
+ display: flex;
215
+ flex-direction: column;
216
+ align-items: center;
217
+ justify-content: center;
218
+ gap: fn.fanui-var("space-3");
219
+ color: fn.fanui-var("color-text-muted");
220
+ font-size: fn.fanui-var("font-size-sm");
221
+ background-color: fn.fanui-alpha(#ffffff, 0.72);
222
+ backdrop-filter: blur(1px);
223
+ border-radius: inherit;
224
+
225
+ :root[data-fanui-theme="dark"] & { background-color: fn.fanui-alpha(#020617, 0.62); }
226
+ }
227
+
228
+ &.is-loading { pointer-events: none; }
229
+ }
230
+
231
+ // 骨架屏
232
+ .fanui-skeleton {
233
+ --fanui-skeleton-bg: #{fn.fanui-var("color-surface-sunken")};
234
+ --fanui-skeleton-shine: #{fn.fanui-alpha(#ffffff, 0.55)};
235
+
236
+ display: block;
237
+ width: 100%;
238
+ height: 1em;
239
+ border-radius: fn.fanui-var("radius-base");
240
+ background-color: var(--fanui-skeleton-bg);
241
+ background-image: linear-gradient(
242
+ 90deg,
243
+ transparent 0%,
244
+ var(--fanui-skeleton-shine) 50%,
245
+ transparent 100%
246
+ );
247
+ background-size: 200% 100%;
248
+ background-repeat: no-repeat;
249
+ animation: fanui-skeleton-shimmer 1.6s ease-in-out infinite;
250
+
251
+ :root[data-fanui-theme="dark"] & { --fanui-skeleton-shine: #{fn.fanui-alpha(#ffffff, 0.08)}; }
252
+
253
+ &--text { height: 1em; border-radius: fn.fanui-var("radius-sm"); }
254
+ &--title { height: 1.4em; width: 40%; border-radius: fn.fanui-var("radius-sm"); }
255
+ &--circle { width: 40px; height: 40px; border-radius: 50%; flex: 0 0 auto; }
256
+ &--rect { height: 120px; border-radius: fn.fanui-var("radius-md"); }
257
+ &--button { height: 32px; width: 88px; border-radius: fn.fanui-var("radius-base"); }
258
+
259
+ &--w-25 { width: 25%; }
260
+ &--w-50 { width: 50%; }
261
+ &--w-75 { width: 75%; }
262
+ &--w-100 { width: 100%; }
263
+
264
+ &--no-anim { animation: none; background-image: none; }
265
+ }
266
+
267
+ .fanui-skeleton-group {
268
+ display: flex;
269
+ flex-direction: column;
270
+ gap: fn.fanui-var("space-2");
271
+ }
272
+
273
+ .fanui-skeleton-media {
274
+ display: flex;
275
+ gap: fn.fanui-var("space-3");
276
+ align-items: flex-start;
277
+ }
278
+
279
+ // -----------------------------------------------------------------------------
280
+ // 3. 空状态 Empty
281
+ // -----------------------------------------------------------------------------
282
+
283
+ .fanui-empty {
284
+ display: flex;
285
+ flex-direction: column;
286
+ align-items: center;
287
+ justify-content: center;
288
+ gap: fn.fanui-var("space-3");
289
+ padding: fn.fanui-var("space-12") fn.fanui-var("space-5");
290
+ text-align: center;
291
+ color: fn.fanui-var("color-text-muted");
292
+
293
+ &__icon {
294
+ display: flex;
295
+ align-items: center;
296
+ justify-content: center;
297
+ width: 64px;
298
+ height: 64px;
299
+ margin-bottom: fn.fanui-var("space-1");
300
+ font-size: 28px;
301
+ color: fn.fanui-var("color-text-subtle");
302
+ background-color: fn.fanui-var("color-surface-sunken");
303
+ border-radius: 50%;
304
+ }
305
+
306
+ &__title {
307
+ margin: 0;
308
+ font-size: fn.fanui-var("font-size-md");
309
+ font-weight: 600;
310
+ color: fn.fanui-var("color-text-strong");
311
+ }
312
+
313
+ &__desc {
314
+ margin: 0;
315
+ max-width: 380px;
316
+ font-size: fn.fanui-var("font-size-base");
317
+ line-height: 1.6;
318
+ color: fn.fanui-var("color-text-muted");
319
+ }
320
+
321
+ &__actions {
322
+ display: flex;
323
+ align-items: center;
324
+ gap: fn.fanui-var("space-3");
325
+ margin-top: fn.fanui-var("space-2");
326
+ }
327
+
328
+ &--sm { padding: fn.fanui-var("space-6") fn.fanui-var("space-4"); }
329
+ &--inline { flex-direction: row; justify-content: flex-start; text-align: start; padding: fn.fanui-var("space-4"); }
330
+ }
331
+
332
+ // -----------------------------------------------------------------------------
333
+ // 4. 结果页 Result
334
+ // -----------------------------------------------------------------------------
335
+
336
+ .fanui-result {
337
+ display: flex;
338
+ flex-direction: column;
339
+ align-items: center;
340
+ gap: fn.fanui-var("space-3");
341
+ padding: fn.fanui-var("space-12") fn.fanui-var("space-5");
342
+ text-align: center;
343
+
344
+ &__icon {
345
+ display: flex;
346
+ align-items: center;
347
+ justify-content: center;
348
+ width: 56px;
349
+ height: 56px;
350
+ font-size: 26px;
351
+ border-radius: 50%;
352
+ color: fn.fanui-var("color-surface");
353
+ background-color: fn.fanui-var("color-text-muted");
354
+ }
355
+
356
+ &__title {
357
+ font-size: fn.fanui-var("font-size-xl");
358
+ font-weight: 600;
359
+ color: fn.fanui-var("color-text-strong");
360
+ }
361
+
362
+ &__desc {
363
+ max-width: 440px;
364
+ font-size: fn.fanui-var("font-size-base");
365
+ color: fn.fanui-var("color-text-muted");
366
+ }
367
+
368
+ @each $name, $color in v.$fanui-theme-colors {
369
+ &--#{$name} .fanui-result__icon { background-color: #{fn.fanui-var("#{$name}", $color)}; }
370
+ }
371
+ }
372
+
373
+ // -----------------------------------------------------------------------------
374
+ // 5. 分隔加载线(顶部进度条)
375
+ // -----------------------------------------------------------------------------
376
+
377
+ .fanui-top-progress {
378
+ position: fixed;
379
+ top: 0;
380
+ left: 0;
381
+ right: 0;
382
+ height: 2px;
383
+ z-index: fn.fanui-var("z-toast", v.$fanui-zindex-toast);
384
+ background-color: transparent;
385
+ overflow: hidden;
386
+ opacity: 0;
387
+ @include mx.fanui-transition(opacity, v.$fanui-duration-fast);
388
+
389
+ &.is-active {
390
+ opacity: 1;
391
+
392
+ &::after {
393
+ content: "";
394
+ position: absolute;
395
+ top: 0;
396
+ bottom: 0;
397
+ width: 40%;
398
+ background-color: fn.fanui-var("primary");
399
+ border-radius: 9999px;
400
+ animation: fanui-progress-indeterminate 1.4s v.$fanui-ease-in-out infinite;
401
+ }
402
+ }
403
+ }