@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,480 @@
1
+ // =============================================================================
2
+ // fanUI · 导航 Navigation
3
+ // -----------------------------------------------------------------------------
4
+ // .fanui-navbar 顶部导航栏(含 brand / menu / actions / toggle)
5
+ // .fanui-nav 导航菜单(水平 / 垂直)
6
+ // .fanui-nav__item 菜单项(.is-active 选中态)
7
+ // .fanui-sidebar 侧边栏
8
+ // .fanui-breadcrumb 面包屑
9
+ // .fanui-menu 多级菜单(可嵌套)
10
+ // =============================================================================
11
+
12
+ @use "sass:map";
13
+ @use "../functions" as fn;
14
+ @use "../variables" as v;
15
+ @use "../mixins" as mx;
16
+
17
+ // -----------------------------------------------------------------------------
18
+ // 1. 顶部导航栏 Navbar
19
+ // -----------------------------------------------------------------------------
20
+
21
+ .fanui-navbar {
22
+ --fanui-navbar-height: 56px;
23
+ --fanui-navbar-bg: #{fn.fanui-var("color-surface")};
24
+ --fanui-navbar-border: #{fn.fanui-var("color-border")};
25
+
26
+ position: relative;
27
+ display: flex;
28
+ align-items: center;
29
+ gap: fn.fanui-var("space-4");
30
+ min-height: var(--fanui-navbar-height);
31
+ padding: 0 fn.fanui-var("container-px", 16px);
32
+ background-color: var(--fanui-navbar-bg);
33
+ border-bottom: 1px solid var(--fanui-navbar-border);
34
+ box-sizing: border-box;
35
+ z-index: fn.fanui-var("z-sticky", v.$fanui-zindex-sticky);
36
+
37
+ &--sticky {
38
+ position: sticky;
39
+ top: 0;
40
+ }
41
+
42
+ &--fixed {
43
+ position: fixed;
44
+ top: 0;
45
+ right: 0;
46
+ left: 0;
47
+ }
48
+
49
+ &--glass {
50
+ @include mx.fanui-glass(fn.fanui-alpha(#ffffff, 0.78), 14px);
51
+ border-bottom-color: fn.fanui-alpha(#0f172a, 0.06);
52
+
53
+ :root[data-fanui-theme="dark"] & {
54
+ @include mx.fanui-glass(fn.fanui-alpha(#0f172a, 0.72), 14px);
55
+ border-bottom-color: fn.fanui-alpha(#ffffff, 0.08);
56
+ }
57
+ }
58
+
59
+ &--dark {
60
+ --fanui-navbar-bg: #{fn.fanui-palette(v.$fanui-palette, "neutral", 900)};
61
+ --fanui-navbar-border: rgba(255, 255, 255, 0.08);
62
+ color: #f1f5f9;
63
+ }
64
+
65
+ &--borderless { border-bottom-color: transparent; }
66
+
67
+ &__inner {
68
+ display: flex;
69
+ align-items: center;
70
+ gap: fn.fanui-var("space-4");
71
+ width: 100%;
72
+ max-width: var(--fanui-navbar-max-width, none);
73
+ margin: 0 auto;
74
+ }
75
+
76
+ &__brand {
77
+ display: inline-flex;
78
+ align-items: center;
79
+ gap: fn.fanui-var("space-2");
80
+ flex: 0 0 auto;
81
+ font-size: fn.fanui-var("font-size-md");
82
+ font-weight: 700;
83
+ color: fn.fanui-var("color-text-strong");
84
+ text-decoration: none;
85
+ white-space: nowrap;
86
+ letter-spacing: -0.01em;
87
+
88
+ &:hover { text-decoration: none; }
89
+
90
+ img, svg { height: 24px; width: auto; }
91
+ }
92
+
93
+ &__menu {
94
+ display: flex;
95
+ align-items: center;
96
+ gap: fn.fanui-var("space-1");
97
+ flex: 1 1 auto;
98
+ min-width: 0;
99
+ }
100
+
101
+ &__actions {
102
+ display: flex;
103
+ align-items: center;
104
+ gap: fn.fanui-var("space-2");
105
+ flex: 0 0 auto;
106
+ margin-inline-start: auto;
107
+ }
108
+
109
+ &__toggle {
110
+ display: none;
111
+ flex: 0 0 auto;
112
+
113
+ @include mx.fanui-media-down("md") { display: inline-flex; }
114
+ }
115
+
116
+ &__divider {
117
+ width: 1px;
118
+ height: 20px;
119
+ background-color: fn.fanui-var("color-border");
120
+ flex: 0 0 auto;
121
+ }
122
+
123
+ // 响应式:窄屏菜单折叠
124
+ @include mx.fanui-media-down("md") {
125
+ &__menu {
126
+ display: none;
127
+
128
+ &.is-open {
129
+ display: flex;
130
+ position: absolute;
131
+ top: 100%;
132
+ left: 0;
133
+ right: 0;
134
+ flex-direction: column;
135
+ align-items: stretch;
136
+ padding: fn.fanui-var("space-2");
137
+ background-color: fn.fanui-var("color-surface");
138
+ border-bottom: 1px solid fn.fanui-var("color-border");
139
+ box-shadow: fn.fanui-var("shadow-lg");
140
+ }
141
+ }
142
+ }
143
+ }
144
+
145
+ // -----------------------------------------------------------------------------
146
+ // 2. 导航菜单 Nav
147
+ // -----------------------------------------------------------------------------
148
+
149
+ .fanui-nav {
150
+ display: flex;
151
+ align-items: center;
152
+ gap: fn.fanui-var("space-1");
153
+ list-style: none;
154
+ margin: 0;
155
+ padding: 0;
156
+
157
+ &--vertical {
158
+ flex-direction: column;
159
+ align-items: stretch;
160
+ }
161
+
162
+ &--pill {
163
+ padding: 3px;
164
+ background-color: fn.fanui-var("color-surface-sunken");
165
+ border-radius: fn.fanui-var("radius-md");
166
+ }
167
+
168
+ &--underline { gap: fn.fanui-var("space-5"); }
169
+ }
170
+
171
+ .fanui-nav__item {
172
+ position: relative;
173
+ display: inline-flex;
174
+ align-items: center;
175
+ gap: 8px;
176
+ padding: 8px 12px;
177
+ font-size: fn.fanui-var("font-size-base");
178
+ font-weight: 500;
179
+ line-height: 1.4;
180
+ color: fn.fanui-var("color-text-muted");
181
+ text-decoration: none;
182
+ border-radius: fn.fanui-var("radius-base");
183
+ cursor: pointer;
184
+ white-space: nowrap;
185
+ box-sizing: border-box;
186
+ @include mx.fanui-transition((color, background-color, border-color), v.$fanui-duration-fast);
187
+
188
+ &:hover {
189
+ color: fn.fanui-var("color-text-strong");
190
+ background-color: fn.fanui-var("color-hover");
191
+ text-decoration: none;
192
+ }
193
+
194
+ &:focus-visible { @include mx.fanui-focus-ring(); }
195
+
196
+ &.is-active,
197
+ &[aria-current="page"] {
198
+ color: fn.fanui-var("primary");
199
+ background-color: fn.fanui-var("primary-soft");
200
+ font-weight: 600;
201
+ }
202
+
203
+ &.is-disabled,
204
+ &[aria-disabled="true"] {
205
+ color: fn.fanui-var("color-disabled-text");
206
+ pointer-events: none;
207
+ cursor: not-allowed;
208
+ }
209
+
210
+ &__icon {
211
+ display: inline-flex;
212
+ flex: 0 0 auto;
213
+ font-size: 1.1em;
214
+ line-height: 1;
215
+ }
216
+
217
+ &__badge { margin-inline-start: auto; }
218
+
219
+ // 下划线风格
220
+ .fanui-nav--underline & {
221
+ padding: 10px 0;
222
+ background: none;
223
+ border-radius: 0;
224
+
225
+ &:hover { background: none; }
226
+
227
+ &::after {
228
+ content: "";
229
+ position: absolute;
230
+ left: 0;
231
+ right: 0;
232
+ bottom: -1px;
233
+ height: 2px;
234
+ background-color: transparent;
235
+ border-radius: 2px;
236
+ @include mx.fanui-transition(background-color, v.$fanui-duration-fast);
237
+ }
238
+
239
+ &.is-active::after,
240
+ &[aria-current="page"]::after {
241
+ background-color: fn.fanui-var("primary");
242
+ }
243
+ }
244
+
245
+ .fanui-nav--vertical & {
246
+ width: 100%;
247
+ justify-content: flex-start;
248
+ }
249
+
250
+ .fanui-nav--pill & {
251
+ &.is-active {
252
+ color: fn.fanui-var("color-text-strong");
253
+ background-color: fn.fanui-var("color-surface");
254
+ box-shadow: fn.fanui-var("shadow-xs");
255
+ }
256
+ }
257
+
258
+ &--sm { padding: 5px 9px; font-size: fn.fanui-var("font-size-sm"); }
259
+ &--lg { padding: 11px 16px; font-size: fn.fanui-var("font-size-md"); }
260
+ }
261
+
262
+ // -----------------------------------------------------------------------------
263
+ // 3. 侧边栏 Sidebar
264
+ // -----------------------------------------------------------------------------
265
+
266
+ .fanui-sidebar {
267
+ --fanui-sidebar-width: 240px;
268
+
269
+ display: flex;
270
+ flex-direction: column;
271
+ width: var(--fanui-sidebar-width);
272
+ flex: 0 0 auto;
273
+ padding: fn.fanui-var("space-4") fn.fanui-var("space-3");
274
+ gap: fn.fanui-var("space-1");
275
+ background-color: fn.fanui-var("color-surface");
276
+ border-inline-end: 1px solid fn.fanui-var("color-border");
277
+ box-sizing: border-box;
278
+ overflow-y: auto;
279
+ @include mx.fanui-scrollbar(8px);
280
+
281
+ &--end {
282
+ border-inline-end: 0;
283
+ border-inline-start: 1px solid fn.fanui-var("color-border");
284
+ }
285
+
286
+ &--sunken { background-color: fn.fanui-var("color-surface-sunken"); }
287
+ &--bordered-none { border: 0; }
288
+
289
+ &__section {
290
+ margin-top: fn.fanui-var("space-4");
291
+
292
+ &:first-child { margin-top: 0; }
293
+ }
294
+
295
+ &__title {
296
+ padding: fn.fanui-var("space-2") fn.fanui-var("space-3");
297
+ font-size: fn.fanui-var("font-size-xs");
298
+ font-weight: 600;
299
+ letter-spacing: 0.06em;
300
+ text-transform: uppercase;
301
+ color: fn.fanui-var("color-text-subtle");
302
+ }
303
+
304
+ &__item {
305
+ display: flex;
306
+ align-items: center;
307
+ gap: 10px;
308
+ width: 100%;
309
+ padding: 8px 12px;
310
+ font-size: fn.fanui-var("font-size-base");
311
+ color: fn.fanui-var("color-text-muted");
312
+ text-decoration: none;
313
+ border-radius: fn.fanui-var("radius-base");
314
+ cursor: pointer;
315
+ box-sizing: border-box;
316
+ @include mx.fanui-transition((color, background-color), v.$fanui-duration-fast);
317
+
318
+ &:hover {
319
+ color: fn.fanui-var("color-text-strong");
320
+ background-color: fn.fanui-var("color-hover");
321
+ text-decoration: none;
322
+ }
323
+
324
+ &.is-active {
325
+ color: fn.fanui-var("primary");
326
+ background-color: fn.fanui-var("primary-soft");
327
+ font-weight: 600;
328
+ }
329
+
330
+ &__icon { flex: 0 0 auto; display: inline-flex; width: 18px; justify-content: center; }
331
+ &__text { flex: 1 1 auto; min-width: 0; @include mx.fanui-truncate(1); }
332
+ &__badge { flex: 0 0 auto; }
333
+ &__arrow {
334
+ flex: 0 0 auto;
335
+ font-size: 12px;
336
+ opacity: 0.6;
337
+ @include mx.fanui-transition(transform, v.$fanui-duration-fast);
338
+ }
339
+ }
340
+
341
+ // 可折叠
342
+ &__item[aria-expanded="true"] .fanui-sidebar__item__arrow { transform: rotate(90deg); }
343
+
344
+ &__sub {
345
+ display: flex;
346
+ flex-direction: column;
347
+ gap: 2px;
348
+ padding-inline-start: fn.fanui-var("space-6");
349
+ margin-top: 2px;
350
+ }
351
+
352
+ &--collapsed { --fanui-sidebar-width: 64px; }
353
+
354
+ &--collapsed .fanui-sidebar__item {
355
+ justify-content: center;
356
+ padding: 10px 0;
357
+ }
358
+
359
+ &--collapsed .fanui-sidebar__item__text,
360
+ &--collapsed .fanui-sidebar__title,
361
+ &--collapsed .fanui-sidebar__item__badge,
362
+ &--collapsed .fanui-sidebar__item__arrow { display: none; }
363
+ }
364
+
365
+ // -----------------------------------------------------------------------------
366
+ // 4. 面包屑 Breadcrumb
367
+ // -----------------------------------------------------------------------------
368
+
369
+ .fanui-breadcrumb {
370
+ display: flex;
371
+ flex-wrap: wrap;
372
+ align-items: center;
373
+ gap: fn.fanui-var("space-2");
374
+ list-style: none;
375
+ margin: 0;
376
+ padding: 0;
377
+ font-size: fn.fanui-var("font-size-sm");
378
+ color: fn.fanui-var("color-text-muted");
379
+
380
+ &__item {
381
+ display: inline-flex;
382
+ align-items: center;
383
+ gap: fn.fanui-var("space-2");
384
+
385
+ a {
386
+ color: fn.fanui-var("color-text-muted");
387
+ text-decoration: none;
388
+
389
+ &:hover { color: fn.fanui-var("primary"); text-decoration: none; }
390
+ }
391
+ }
392
+
393
+ &__item + &__item::before,
394
+ &__separator {
395
+ content: "/";
396
+ color: fn.fanui-var("color-text-subtle");
397
+ user-select: none;
398
+ }
399
+
400
+ &__item.is-active,
401
+ &__item[aria-current="page"] {
402
+ color: fn.fanui-var("color-text-strong");
403
+ font-weight: 500;
404
+ }
405
+
406
+ &--arrow &__separator { content: "›"; }
407
+ &--chevron &__item + &__item::before { content: "›"; }
408
+ }
409
+
410
+ // -----------------------------------------------------------------------------
411
+ // 5. 多级菜单 Menu
412
+ // -----------------------------------------------------------------------------
413
+
414
+ .fanui-menu {
415
+ display: flex;
416
+ flex-direction: column;
417
+ gap: 2px;
418
+ list-style: none;
419
+ margin: 0;
420
+ padding: 0;
421
+ min-width: 160px;
422
+
423
+ &__item {
424
+ display: flex;
425
+ align-items: center;
426
+ gap: 10px;
427
+ padding: 7px 12px;
428
+ font-size: fn.fanui-var("font-size-base");
429
+ color: fn.fanui-var("color-text");
430
+ text-decoration: none;
431
+ border-radius: fn.fanui-var("radius-base");
432
+ cursor: pointer;
433
+ @include mx.fanui-transition((background-color, color), v.$fanui-duration-fast);
434
+
435
+ &:hover {
436
+ background-color: fn.fanui-var("color-hover");
437
+ text-decoration: none;
438
+ color: fn.fanui-var("color-text-strong");
439
+ }
440
+
441
+ &.is-active {
442
+ color: fn.fanui-var("primary");
443
+ background-color: fn.fanui-var("primary-soft");
444
+ }
445
+
446
+ &.is-disabled {
447
+ color: fn.fanui-var("color-disabled-text");
448
+ pointer-events: none;
449
+ }
450
+ }
451
+
452
+ &__label { flex: 1 1 auto; min-width: 0; @include mx.fanui-truncate(1); }
453
+
454
+ &__shortcut {
455
+ flex: 0 0 auto;
456
+ font-size: fn.fanui-var("font-size-xs");
457
+ color: fn.fanui-var("color-text-subtle");
458
+ font-family: fn.fanui-var("font-mono");
459
+ }
460
+
461
+ &__divider {
462
+ height: 1px;
463
+ margin: 5px 2px;
464
+ background-color: fn.fanui-var("color-border-subtle");
465
+ }
466
+
467
+ &__group-title {
468
+ padding: 8px 12px 4px;
469
+ font-size: fn.fanui-var("font-size-xs");
470
+ font-weight: 600;
471
+ color: fn.fanui-var("color-text-subtle");
472
+ text-transform: uppercase;
473
+ letter-spacing: 0.05em;
474
+ }
475
+
476
+ &--horizontal {
477
+ flex-direction: row;
478
+ align-items: center;
479
+ }
480
+ }