@icen.ai/ui 0.10.0 → 0.11.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 +79 -309
- package/LICENSE +21 -0
- package/README.md +43 -54
- package/dist/base.css +57 -16
- package/dist/behaviors/accordion.mjs +1 -1
- package/dist/behaviors/ai-branch.mjs +1 -0
- package/dist/behaviors/ai-chat.d.mts +2 -2
- package/dist/behaviors/ai-chat.mjs +53 -10
- package/dist/behaviors/ai-composer.d.mts +5 -5
- package/dist/behaviors/ai-composer.mjs +21 -10
- package/dist/behaviors/ai-core.mjs +1 -0
- package/dist/behaviors/ai-diff.mjs +1 -0
- package/dist/behaviors/ai-feedback.mjs +1 -0
- package/dist/behaviors/ai-panel.d.mts +2 -2
- package/dist/behaviors/ai-panel.mjs +1 -0
- package/dist/behaviors/ai-provider.d.mts +1 -1
- package/dist/behaviors/ai-provider.mjs +1 -0
- package/dist/behaviors/ai-threads.mjs +1 -0
- package/dist/behaviors/ai-tool.d.mts +1 -1
- package/dist/behaviors/ai-tool.mjs +57 -24
- package/dist/behaviors/ai-tools.mjs +937 -28
- package/dist/behaviors/autocomplete.d.mts +1 -1
- package/dist/behaviors/autocomplete.mjs +1 -0
- package/dist/behaviors/back-top.mjs +1 -0
- package/dist/behaviors/carousel.mjs +8 -1
- package/dist/behaviors/cascader.mjs +14 -0
- package/dist/behaviors/charts.mjs +56 -20
- package/dist/behaviors/code-block.mjs +9 -1
- package/dist/behaviors/command-palette.mjs +3 -3
- package/dist/behaviors/context-menu.d.mts +2 -2
- package/dist/behaviors/context-menu.mjs +1 -0
- package/dist/behaviors/controls.d.mts +8 -8
- package/dist/behaviors/controls.mjs +37 -6
- package/dist/behaviors/copy.mjs +1 -0
- package/dist/behaviors/datatable.d.mts +3 -3
- package/dist/behaviors/datatable.mjs +76 -11
- package/dist/behaviors/date-picker.mjs +1 -0
- package/dist/behaviors/events.d.mts +10 -10
- package/dist/behaviors/events.mjs +11 -1
- package/dist/behaviors/form-validate.d.mts +10 -1
- package/dist/behaviors/form-validate.mjs +266 -4611
- package/dist/behaviors/i18n.d.mts +1 -0
- package/dist/behaviors/i18n.mjs +2 -0
- package/dist/behaviors/input.mjs +3 -0
- package/dist/behaviors/kb-access.d.mts +2 -2
- package/dist/behaviors/kb-access.mjs +8 -2
- package/dist/behaviors/kb-acl.d.mts +2 -2
- package/dist/behaviors/kb-acl.mjs +1 -0
- package/dist/behaviors/kb-answer.d.mts +2 -2
- package/dist/behaviors/kb-answer.mjs +56 -23
- package/dist/behaviors/kb-audit.d.mts +2 -2
- package/dist/behaviors/kb-audit.mjs +1 -0
- package/dist/behaviors/kb-canvas.d.mts +3 -3
- package/dist/behaviors/kb-canvas.mjs +1 -0
- package/dist/behaviors/kb-chain.d.mts +2 -2
- package/dist/behaviors/kb-chain.mjs +1 -0
- package/dist/behaviors/kb-checkpoint.d.mts +2 -2
- package/dist/behaviors/kb-checkpoint.mjs +1 -0
- package/dist/behaviors/kb-chunks.d.mts +2 -2
- package/dist/behaviors/kb-chunks.mjs +1 -0
- package/dist/behaviors/kb-citation.d.mts +2 -2
- package/dist/behaviors/kb-citation.mjs +20 -6
- package/dist/behaviors/kb-clarify.d.mts +2 -2
- package/dist/behaviors/kb-clarify.mjs +1 -0
- package/dist/behaviors/kb-conflict.d.mts +2 -2
- package/dist/behaviors/kb-conflict.mjs +1 -0
- package/dist/behaviors/kb-connector.d.mts +2 -2
- package/dist/behaviors/kb-connector.mjs +1 -0
- package/dist/behaviors/kb-core.d.mts +1 -1
- package/dist/behaviors/kb-core.mjs +1 -0
- package/dist/behaviors/kb-eval.d.mts +2 -2
- package/dist/behaviors/kb-eval.mjs +8 -2
- package/dist/behaviors/kb-explain.d.mts +2 -2
- package/dist/behaviors/kb-explain.mjs +13 -2
- package/dist/behaviors/kb-filter.d.mts +2 -2
- package/dist/behaviors/kb-filter.mjs +8 -2
- package/dist/behaviors/kb-gap.d.mts +2 -2
- package/dist/behaviors/kb-gap.mjs +1 -0
- package/dist/behaviors/kb-hittest.d.mts +2 -2
- package/dist/behaviors/kb-hittest.mjs +2 -1
- package/dist/behaviors/kb-metadata.mjs +6 -0
- package/dist/behaviors/kb-passage.d.mts +2 -2
- package/dist/behaviors/kb-passage.mjs +1 -0
- package/dist/behaviors/kb-pipeline.d.mts +2 -2
- package/dist/behaviors/kb-pipeline.mjs +1 -0
- package/dist/behaviors/kb-qa.mjs +1 -0
- package/dist/behaviors/kb-rerank.d.mts +2 -2
- package/dist/behaviors/kb-rerank.mjs +1 -0
- package/dist/behaviors/kb-retrieval.d.mts +2 -2
- package/dist/behaviors/kb-retrieval.mjs +18 -4
- package/dist/behaviors/kb-review.d.mts +2 -2
- package/dist/behaviors/kb-review.mjs +8 -2
- package/dist/behaviors/kb-sandbox.d.mts +2 -2
- package/dist/behaviors/kb-sandbox.mjs +7 -1
- package/dist/behaviors/kb-segment.d.mts +2 -2
- package/dist/behaviors/kb-segment.mjs +2 -1
- package/dist/behaviors/kb-select.mjs +8 -2
- package/dist/behaviors/kb-sources.d.mts +2 -2
- package/dist/behaviors/kb-sources.mjs +1 -0
- package/dist/behaviors/kb-sql.d.mts +2 -2
- package/dist/behaviors/kb-sql.mjs +1 -0
- package/dist/behaviors/kb-trace.d.mts +2 -2
- package/dist/behaviors/kb-trace.mjs +9 -3
- package/dist/behaviors/kb-visibility.d.mts +2 -2
- package/dist/behaviors/kb-visibility.mjs +1 -0
- package/dist/behaviors/kb-who-can.d.mts +2 -2
- package/dist/behaviors/kb-who-can.mjs +8 -2
- package/dist/behaviors/mentions.d.mts +1 -1
- package/dist/behaviors/mentions.mjs +1 -0
- package/dist/behaviors/modal.d.mts +1 -1
- package/dist/behaviors/modal.mjs +1 -0
- package/dist/behaviors/notification.d.mts +2 -2
- package/dist/behaviors/notification.mjs +14 -3
- package/dist/behaviors/panel.mjs +1 -0
- package/dist/behaviors/scroll-area.d.mts +17 -0
- package/dist/behaviors/scroll-area.mjs +59 -0
- package/dist/behaviors/select.mjs +8 -2
- package/dist/behaviors/slider.mjs +3 -3
- package/dist/behaviors/split-pane.mjs +2 -0
- package/dist/behaviors/suggestions.mjs +1 -0
- package/dist/behaviors/tabs.mjs +10 -0
- package/dist/behaviors/tag-input.mjs +1 -0
- package/dist/behaviors/theme-switcher.d.mts +2 -2
- package/dist/behaviors/theme-switcher.mjs +17 -2
- package/dist/behaviors/theme.mjs +16 -2
- package/dist/behaviors/toast.d.mts +2 -2
- package/dist/behaviors/toast.mjs +1 -0
- package/dist/behaviors/tree-select.mjs +14 -0
- package/dist/behaviors/tree.mjs +4 -4
- package/dist/behaviors/upload.mjs +1 -0
- package/dist/behaviors/url-safety.d.mts +8 -0
- package/dist/behaviors/url-safety.mjs +11 -0
- package/dist/components/accordion.d.mts +2 -0
- package/dist/components/ai-branch.d.mts +2 -0
- package/dist/components/ai-chat.css +40 -33
- package/dist/components/ai-chat.d.mts +2 -0
- package/dist/components/ai-composer.d.mts +2 -0
- package/dist/components/ai-context.d.mts +2 -0
- package/dist/components/ai-context.mjs +1 -0
- package/dist/components/ai-diff.css +6 -6
- package/dist/components/ai-diff.d.mts +2 -0
- package/dist/components/ai-feedback.d.mts +2 -0
- package/dist/components/ai-files.d.mts +2 -0
- package/dist/components/ai-message.d.mts +2 -0
- package/dist/components/ai-panel.css +12 -10
- package/dist/components/ai-reasoning.d.mts +2 -0
- package/dist/components/ai-subagent.d.mts +2 -0
- package/dist/components/ai-subagent.mjs +1 -0
- package/dist/components/ai-threads.d.mts +2 -0
- package/dist/components/ai-todo.d.mts +2 -0
- package/dist/components/ai-todo.mjs +1 -0
- package/dist/components/ai-tool-call.d.mts +2 -0
- package/dist/components/ai-tool-call.mjs +1 -0
- package/dist/components/ai-tool.css +16 -16
- package/dist/components/ai-usage.d.mts +2 -0
- package/dist/components/alert.d.mts +2 -0
- package/dist/components/autocomplete.css +12 -12
- package/dist/components/autocomplete.d.mts +2 -0
- package/dist/components/avatar.d.mts +2 -0
- package/dist/components/back-top.css +47 -16
- package/dist/components/back-top.d.mts +2 -0
- package/dist/components/badge.css +1 -1
- package/dist/components/badge.d.mts +2 -0
- package/dist/components/breadcrumb.css +26 -8
- package/dist/components/breadcrumb.d.mts +2 -0
- package/dist/components/btn.css +67 -62
- package/dist/components/btn.d.mts +2 -0
- package/dist/components/card.css +22 -22
- package/dist/components/card.d.mts +2 -0
- package/dist/components/carousel.d.mts +2 -0
- package/dist/components/cascader.css +56 -35
- package/dist/components/cascader.d.mts +2 -0
- package/dist/components/chart-area.css +46 -0
- package/dist/components/chart-area.d.mts +2 -0
- package/dist/components/chart-bar.css +66 -19
- package/dist/components/chart-bar.d.mts +2 -0
- package/dist/components/chart-calendar.d.mts +2 -0
- package/dist/components/chart-gauge.css +23 -3
- package/dist/components/chart-gauge.d.mts +2 -0
- package/dist/components/chart-graph.css +15 -3
- package/dist/components/chart-graph.d.mts +2 -0
- package/dist/components/chart-heatmap.css +117 -95
- package/dist/components/chart-heatmap.d.mts +2 -0
- package/dist/components/chart-line.css +54 -0
- package/dist/components/chart-line.d.mts +2 -0
- package/dist/components/chart-map.d.mts +2 -0
- package/dist/components/chart-pie.css +29 -0
- package/dist/components/chart-pie.d.mts +2 -0
- package/dist/components/chart-radar.css +50 -1
- package/dist/components/chart-radar.d.mts +2 -0
- package/dist/components/chart-scatter.css +39 -2
- package/dist/components/chart-scatter.d.mts +2 -0
- package/dist/components/chart-sparkline.css +20 -0
- package/dist/components/chart-sparkline.d.mts +2 -0
- package/dist/components/chart-stack.css +16 -5
- package/dist/components/chart-stack.d.mts +2 -0
- package/dist/components/charts.css +80 -35
- package/dist/components/charts.d.mts +2 -0
- package/dist/components/code-block.css +10 -8
- package/dist/components/code-block.d.mts +2 -0
- package/dist/components/command-palette.css +45 -38
- package/dist/components/command-palette.d.mts +2 -0
- package/dist/components/content.css +62 -57
- package/dist/components/context-menu.d.mts +2 -0
- package/dist/components/copy.css +10 -10
- package/dist/components/copy.d.mts +2 -0
- package/dist/components/datatable.css +72 -59
- package/dist/components/datatable.d.mts +2 -0
- package/dist/components/date-picker.css +26 -26
- package/dist/components/date-picker.d.mts +2 -0
- package/dist/components/desc.d.mts +2 -0
- package/dist/components/dropdown.d.mts +2 -0
- package/dist/components/empty.css +16 -16
- package/dist/components/empty.d.mts +2 -0
- package/dist/components/feedback.css +31 -29
- package/dist/components/form-validate.css +20 -6
- package/dist/components/form-validate.d.mts +2 -0
- package/dist/components/form.css +17 -14
- package/dist/components/form.d.mts +2 -0
- package/dist/components/icon.css +21 -10
- package/dist/components/icon.d.mts +2 -0
- package/dist/components/input.css +22 -22
- package/dist/components/input.d.mts +2 -0
- package/dist/components/kb-access.d.mts +2 -0
- package/dist/components/kb-acl.d.mts +2 -0
- package/dist/components/kb-agent.css +134 -55
- package/dist/components/kb-answer.d.mts +2 -0
- package/dist/components/kb-audit.d.mts +2 -0
- package/dist/components/kb-canvas.d.mts +2 -0
- package/dist/components/kb-chain.d.mts +2 -0
- package/dist/components/kb-checkpoint.d.mts +2 -0
- package/dist/components/kb-chunks.d.mts +2 -0
- package/dist/components/kb-citation.d.mts +2 -0
- package/dist/components/kb-clarify.d.mts +2 -0
- package/dist/components/kb-conflict.d.mts +2 -0
- package/dist/components/kb-connector.d.mts +2 -0
- package/dist/components/kb-data.css +192 -80
- package/dist/components/kb-eval.d.mts +2 -0
- package/dist/components/kb-explain.d.mts +2 -0
- package/dist/components/kb-filter.d.mts +2 -0
- package/dist/components/kb-gap.d.mts +2 -0
- package/dist/components/kb-ground.css +165 -73
- package/dist/components/kb-hittest.d.mts +2 -0
- package/dist/components/kb-ingest.css +308 -113
- package/dist/components/kb-metadata.d.mts +2 -0
- package/dist/components/kb-ops.css +189 -75
- package/dist/components/kb-passage.d.mts +2 -0
- package/dist/components/kb-perm.css +158 -87
- package/dist/components/kb-pipeline.d.mts +2 -0
- package/dist/components/kb-qa.d.mts +2 -0
- package/dist/components/kb-rerank.d.mts +2 -0
- package/dist/components/kb-retrieval.d.mts +2 -0
- package/dist/components/kb-review.d.mts +2 -0
- package/dist/components/kb-sandbox.d.mts +2 -0
- package/dist/components/kb-search.css +353 -116
- package/dist/components/kb-segment.d.mts +2 -0
- package/dist/components/kb-sources.d.mts +2 -0
- package/dist/components/kb-sql.d.mts +2 -0
- package/dist/components/kb-trace.d.mts +2 -0
- package/dist/components/kb-visibility.d.mts +2 -0
- package/dist/components/kb-who-can.d.mts +2 -0
- package/dist/components/kb.css +60 -36
- package/dist/components/kb.d.mts +2 -0
- package/dist/components/kbd.d.mts +2 -0
- package/dist/components/layout.css +10 -10
- package/dist/components/layout.d.mts +2 -0
- package/dist/components/list.d.mts +2 -0
- package/dist/components/material-chinese.css +10 -0
- package/dist/components/material-soviet.css +10 -0
- package/dist/components/material.css +61 -18
- package/dist/components/media-card.d.mts +2 -0
- package/dist/components/media.css +22 -27
- package/dist/components/mentions.css +18 -17
- package/dist/components/mentions.d.mts +2 -0
- package/dist/components/menu.css +32 -28
- package/dist/components/modal.css +30 -27
- package/dist/components/modal.d.mts +2 -0
- package/dist/components/nav.css +48 -44
- package/dist/components/nav.d.mts +2 -0
- package/dist/components/notification.css +31 -25
- package/dist/components/notification.d.mts +2 -0
- package/dist/components/pagination.css +15 -13
- package/dist/components/pagination.d.mts +2 -0
- package/dist/components/panel.css +19 -20
- package/dist/components/panel.d.mts +2 -0
- package/dist/components/pill.css +8 -7
- package/dist/components/pill.d.mts +2 -0
- package/dist/components/popover.css +32 -23
- package/dist/components/popover.d.mts +2 -0
- package/dist/components/progress.d.mts +2 -0
- package/dist/components/rating.d.mts +2 -0
- package/dist/components/result.d.mts +2 -0
- package/dist/components/scroll-area.css +84 -112
- package/dist/components/scroll-area.d.mts +2 -0
- package/dist/components/scroll-area.mjs +1 -0
- package/dist/components/segmented.css +47 -29
- package/dist/components/segmented.d.mts +2 -0
- package/dist/components/select.css +80 -41
- package/dist/components/select.d.mts +2 -0
- package/dist/components/sidebar.css +42 -38
- package/dist/components/sidebar.d.mts +2 -0
- package/dist/components/skeleton.d.mts +2 -0
- package/dist/components/slider.css +26 -22
- package/dist/components/slider.d.mts +2 -0
- package/dist/components/spinner.d.mts +2 -0
- package/dist/components/split-pane.css +16 -7
- package/dist/components/split-pane.d.mts +2 -0
- package/dist/components/stat.css +17 -16
- package/dist/components/stat.d.mts +2 -0
- package/dist/components/steps.css +26 -26
- package/dist/components/steps.d.mts +2 -0
- package/dist/components/switch.css +78 -39
- package/dist/components/switch.d.mts +2 -0
- package/dist/components/table.css +54 -32
- package/dist/components/table.d.mts +2 -0
- package/dist/components/tabs.css +53 -32
- package/dist/components/tabs.d.mts +2 -0
- package/dist/components/tag-input.css +12 -8
- package/dist/components/tag-input.d.mts +2 -0
- package/dist/components/tag.css +20 -12
- package/dist/components/tag.d.mts +2 -0
- package/dist/components/theme-switcher.css +7 -7
- package/dist/components/theme-switcher.d.mts +2 -0
- package/dist/components/timeline.d.mts +2 -0
- package/dist/components/toast.css +34 -30
- package/dist/components/toast.d.mts +2 -0
- package/dist/components/toolbar.css +19 -18
- package/dist/components/toolbar.d.mts +2 -0
- package/dist/components/tooltip.css +9 -8
- package/dist/components/tooltip.d.mts +2 -0
- package/dist/components/tree-select.css +63 -40
- package/dist/components/tree-select.d.mts +2 -0
- package/dist/components/tree.d.mts +2 -0
- package/dist/components/upload.css +9 -11
- package/dist/components/upload.d.mts +2 -0
- package/dist/index.d.mts +85 -84
- package/dist/index.mjs +14764 -14311
- package/dist/react.d.mts +18 -18
- package/dist/react.mjs +135 -36
- package/dist/registry.json +795 -64
- package/dist/tokens/colors.css +6 -0
- package/dist/tokens/design.css +130 -30
- package/dist/tokens/dtcg.json +6189 -1461
- package/dist/tokens/figma.variables.json +4107 -345
- package/dist/tokens/pixel.css +3 -0
- package/dist/tokens/scrollbars.css +40 -0
- package/dist/tokens/tokens-studio.json +5191 -271
- package/dist/tokens.css +304 -81
- package/dist/ui.css +4050 -2148
- package/dist/vue.d.mts +17 -17
- package/dist/vue.mjs +129 -34
- package/docs/spec/design-philosophy.md +5 -5
- package/docs/spec/design-primitives.md +10 -10
- package/docs/spec/scrollbars.md +46 -0
- package/package.json +16 -3
package/dist/vue.d.mts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { AiClient, AiAuditor } from './behaviors/ai-provider.
|
|
1
|
+
import { AiClient, AiAuditor } from './behaviors/ai-provider.mjs';
|
|
2
2
|
import * as vue from 'vue';
|
|
3
3
|
import { PropType, Ref } from 'vue';
|
|
4
|
-
import { IcenEventMap } from './behaviors/events.
|
|
5
|
-
import { ChartSpec } from './behaviors/charts.
|
|
6
|
-
export { ChartHandle } from './behaviors/charts.
|
|
7
|
-
import { TableOptions } from './behaviors/datatable.
|
|
8
|
-
export { TableColumn, TableHandle } from './behaviors/datatable.
|
|
9
|
-
import { AiMessageModel } from './behaviors/ai-chat.
|
|
10
|
-
export { AiMessageHandle } from './behaviors/ai-chat.
|
|
11
|
-
import { AiProviderOption, AiComposerCurrentModel, AiComposerBindOpts } from './behaviors/ai-composer.
|
|
12
|
-
export { AiContent, AiContentPart, AiStatus, AiToolCallModel, AiUsage } from './behaviors/ai-core.
|
|
13
|
-
import './behaviors/mentions.
|
|
14
|
-
import './behaviors/suggestions.
|
|
15
|
-
import './behaviors/kb-core.
|
|
16
|
-
import './behaviors/icons.
|
|
17
|
-
import './behaviors/popover.
|
|
18
|
-
import './behaviors/ai-panel.
|
|
19
|
-
import './behaviors/context-menu.
|
|
4
|
+
import { IcenEventMap } from './behaviors/events.mjs';
|
|
5
|
+
import { ChartSpec } from './behaviors/charts.mjs';
|
|
6
|
+
export { ChartHandle } from './behaviors/charts.mjs';
|
|
7
|
+
import { TableOptions } from './behaviors/datatable.mjs';
|
|
8
|
+
export { TableColumn, TableHandle } from './behaviors/datatable.mjs';
|
|
9
|
+
import { AiMessageModel } from './behaviors/ai-chat.mjs';
|
|
10
|
+
export { AiMessageHandle } from './behaviors/ai-chat.mjs';
|
|
11
|
+
import { AiProviderOption, AiComposerCurrentModel, AiComposerBindOpts } from './behaviors/ai-composer.mjs';
|
|
12
|
+
export { AiContent, AiContentPart, AiStatus, AiToolCallModel, AiUsage } from './behaviors/ai-core.mjs';
|
|
13
|
+
import './behaviors/mentions.mjs';
|
|
14
|
+
import './behaviors/suggestions.mjs';
|
|
15
|
+
import './behaviors/kb-core.mjs';
|
|
16
|
+
import './behaviors/icons.mjs';
|
|
17
|
+
import './behaviors/popover.mjs';
|
|
18
|
+
import './behaviors/ai-panel.mjs';
|
|
19
|
+
import './behaviors/context-menu.mjs';
|
|
20
20
|
|
|
21
21
|
type MaybeRef<T> = T | Ref<T | null>;
|
|
22
22
|
type Cleanup = (() => void) | void;
|
package/dist/vue.mjs
CHANGED
|
@@ -168,6 +168,7 @@ var ICEN_LOCALE_ZH_CN = {
|
|
|
168
168
|
"aiChat.roleTool": "\u5DE5",
|
|
169
169
|
"aiChat.roleUser": "\u6211",
|
|
170
170
|
"aiChat.thinking": "\u601D\u8003 {p0}",
|
|
171
|
+
"aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
|
|
171
172
|
/* ── aiComposer ── */
|
|
172
173
|
"aiComposer.attachAgent": "\u4EE3\u7406",
|
|
173
174
|
"aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
|
|
@@ -1215,7 +1216,8 @@ function withChrome(el, opts, hasLegend, paint, state, extras) {
|
|
|
1215
1216
|
emitIcen(el, "icen:chart-legend-visibility", { visible: hidden ? false : true });
|
|
1216
1217
|
});
|
|
1217
1218
|
syncEye();
|
|
1218
|
-
head.append(title, eye);
|
|
1219
|
+
if (hasLegend) head.append(title, eye);
|
|
1220
|
+
else head.append(title);
|
|
1219
1221
|
el.append(head, body);
|
|
1220
1222
|
paint(body);
|
|
1221
1223
|
}
|
|
@@ -1316,7 +1318,7 @@ function renderVBar(el, opts) {
|
|
|
1316
1318
|
wrap.appendChild(track);
|
|
1317
1319
|
}
|
|
1318
1320
|
body.append(wrap, labelsRow(labelsUsed));
|
|
1319
|
-
if (seriesList.length > 1) body.appendChild(toggleLegend(seriesList.map((s, si) => ({ key: s.name
|
|
1321
|
+
if (seriesList.length > 1) body.appendChild(toggleLegend(seriesList.map((s, si) => ({ key: `${si}:${s.name}`, label: s.name, tone: s.tone ?? (si === 0 ? opts.tone : void 0), si })), wrap));
|
|
1320
1322
|
});
|
|
1321
1323
|
attachChartInteraction(el, "vbar");
|
|
1322
1324
|
return el;
|
|
@@ -1411,8 +1413,10 @@ function renderDonut(el, opts) {
|
|
|
1411
1413
|
"stroke-width": "14"
|
|
1412
1414
|
}));
|
|
1413
1415
|
let offset = 0;
|
|
1416
|
+
const gap = opts.segments.length > 1 ? 2.5 : 0;
|
|
1414
1417
|
opts.segments.forEach((seg, segIndex) => {
|
|
1415
|
-
const
|
|
1418
|
+
const arcLength = Math.max(0, seg.value / total * circumference);
|
|
1419
|
+
const dash = arcLength - Math.min(gap, arcLength * 0.1);
|
|
1416
1420
|
const arc = svgEl("circle", {
|
|
1417
1421
|
cx: "60",
|
|
1418
1422
|
cy: "60",
|
|
@@ -1426,7 +1430,7 @@ function renderDonut(el, opts) {
|
|
|
1426
1430
|
});
|
|
1427
1431
|
setMarkData(arc, { index: segIndex, label: seg.label, value: seg.value });
|
|
1428
1432
|
svg.appendChild(arc);
|
|
1429
|
-
offset +=
|
|
1433
|
+
offset += arcLength;
|
|
1430
1434
|
});
|
|
1431
1435
|
const legend = document.createElement("div");
|
|
1432
1436
|
legend.className = "icen-chart-legend";
|
|
@@ -1461,8 +1465,9 @@ function renderLine(el, opts) {
|
|
|
1461
1465
|
const svg = svgEl("svg", { viewBox: `0 0 ${width} ${height}`, role: "img", "aria-label": chartAriaLabel(opts.title, t("charts.type.line")) });
|
|
1462
1466
|
const defs = svgEl("defs", {});
|
|
1463
1467
|
for (let i = 0; i < 4; i++) {
|
|
1464
|
-
const y = pad + i * (height - pad * 2) / 3;
|
|
1468
|
+
const y = Math.round(pad + i * (height - pad * 2) / 3) + 0.5;
|
|
1465
1469
|
svg.appendChild(svgEl("line", {
|
|
1470
|
+
class: i === 3 ? "icen-chart-grid icen-chart-baseline" : "icen-chart-grid",
|
|
1466
1471
|
x1: String(pad),
|
|
1467
1472
|
x2: String(width - pad),
|
|
1468
1473
|
y1: String(y),
|
|
@@ -1546,7 +1551,7 @@ function renderLine(el, opts) {
|
|
|
1546
1551
|
if (defs.firstChild) svg.insertBefore(defs, svg.firstChild);
|
|
1547
1552
|
wrap.append(svg, pointLabelsRow(labelsUsed, width, pad));
|
|
1548
1553
|
body.appendChild(wrap);
|
|
1549
|
-
if (seriesList.length > 1) body.appendChild(toggleLegend(seriesList.map((s, si) => ({ key: s.name
|
|
1554
|
+
if (seriesList.length > 1) body.appendChild(toggleLegend(seriesList.map((s, si) => ({ key: `${si}:${s.name}`, label: s.name, tone: s.tone ?? (si === 0 ? opts.tone : void 0), si })), wrap));
|
|
1550
1555
|
});
|
|
1551
1556
|
if (el.dataset.icenChartBody == null) observeFluidWidth(el, () => renderLine(el, opts));
|
|
1552
1557
|
attachChartInteraction(el, "line");
|
|
@@ -1653,7 +1658,7 @@ function renderRadar(el, opts) {
|
|
|
1653
1658
|
setMarkData(dot, { index: i, seriesIndex: si, seriesName: s.name || void 0, label: axes[i] ?? "", value: s.values[i] ?? 0 });
|
|
1654
1659
|
svg.appendChild(dot);
|
|
1655
1660
|
}
|
|
1656
|
-
legendItems.push({ key: s.name || t("charts.seriesName", { p0: si + 1 })
|
|
1661
|
+
legendItems.push({ key: `${si}:${s.name || t("charts.seriesName", { p0: si + 1 })}`, label: s.name || t("charts.seriesName", { p0: si + 1 }), tone: s.tone, si });
|
|
1657
1662
|
});
|
|
1658
1663
|
wrap.appendChild(svg);
|
|
1659
1664
|
body.appendChild(wrap);
|
|
@@ -1675,6 +1680,11 @@ function niceCeil(v) {
|
|
|
1675
1680
|
else nice = 10;
|
|
1676
1681
|
return nice * base;
|
|
1677
1682
|
}
|
|
1683
|
+
function tickPrecision(min, max, steps) {
|
|
1684
|
+
const span = Math.abs(max - min);
|
|
1685
|
+
if (!Number.isFinite(span) || span <= 0) return 0;
|
|
1686
|
+
return Math.max(0, Math.ceil(-Math.log10(span / steps)));
|
|
1687
|
+
}
|
|
1678
1688
|
function isoDate(d) {
|
|
1679
1689
|
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
1680
1690
|
const day = String(d.getDate()).padStart(2, "0");
|
|
@@ -1770,7 +1780,8 @@ function renderSparkline(el, opts) {
|
|
|
1770
1780
|
const tone = toneVar(opts.tone);
|
|
1771
1781
|
const points = values.map((value, i) => ({
|
|
1772
1782
|
x: values.length <= 1 ? width / 2 : pad + i / (values.length - 1) * (width - pad * 2),
|
|
1773
|
-
|
|
1783
|
+
/* 负值钳到基线(与折线图同口径):viewBox 仅 28 高,反向射出更刺眼 */
|
|
1784
|
+
y: height - pad - Math.max(0, value) / max * (height - pad * 2),
|
|
1774
1785
|
value
|
|
1775
1786
|
}));
|
|
1776
1787
|
const line = points.map((p, i) => `${i === 0 ? "M" : "L"}${p.x.toFixed(1)},${p.y.toFixed(1)}`).join(" ");
|
|
@@ -1895,6 +1906,7 @@ function renderCalendar(el, opts) {
|
|
|
1895
1906
|
weekdayRow.appendChild(s);
|
|
1896
1907
|
});
|
|
1897
1908
|
const max = maxOf(entries.map((e) => e.value));
|
|
1909
|
+
entries.sort((a, b) => a.date.localeCompare(b.date));
|
|
1898
1910
|
const pad = padFirstWeek(grid, entries[0].date, weekStart);
|
|
1899
1911
|
let lastMonth = -1;
|
|
1900
1912
|
entries.forEach((entry, i) => {
|
|
@@ -1953,8 +1965,9 @@ function renderScatter(el, opts) {
|
|
|
1953
1965
|
const xAt = (x) => pad + (x - xMin) / (xMax - xMin) * (width - pad * 2);
|
|
1954
1966
|
const yAt = (y) => height - pad - (y - yMin) / (yMax - yMin) * (height - pad * 2);
|
|
1955
1967
|
for (let i = 0; i <= 3; i++) {
|
|
1956
|
-
const y = pad + i * (height - pad * 2) / 3;
|
|
1968
|
+
const y = Math.round(pad + i * (height - pad * 2) / 3) + 0.5;
|
|
1957
1969
|
svg.appendChild(svgEl("line", {
|
|
1970
|
+
class: i === 3 ? "icen-chart-grid icen-chart-baseline" : "icen-chart-grid",
|
|
1958
1971
|
x1: String(pad),
|
|
1959
1972
|
x2: String(width - pad),
|
|
1960
1973
|
y1: String(y),
|
|
@@ -1970,12 +1983,13 @@ function renderScatter(el, opts) {
|
|
|
1970
1983
|
"font-size": "8",
|
|
1971
1984
|
fill: "var(--icen-token-text-faint)"
|
|
1972
1985
|
});
|
|
1973
|
-
txt.textContent = fmt(opts,
|
|
1986
|
+
txt.textContent = fmt(opts, +tv.toFixed(tickPrecision(yMin, yMax, 3)));
|
|
1974
1987
|
svg.appendChild(txt);
|
|
1975
1988
|
}
|
|
1976
1989
|
for (let i = 0; i <= 4; i++) {
|
|
1977
|
-
const x = pad + i * (width - pad * 2) / 4;
|
|
1990
|
+
const x = Math.round(pad + i * (width - pad * 2) / 4) + 0.5;
|
|
1978
1991
|
svg.appendChild(svgEl("line", {
|
|
1992
|
+
class: i === 0 ? "icen-chart-grid icen-chart-grid--v icen-chart-axis" : "icen-chart-grid icen-chart-grid--v",
|
|
1979
1993
|
x1: String(x),
|
|
1980
1994
|
x2: String(x),
|
|
1981
1995
|
y1: String(pad),
|
|
@@ -1992,7 +2006,7 @@ function renderScatter(el, opts) {
|
|
|
1992
2006
|
"font-size": "8",
|
|
1993
2007
|
fill: "var(--icen-token-text-faint)"
|
|
1994
2008
|
});
|
|
1995
|
-
txt.textContent = fmt(opts,
|
|
2009
|
+
txt.textContent = fmt(opts, +tv.toFixed(tickPrecision(xMin, xMax, 4)));
|
|
1996
2010
|
svg.appendChild(txt);
|
|
1997
2011
|
}
|
|
1998
2012
|
if (opts.yLabel) {
|
|
@@ -2356,6 +2370,7 @@ function renderChartSkeleton(body) {
|
|
|
2356
2370
|
body.appendChild(box);
|
|
2357
2371
|
}
|
|
2358
2372
|
var CHART_MARK_ACCENT = "var(--icen-token-accent)";
|
|
2373
|
+
var CHART_MARK_ACCENT_TEXT = "var(--icen-token-accent-text)";
|
|
2359
2374
|
function markToneVar(tone) {
|
|
2360
2375
|
switch (tone) {
|
|
2361
2376
|
case "success":
|
|
@@ -2491,7 +2506,7 @@ function paintSvgChartMarks(root, view, marks, formatValue, warned) {
|
|
|
2491
2506
|
y: String(clampNum(y - 10, 8, CHART_LINE_H - 4)),
|
|
2492
2507
|
"text-anchor": "middle",
|
|
2493
2508
|
"font-size": "8",
|
|
2494
|
-
fill:
|
|
2509
|
+
fill: CHART_MARK_ACCENT_TEXT
|
|
2495
2510
|
});
|
|
2496
2511
|
label.textContent = mark.text ?? mark.label;
|
|
2497
2512
|
g.appendChild(label);
|
|
@@ -3049,6 +3064,12 @@ function renderChart(el, raw) {
|
|
|
3049
3064
|
const graphic = root.querySelector('[role="img"]');
|
|
3050
3065
|
if (graphic && !graphic.getAttribute("aria-label")) {
|
|
3051
3066
|
graphic.setAttribute("aria-label", spec.title ? `${spec.title}\uFF08${type}\uFF09` : type);
|
|
3067
|
+
} else if (!graphic) {
|
|
3068
|
+
const dom = root.querySelector(".icen-chart-vbar, .icen-chart-hbar");
|
|
3069
|
+
if (dom) {
|
|
3070
|
+
dom.setAttribute("role", "img");
|
|
3071
|
+
dom.setAttribute("aria-label", spec.title ? `${spec.title}\uFF08${type}\uFF09` : type);
|
|
3072
|
+
}
|
|
3052
3073
|
}
|
|
3053
3074
|
}
|
|
3054
3075
|
if (loading) return;
|
|
@@ -3761,7 +3782,13 @@ function onKeyDown2(e) {
|
|
|
3761
3782
|
|
|
3762
3783
|
// src/behaviors/datatable.ts
|
|
3763
3784
|
function defaultCompare(a, b) {
|
|
3764
|
-
if (typeof a === "number" && typeof b === "number")
|
|
3785
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
3786
|
+
if (Number.isNaN(a) || Number.isNaN(b)) {
|
|
3787
|
+
if (Number.isNaN(a) && Number.isNaN(b)) return 0;
|
|
3788
|
+
return Number.isNaN(a) ? 1 : -1;
|
|
3789
|
+
}
|
|
3790
|
+
return a - b;
|
|
3791
|
+
}
|
|
3765
3792
|
return String(a ?? "").localeCompare(String(b ?? ""), "zh-CN", { numeric: true });
|
|
3766
3793
|
}
|
|
3767
3794
|
function toNum2(v) {
|
|
@@ -4050,11 +4077,13 @@ function createTable(el, opts) {
|
|
|
4050
4077
|
const body = document.createElement("div");
|
|
4051
4078
|
body.className = "icen-dt-body";
|
|
4052
4079
|
body.setAttribute("role", "rowgroup");
|
|
4053
|
-
const summaryEl = document.createElement("div");
|
|
4054
|
-
summaryEl
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4080
|
+
const summaryEl = opts.summaryRow ? document.createElement("div") : null;
|
|
4081
|
+
if (summaryEl) {
|
|
4082
|
+
summaryEl.className = "icen-dt-row icen-dt-row--summary";
|
|
4083
|
+
summaryEl.setAttribute("role", "row");
|
|
4084
|
+
summaryEl.hidden = true;
|
|
4085
|
+
}
|
|
4086
|
+
canvas.append(head, body, ...summaryEl ? [summaryEl] : []);
|
|
4058
4087
|
scroll.appendChild(canvas);
|
|
4059
4088
|
root.appendChild(scroll);
|
|
4060
4089
|
const foot = document.createElement("div");
|
|
@@ -4868,6 +4897,7 @@ function createTable(el, opts) {
|
|
|
4868
4897
|
return wrap;
|
|
4869
4898
|
}
|
|
4870
4899
|
function renderSummary() {
|
|
4900
|
+
if (!summaryEl) return;
|
|
4871
4901
|
summaryEl.textContent = "";
|
|
4872
4902
|
summaryEl.hidden = true;
|
|
4873
4903
|
const cfg = opts.summaryRow;
|
|
@@ -5064,9 +5094,9 @@ function createTable(el, opts) {
|
|
|
5064
5094
|
}
|
|
5065
5095
|
}
|
|
5066
5096
|
let currentTotal = 0;
|
|
5067
|
-
function visibleRange(total) {
|
|
5097
|
+
function visibleRange(total, avail) {
|
|
5068
5098
|
if (!virtual) {
|
|
5069
|
-
if (opts.remote || opts.pagination === false) return [0, total];
|
|
5099
|
+
if (opts.remote || opts.pagination === false) return [0, Math.min(total, avail)];
|
|
5070
5100
|
const start2 = (page - 1) * pageSize;
|
|
5071
5101
|
return [start2, Math.min(total, start2 + pageSize)];
|
|
5072
5102
|
}
|
|
@@ -5081,6 +5111,10 @@ function createTable(el, opts) {
|
|
|
5081
5111
|
const rows = pipeline();
|
|
5082
5112
|
const entries = groupFn ? flatEntries() : null;
|
|
5083
5113
|
const total = entries ? entries.length : opts.remote ? opts.totalCount ?? data.length : rows.length;
|
|
5114
|
+
if (!opts.remote && opts.pagination !== false) {
|
|
5115
|
+
const pages = Math.max(1, Math.ceil(total / pageSize));
|
|
5116
|
+
if (page > pages) page = pages;
|
|
5117
|
+
}
|
|
5084
5118
|
navTotal = entries ? entries.length : rows.length;
|
|
5085
5119
|
currentTotal = total;
|
|
5086
5120
|
const keepTop = virtual ? scroll.scrollTop : 0;
|
|
@@ -5109,7 +5143,7 @@ function createTable(el, opts) {
|
|
|
5109
5143
|
renderSummary();
|
|
5110
5144
|
return;
|
|
5111
5145
|
}
|
|
5112
|
-
const [start, end] = visibleRange(total);
|
|
5146
|
+
const [start, end] = visibleRange(total, rows.length);
|
|
5113
5147
|
const frag = document.createDocumentFragment();
|
|
5114
5148
|
const offsets = frozenOffsets();
|
|
5115
5149
|
if (virtual && start > 0) {
|
|
@@ -5172,11 +5206,21 @@ function createTable(el, opts) {
|
|
|
5172
5206
|
const pages = Math.ceil(total / pageSize);
|
|
5173
5207
|
const pager = document.createElement("nav");
|
|
5174
5208
|
pager.className = "icen-dt-pager";
|
|
5175
|
-
|
|
5209
|
+
{
|
|
5210
|
+
const base = t("datatable.paginationAria");
|
|
5211
|
+
const used = /* @__PURE__ */ new Set();
|
|
5212
|
+
for (const el2 of document.querySelectorAll(".icen-dt-pager[aria-label]")) {
|
|
5213
|
+
if (!root.contains(el2)) used.add(el2.getAttribute("aria-label") ?? "");
|
|
5214
|
+
}
|
|
5215
|
+
let label = base, n = 2;
|
|
5216
|
+
while (used.has(label)) label = `${base} ${n++}`;
|
|
5217
|
+
pager.setAttribute("aria-label", label);
|
|
5218
|
+
}
|
|
5176
5219
|
const sizeSel = document.createElement("select");
|
|
5177
5220
|
sizeSel.className = "icen-dt-page-size";
|
|
5178
5221
|
sizeSel.setAttribute("aria-label", t("datatable.pageSizeAria"));
|
|
5179
|
-
|
|
5222
|
+
const sizeOptions = pageSizes.includes(pageSize) ? pageSizes : [...pageSizes, pageSize].sort((a, b) => a - b);
|
|
5223
|
+
for (const s of sizeOptions) {
|
|
5180
5224
|
const o = document.createElement("option");
|
|
5181
5225
|
o.value = String(s);
|
|
5182
5226
|
o.textContent = t("pagination.pageSize", { p0: s });
|
|
@@ -5268,6 +5312,7 @@ function createTable(el, opts) {
|
|
|
5268
5312
|
if (destroyed) return;
|
|
5269
5313
|
renderHead();
|
|
5270
5314
|
renderBody();
|
|
5315
|
+
syncFrozenWidths();
|
|
5271
5316
|
}
|
|
5272
5317
|
rekey();
|
|
5273
5318
|
renderAll();
|
|
@@ -5288,12 +5333,52 @@ function createTable(el, opts) {
|
|
|
5288
5333
|
opts.onPageChange?.(page, pageSize);
|
|
5289
5334
|
renderAll();
|
|
5290
5335
|
}
|
|
5336
|
+
function hasFluidFrozen() {
|
|
5337
|
+
return cols().some((c) => frozenSide(c) != null && !/^(\d+(?:\.\d+)?)px/.test(colWidths.get(c.key) ?? c.width ?? ""));
|
|
5338
|
+
}
|
|
5339
|
+
function syncFrozenWidths() {
|
|
5340
|
+
if (!hasFluidFrozen()) return;
|
|
5341
|
+
const visible = cols();
|
|
5342
|
+
const headCells = Array.from(headRow.children);
|
|
5343
|
+
const lead = headCells.length - visible.length;
|
|
5344
|
+
const left = /* @__PURE__ */ new Map();
|
|
5345
|
+
const right = /* @__PURE__ */ new Map();
|
|
5346
|
+
let acc = headCells.slice(0, lead).reduce((s, c) => s + c.offsetWidth, 0);
|
|
5347
|
+
for (let i = 0; i < visible.length; i++) {
|
|
5348
|
+
const c = visible[i];
|
|
5349
|
+
if (frozenSide(c) === "left") left.set(c.key, acc);
|
|
5350
|
+
acc += headCells[lead + i]?.offsetWidth ?? 0;
|
|
5351
|
+
}
|
|
5352
|
+
let accR = 0;
|
|
5353
|
+
for (let i = visible.length - 1; i >= 0; i--) {
|
|
5354
|
+
const c = visible[i];
|
|
5355
|
+
if (frozenSide(c) === "right") right.set(c.key, accR);
|
|
5356
|
+
accR += headCells[lead + i]?.offsetWidth ?? 0;
|
|
5357
|
+
}
|
|
5358
|
+
const rows = [headRow, ...summaryEl ? [summaryEl] : [], ...Array.from(body.querySelectorAll(".icen-dt-row"))];
|
|
5359
|
+
for (const row of rows) {
|
|
5360
|
+
const cells = Array.from(row.children);
|
|
5361
|
+
if (cells.length !== headCells.length) continue;
|
|
5362
|
+
cells.forEach((cell, i) => {
|
|
5363
|
+
const col = i >= lead ? visible[i - lead] : void 0;
|
|
5364
|
+
if (!col) return;
|
|
5365
|
+
const l = left.get(col.key);
|
|
5366
|
+
if (l != null && cell.classList.contains("icen-dt-cell--frozen")) cell.style.left = `${l}px`;
|
|
5367
|
+
const r = right.get(col.key);
|
|
5368
|
+
if (r != null && cell.classList.contains("icen-dt-cell--frozen-right")) cell.style.right = `${r}px`;
|
|
5369
|
+
});
|
|
5370
|
+
}
|
|
5371
|
+
}
|
|
5291
5372
|
return {
|
|
5292
5373
|
setPage,
|
|
5293
5374
|
setPageSize,
|
|
5294
5375
|
setData(next) {
|
|
5295
5376
|
if (editing) cancelEdit(true);
|
|
5296
5377
|
data = next;
|
|
5378
|
+
if (typeof opts.rowKey !== "function" && typeof opts.rowKey !== "string" && selected.size > 0) {
|
|
5379
|
+
selected.clear();
|
|
5380
|
+
emitSelection();
|
|
5381
|
+
}
|
|
5297
5382
|
rekey();
|
|
5298
5383
|
invalidate();
|
|
5299
5384
|
page = 1;
|
|
@@ -5536,6 +5621,15 @@ function svgIcon(svg) {
|
|
|
5536
5621
|
return parseSvg(svg);
|
|
5537
5622
|
}
|
|
5538
5623
|
|
|
5624
|
+
// src/behaviors/url-safety.ts
|
|
5625
|
+
function safeUrl(uri) {
|
|
5626
|
+
const s = uri.replace(/[\t\n\r\0-\x1f\x7f]/g, "").trim().toLowerCase();
|
|
5627
|
+
if (!s) return void 0;
|
|
5628
|
+
if (s.startsWith("javascript:") || s.startsWith("vbscript:")) return void 0;
|
|
5629
|
+
if (/^data:\s*text\/html/.test(s)) return void 0;
|
|
5630
|
+
return uri;
|
|
5631
|
+
}
|
|
5632
|
+
|
|
5539
5633
|
// src/behaviors/ai-chat.ts
|
|
5540
5634
|
var ICON_COPY = iconHTML("copy");
|
|
5541
5635
|
var ICON_RETRY = iconHTML("refresh");
|
|
@@ -5563,6 +5657,8 @@ function createAiStream(el) {
|
|
|
5563
5657
|
el.setAttribute("aria-busy", "true");
|
|
5564
5658
|
if (reasoning) {
|
|
5565
5659
|
reasoning.classList.add("is-streaming");
|
|
5660
|
+
const timeEl = reasoning.querySelector(".icen-ai-reasoning-time");
|
|
5661
|
+
if (timeEl) timeEl.textContent = t("aiChat.thinkingNow");
|
|
5566
5662
|
setReasoningOpen(reasoning, true);
|
|
5567
5663
|
const head = reasoning.querySelector(".icen-ai-reasoning-head");
|
|
5568
5664
|
if (head && head.dataset.icenReasoningStart == null) head.dataset.icenReasoningStart = String(startedAt);
|
|
@@ -5650,10 +5746,9 @@ var ROLE_AVATAR = {
|
|
|
5650
5746
|
system: t("aiChat.roleSystem"),
|
|
5651
5747
|
tool: t("aiChat.roleTool")
|
|
5652
5748
|
};
|
|
5653
|
-
function
|
|
5654
|
-
const
|
|
5655
|
-
|
|
5656
|
-
return uri;
|
|
5749
|
+
function safeContentUrl(part) {
|
|
5750
|
+
const src = aiContentUrl(part);
|
|
5751
|
+
return src ? safeUrl(src) : void 0;
|
|
5657
5752
|
}
|
|
5658
5753
|
function renderAiContentPart(part) {
|
|
5659
5754
|
if (part.type === "text") {
|
|
@@ -5663,7 +5758,7 @@ function renderAiContentPart(part) {
|
|
|
5663
5758
|
return span;
|
|
5664
5759
|
}
|
|
5665
5760
|
if (part.type === "image") {
|
|
5666
|
-
const src =
|
|
5761
|
+
const src = safeContentUrl(part);
|
|
5667
5762
|
if (!src) return void 0;
|
|
5668
5763
|
const img = document.createElement("img");
|
|
5669
5764
|
img.className = "icen-ai-msg-media icen-ai-msg-media--image";
|
|
@@ -5673,7 +5768,7 @@ function renderAiContentPart(part) {
|
|
|
5673
5768
|
return img;
|
|
5674
5769
|
}
|
|
5675
5770
|
if (part.type === "audio") {
|
|
5676
|
-
const src =
|
|
5771
|
+
const src = safeContentUrl(part);
|
|
5677
5772
|
if (!src) return void 0;
|
|
5678
5773
|
const audio = document.createElement("audio");
|
|
5679
5774
|
audio.className = "icen-ai-msg-media icen-ai-msg-media--audio";
|
|
@@ -5682,7 +5777,7 @@ function renderAiContentPart(part) {
|
|
|
5682
5777
|
return audio;
|
|
5683
5778
|
}
|
|
5684
5779
|
if (part.type === "video") {
|
|
5685
|
-
const src =
|
|
5780
|
+
const src = safeContentUrl(part);
|
|
5686
5781
|
if (!src) return void 0;
|
|
5687
5782
|
const video = document.createElement("video");
|
|
5688
5783
|
video.className = "icen-ai-msg-media icen-ai-msg-media--video";
|
|
@@ -5694,7 +5789,7 @@ function renderAiContentPart(part) {
|
|
|
5694
5789
|
if (part.type === "file") {
|
|
5695
5790
|
const chip = h("span", "icen-ai-msg-file");
|
|
5696
5791
|
chip.appendChild(h("span", "ai-msg-file-name", part.filename ?? t("aiChat.file")));
|
|
5697
|
-
const href2 = part.url ?
|
|
5792
|
+
const href2 = part.url ? safeUrl(part.url) : void 0;
|
|
5698
5793
|
if (href2 && /^(https?:|data:)/i.test(href2)) {
|
|
5699
5794
|
const a2 = document.createElement("a");
|
|
5700
5795
|
a2.className = "icen-ai-msg-file-link";
|
|
@@ -5707,7 +5802,7 @@ function renderAiContentPart(part) {
|
|
|
5707
5802
|
}
|
|
5708
5803
|
const a = document.createElement("a");
|
|
5709
5804
|
a.className = "icen-ai-msg-link";
|
|
5710
|
-
const href =
|
|
5805
|
+
const href = safeUrl(part.uri);
|
|
5711
5806
|
if (href) a.href = href;
|
|
5712
5807
|
a.textContent = part.name ?? part.uri;
|
|
5713
5808
|
a.title = part.uri;
|
|
@@ -5769,7 +5864,7 @@ function renderAiMessage(scrollEl, model) {
|
|
|
5769
5864
|
errEl.textContent = message;
|
|
5770
5865
|
},
|
|
5771
5866
|
stream() {
|
|
5772
|
-
const span = h("span", "ai-msg-stream-text");
|
|
5867
|
+
const span = h("span", "icen-ai-msg-text ai-msg-stream-text");
|
|
5773
5868
|
body.appendChild(span);
|
|
5774
5869
|
return createAiStream(span);
|
|
5775
5870
|
}
|
|
@@ -47,11 +47,11 @@ GitHub Primer 的语义色纪律、Radix Colors 的阶梯尺、Stripe 的"深档
|
|
|
47
47
|
### 2.1 圆角六档职责
|
|
48
48
|
| 档 | 现代默认值(随 design-radius 联动) | 职责 |
|
|
49
49
|
|---|---|---|
|
|
50
|
-
| `xs` |
|
|
51
|
-
| `sm` | 8px |
|
|
52
|
-
| `md` | 10px |
|
|
53
|
-
| `lg` |
|
|
54
|
-
| `xl` |
|
|
50
|
+
| `xs` | 5px | 微型件内角:复选框、菜单项、日期格、小标签 |
|
|
51
|
+
| `sm` | 8px | 控件:按钮、输入框、选择器 |
|
|
52
|
+
| `md` | 10px | 内嵌块、大控件 |
|
|
53
|
+
| `lg` | 14px | 卡片、面板、菜单与 popover |
|
|
54
|
+
| `xl` | 20px | 弹窗与页面级展示面 |
|
|
55
55
|
| `full` | 999px | **胶囊语义专用**(跑道形) |
|
|
56
56
|
|
|
57
57
|
### 2.2 同心圆法则(Concentric Corners,取法 Apple HIG)
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
1. **作者种子** `--icen-design-*`:品牌色、表面、文字、几何、节奏、字体、材料参数。
|
|
24
24
|
2. **语义映射**:推导已有 `--icen-token-* / --icen-radius-* / --icen-density-*`,让现有组件受益。
|
|
25
|
-
3. **材料角色**:content / chrome / floating
|
|
25
|
+
3. **材料角色**:content / chrome / floating,共享边缘、实面和阴影配方。
|
|
26
26
|
4. **组件适配**:按钮、输入、分段选择、菜单、弹窗等,处理仅靠变量无法表达的细节。
|
|
27
27
|
|
|
28
28
|
现代主题为中性瓷白+冷蓝,独立校准,不继承其它主题的配色。
|
|
@@ -40,12 +40,12 @@
|
|
|
40
40
|
| 角色 | 背景 | 光与影 | 用途 |
|
|
41
41
|
| --- | --- | --- | --- |
|
|
42
42
|
| content | 不透明 | 轻边界,不投影 | 阅读与编辑 |
|
|
43
|
-
| chrome |
|
|
44
|
-
| floating |
|
|
43
|
+
| chrome | 不透明 | 顶部微光 | 导航与操作 |
|
|
44
|
+
| floating | 不透明 | 接触影+环境影+顶部微光 | 临时面板 |
|
|
45
45
|
|
|
46
46
|
布局、定位和内边距归业务页面。材料不携带固定宽高,不强行让所有内容成为卡片。`data-icen-material` 的通用外轮廓使用 lg 圆角;需要贴边的站栏可由布局覆盖。
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
modern 的内容、操作与临时面板始终使用不透明表面,不启用背景模糊。`glass-*` 参数保留供自有材料和既有品牌配方兼容使用;不会让 modern 的标准操作面变成玻璃。`prefers-reduced-transparency: reduce` 与 `<html data-icen-transparency="reduced">` 继续提供跨原语的实面降级。
|
|
49
49
|
|
|
50
50
|
## 修改与新增品牌
|
|
51
51
|
|
|
@@ -115,9 +115,9 @@ setDesign(brand.name);
|
|
|
115
115
|
| success / warning / error / info | 明暗各有独立值,见源码 | 语义色 |
|
|
116
116
|
| radius | 10px | 六档轮廓的共同起点 |
|
|
117
117
|
| space | 4px | 布局节奏单位 |
|
|
118
|
-
| control-height |
|
|
119
|
-
| font-size / font |
|
|
120
|
-
| glass-opacity / glass-blur |
|
|
118
|
+
| control-height | 34px | 标准操作高度(density compact 28 / comfortable 38) |
|
|
119
|
+
| font-size / font | 13px / 系统无衬线 | 界面阅读基准;中文下限 12px |
|
|
120
|
+
| glass-opacity / glass-blur | 84% / 24px;90% / 24px | 自有材料的兼容参数,modern 标准组件不消费模糊 |
|
|
121
121
|
| shadow-color / shadow-strength | 中性灰 11%;黑 28% | 接触影与环境影 |
|
|
122
122
|
| light / highlight-strength | 白 70%;白 9% | 表面边缘光 |
|
|
123
123
|
| edge-strength | 12% / 14% | 材料边界 |
|
|
@@ -128,8 +128,8 @@ CSS 作者可以直接覆盖全部种子;类型 API 暴露常用旋钮,并
|
|
|
128
128
|
## 现代的具体判断
|
|
129
129
|
|
|
130
130
|
- **文字**:界面系统无衬线;代码单独等宽;数据才使用 tabular-nums。取消全局 Numeric Math 混排。正文阅读可在业务排版中提高到 16px。
|
|
131
|
-
- **几何**:xs/sm/md/lg/xl
|
|
132
|
-
- **密度**:normal / compact / comfortable 改变间距和控件高度,不缩小文字;嵌套密度可恢复 normal。触摸环境控件至少 44px。
|
|
131
|
+
- **几何**:xs/sm/md/lg/xl 为 5/8/10/14/20px,从共同基准推导。控件 8px、卡片与面板 14px、弹窗 20px;贴合内外轮廓同心,独立控件保留自身半径。分段选择内角扣掉外壳 padding 与边框。
|
|
132
|
+
- **密度**:normal / compact / comfortable 改变间距和控件高度,不缩小文字;嵌套密度可恢复 normal。触摸环境控件至少 44px。KB 行内操作使用 `--icen-density-item-height`(normal 28 / compact 24 / comfortable 32px),嵌套密度重新计算字号角色。
|
|
133
133
|
- **反馈**:hover 以中性变化为主,主要动作用品牌色;键盘焦点始终明确。按压轻缩放,减少位置漂移。
|
|
134
134
|
- **选择**:分段选择使用中性表面和接触影,不把每次选择都变成品牌强调。
|
|
135
135
|
- **光照**:暗色保留遮挡阴影,降低高光并重新设置边缘,避免照搬亮色投影。
|
|
@@ -149,7 +149,7 @@ CSS 作者可以直接覆盖全部种子;类型 API 暴露常用旋钮,并
|
|
|
149
149
|
|
|
150
150
|
运行时使用 `setPrimitive("pixel")`;自建原语先 `registerPrimitive("brand-shape")`,再用 `[data-icen-style="brand-shape"]` 覆盖几何、字体、光影参数。主题仍单独由 setTheme({preset:...}) 选择。
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
现代实现以内容/操作分层、同心几何、文字可读性为准则;使用稳定实面、细边与接触影建立空间。
|
|
153
153
|
|
|
154
154
|
## 中式与苏式原语
|
|
155
155
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# 滚动条
|
|
2
|
+
|
|
3
|
+
全局使用原生滚动条,不替换滚动容器、不拦截滚轮、不模拟滑块。Chromium/WebKit 使用统一无箭头样式;Firefox 使用标准细滚动条,具体几何由浏览器和系统控制。浏览器、系统或强制颜色模式的可访问性设置可覆盖皮肤。
|
|
4
|
+
|
|
5
|
+
标准 `scrollbar-color` / `scrollbar-width` 的非 auto 值会覆盖 WebKit 伪元素皮肤,因此支持伪元素的浏览器使用 auto 值以保留无箭头规则;其余浏览器使用标准属性回退。参考 [MDN scrollbar-color](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/scrollbar-color) 与 [WebKit 滚动条说明](https://webkit.org/blog/363/styling-scrollbars/)。
|
|
6
|
+
|
|
7
|
+
全量引入 `@icen.ai/ui/ui.css` 即包含样式。按需引入时使用 `tokens.css` + `base.css`,再加需要的组件 CSS;`kit/scroll-area` 导出行为和容器样式,仍需上述全局底座。只引 CSS 时保持可见。启用闲置策略:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { initScrollArea } from '@icen.ai/ui/behaviors/scroll-area';
|
|
11
|
+
const dispose = initScrollArea(); // 文档委托,接管之后插入的原生滚动区与 portal
|
|
12
|
+
// 或 initScrollArea({ root: element, idleDelay: 1200 })
|
|
13
|
+
// 卸载时 dispose():移除监听、清理定时器并恢复状态属性
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
| `data-icen-scrollbars` | 滚动时 | 悬停时 | 聚焦时 | 闲置后 |
|
|
17
|
+
| --- | --- | --- | --- | --- |
|
|
18
|
+
| `auto` | 显示 | 容器悬停时显示 | 显示 | 指针离开且失焦后隐藏 |
|
|
19
|
+
| `scroll`(启用行为后的默认) | 显示 | 不唤醒 | 显示 | 未聚焦时隐藏 |
|
|
20
|
+
| `visible` | 显示 | 显示 | 显示 | 显示 |
|
|
21
|
+
| `hidden` | 隐藏 | 隐藏 | 隐藏 | 隐藏,仍可滚动 |
|
|
22
|
+
|
|
23
|
+
策略在子树继承,嵌套组件可另设模式。默认 scroll 下,指针停在内容区不阻止闲置隐藏;菜单等需要悬停时保持可见的区域可显式使用 auto。文档根滚动条不因整页悬停一直亮起。无溢出时浏览器不绘制滑块。闲置策略只改变颜色,不反复增减宽度,因此停止滚动时不会造成内容跳动。`hidden` 会取消滚动条占位,适合已有其他导航提示的区域。需要持续位置提示时用 visible。需要直接键盘滚动的普通容器应提供 `tabindex="0"` 和名称。
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<div class="icen-scroll-area" tabindex="0" aria-label="运行日志"
|
|
27
|
+
data-icen-scrollbars="scroll" data-icen-scrollbar-delay="1200"
|
|
28
|
+
data-icen-scrollbar-gutter="stable"
|
|
29
|
+
style="max-height:20rem; --icen-token-scrollbar-size:10px">
|
|
30
|
+
…
|
|
31
|
+
</div>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
| 局部控制槽 | 默认 | 用途 |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| `--icen-token-scrollbar-size` | 8px | 双轴尺寸;`--sm` 6px、`--lg` 12px |
|
|
37
|
+
| `--icen-token-scrollbar-inset` | 2px | 滑块与槽边的透明内距 |
|
|
38
|
+
| `--icen-token-scrollbar-track` | transparent | 轨道颜色 |
|
|
39
|
+
| `--icen-token-scrollbar-thumb` / `-thumb-hover` | 当前主题墨色混合 | 默认/悬停滑块颜色 |
|
|
40
|
+
| `--icen-token-scrollbar-idle-delay` | 900ms | 停止滚动多久后隐藏 |
|
|
41
|
+
| `--icen-token-scrollbar-fade-duration` | normal 动效时长 | 支持原生滑块颜色过渡的浏览器使用;其他环境直接隐藏 |
|
|
42
|
+
| `--icen-token-scrollbar-gutter` | auto | 原生留槽策略 |
|
|
43
|
+
|
|
44
|
+
延时优先级:最近祖先的 `data-icen-scrollbar-delay`(毫秒)→ `idleDelay` 参数 → CSS token。运行时读取当前值,修改后下一次滚动生效。非法延时回退 900ms,范围限制为 0–60000ms。留槽也可用 `data-icen-scrollbar-gutter="auto|stable|both-edges"`,与是否显示滑块独立。
|
|
45
|
+
|
|
46
|
+
减少动效时禁用颜色过渡,保留延时显示/隐藏;强制颜色模式恢复系统可见滚动条。原生控件内部、跨源 iframe 与 Shadow DOM 的封闭内部由其宿主控制;如需开放影子树内的滚动活动跟踪,应在内部容器单独初始化。
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@icen.ai/ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Icen Design System — 设计 tokens(
|
|
3
|
+
"version": "0.11.0",
|
|
4
|
+
"description": "Icen Design System — 设计 tokens(6 主题 × 4 原语 × 明暗)+ 无框架组件 CSS/行为 JS + AI 原生组件族(7 态状态机/多模态/定价审计)+ 图表通用层(ChartSpec 纯 JSON)+ AI 工具体系",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/icen-ai/ui.git"
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
"sideEffects": [
|
|
29
29
|
"**/*.css"
|
|
30
30
|
],
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18"
|
|
33
|
+
},
|
|
34
|
+
"packageManager": "bun@1.3.5",
|
|
31
35
|
"peerDependencies": {
|
|
32
36
|
"react": ">=18",
|
|
33
37
|
"react-dom": ">=18",
|
|
@@ -58,14 +62,22 @@
|
|
|
58
62
|
"dtcg": "bun scripts/dtcg.mjs",
|
|
59
63
|
"design-tokens": "bun scripts/design-tokens.mjs",
|
|
60
64
|
"guard": "bun scripts/guard/index.ts",
|
|
65
|
+
"contracts": "bun scripts/contracts.ts --check",
|
|
66
|
+
"contracts:update": "bun scripts/contracts.ts --write",
|
|
67
|
+
"contracts:diff": "bun scripts/contracts.ts --diff",
|
|
68
|
+
"size": "bun scripts/size.ts",
|
|
69
|
+
"check:pkg": "bunx publint && bunx @arethetypeswrong/cli --pack . --ignore-rules no-resolution cjs-resolves-to-esm",
|
|
61
70
|
"prepublishOnly": "bun run build",
|
|
62
71
|
"pretest:e2e": "cd site && bun run build",
|
|
63
72
|
"test": "bun test",
|
|
73
|
+
"test:coverage": "bun scripts/coverage.ts",
|
|
64
74
|
"test:e2e": "playwright test",
|
|
65
|
-
"
|
|
75
|
+
"test:e2e:update": "playwright test --update-snapshots",
|
|
76
|
+
"verify": "bunx tsc --noEmit && bun run guard && bun test && bun run build && bun run size",
|
|
66
77
|
"colors": "bun scripts/theme-colors.mjs"
|
|
67
78
|
},
|
|
68
79
|
"devDependencies": {
|
|
80
|
+
"@arethetypeswrong/cli": "^0.18.5",
|
|
69
81
|
"@happy-dom/global-registrator": "^20.14.5",
|
|
70
82
|
"@playwright/test": "^1.63.0",
|
|
71
83
|
"@types/node": "^20.14.0",
|
|
@@ -73,6 +85,7 @@
|
|
|
73
85
|
"@types/react-dom": "^19.3.0",
|
|
74
86
|
"axe-core": "^4.14.0",
|
|
75
87
|
"happy-dom": "^20.14.5",
|
|
88
|
+
"publint": "^0.3.25",
|
|
76
89
|
"react": "^19.3.0",
|
|
77
90
|
"react-dom": "^19.3.0",
|
|
78
91
|
"tsup": "^8.3.0",
|