@icen.ai/ui 0.3.0 → 0.4.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/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "@icen.ai/ui",
4
- version: "0.3.0",
4
+ version: "0.4.0",
5
5
  description: "Icen Design System \u2014 \u8BBE\u8BA1 tokens\uFF086 \u9884\u8BBE \xD7 \u660E\u6697\uFF09\u3001\u65E0\u6846\u67B6\u7EC4\u4EF6 CSS \u4E0E\u884C\u4E3A JS",
6
6
  repository: {
7
7
  type: "git",
@@ -2057,6 +2057,192 @@ function renderLine(el, opts) {
2057
2057
  wrap.append(svg, labelsRow(labels.slice(-7)));
2058
2058
  el.appendChild(wrap);
2059
2059
  }
2060
+ function renderArea(el, opts) {
2061
+ if (typeof document === "undefined") return;
2062
+ el.textContent = "";
2063
+ const n = Math.min(opts.labels.length, opts.values.length);
2064
+ if (n === 0) {
2065
+ renderEmpty(el, opts.emptyLabel);
2066
+ return;
2067
+ }
2068
+ const labels = opts.labels.slice(0, n);
2069
+ const values = opts.values.slice(0, n);
2070
+ const width = 360;
2071
+ const height = 150;
2072
+ const pad = 14;
2073
+ const max = Math.max(...values, 1);
2074
+ const tone = toneVar(opts.tone);
2075
+ const points = values.map((value, i) => ({
2076
+ x: values.length <= 1 ? width / 2 : pad + i / (values.length - 1) * (width - pad * 2),
2077
+ y: height - pad - value / max * (height - pad * 2),
2078
+ value,
2079
+ label: labels[i] ?? ""
2080
+ }));
2081
+ const line = points.map((p, i) => `${i === 0 ? "M" : "L"}${p.x.toFixed(1)},${p.y.toFixed(1)}`).join(" ");
2082
+ const last = points[points.length - 1];
2083
+ const first = points[0];
2084
+ const area = `${line} L${last.x.toFixed(1)},${height - pad} L${first.x.toFixed(1)},${height - pad} Z`;
2085
+ const gradientId = `icen-chart-area-${++lineGradientSeq}`;
2086
+ const wrap = document.createElement("div");
2087
+ wrap.className = "chart-area";
2088
+ const svg = svgEl("svg", { viewBox: `0 0 ${width} ${height}`, role: "img" });
2089
+ const defs = svgEl("defs", {});
2090
+ const gradient = svgEl("linearGradient", { id: gradientId, x1: "0", x2: "0", y1: "0", y2: "1" });
2091
+ gradient.appendChild(svgEl("stop", { offset: "0%", "stop-color": tone, "stop-opacity": "0.5" }));
2092
+ gradient.appendChild(svgEl("stop", { offset: "100%", "stop-color": tone, "stop-opacity": "0.05" }));
2093
+ defs.appendChild(gradient);
2094
+ svg.appendChild(defs);
2095
+ for (let i = 0; i < 4; i++) {
2096
+ const y = pad + i * (height - pad * 2) / 3;
2097
+ svg.appendChild(svgEl("line", {
2098
+ x1: String(pad),
2099
+ x2: String(width - pad),
2100
+ y1: String(y),
2101
+ y2: String(y),
2102
+ stroke: "var(--token-line-soft)",
2103
+ "stroke-width": "1"
2104
+ }));
2105
+ }
2106
+ svg.appendChild(svgEl("path", { d: area, fill: `url(#${gradientId})` }));
2107
+ svg.appendChild(svgEl("path", {
2108
+ d: line,
2109
+ fill: "none",
2110
+ stroke: tone,
2111
+ "stroke-width": "1.5",
2112
+ "stroke-linecap": "round",
2113
+ "stroke-linejoin": "round"
2114
+ }));
2115
+ for (const p of points) {
2116
+ const title = svgEl("title", {});
2117
+ title.textContent = `${p.label}: ${fmt(opts, p.value)}`;
2118
+ const inv = svgEl("circle", {
2119
+ cx: p.x.toFixed(1),
2120
+ cy: p.y.toFixed(1),
2121
+ r: "2",
2122
+ fill: "transparent"
2123
+ });
2124
+ inv.appendChild(title);
2125
+ svg.appendChild(inv);
2126
+ }
2127
+ wrap.append(svg, labelsRow(labels.slice(-7)));
2128
+ el.appendChild(wrap);
2129
+ }
2130
+ function renderRadar(el, opts) {
2131
+ if (typeof document === "undefined") return;
2132
+ el.textContent = "";
2133
+ const axes = opts.axes;
2134
+ const n = axes.length;
2135
+ if (n < 3 || opts.series.length === 0) {
2136
+ renderEmpty(el, opts.emptyLabel);
2137
+ return;
2138
+ }
2139
+ let maxVal = opts.max ?? 0;
2140
+ if (opts.max == null) {
2141
+ for (const s of opts.series) {
2142
+ for (let i = 0; i < n; i++) maxVal = Math.max(maxVal, s.values[i] ?? 0);
2143
+ }
2144
+ maxVal = niceCeil(maxVal);
2145
+ }
2146
+ if (maxVal <= 0) maxVal = 1;
2147
+ const size = 200;
2148
+ const cx = size / 2;
2149
+ const cy = size / 2;
2150
+ const radius = 78;
2151
+ const levels = Math.max(2, opts.levels ?? 4);
2152
+ const angleOf = (i) => -Math.PI / 2 + i * 2 * Math.PI / n;
2153
+ const pointAt = (i, r) => ({
2154
+ x: cx + r * Math.cos(angleOf(i)),
2155
+ y: cy + r * Math.sin(angleOf(i))
2156
+ });
2157
+ const wrap = document.createElement("div");
2158
+ wrap.className = "chart-radar";
2159
+ const svg = svgEl("svg", { viewBox: `0 0 ${size} ${size}`, role: "img" });
2160
+ for (let lv = 1; lv <= levels; lv++) {
2161
+ const r = radius * lv / levels;
2162
+ const pts = Array.from({ length: n }, (_, i) => {
2163
+ const p = pointAt(i, r);
2164
+ return `${p.x.toFixed(1)},${p.y.toFixed(1)}`;
2165
+ }).join(" ");
2166
+ svg.appendChild(svgEl("polygon", {
2167
+ points: pts,
2168
+ fill: "none",
2169
+ stroke: "var(--token-line-soft)",
2170
+ "stroke-width": "1",
2171
+ "stroke-dasharray": lv === levels ? "0" : "3 2"
2172
+ }));
2173
+ }
2174
+ for (let i = 0; i < n; i++) {
2175
+ const edge = pointAt(i, radius);
2176
+ svg.appendChild(svgEl("line", {
2177
+ x1: String(cx),
2178
+ y1: String(cy),
2179
+ x2: edge.x.toFixed(1),
2180
+ y2: edge.y.toFixed(1),
2181
+ stroke: "var(--token-line-soft)",
2182
+ "stroke-width": "1"
2183
+ }));
2184
+ const labelP = pointAt(i, radius + 14);
2185
+ const txt = svgEl("text", {
2186
+ x: labelP.x.toFixed(1),
2187
+ y: labelP.y.toFixed(1),
2188
+ "text-anchor": "middle",
2189
+ "dominant-baseline": "middle",
2190
+ "font-size": "9",
2191
+ fill: "var(--token-text-muted)"
2192
+ });
2193
+ txt.textContent = axes[i] ?? "";
2194
+ svg.appendChild(txt);
2195
+ }
2196
+ const legend = document.createElement("div");
2197
+ legend.className = "chart-legend";
2198
+ for (const s of opts.series) {
2199
+ const tone = toneVar(s.tone);
2200
+ const pts = Array.from({ length: n }, (_, i) => {
2201
+ const v = Math.max(0, Math.min(maxVal, s.values[i] ?? 0));
2202
+ const p = pointAt(i, v / maxVal * radius);
2203
+ return `${p.x.toFixed(1)},${p.y.toFixed(1)}`;
2204
+ }).join(" ");
2205
+ const polyFill = svgEl("polygon", {
2206
+ points: pts,
2207
+ fill: tone,
2208
+ "fill-opacity": "0.16",
2209
+ stroke: tone,
2210
+ "stroke-width": "2",
2211
+ "stroke-linejoin": "round"
2212
+ });
2213
+ const title = svgEl("title", {});
2214
+ title.textContent = `${s.name}: ${s.values.map((v) => fmt(opts, v)).join(" / ")}`;
2215
+ polyFill.appendChild(title);
2216
+ svg.appendChild(polyFill);
2217
+ for (let i = 0; i < n; i++) {
2218
+ const v = Math.max(0, Math.min(maxVal, s.values[i] ?? 0));
2219
+ const p = pointAt(i, v / maxVal * radius);
2220
+ svg.appendChild(svgEl("circle", {
2221
+ cx: p.x.toFixed(1),
2222
+ cy: p.y.toFixed(1),
2223
+ r: "2.5",
2224
+ fill: "var(--token-card)",
2225
+ stroke: tone,
2226
+ "stroke-width": "1.5"
2227
+ }));
2228
+ }
2229
+ legend.appendChild(legendItem(s.name, "", s.tone));
2230
+ }
2231
+ wrap.append(svg, legend);
2232
+ el.appendChild(wrap);
2233
+ }
2234
+ function niceCeil(v) {
2235
+ if (v <= 0) return 1;
2236
+ const exp = Math.floor(Math.log10(v));
2237
+ const base = Math.pow(10, exp);
2238
+ const frac = v / base;
2239
+ let nice;
2240
+ if (frac <= 1) nice = 1;
2241
+ else if (frac <= 2) nice = 2;
2242
+ else if (frac <= 5) nice = 5;
2243
+ else nice = 10;
2244
+ return nice * base;
2245
+ }
2060
2246
  function isoDate(d) {
2061
2247
  const m = String(d.getMonth() + 1).padStart(2, "0");
2062
2248
  const day = String(d.getDate()).padStart(2, "0");
@@ -2348,11 +2534,13 @@ export {
2348
2534
  openModal,
2349
2535
  openPopover,
2350
2536
  registerContextMenu,
2537
+ renderArea,
2351
2538
  renderDonut,
2352
2539
  renderGauge,
2353
2540
  renderHBar,
2354
2541
  renderHeatmap,
2355
2542
  renderLine,
2543
+ renderRadar,
2356
2544
  renderSparkline,
2357
2545
  renderStack,
2358
2546
  renderVBar,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icen.ai/ui",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "tokens": [
5
5
  "colors.css",
6
6
  "style-profiles.css",
@@ -14,6 +14,15 @@
14
14
  "breadcrumb",
15
15
  "btn",
16
16
  "card",
17
+ "chart-area",
18
+ "chart-bar",
19
+ "chart-gauge",
20
+ "chart-heatmap",
21
+ "chart-line",
22
+ "chart-pie",
23
+ "chart-radar",
24
+ "chart-sparkline",
25
+ "chart-stack",
17
26
  "charts",
18
27
  "content",
19
28
  "datatable",
@@ -84,9 +93,6 @@
84
93
  "stat": {
85
94
  "css": "stat.css"
86
95
  },
87
- "table": {
88
- "css": "table.css"
89
- },
90
96
  "toast": {
91
97
  "css": "toast.css",
92
98
  "behavior": "toast",
@@ -158,21 +164,6 @@
158
164
  "empty": {
159
165
  "css": "empty.css"
160
166
  },
161
- "alert": {
162
- "css": "feedback.css"
163
- },
164
- "result": {
165
- "css": "feedback.css"
166
- },
167
- "progress": {
168
- "css": "feedback.css"
169
- },
170
- "spinner": {
171
- "css": "feedback.css"
172
- },
173
- "skeleton": {
174
- "css": "feedback.css"
175
- },
176
167
  "avatar": {
177
168
  "css": "media.css"
178
169
  },
@@ -209,8 +200,32 @@
209
200
  "behavior": "carousel",
210
201
  "init": "initCarousel"
211
202
  },
203
+ "table": {
204
+ "css": "table.css"
205
+ },
206
+ "datatable": {
207
+ "css": "datatable.css",
208
+ "extraCss": [
209
+ "menu.css"
210
+ ],
211
+ "behavior": "datatable",
212
+ "exports": [
213
+ "createTable"
214
+ ]
215
+ },
212
216
  "charts": {
213
217
  "css": "charts.css",
218
+ "extraCss": [
219
+ "chart-line.css",
220
+ "chart-bar.css",
221
+ "chart-pie.css",
222
+ "chart-radar.css",
223
+ "chart-heatmap.css",
224
+ "chart-area.css",
225
+ "chart-stack.css",
226
+ "chart-gauge.css",
227
+ "chart-sparkline.css"
228
+ ],
214
229
  "behavior": "charts",
215
230
  "exports": [
216
231
  "renderVBar",
@@ -218,21 +233,119 @@
218
233
  "renderStack",
219
234
  "renderDonut",
220
235
  "renderLine",
236
+ "renderArea",
237
+ "renderRadar",
221
238
  "renderHeatmap",
222
239
  "renderSparkline",
223
240
  "renderGauge"
224
241
  ]
225
242
  },
226
- "datatable": {
227
- "css": "datatable.css",
243
+ "chart-line": {
244
+ "css": "chart-line.css",
228
245
  "extraCss": [
229
- "menu.css"
246
+ "charts.css"
230
247
  ],
231
- "behavior": "datatable",
248
+ "behavior": "charts",
232
249
  "exports": [
233
- "createTable"
250
+ "renderLine"
251
+ ]
252
+ },
253
+ "chart-bar": {
254
+ "css": "chart-bar.css",
255
+ "extraCss": [
256
+ "charts.css"
257
+ ],
258
+ "behavior": "charts",
259
+ "exports": [
260
+ "renderVBar",
261
+ "renderHBar"
262
+ ]
263
+ },
264
+ "chart-pie": {
265
+ "css": "chart-pie.css",
266
+ "extraCss": [
267
+ "charts.css"
268
+ ],
269
+ "behavior": "charts",
270
+ "exports": [
271
+ "renderDonut"
234
272
  ]
235
273
  },
274
+ "chart-radar": {
275
+ "css": "chart-radar.css",
276
+ "extraCss": [
277
+ "charts.css"
278
+ ],
279
+ "behavior": "charts",
280
+ "exports": [
281
+ "renderRadar"
282
+ ]
283
+ },
284
+ "chart-heatmap": {
285
+ "css": "chart-heatmap.css",
286
+ "extraCss": [
287
+ "charts.css"
288
+ ],
289
+ "behavior": "charts",
290
+ "exports": [
291
+ "renderHeatmap"
292
+ ]
293
+ },
294
+ "chart-area": {
295
+ "css": "chart-area.css",
296
+ "extraCss": [
297
+ "charts.css"
298
+ ],
299
+ "behavior": "charts",
300
+ "exports": [
301
+ "renderArea"
302
+ ]
303
+ },
304
+ "chart-stack": {
305
+ "css": "chart-stack.css",
306
+ "extraCss": [
307
+ "charts.css"
308
+ ],
309
+ "behavior": "charts",
310
+ "exports": [
311
+ "renderStack"
312
+ ]
313
+ },
314
+ "chart-gauge": {
315
+ "css": "chart-gauge.css",
316
+ "extraCss": [
317
+ "charts.css"
318
+ ],
319
+ "behavior": "charts",
320
+ "exports": [
321
+ "renderGauge"
322
+ ]
323
+ },
324
+ "chart-sparkline": {
325
+ "css": "chart-sparkline.css",
326
+ "extraCss": [
327
+ "charts.css"
328
+ ],
329
+ "behavior": "charts",
330
+ "exports": [
331
+ "renderSparkline"
332
+ ]
333
+ },
334
+ "alert": {
335
+ "css": "feedback.css"
336
+ },
337
+ "result": {
338
+ "css": "feedback.css"
339
+ },
340
+ "progress": {
341
+ "css": "feedback.css"
342
+ },
343
+ "spinner": {
344
+ "css": "feedback.css"
345
+ },
346
+ "skeleton": {
347
+ "css": "feedback.css"
348
+ },
236
349
  "nav": {
237
350
  "css": "nav.css",
238
351
  "behavior": "nav",