@icen.ai/ui 0.5.0 → 0.8.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.
- package/AGENTS.md +256 -0
- package/README.md +47 -13
- package/dist/base.css +31 -4
- package/dist/behaviors/accordion.d.mts +4 -0
- package/dist/behaviors/accordion.mjs +4 -3
- package/dist/behaviors/ai-chat.d.mts +57 -0
- package/dist/behaviors/ai-chat.mjs +557 -0
- package/dist/behaviors/ai-composer.d.mts +112 -0
- package/dist/behaviors/ai-composer.mjs +2032 -0
- package/dist/behaviors/ai-core.d.mts +151 -0
- package/dist/behaviors/ai-core.mjs +491 -0
- package/dist/behaviors/ai-diff.d.mts +53 -0
- package/dist/behaviors/ai-diff.mjs +282 -0
- package/dist/behaviors/ai-panel.d.mts +98 -0
- package/dist/behaviors/ai-panel.mjs +1012 -0
- package/dist/behaviors/ai-provider.d.mts +198 -0
- package/dist/behaviors/ai-provider.mjs +1055 -0
- package/dist/behaviors/ai-tool.d.mts +18 -0
- package/dist/behaviors/ai-tool.mjs +2125 -0
- package/dist/behaviors/ai-tools.d.mts +81 -0
- package/dist/behaviors/ai-tools.mjs +1658 -0
- package/dist/behaviors/back-top.d.mts +20 -0
- package/dist/behaviors/back-top.mjs +49 -32
- package/dist/behaviors/carousel.d.mts +4 -0
- package/dist/behaviors/carousel.mjs +34 -16
- package/dist/behaviors/charts.d.mts +250 -0
- package/dist/behaviors/charts.mjs +1301 -448
- package/dist/behaviors/command-palette.d.mts +8 -0
- package/dist/behaviors/command-palette.mjs +24 -12
- package/dist/behaviors/context-menu.d.mts +36 -0
- package/dist/behaviors/context-menu.mjs +6 -2
- package/dist/behaviors/copy.d.mts +4 -0
- package/dist/behaviors/copy.mjs +7 -6
- package/dist/behaviors/datatable.d.mts +78 -0
- package/dist/behaviors/datatable.mjs +54 -11
- package/dist/behaviors/date-picker.d.mts +4 -0
- package/dist/behaviors/date-picker.mjs +104 -36
- package/dist/behaviors/dropdown.d.mts +4 -0
- package/dist/behaviors/dropdown.mjs +7 -3
- package/dist/behaviors/input.d.mts +4 -0
- package/dist/behaviors/input.mjs +29 -22
- package/dist/behaviors/modal.d.mts +11 -0
- package/dist/behaviors/modal.mjs +11 -6
- package/dist/behaviors/nav.d.mts +7 -0
- package/dist/behaviors/nav.mjs +25 -9
- package/dist/behaviors/notification.d.mts +172 -0
- package/dist/behaviors/notification.mjs +243 -89
- package/dist/behaviors/popover.d.mts +46 -0
- package/dist/behaviors/popover.mjs +2 -1
- package/dist/behaviors/select.d.mts +4 -0
- package/dist/behaviors/select.mjs +131 -26
- package/dist/behaviors/sidebar.d.mts +4 -0
- package/dist/behaviors/sidebar.mjs +4 -3
- package/dist/behaviors/slider.d.mts +4 -0
- package/dist/behaviors/slider.mjs +4 -3
- package/dist/behaviors/split-pane.d.mts +4 -0
- package/dist/behaviors/split-pane.mjs +13 -13
- package/dist/behaviors/tabs.d.mts +8 -0
- package/dist/behaviors/tabs.mjs +44 -19
- package/dist/behaviors/tag-input.d.mts +4 -0
- package/dist/behaviors/tag-input.mjs +12 -3
- package/dist/behaviors/theme.d.mts +25 -0
- package/dist/behaviors/theme.mjs +3 -1
- package/dist/behaviors/toast.d.mts +26 -0
- package/dist/behaviors/toast.mjs +24 -18
- package/dist/behaviors/tree.d.mts +4 -0
- package/dist/behaviors/tree.mjs +4 -3
- package/dist/behaviors/upload.d.mts +4 -0
- package/dist/behaviors/upload.mjs +63 -26
- package/dist/components/ai-chat.css +1037 -0
- package/dist/components/ai-chat.mjs +3 -0
- package/dist/components/ai-composer.mjs +3 -0
- package/dist/components/ai-context.mjs +2 -0
- package/dist/components/ai-diff.css +311 -0
- package/dist/components/ai-diff.mjs +3 -0
- package/dist/components/ai-files.mjs +3 -0
- package/dist/components/ai-message.mjs +3 -0
- package/dist/components/ai-panel.css +682 -0
- package/dist/components/ai-reasoning.mjs +3 -0
- package/dist/components/ai-subagent.mjs +2 -0
- package/dist/components/ai-todo.mjs +2 -0
- package/dist/components/ai-tool-call.mjs +2 -0
- package/dist/components/ai-tool.css +532 -0
- package/dist/components/ai-usage.mjs +3 -0
- package/dist/components/badge.css +4 -8
- package/dist/components/breadcrumb.css +1 -5
- package/dist/components/btn.css +4 -7
- package/dist/components/card.css +3 -6
- package/dist/components/chart-bar.css +10 -0
- package/dist/components/chart-calendar.mjs +5 -0
- package/dist/components/chart-gauge.css +1 -1
- package/dist/components/chart-heatmap.css +40 -0
- package/dist/components/chart-scatter.css +24 -0
- package/dist/components/chart-scatter.mjs +4 -0
- package/dist/components/charts.css +86 -1
- package/dist/components/charts.mjs +1 -0
- package/dist/components/command-palette.css +2 -2
- package/dist/components/content.css +8 -9
- package/dist/components/copy.css +8 -8
- package/dist/components/datatable.css +4 -8
- package/dist/components/date-picker.css +3 -7
- package/dist/components/empty.css +0 -4
- package/dist/components/feedback.css +10 -17
- package/dist/components/form.css +13 -14
- package/dist/components/input.css +2 -2
- package/dist/components/layout.css +36 -36
- package/dist/components/media.css +12 -8
- package/dist/components/menu.css +2 -2
- package/dist/components/modal.css +1 -1
- package/dist/components/nav.css +11 -6
- package/dist/components/notification.css +28 -28
- package/dist/components/pagination.css +1 -1
- package/dist/components/panel.css +16 -16
- package/dist/components/pill.css +15 -15
- package/dist/components/segmented.css +5 -5
- package/dist/components/segmented.mjs +1 -0
- package/dist/components/select.css +12 -20
- package/dist/components/sidebar.css +1 -1
- package/dist/components/split-pane.css +0 -1
- package/dist/components/stat.css +14 -18
- package/dist/components/steps.css +2 -2
- package/dist/components/switch.css +8 -12
- package/dist/components/table.css +46 -47
- package/dist/components/tabs.css +35 -46
- package/dist/components/tag-input.css +4 -4
- package/dist/components/toast.css +16 -13
- package/dist/components/tooltip.css +2 -2
- package/dist/index.d.mts +37 -0
- package/dist/index.mjs +7890 -1199
- package/dist/registry.json +113 -4
- package/dist/retro-effects.css +21 -17
- package/dist/tokens/colors.css +4 -1
- package/dist/tokens/retro-effects.css +21 -17
- package/dist/tokens/style-profiles.css +21 -0
- package/dist/tokens.css +25 -1
- package/dist/ui.css +3168 -433
- package/docs/spec/ai-native.md +659 -0
- package/package.json +15 -5
|
@@ -18,6 +18,19 @@ function isAccepted(file, accept) {
|
|
|
18
18
|
}
|
|
19
19
|
var fileIconSvg = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>';
|
|
20
20
|
var xIconSvg = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>';
|
|
21
|
+
function parseSvg(source) {
|
|
22
|
+
try {
|
|
23
|
+
const doc = new DOMParser().parseFromString(source, "image/svg+xml");
|
|
24
|
+
const svg = doc.documentElement;
|
|
25
|
+
if (!svg || svg.tagName.toLowerCase() !== "svg") return null;
|
|
26
|
+
return document.importNode(svg, true);
|
|
27
|
+
} catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function sameFile(a, b) {
|
|
32
|
+
return a.name === b.name && a.size === b.size && a.lastModified === b.lastModified;
|
|
33
|
+
}
|
|
21
34
|
function setup(zone) {
|
|
22
35
|
const el = zone;
|
|
23
36
|
if (el.__icenUploadInit) return;
|
|
@@ -30,6 +43,7 @@ function setup(zone) {
|
|
|
30
43
|
const accept = input.getAttribute("accept") ?? "";
|
|
31
44
|
let currentFiles = [];
|
|
32
45
|
const urlMap = /* @__PURE__ */ new Map();
|
|
46
|
+
let syncing = false;
|
|
33
47
|
function getListEl() {
|
|
34
48
|
if (!hasList) return null;
|
|
35
49
|
let list = zone.querySelector(".upload-list");
|
|
@@ -43,8 +57,12 @@ function setup(zone) {
|
|
|
43
57
|
function renderList() {
|
|
44
58
|
const list = getListEl();
|
|
45
59
|
if (!list) return;
|
|
46
|
-
urlMap.forEach((url) =>
|
|
47
|
-
|
|
60
|
+
urlMap.forEach((url, f) => {
|
|
61
|
+
if (!currentFiles.includes(f)) {
|
|
62
|
+
URL.revokeObjectURL(url);
|
|
63
|
+
urlMap.delete(f);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
48
66
|
list.textContent = "";
|
|
49
67
|
if (currentFiles.length === 0) {
|
|
50
68
|
list.hidden = true;
|
|
@@ -55,25 +73,29 @@ function setup(zone) {
|
|
|
55
73
|
const li = document.createElement("li");
|
|
56
74
|
li.className = "upload-list-item";
|
|
57
75
|
const isImage = file.type.startsWith("image/");
|
|
76
|
+
let thumbUrl;
|
|
58
77
|
if (isImage) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
} catch {
|
|
68
|
-
const icon = document.createElement("span");
|
|
69
|
-
icon.className = "upload-list-item-icon";
|
|
70
|
-
icon.innerHTML = fileIconSvg;
|
|
71
|
-
li.appendChild(icon);
|
|
78
|
+
thumbUrl = urlMap.get(file);
|
|
79
|
+
if (!thumbUrl) {
|
|
80
|
+
try {
|
|
81
|
+
thumbUrl = URL.createObjectURL(file);
|
|
82
|
+
urlMap.set(file, thumbUrl);
|
|
83
|
+
} catch {
|
|
84
|
+
thumbUrl = void 0;
|
|
85
|
+
}
|
|
72
86
|
}
|
|
87
|
+
}
|
|
88
|
+
if (thumbUrl) {
|
|
89
|
+
const img = document.createElement("img");
|
|
90
|
+
img.className = "upload-list-item-thumb";
|
|
91
|
+
img.src = thumbUrl;
|
|
92
|
+
img.alt = file.name;
|
|
93
|
+
li.appendChild(img);
|
|
73
94
|
} else {
|
|
74
95
|
const icon = document.createElement("span");
|
|
75
96
|
icon.className = "upload-list-item-icon";
|
|
76
|
-
|
|
97
|
+
const svg = parseSvg(fileIconSvg);
|
|
98
|
+
if (svg) icon.appendChild(svg);
|
|
77
99
|
li.appendChild(icon);
|
|
78
100
|
}
|
|
79
101
|
const info = document.createElement("div");
|
|
@@ -91,7 +113,8 @@ function setup(zone) {
|
|
|
91
113
|
removeBtn.className = "upload-list-item-x";
|
|
92
114
|
removeBtn.type = "button";
|
|
93
115
|
removeBtn.setAttribute("aria-label", `\u79FB\u9664 ${file.name}`);
|
|
94
|
-
|
|
116
|
+
const xSvg = parseSvg(xIconSvg);
|
|
117
|
+
if (xSvg) removeBtn.appendChild(xSvg);
|
|
95
118
|
removeBtn.addEventListener("click", (ev) => {
|
|
96
119
|
ev.stopPropagation();
|
|
97
120
|
currentFiles = currentFiles.filter((f) => f !== file);
|
|
@@ -107,9 +130,12 @@ function setup(zone) {
|
|
|
107
130
|
try {
|
|
108
131
|
const dt = new DataTransfer();
|
|
109
132
|
for (const f of currentFiles) dt.items.add(f);
|
|
133
|
+
syncing = true;
|
|
110
134
|
input.files = dt.files;
|
|
111
135
|
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
112
136
|
} catch {
|
|
137
|
+
} finally {
|
|
138
|
+
syncing = false;
|
|
113
139
|
}
|
|
114
140
|
}
|
|
115
141
|
function validate(file) {
|
|
@@ -129,20 +155,28 @@ function setup(zone) {
|
|
|
129
155
|
}
|
|
130
156
|
if (valid.length === 0) return;
|
|
131
157
|
if (hasList) {
|
|
158
|
+
const fresh = [];
|
|
159
|
+
for (const f of valid) {
|
|
160
|
+
if (currentFiles.some((c) => sameFile(c, f)) || fresh.some((c) => sameFile(c, f))) continue;
|
|
161
|
+
fresh.push(f);
|
|
162
|
+
}
|
|
163
|
+
if (fresh.length === 0) return;
|
|
132
164
|
if (maxFiles > 0) {
|
|
133
165
|
const remaining = maxFiles - currentFiles.length;
|
|
134
166
|
if (remaining <= 0) {
|
|
135
167
|
zone.dispatchEvent(new CustomEvent("icen:upload-error", {
|
|
136
168
|
bubbles: true,
|
|
137
|
-
detail: { reason: `\u6700\u591A ${maxFiles} \u4E2A\u6587\u4EF6` }
|
|
169
|
+
detail: { file: null, reason: `\u6700\u591A ${maxFiles} \u4E2A\u6587\u4EF6` }
|
|
138
170
|
}));
|
|
139
171
|
return;
|
|
140
172
|
}
|
|
141
|
-
|
|
173
|
+
if (fresh.length > remaining) fresh.length = remaining;
|
|
142
174
|
}
|
|
143
|
-
currentFiles.push(...
|
|
175
|
+
currentFiles.push(...fresh);
|
|
144
176
|
renderList();
|
|
145
177
|
syncInputFiles();
|
|
178
|
+
zone.dispatchEvent(new CustomEvent("icen:upload", { bubbles: true, detail: { files: fresh } }));
|
|
179
|
+
return;
|
|
146
180
|
}
|
|
147
181
|
zone.dispatchEvent(new CustomEvent("icen:upload", { bubbles: true, detail: { files: valid } }));
|
|
148
182
|
}
|
|
@@ -160,14 +194,13 @@ function setup(zone) {
|
|
|
160
194
|
}
|
|
161
195
|
});
|
|
162
196
|
input.addEventListener("change", () => {
|
|
197
|
+
if (syncing) return;
|
|
163
198
|
if (!input.files) return;
|
|
164
199
|
const files = Array.from(input.files);
|
|
165
200
|
if (hasList) {
|
|
166
|
-
handleFiles(files);
|
|
167
201
|
input.value = "";
|
|
168
|
-
} else {
|
|
169
|
-
handleFiles(files);
|
|
170
202
|
}
|
|
203
|
+
handleFiles(files);
|
|
171
204
|
});
|
|
172
205
|
zone.addEventListener("dragover", (ev) => {
|
|
173
206
|
ev.preventDefault();
|
|
@@ -186,18 +219,22 @@ function setup(zone) {
|
|
|
186
219
|
try {
|
|
187
220
|
const dt = new DataTransfer();
|
|
188
221
|
for (const f of Array.from(files)) dt.items.add(f);
|
|
222
|
+
syncing = true;
|
|
189
223
|
input.files = dt.files;
|
|
190
224
|
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
191
225
|
} catch {
|
|
226
|
+
} finally {
|
|
227
|
+
syncing = false;
|
|
192
228
|
}
|
|
193
229
|
}
|
|
194
230
|
});
|
|
195
231
|
}
|
|
196
|
-
function initUpload(root
|
|
232
|
+
function initUpload(root) {
|
|
197
233
|
if (typeof document === "undefined") return;
|
|
234
|
+
const scope = root ?? document;
|
|
198
235
|
const zones = [];
|
|
199
|
-
if (
|
|
200
|
-
zones.push(...Array.from(
|
|
236
|
+
if (scope instanceof HTMLElement && scope.matches(".upload")) zones.push(scope);
|
|
237
|
+
zones.push(...Array.from(scope.querySelectorAll(".upload")));
|
|
201
238
|
for (const z of zones) setup(z);
|
|
202
239
|
}
|
|
203
240
|
export {
|