@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,408 @@
1
+ // =============================================================================
2
+ // fanUI · 表单体系(输入框 / 文本域 / 选择器 / 校验 / 表单布局)
3
+ // -----------------------------------------------------------------------------
4
+ // .fanui-form 表单块
5
+ // .fanui-form-item 表单项(标签 + 控件 + 反馈)
6
+ // .fanui-form-label 标签
7
+ // .fanui-form-control 输入框(input)
8
+ // .fanui-textarea 文本域
9
+ // .fanui-select 下拉选择
10
+ // .fanui-input-group 输入框组合(前后缀/按钮)
11
+ // .fanui-form-feedback 反馈文本(help / error)
12
+ // .fanui-form-item--error|--success|--warning
13
+ // 尺寸:.fanui-form-control--xs|sm|md|lg|xl
14
+ // =============================================================================
15
+
16
+ @use "sass:map";
17
+ @use "../functions" as fn;
18
+ @use "../variables" as v;
19
+ @use "../mixins" as mx;
20
+
21
+ // -----------------------------------------------------------------------------
22
+ // 1. 表单容器
23
+ // -----------------------------------------------------------------------------
24
+
25
+ .fanui-form {
26
+ display: block;
27
+ }
28
+
29
+ .fanui-form-item {
30
+ margin-bottom: fn.fanui-var("space-5");
31
+
32
+ &:last-child { margin-bottom: 0; }
33
+ }
34
+
35
+ // 水平布局
36
+ .fanui-form--horizontal .fanui-form-item {
37
+ display: flex;
38
+ align-items: flex-start;
39
+ gap: fn.fanui-var("space-4");
40
+
41
+ > .fanui-form-label {
42
+ flex: 0 0 auto;
43
+ width: var(--fanui-form-label-width, 120px);
44
+ padding-top: 8px;
45
+ margin-bottom: 0;
46
+ text-align: end;
47
+ }
48
+
49
+ > .fanui-form-content {
50
+ flex: 1 1 auto;
51
+ min-width: 0;
52
+ }
53
+ }
54
+
55
+ @include mx.fanui-media-down("sm") {
56
+ .fanui-form--horizontal .fanui-form-item {
57
+ display: block;
58
+
59
+ > .fanui-form-label {
60
+ width: auto;
61
+ text-align: start;
62
+ padding-top: 0;
63
+ margin-bottom: fn.fanui-var("space-2");
64
+ }
65
+ }
66
+ }
67
+
68
+ // 内联表单
69
+ .fanui-form--inline {
70
+ display: flex;
71
+ flex-wrap: wrap;
72
+ align-items: flex-end;
73
+ gap: fn.fanui-var("space-4");
74
+
75
+ .fanui-form-item {
76
+ margin-bottom: 0;
77
+ flex: 0 1 auto;
78
+ }
79
+ }
80
+
81
+ // -----------------------------------------------------------------------------
82
+ // 2. 标签
83
+ // -----------------------------------------------------------------------------
84
+
85
+ .fanui-form-label,
86
+ .fanui-label {
87
+ display: inline-block;
88
+ margin-bottom: fn.fanui-var("space-2");
89
+ font-size: fn.fanui-var("font-size-base");
90
+ font-weight: 500;
91
+ line-height: 1.5;
92
+ color: fn.fanui-var("color-text");
93
+
94
+ &--required::after,
95
+ &.is-required::after {
96
+ content: "*";
97
+ margin-inline-start: 4px;
98
+ color: fn.fanui-var("danger");
99
+ }
100
+
101
+ &--optional::after {
102
+ content: "(选填)";
103
+ margin-inline-start: 6px;
104
+ font-weight: 400;
105
+ color: fn.fanui-var("color-text-subtle");
106
+ font-size: fn.fanui-var("font-size-xs");
107
+ }
108
+ }
109
+
110
+ .fanui-form-help {
111
+ display: block;
112
+ margin-top: fn.fanui-var("space-1");
113
+ font-size: fn.fanui-var("font-size-sm");
114
+ line-height: 1.5;
115
+ color: fn.fanui-var("color-text-muted");
116
+ }
117
+
118
+ // -----------------------------------------------------------------------------
119
+ // 3. 输入框 / 文本域
120
+ // -----------------------------------------------------------------------------
121
+
122
+ .fanui-form-control {
123
+ @include mx.fanui-form-control();
124
+ }
125
+
126
+ textarea.fanui-form-control,
127
+ .fanui-textarea {
128
+ min-height: 88px;
129
+ padding-top: 8px;
130
+ padding-bottom: 8px;
131
+ line-height: fn.fanui-var("line-height-base");
132
+ resize: vertical;
133
+ }
134
+
135
+ // -----------------------------------------------------------------------------
136
+ // 4. 尺寸变体
137
+ // -----------------------------------------------------------------------------
138
+
139
+ // 说明:$font-size 参与高度内边距计算,必须传入具体数值(不可用 CSS 变量)
140
+ .fanui-form-control--xs, .fanui-textarea--xs, .fanui-select--xs { @include mx.fanui-form-control(24px, 8px, map.get(v.$fanui-font-sizes, "xs"), v.$fanui-radius-sm); }
141
+ .fanui-form-control--sm, .fanui-textarea--sm, .fanui-select--sm { @include mx.fanui-form-control(28px, 10px, map.get(v.$fanui-font-sizes, "sm"), v.$fanui-radius-sm); }
142
+ .fanui-form-control--md, .fanui-textarea--md, .fanui-select--md { @include mx.fanui-form-control(32px, 12px, map.get(v.$fanui-font-sizes, "base"), v.$fanui-radius-base); }
143
+ .fanui-form-control--lg, .fanui-textarea--lg, .fanui-select--lg { @include mx.fanui-form-control(40px, 16px, map.get(v.$fanui-font-sizes, "md"), v.$fanui-radius-md); }
144
+ .fanui-form-control--xl, .fanui-textarea--xl, .fanui-select--xl { @include mx.fanui-form-control(48px, 20px, map.get(v.$fanui-font-sizes, "lg"), v.$fanui-radius-md); }
145
+
146
+ // 无边框 / 下划线风格
147
+ .fanui-form-control--flush {
148
+ border-color: transparent;
149
+ background-color: transparent;
150
+ border-radius: 0;
151
+
152
+ &:hover:not(:disabled) { border-color: transparent; background-color: fn.fanui-var("color-hover"); }
153
+ &:focus { border-color: transparent; box-shadow: none; background-color: fn.fanui-var("color-surface"); }
154
+ }
155
+
156
+ .fanui-form-control--underline {
157
+ border-width: 0 0 1px 0;
158
+ border-radius: 0;
159
+ background-color: transparent;
160
+ padding-inline-start: 0;
161
+ padding-inline-end: 0;
162
+
163
+ &:focus { box-shadow: none; border-bottom-color: fn.fanui-var("primary"); }
164
+ }
165
+
166
+ // 只读 / 纯文本
167
+ .fanui-form-control-plaintext {
168
+ display: block;
169
+ width: 100%;
170
+ padding-top: 8px;
171
+ padding-bottom: 8px;
172
+ font-size: fn.fanui-var("font-size-base");
173
+ line-height: 1.5;
174
+ color: fn.fanui-var("color-text");
175
+ background-color: transparent;
176
+ border: 1px solid transparent;
177
+ }
178
+
179
+ // -----------------------------------------------------------------------------
180
+ // 5. 输入框组合(前缀/后缀/按钮)
181
+ // -----------------------------------------------------------------------------
182
+
183
+ .fanui-input-group {
184
+ display: flex;
185
+ align-items: stretch;
186
+ width: 100%;
187
+
188
+ > .fanui-form-control,
189
+ > .fanui-select {
190
+ flex: 1 1 auto;
191
+ width: 1%;
192
+ min-width: 0;
193
+ }
194
+
195
+ > .fanui-input-group__text,
196
+ > .fanui-input-group__icon {
197
+ display: flex;
198
+ align-items: center;
199
+ justify-content: center;
200
+ gap: 6px;
201
+ padding: 0 fn.fanui-var("control-px", 14px);
202
+ font-size: fn.fanui-var("font-size-base");
203
+ color: fn.fanui-var("color-text-muted");
204
+ background-color: fn.fanui-var("color-surface-sunken");
205
+ border: 1px solid fn.fanui-var("color-border");
206
+ white-space: nowrap;
207
+ flex: 0 0 auto;
208
+ }
209
+
210
+ > .fanui-input-group__icon { padding: 0 10px; }
211
+
212
+ // 圆角处理:首尾元素
213
+ > :first-child:not(:last-child) {
214
+ border-start-end-radius: 0;
215
+ border-end-end-radius: 0;
216
+ }
217
+
218
+ > :last-child:not(:first-child) {
219
+ border-start-start-radius: 0;
220
+ border-end-start-radius: 0;
221
+ }
222
+
223
+ > * + * { margin-inline-start: -1px; }
224
+
225
+ > .fanui-btn { flex: 0 0 auto; }
226
+
227
+ &:focus-within > .fanui-form-control {
228
+ border-color: fn.fanui-var("primary");
229
+ z-index: 2;
230
+ }
231
+ }
232
+
233
+ // 搜索框
234
+ .fanui-search {
235
+ position: relative;
236
+ display: block;
237
+
238
+ > .fanui-form-control {
239
+ padding-inline-start: 36px;
240
+ padding-inline-end: 36px;
241
+ }
242
+
243
+ &__icon {
244
+ position: absolute;
245
+ top: 50%;
246
+ left: 12px;
247
+ transform: translateY(-50%);
248
+ display: flex;
249
+ color: fn.fanui-var("color-text-subtle");
250
+ pointer-events: none;
251
+ }
252
+
253
+ &__clear {
254
+ position: absolute;
255
+ top: 50%;
256
+ right: 10px;
257
+ transform: translateY(-50%);
258
+ display: flex;
259
+ padding: 2px;
260
+ color: fn.fanui-var("color-text-subtle");
261
+ background: none;
262
+ border: 0;
263
+ border-radius: 50%;
264
+ cursor: pointer;
265
+
266
+ &:hover { color: fn.fanui-var("color-text"); background-color: fn.fanui-var("color-hover"); }
267
+ }
268
+ }
269
+
270
+ // 字数统计
271
+ .fanui-form-counter {
272
+ display: block;
273
+ margin-top: fn.fanui-var("space-1");
274
+ font-size: fn.fanui-var("font-size-xs");
275
+ color: fn.fanui-var("color-text-subtle");
276
+ text-align: end;
277
+
278
+ &.is-limit { color: fn.fanui-var("danger"); }
279
+ }
280
+
281
+ // -----------------------------------------------------------------------------
282
+ // 6. 校验状态
283
+ // -----------------------------------------------------------------------------
284
+
285
+ .fanui-form-feedback {
286
+ display: block;
287
+ margin-top: fn.fanui-var("space-1");
288
+ font-size: fn.fanui-var("font-size-sm");
289
+ line-height: 1.5;
290
+ color: fn.fanui-var("color-text-muted");
291
+
292
+ &::before { content: ""; }
293
+ &:empty { display: none; }
294
+ }
295
+
296
+ .fanui-form-item--error { @include mx.fanui-form-validation(v.$fanui-danger); .fanui-form-feedback { color: fn.fanui-var("danger"); } }
297
+ .fanui-form-item--success { @include mx.fanui-form-validation(v.$fanui-success); .fanui-form-feedback { color: fn.fanui-var("success"); } }
298
+ .fanui-form-item--warning { @include mx.fanui-form-validation(v.$fanui-warning); .fanui-form-feedback { color: fn.fanui-var("warning"); } }
299
+
300
+ // 独立工具类(不依赖父级)
301
+ .fanui-is-invalid,
302
+ .fanui-is-error {
303
+ border-color: fn.fanui-var("danger") !important;
304
+
305
+ &:focus,
306
+ &:focus-visible {
307
+ box-shadow: 0 0 0 3px fn.fanui-var("danger-ring") !important;
308
+ }
309
+ }
310
+
311
+ .fanui-is-valid,
312
+ .fanui-is-success {
313
+ border-color: fn.fanui-var("success") !important;
314
+
315
+ &:focus,
316
+ &:focus-visible {
317
+ box-shadow: 0 0 0 3px fn.fanui-var("success-ring") !important;
318
+ }
319
+ }
320
+
321
+ .fanui-shake { animation: fanui-shake 420ms v.$fanui-ease-in-out both; }
322
+
323
+ // -----------------------------------------------------------------------------
324
+ // 7. 文件上传
325
+ // -----------------------------------------------------------------------------
326
+
327
+ .fanui-file {
328
+ display: flex;
329
+ align-items: center;
330
+ gap: fn.fanui-var("space-3");
331
+ padding: fn.fanui-var("space-3") fn.fanui-var("space-4");
332
+ border: 1px dashed fn.fanui-var("color-border-strong");
333
+ border-radius: fn.fanui-var("radius-md");
334
+ background-color: fn.fanui-var("color-surface-sunken");
335
+ cursor: pointer;
336
+ @include mx.fanui-transition((border-color, background-color), v.$fanui-duration-fast);
337
+
338
+ &:hover {
339
+ border-color: fn.fanui-var("primary");
340
+ background-color: fn.fanui-var("primary-soft");
341
+ }
342
+
343
+ input[type="file"] { @include mx.fanui-visually-hidden(); }
344
+ }
345
+
346
+ .fanui-dropzone {
347
+ display: flex;
348
+ flex-direction: column;
349
+ align-items: center;
350
+ justify-content: center;
351
+ gap: fn.fanui-var("space-2");
352
+ padding: fn.fanui-var("space-8") fn.fanui-var("space-4");
353
+ text-align: center;
354
+ border: 2px dashed fn.fanui-var("color-border-strong");
355
+ border-radius: fn.fanui-var("radius-lg");
356
+ color: fn.fanui-var("color-text-muted");
357
+ background-color: fn.fanui-var("color-surface-sunken");
358
+ cursor: pointer;
359
+ @include mx.fanui-transition((border-color, background-color, color), v.$fanui-duration-fast);
360
+
361
+ // 隐藏原生文件选择控件(保留键盘可达性)
362
+ input[type="file"] { @include mx.fanui-visually-hidden($focusable: true); }
363
+
364
+ &.is-dragover,
365
+ &:hover {
366
+ border-color: fn.fanui-var("primary");
367
+ background-color: fn.fanui-var("primary-soft");
368
+ color: fn.fanui-var("primary");
369
+ }
370
+ }
371
+
372
+ // -----------------------------------------------------------------------------
373
+ // 8. 表单区块(fieldset 风格)
374
+ // -----------------------------------------------------------------------------
375
+
376
+ .fanui-form-section {
377
+ padding: fn.fanui-var("space-5");
378
+ border: 1px solid fn.fanui-var("color-border");
379
+ border-radius: fn.fanui-var("radius-lg");
380
+ background-color: fn.fanui-var("color-surface");
381
+
382
+ &__title {
383
+ margin-bottom: fn.fanui-var("space-1");
384
+ font-size: fn.fanui-var("font-size-md");
385
+ font-weight: 600;
386
+ color: fn.fanui-var("color-text-strong");
387
+ }
388
+
389
+ &__desc {
390
+ margin-bottom: fn.fanui-var("space-5");
391
+ font-size: fn.fanui-var("font-size-sm");
392
+ color: fn.fanui-var("color-text-muted");
393
+ }
394
+ }
395
+
396
+ // 表单操作区
397
+ .fanui-form-actions {
398
+ display: flex;
399
+ align-items: center;
400
+ justify-content: flex-end;
401
+ gap: fn.fanui-var("space-3");
402
+ padding-top: fn.fanui-var("space-5");
403
+ margin-top: fn.fanui-var("space-5");
404
+ border-top: 1px solid fn.fanui-var("color-border");
405
+
406
+ &--start { justify-content: flex-start; }
407
+ &--between { justify-content: space-between; }
408
+ }