@icen.ai/ui 0.2.0 → 0.3.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 (103) hide show
  1. package/README.md +29 -16
  2. package/dist/base.css +389 -48
  3. package/dist/behaviors/accordion.mjs +20 -0
  4. package/dist/behaviors/carousel.mjs +30 -1
  5. package/dist/behaviors/charts.mjs +168 -0
  6. package/dist/behaviors/copy.mjs +4 -3
  7. package/dist/behaviors/datatable.mjs +748 -0
  8. package/dist/behaviors/input.mjs +20 -1
  9. package/dist/behaviors/modal.mjs +15 -1
  10. package/dist/behaviors/nav.mjs +31 -4
  11. package/dist/behaviors/sidebar.mjs +12 -0
  12. package/dist/behaviors/slider.mjs +35 -3
  13. package/dist/behaviors/tabs.mjs +100 -9
  14. package/dist/behaviors/tag-input.mjs +11 -0
  15. package/dist/behaviors/theme.mjs +26 -0
  16. package/dist/behaviors/toast.mjs +83 -15
  17. package/dist/behaviors/tree.mjs +57 -1
  18. package/dist/behaviors/upload.mjs +2 -3
  19. package/dist/cli.mjs +74 -0
  20. package/dist/components/accordion.mjs +3 -0
  21. package/dist/components/alert.mjs +2 -0
  22. package/dist/components/avatar.mjs +2 -0
  23. package/dist/components/breadcrumb.css +91 -18
  24. package/dist/components/breadcrumb.mjs +2 -0
  25. package/dist/components/btn.css +174 -14
  26. package/dist/components/btn.mjs +2 -0
  27. package/dist/components/card.css +118 -18
  28. package/dist/components/card.mjs +2 -0
  29. package/dist/components/carousel.mjs +3 -0
  30. package/dist/components/charts.css +225 -33
  31. package/dist/components/charts.mjs +3 -0
  32. package/dist/components/content.css +256 -74
  33. package/dist/components/context-menu.mjs +3 -0
  34. package/dist/components/datatable.css +343 -0
  35. package/dist/components/datatable.mjs +4 -0
  36. package/dist/components/desc.mjs +2 -0
  37. package/dist/components/dropdown.mjs +3 -0
  38. package/dist/components/empty.css +50 -10
  39. package/dist/components/empty.mjs +2 -0
  40. package/dist/components/feedback.css +158 -47
  41. package/dist/components/form.css +139 -22
  42. package/dist/components/input.css +165 -45
  43. package/dist/components/input.mjs +3 -0
  44. package/dist/components/kbd.mjs +2 -0
  45. package/dist/components/layout.mjs +2 -0
  46. package/dist/components/list.mjs +2 -0
  47. package/dist/components/media-card.mjs +2 -0
  48. package/dist/components/media.css +187 -40
  49. package/dist/components/menu.css +159 -32
  50. package/dist/components/modal.css +140 -34
  51. package/dist/components/modal.mjs +3 -0
  52. package/dist/components/nav.css +134 -32
  53. package/dist/components/nav.mjs +3 -0
  54. package/dist/components/pagination.css +105 -19
  55. package/dist/components/pagination.mjs +2 -0
  56. package/dist/components/panel.css +61 -6
  57. package/dist/components/panel.mjs +2 -0
  58. package/dist/components/pill.css +74 -14
  59. package/dist/components/pill.mjs +2 -0
  60. package/dist/components/popover.css +109 -7
  61. package/dist/components/popover.mjs +3 -0
  62. package/dist/components/progress.mjs +2 -0
  63. package/dist/components/rating.mjs +2 -0
  64. package/dist/components/result.mjs +2 -0
  65. package/dist/components/segmented.css +199 -50
  66. package/dist/components/segmented.mjs +2 -0
  67. package/dist/components/select.css +140 -39
  68. package/dist/components/select.mjs +3 -0
  69. package/dist/components/sidebar.css +162 -34
  70. package/dist/components/sidebar.mjs +3 -0
  71. package/dist/components/skeleton.mjs +2 -0
  72. package/dist/components/slider.css +169 -31
  73. package/dist/components/slider.mjs +3 -0
  74. package/dist/components/spinner.mjs +2 -0
  75. package/dist/components/stat.css +103 -8
  76. package/dist/components/stat.mjs +2 -0
  77. package/dist/components/steps.css +105 -31
  78. package/dist/components/steps.mjs +2 -0
  79. package/dist/components/switch.css +171 -54
  80. package/dist/components/switch.mjs +2 -0
  81. package/dist/components/table.css +114 -12
  82. package/dist/components/table.mjs +2 -0
  83. package/dist/components/tabs.css +104 -17
  84. package/dist/components/tabs.mjs +3 -0
  85. package/dist/components/tag-input.css +119 -23
  86. package/dist/components/tag-input.mjs +3 -0
  87. package/dist/components/timeline.mjs +2 -0
  88. package/dist/components/toast.css +85 -12
  89. package/dist/components/toast.mjs +3 -0
  90. package/dist/components/tooltip.css +86 -26
  91. package/dist/components/tooltip.mjs +2 -0
  92. package/dist/components/tree.mjs +3 -0
  93. package/dist/components/upload.css +144 -17
  94. package/dist/components/upload.mjs +3 -0
  95. package/dist/index.mjs +629 -48
  96. package/dist/registry.json +197 -2
  97. package/dist/retro-effects.css +264 -0
  98. package/dist/tokens/colors.css +18 -90
  99. package/dist/tokens/retro-effects.css +264 -0
  100. package/dist/tokens/style-profiles.css +47 -47
  101. package/dist/tokens.css +65 -137
  102. package/dist/ui.css +4861 -1019
  103. package/package.json +9 -1
@@ -0,0 +1,343 @@
1
+ /*
2
+ * @icen.ai/ui — Component: datatable(数据表格,与 behaviors/datatable 配套)
3
+ *
4
+ * 结构(全部由 createTable 渲染,div + ARIA role 网格):
5
+ * .datatable [--striped|--virtual]
6
+ * ├─ .dt-toolbar > .dt-search > svg + input.dt-search-input
7
+ * ├─ .dt-scroll > .dt-canvas[role=grid]
8
+ * │ ├─ .dt-head > .dt-row--head > .dt-cell--head(.is-sortable / .dt-filter-btn / .dt-filter-panel)
9
+ * │ └─ .dt-body > .dt-row[.is-selected] > .dt-cell;.dt-expand-row;.dt-empty;.dt-skeleton-row
10
+ * └─ .dt-foot > .dt-stat(含 .dt-clear-sel)+ .dt-pager(.dt-page-size / .dt-page-btn / .dt-page-dots)
11
+ *
12
+ * 行布局 = grid,grid-template-columns 由 behavior 按列宽计算;行内容溢出省略号。
13
+ * 右键菜单面板样式在 menu.css(kit 入口自动带上)。
14
+ */
15
+
16
+ .datatable {
17
+ border: 1px solid var(--token-line-soft);
18
+ border-radius: var(--radius-lg);
19
+ background: var(--token-surface);
20
+ overflow: hidden;
21
+ font-size: var(--density-font-size-md);
22
+ }
23
+
24
+ /* ── 工具栏(搜索) ── */
25
+ .dt-toolbar {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: var(--density-space-sm);
29
+ padding: 10px 14px;
30
+ border-bottom: 1px solid var(--token-line-soft);
31
+ }
32
+ .dt-search {
33
+ display: flex;
34
+ align-items: center;
35
+ gap: 8px;
36
+ height: 32px;
37
+ width: 260px;
38
+ max-width: 100%;
39
+ padding: 0 10px;
40
+ color: var(--token-text-faint);
41
+ background: var(--token-control);
42
+ border: 1px solid var(--token-outline-soft);
43
+ border-radius: var(--radius-md);
44
+ box-shadow: var(--token-shadow-inset);
45
+ transition: border-color var(--icen-tx-fast), box-shadow var(--icen-tx-fast);
46
+ }
47
+ .dt-search:focus-within {
48
+ border-color: var(--icen-control-focus-border, var(--token-accent));
49
+ box-shadow: var(--icen-control-focus-shadow);
50
+ }
51
+ .dt-search-input {
52
+ flex: 1;
53
+ min-width: 0;
54
+ border: 0;
55
+ outline: none;
56
+ background: transparent;
57
+ color: var(--token-text);
58
+ font: inherit;
59
+ font-size: var(--density-font-size-sm);
60
+ }
61
+ .dt-search-input::placeholder { color: var(--token-text-faint); }
62
+ .dt-search-input::-webkit-search-cancel-button { -webkit-appearance: none; }
63
+
64
+ /* ── 滚动容器与画布 ── */
65
+ .dt-scroll { overflow: auto; }
66
+ .datatable--virtual .dt-scroll { overscroll-behavior: contain; }
67
+ .dt-canvas { min-width: 560px; }
68
+
69
+ /* ── 行 ── */
70
+ .dt-row {
71
+ display: grid;
72
+ align-items: center;
73
+ border-bottom: 1px solid var(--token-line-soft);
74
+ transition: background var(--icen-tx-fast);
75
+ }
76
+ .dt-body .dt-row:last-child { border-bottom: 0; }
77
+ .dt-body .dt-row:hover { background: var(--token-fill-1); }
78
+ .dt-row.is-selected { background: var(--token-accent-subtle); }
79
+ .dt-row.is-selected:hover { background: color-mix(in srgb, var(--token-accent-subtle) 82%, var(--token-fill-1)); }
80
+ .dt-row.is-clickable { cursor: pointer; }
81
+ .datatable--striped .dt-body .dt-row:nth-child(even):not(.is-selected) {
82
+ background: color-mix(in srgb, var(--token-fill-1) 55%, transparent);
83
+ }
84
+ .datatable--striped .dt-body .dt-row:nth-child(even):not(.is-selected):hover {
85
+ background: var(--token-fill-1);
86
+ }
87
+
88
+ .dt-cell {
89
+ padding: 0 12px;
90
+ min-width: 0;
91
+ overflow: hidden;
92
+ text-overflow: ellipsis;
93
+ white-space: nowrap;
94
+ color: var(--token-text);
95
+ display: flex;
96
+ align-items: center;
97
+ gap: 8px;
98
+ min-height: 44px;
99
+ }
100
+ .datatable--virtual .dt-cell { min-height: 0; height: 100%; }
101
+ .dt-cell[data-align='center'] { justify-content: center; text-align: center; }
102
+ .dt-cell[data-align='right'] { justify-content: flex-end; text-align: right; }
103
+ .dt-cell--check, .dt-cell--expand { justify-content: center; padding: 0 4px; }
104
+
105
+ /* ── 表头 ── */
106
+ .dt-head { border-bottom: 1px solid var(--token-line-soft); }
107
+ .dt-row--head {
108
+ background: var(--token-bg-soft);
109
+ border-bottom: 0;
110
+ }
111
+ .datatable--virtual .dt-row--head {
112
+ position: sticky;
113
+ top: 0;
114
+ z-index: var(--z-raised);
115
+ }
116
+ .dt-cell--head {
117
+ position: relative;
118
+ min-height: 40px;
119
+ font-size: var(--density-font-size-sm);
120
+ font-weight: 600;
121
+ color: var(--token-text-muted);
122
+ user-select: none;
123
+ }
124
+ .dt-cell--head.is-sortable { cursor: pointer; }
125
+ .dt-cell--head.is-sortable:hover { color: var(--token-text); }
126
+ .dt-cell--head:focus-visible {
127
+ outline: none;
128
+ box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--token-accent) 50%, transparent);
129
+ }
130
+ .dt-head-title { overflow: hidden; text-overflow: ellipsis; }
131
+ .dt-sort {
132
+ font-size: 10px;
133
+ color: var(--token-text-faint);
134
+ flex-shrink: 0;
135
+ }
136
+ .dt-sort.is-active { color: var(--token-accent); }
137
+
138
+ /* 筛选按钮与面板 */
139
+ .dt-filter-btn {
140
+ display: inline-flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ width: 22px;
144
+ height: 22px;
145
+ flex-shrink: 0;
146
+ border: 0;
147
+ border-radius: var(--radius-sm);
148
+ background: transparent;
149
+ color: var(--token-text-faint);
150
+ cursor: pointer;
151
+ transition: color var(--icen-tx-fast), background var(--icen-tx-fast);
152
+ }
153
+ .dt-filter-btn:hover { color: var(--token-text); background: var(--token-fill-2); }
154
+ .dt-filter-btn.is-open, .dt-filter-btn.is-active { color: var(--token-accent); }
155
+ .dt-filter-btn.is-active { background: var(--token-accent-subtle); }
156
+
157
+ .dt-filter-panel {
158
+ position: fixed; /* portal 到 body,由 behavior 按 trigger rect 定位 */
159
+ z-index: var(--z-popover);
160
+ min-width: 168px;
161
+ max-width: 240px;
162
+ padding: 4px;
163
+ background: var(--token-card-strong);
164
+ border: 1px solid var(--token-outline);
165
+ border-radius: var(--radius-md);
166
+ box-shadow: var(--token-shadow-overlay);
167
+ font-weight: 400;
168
+ animation: dt-panel-in var(--icen-tx-fast);
169
+ }
170
+ @keyframes dt-panel-in {
171
+ from { opacity: 0; transform: scale(0.96) translateY(-4px); }
172
+ to { opacity: 1; transform: scale(1) translateY(0); }
173
+ }
174
+ .dt-filter-list {
175
+ max-height: 220px;
176
+ overflow-y: auto;
177
+ display: flex;
178
+ flex-direction: column;
179
+ }
180
+ .dt-filter-item {
181
+ display: flex;
182
+ align-items: center;
183
+ gap: 8px;
184
+ padding: 6px 8px;
185
+ border-radius: var(--radius-sm);
186
+ font-size: var(--density-font-size-sm);
187
+ color: var(--token-text);
188
+ cursor: pointer;
189
+ }
190
+ .dt-filter-item:hover { background: var(--token-fill-1); }
191
+ .dt-filter-item > span {
192
+ overflow: hidden;
193
+ text-overflow: ellipsis;
194
+ white-space: nowrap;
195
+ }
196
+ .dt-filter-foot {
197
+ display: flex;
198
+ justify-content: flex-end;
199
+ padding: 4px 6px 2px;
200
+ border-top: 1px solid var(--token-line-soft);
201
+ margin-top: 4px;
202
+ }
203
+ .dt-filter-reset {
204
+ border: 0;
205
+ background: transparent;
206
+ color: var(--token-accent);
207
+ font: inherit;
208
+ font-size: var(--density-font-size-xs);
209
+ cursor: pointer;
210
+ padding: 2px 4px;
211
+ }
212
+ .dt-filter-reset:hover { text-decoration: underline; }
213
+
214
+ /* ── 复选框(accent-color 直达 token,三态由 behavior 控制 indeterminate) ── */
215
+ .dt-check {
216
+ width: 15px;
217
+ height: 15px;
218
+ margin: 0;
219
+ accent-color: var(--token-accent);
220
+ cursor: pointer;
221
+ flex-shrink: 0;
222
+ }
223
+
224
+ /* ── 行展开 ── */
225
+ .dt-expand-btn {
226
+ display: inline-flex;
227
+ align-items: center;
228
+ justify-content: center;
229
+ width: 24px;
230
+ height: 24px;
231
+ border: 0;
232
+ border-radius: var(--radius-sm);
233
+ background: transparent;
234
+ color: var(--token-text-faint);
235
+ cursor: pointer;
236
+ transition: transform var(--icen-tx-fast), color var(--icen-tx-fast), background var(--icen-tx-fast);
237
+ }
238
+ .dt-expand-btn:hover { color: var(--token-text); background: var(--token-fill-2); }
239
+ .dt-expand-btn[aria-expanded='true'] { transform: rotate(180deg); color: var(--token-accent); }
240
+ .dt-expand-row {
241
+ padding: 14px 16px;
242
+ border-bottom: 1px solid var(--token-line-soft);
243
+ background: var(--token-bg-soft);
244
+ color: var(--token-text-muted);
245
+ font-size: var(--density-font-size-sm);
246
+ line-height: 1.7;
247
+ white-space: normal;
248
+ }
249
+
250
+ /* ── 空态 / 加载骨架 ── */
251
+ .dt-empty {
252
+ padding: 48px 16px;
253
+ text-align: center;
254
+ color: var(--token-text-faint);
255
+ font-size: var(--density-font-size-sm);
256
+ }
257
+ .dt-skeleton-row {
258
+ padding: 14px 16px;
259
+ border-bottom: 1px solid var(--token-line-soft);
260
+ }
261
+
262
+ /* ── 底部(统计 + 分页) ── */
263
+ .dt-foot {
264
+ display: flex;
265
+ align-items: center;
266
+ gap: 12px;
267
+ flex-wrap: wrap;
268
+ padding: 10px 14px;
269
+ border-top: 1px solid var(--token-line-soft);
270
+ }
271
+ .dt-foot:empty { display: none; }
272
+ .dt-stat {
273
+ font-size: var(--density-font-size-xs);
274
+ color: var(--token-text-faint);
275
+ font-variant-numeric: tabular-nums;
276
+ }
277
+ .dt-stat--sel { color: var(--token-accent); display: inline-flex; align-items: center; gap: 6px; }
278
+ .dt-clear-sel {
279
+ border: 0;
280
+ background: transparent;
281
+ color: var(--token-accent);
282
+ font: inherit;
283
+ font-size: var(--density-font-size-xs);
284
+ cursor: pointer;
285
+ padding: 0;
286
+ }
287
+ .dt-clear-sel:hover { text-decoration: underline; }
288
+
289
+ .dt-pager {
290
+ margin-left: auto;
291
+ display: flex;
292
+ align-items: center;
293
+ gap: 4px;
294
+ }
295
+ .dt-page-size {
296
+ appearance: none;
297
+ -webkit-appearance: none;
298
+ height: 28px;
299
+ padding: 0 8px;
300
+ margin-right: 6px;
301
+ font: inherit;
302
+ font-size: var(--density-font-size-xs);
303
+ color: var(--token-text-muted);
304
+ background: transparent;
305
+ border: 1px solid var(--token-line-soft);
306
+ border-radius: var(--radius-sm);
307
+ cursor: pointer;
308
+ }
309
+ .dt-page-size:hover { border-color: var(--token-accent); color: var(--token-text); }
310
+ .dt-page-btn {
311
+ min-width: 28px;
312
+ height: 28px;
313
+ padding: 0 6px;
314
+ border: 1px solid transparent;
315
+ border-radius: var(--radius-sm);
316
+ background: transparent;
317
+ color: var(--token-text-muted);
318
+ font: inherit;
319
+ font-size: var(--density-font-size-xs);
320
+ font-variant-numeric: tabular-nums;
321
+ cursor: pointer;
322
+ transition: color var(--icen-tx-fast), border-color var(--icen-tx-fast), background var(--icen-tx-fast);
323
+ }
324
+ .dt-page-btn:hover:not(:disabled):not(.is-active) {
325
+ color: var(--token-text);
326
+ border-color: var(--token-line-soft);
327
+ }
328
+ .dt-page-btn.is-active {
329
+ color: var(--token-accent);
330
+ border-color: var(--token-accent);
331
+ background: var(--token-accent-subtle);
332
+ font-weight: 600;
333
+ }
334
+ .dt-page-btn:disabled { opacity: 0.35; cursor: not-allowed; }
335
+ .dt-page-dots {
336
+ color: var(--token-text-faint);
337
+ font-size: var(--density-font-size-xs);
338
+ padding: 0 2px;
339
+ }
340
+
341
+ @media (prefers-reduced-motion: reduce) {
342
+ .dt-filter-panel { animation: none; }
343
+ }
@@ -0,0 +1,4 @@
1
+ // @icen.ai/ui — kit: datatable(CSS + behavior 一行入口;构建产物,勿手改)
2
+ import './datatable.css';
3
+ import './menu.css';
4
+ export * from '../behaviors/datatable.mjs';
@@ -0,0 +1,2 @@
1
+ // @icen.ai/ui — kit: desc(CSS + behavior 一行入口;构建产物,勿手改)
2
+ import './content.css';
@@ -0,0 +1,3 @@
1
+ // @icen.ai/ui — kit: dropdown(CSS + behavior 一行入口;构建产物,勿手改)
2
+ import './menu.css';
3
+ export * from '../behaviors/dropdown.mjs';
@@ -1,25 +1,65 @@
1
1
  /*
2
- * @icen.ai/ui — Component: empty(空状态)
3
- * 包含:.empty 容器 + .empty-icon / .empty-title / .empty-desc / .empty-action
2
+ * @icen.ai/ui — Component: empty(空状态 / 无数据 / 404 占位)
3
+ *
4
+ * 完整契约:
5
+ * <div class="empty [.empty--sm|.empty--lg]">
6
+ * <div class="empty-icon">…svg…</div> ← 可选,缺省显示默认占位
7
+ * <h3 class="empty-title">暂无数据</h3>
8
+ * <p class="empty-desc">描述文案(可选)</p>
9
+ * <div class="empty-action"> ← 可选:操作按钮位
10
+ * <button class="btn btn-primary">…</button>
11
+ * </div>
12
+ * </div>
13
+ *
4
14
  * 规格源自 opengal src/presentation/ui/data/display.tsx 的 EmptyState。
5
15
  */
6
16
 
7
17
  .empty {
8
- display: flex; flex-direction: column; align-items: center; justify-content: center;
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: center;
21
+ justify-content: center;
9
22
  text-align: center;
10
- padding: 48px 16px;
23
+ padding: var(--density-space-lg) var(--density-space-md);
11
24
  }
25
+ .empty--sm { padding: var(--density-space-md); }
26
+ .empty--lg { padding: 64px var(--density-space-md); }
27
+
12
28
  .empty-icon {
13
- width: 48px; height: 48px;
29
+ width: 48px;
30
+ height: 48px;
14
31
  border-radius: var(--radius-lg);
15
32
  background: var(--token-card);
16
33
  border: 1px solid var(--token-outline-soft);
17
34
  box-shadow: var(--token-shadow-inset);
18
- display: flex; align-items: center; justify-content: center;
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: center;
19
38
  color: var(--token-text-faint);
20
- margin-bottom: 16px;
39
+ margin-bottom: var(--density-space-md);
21
40
  }
41
+ .empty--lg .empty-icon { width: 64px; height: 64px; }
42
+ .empty--sm .empty-icon { width: 36px; height: 36px; margin-bottom: var(--density-space-sm); }
22
43
  .empty-icon svg { width: 24px; height: 24px; }
23
- .empty-title { font-size: 14px; font-weight: 500; color: var(--token-text); margin: 0; }
24
- .empty-desc { font-size: 12px; color: var(--token-text-muted); margin: 4px 0 0; max-width: 240px; }
25
- .empty-action { margin-top: 16px; }
44
+ .empty--lg .empty-icon svg { width: 32px; height: 32px; }
45
+ .empty--sm .empty-icon svg { width: 18px; height: 18px; }
46
+
47
+ .empty-title {
48
+ font-size: var(--density-font-size-md);
49
+ font-weight: 500;
50
+ color: var(--token-text);
51
+ margin: 0;
52
+ line-height: 1.4;
53
+ }
54
+ .empty-desc {
55
+ font-size: var(--density-font-size-sm);
56
+ color: var(--token-text-muted);
57
+ margin: 4px 0 0;
58
+ max-width: 240px;
59
+ line-height: 1.5;
60
+ }
61
+ .empty-action {
62
+ margin-top: var(--density-space-md);
63
+ display: flex;
64
+ gap: var(--density-space-xs);
65
+ }
@@ -0,0 +1,2 @@
1
+ // @icen.ai/ui — kit: empty(CSS + behavior 一行入口;构建产物,勿手改)
2
+ import './empty.css';