@icen.ai/ui 0.10.0 → 0.11.1
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 +68 -22
- package/dist/behaviors/accordion.mjs +1 -1
- package/dist/behaviors/ai-branch.mjs +14 -0
- package/dist/behaviors/ai-chat.d.mts +2 -2
- package/dist/behaviors/ai-chat.mjs +66 -10
- package/dist/behaviors/ai-composer.d.mts +5 -5
- package/dist/behaviors/ai-composer.mjs +34 -10
- package/dist/behaviors/ai-core.mjs +14 -0
- package/dist/behaviors/ai-diff.mjs +14 -0
- package/dist/behaviors/ai-feedback.mjs +14 -0
- package/dist/behaviors/ai-panel.d.mts +2 -2
- package/dist/behaviors/ai-panel.mjs +14 -0
- package/dist/behaviors/ai-provider.d.mts +1 -1
- package/dist/behaviors/ai-provider.mjs +14 -0
- package/dist/behaviors/ai-threads.mjs +14 -0
- package/dist/behaviors/ai-tool.d.mts +1 -1
- package/dist/behaviors/ai-tool.mjs +299 -24
- package/dist/behaviors/ai-tools.mjs +1179 -28
- package/dist/behaviors/autocomplete.d.mts +1 -1
- package/dist/behaviors/autocomplete.mjs +14 -0
- package/dist/behaviors/back-top.mjs +14 -0
- package/dist/behaviors/carousel.mjs +21 -1
- package/dist/behaviors/cascader.mjs +27 -0
- package/dist/behaviors/charts.d.mts +12 -1
- package/dist/behaviors/charts.mjs +298 -20
- package/dist/behaviors/code-block.mjs +22 -1
- package/dist/behaviors/command-palette.mjs +3 -3
- package/dist/behaviors/context-menu.d.mts +2 -2
- package/dist/behaviors/context-menu.mjs +14 -0
- package/dist/behaviors/controls.d.mts +8 -8
- package/dist/behaviors/controls.mjs +50 -6
- package/dist/behaviors/copy.mjs +14 -0
- package/dist/behaviors/datatable.d.mts +3 -3
- package/dist/behaviors/datatable.mjs +89 -11
- package/dist/behaviors/date-picker.mjs +14 -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 +279 -4611
- package/dist/behaviors/i18n.d.mts +14 -0
- package/dist/behaviors/i18n.mjs +28 -0
- package/dist/behaviors/input.mjs +16 -0
- package/dist/behaviors/kb-access.d.mts +2 -2
- package/dist/behaviors/kb-access.mjs +21 -2
- package/dist/behaviors/kb-acl.d.mts +2 -2
- package/dist/behaviors/kb-acl.mjs +14 -0
- package/dist/behaviors/kb-answer.d.mts +2 -2
- package/dist/behaviors/kb-answer.mjs +298 -23
- package/dist/behaviors/kb-audit.d.mts +2 -2
- package/dist/behaviors/kb-audit.mjs +14 -0
- package/dist/behaviors/kb-canvas.d.mts +3 -3
- package/dist/behaviors/kb-canvas.mjs +14 -0
- package/dist/behaviors/kb-chain.d.mts +2 -2
- package/dist/behaviors/kb-chain.mjs +14 -0
- package/dist/behaviors/kb-checkpoint.d.mts +2 -2
- package/dist/behaviors/kb-checkpoint.mjs +14 -0
- package/dist/behaviors/kb-chunks.d.mts +2 -2
- package/dist/behaviors/kb-chunks.mjs +14 -0
- package/dist/behaviors/kb-citation.d.mts +2 -2
- package/dist/behaviors/kb-citation.mjs +33 -6
- package/dist/behaviors/kb-clarify.d.mts +2 -2
- package/dist/behaviors/kb-clarify.mjs +14 -0
- package/dist/behaviors/kb-conflict.d.mts +2 -2
- package/dist/behaviors/kb-conflict.mjs +14 -0
- package/dist/behaviors/kb-connector.d.mts +2 -2
- package/dist/behaviors/kb-connector.mjs +14 -0
- package/dist/behaviors/kb-core.d.mts +1 -1
- package/dist/behaviors/kb-core.mjs +14 -0
- package/dist/behaviors/kb-eval.d.mts +2 -2
- package/dist/behaviors/kb-eval.mjs +21 -2
- package/dist/behaviors/kb-explain.d.mts +2 -2
- package/dist/behaviors/kb-explain.mjs +26 -2
- package/dist/behaviors/kb-filter.d.mts +2 -2
- package/dist/behaviors/kb-filter.mjs +21 -2
- package/dist/behaviors/kb-gap.d.mts +2 -2
- package/dist/behaviors/kb-gap.mjs +14 -0
- package/dist/behaviors/kb-hittest.d.mts +2 -2
- package/dist/behaviors/kb-hittest.mjs +15 -1
- package/dist/behaviors/kb-metadata.mjs +19 -0
- package/dist/behaviors/kb-passage.d.mts +2 -2
- package/dist/behaviors/kb-passage.mjs +14 -0
- package/dist/behaviors/kb-pipeline.d.mts +2 -2
- package/dist/behaviors/kb-pipeline.mjs +14 -0
- package/dist/behaviors/kb-qa.mjs +14 -0
- package/dist/behaviors/kb-rerank.d.mts +2 -2
- package/dist/behaviors/kb-rerank.mjs +14 -0
- package/dist/behaviors/kb-retrieval.d.mts +2 -2
- package/dist/behaviors/kb-retrieval.mjs +31 -4
- package/dist/behaviors/kb-review.d.mts +2 -2
- package/dist/behaviors/kb-review.mjs +21 -2
- package/dist/behaviors/kb-sandbox.d.mts +2 -2
- package/dist/behaviors/kb-sandbox.mjs +20 -1
- package/dist/behaviors/kb-segment.d.mts +2 -2
- package/dist/behaviors/kb-segment.mjs +15 -1
- package/dist/behaviors/kb-select.mjs +21 -2
- package/dist/behaviors/kb-sources.d.mts +2 -2
- package/dist/behaviors/kb-sources.mjs +14 -0
- package/dist/behaviors/kb-sql.d.mts +2 -2
- package/dist/behaviors/kb-sql.mjs +14 -0
- package/dist/behaviors/kb-trace.d.mts +2 -2
- package/dist/behaviors/kb-trace.mjs +22 -3
- package/dist/behaviors/kb-visibility.d.mts +2 -2
- package/dist/behaviors/kb-visibility.mjs +14 -0
- package/dist/behaviors/kb-who-can.d.mts +2 -2
- package/dist/behaviors/kb-who-can.mjs +21 -2
- package/dist/behaviors/mentions.d.mts +1 -1
- package/dist/behaviors/mentions.mjs +14 -0
- package/dist/behaviors/modal.d.mts +1 -1
- package/dist/behaviors/modal.mjs +14 -0
- package/dist/behaviors/motion.d.mts +16 -0
- package/dist/behaviors/motion.mjs +39 -0
- package/dist/behaviors/notification.d.mts +2 -2
- package/dist/behaviors/notification.mjs +27 -3
- package/dist/behaviors/panel.mjs +14 -0
- package/dist/behaviors/scroll-area.d.mts +17 -0
- package/dist/behaviors/scroll-area.mjs +59 -0
- package/dist/behaviors/select.mjs +21 -2
- package/dist/behaviors/slider.mjs +3 -3
- package/dist/behaviors/split-pane.mjs +2 -0
- package/dist/behaviors/suggestions.mjs +14 -0
- package/dist/behaviors/tabs.mjs +10 -0
- package/dist/behaviors/tag-input.mjs +14 -0
- package/dist/behaviors/theme-switcher.d.mts +2 -2
- package/dist/behaviors/theme-switcher.mjs +30 -2
- package/dist/behaviors/theme.mjs +16 -2
- package/dist/behaviors/toast.d.mts +2 -2
- package/dist/behaviors/toast.mjs +14 -0
- package/dist/behaviors/tree-select.mjs +27 -0
- package/dist/behaviors/tree.mjs +4 -4
- package/dist/behaviors/upload.mjs +14 -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 +109 -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 +14644 -13935
- package/dist/react.d.mts +18 -18
- package/dist/react.mjs +377 -36
- package/dist/registry.json +797 -64
- package/dist/tokens/colors.css +6 -0
- package/dist/tokens/design.css +137 -31
- package/dist/tokens/dtcg.json +9592 -2008
- package/dist/tokens/figma.variables.json +7451 -2141
- package/dist/tokens/motion.css +51 -0
- package/dist/tokens/pixel.css +10 -0
- package/dist/tokens/scrollbars.css +40 -0
- package/dist/tokens/tokens-studio.json +8390 -1142
- package/dist/tokens/typography.css +33 -0
- package/dist/tokens.css +402 -82
- package/dist/ui.css +4196 -2163
- package/dist/vue.d.mts +17 -17
- package/dist/vue.mjs +371 -34
- package/docs/spec/charts-scale-a11y.md +115 -0
- package/docs/spec/design-philosophy.md +5 -5
- package/docs/spec/design-primitives.md +10 -10
- package/docs/spec/motion-typography.md +105 -0
- package/docs/spec/scrollbars.md +46 -0
- package/package.json +17 -3
|
@@ -116,6 +116,7 @@ var ICEN_LOCALE_ZH_CN = {
|
|
|
116
116
|
"aiChat.roleTool": "\u5DE5",
|
|
117
117
|
"aiChat.roleUser": "\u6211",
|
|
118
118
|
"aiChat.thinking": "\u601D\u8003 {p0}",
|
|
119
|
+
"aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
|
|
119
120
|
/* ── aiComposer ── */
|
|
120
121
|
"aiComposer.attachAgent": "\u4EE3\u7406",
|
|
121
122
|
"aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
|
|
@@ -298,6 +299,19 @@ var ICEN_LOCALE_ZH_CN = {
|
|
|
298
299
|
"charts.noData": "\u6682\u65E0\u6570\u636E",
|
|
299
300
|
"charts.resetZoom": "\u91CD\u7F6E\u7F29\u653E",
|
|
300
301
|
"charts.sampled": "\u5DF2\u62BD\u6837 {p0}\u2192{p1} \u70B9",
|
|
302
|
+
"charts.a11y.keyboardHint": "\u65B9\u5411\u952E\u9010\u70B9\u6D4F\u89C8\uFF0CHome/End \u8DF3\u9996\u5C3E\uFF0CEsc \u91CD\u7F6E\u7F29\u653E",
|
|
303
|
+
"charts.a11y.max": "\u6700\u5927 {p0}\uFF08{p1}\uFF09",
|
|
304
|
+
"charts.a11y.min": "\u6700\u5C0F {p0}\uFF08{p1}\uFF09",
|
|
305
|
+
"charts.a11y.point": "{p0}\uFF1A{p1}\uFF0C\u7B2C {p2}/{p3} \u70B9",
|
|
306
|
+
"charts.a11y.pointSeries": "{p0} \xB7 {p1}\uFF1A{p2}\uFF0C\u7B2C {p3}/{p4} \u70B9",
|
|
307
|
+
"charts.a11y.range": "\u7C7B\u76EE {p0} \u81F3 {p1}",
|
|
308
|
+
"charts.a11y.scatterRange": "x \u8303\u56F4 {p0}\u2013{p1}\uFF0Cy \u8303\u56F4 {p2}\u2013{p3}",
|
|
309
|
+
"charts.a11y.seriesCount": "{p0} \u4E2A\u7CFB\u5217",
|
|
310
|
+
"charts.a11y.tableCaption": "{p0} \u6570\u636E\u8868",
|
|
311
|
+
"charts.a11y.trend": "\u9996\u7CFB\u5217\u8D8B\u52BF{p0}",
|
|
312
|
+
"charts.a11y.trendDown": "\u4E0B\u964D",
|
|
313
|
+
"charts.a11y.trendFlat": "\u6301\u5E73",
|
|
314
|
+
"charts.a11y.trendUp": "\u4E0A\u5347",
|
|
301
315
|
"charts.type.area": "\u9762\u79EF\u56FE",
|
|
302
316
|
"charts.type.donut": "\u73AF\u5F62\u56FE",
|
|
303
317
|
"charts.type.gauge": "\u4EEA\u8868\u76D8",
|
|
@@ -1167,7 +1181,8 @@ function withChrome(el, opts, hasLegend, paint, state, extras) {
|
|
|
1167
1181
|
emitIcen(el, "icen:chart-legend-visibility", { visible: hidden ? false : true });
|
|
1168
1182
|
});
|
|
1169
1183
|
syncEye();
|
|
1170
|
-
head.append(title, eye);
|
|
1184
|
+
if (hasLegend) head.append(title, eye);
|
|
1185
|
+
else head.append(title);
|
|
1171
1186
|
el.append(head, body);
|
|
1172
1187
|
paint(body);
|
|
1173
1188
|
}
|
|
@@ -1268,7 +1283,7 @@ function renderVBar(el, opts) {
|
|
|
1268
1283
|
wrap.appendChild(track);
|
|
1269
1284
|
}
|
|
1270
1285
|
body.append(wrap, labelsRow(labelsUsed));
|
|
1271
|
-
if (seriesList.length > 1) body.appendChild(toggleLegend(seriesList.map((s, si) => ({ key: s.name
|
|
1286
|
+
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));
|
|
1272
1287
|
});
|
|
1273
1288
|
attachChartInteraction(el, "vbar");
|
|
1274
1289
|
return el;
|
|
@@ -1363,8 +1378,10 @@ function renderDonut(el, opts) {
|
|
|
1363
1378
|
"stroke-width": "14"
|
|
1364
1379
|
}));
|
|
1365
1380
|
let offset = 0;
|
|
1381
|
+
const gap = opts.segments.length > 1 ? 2.5 : 0;
|
|
1366
1382
|
opts.segments.forEach((seg, segIndex) => {
|
|
1367
|
-
const
|
|
1383
|
+
const arcLength = Math.max(0, seg.value / total * circumference);
|
|
1384
|
+
const dash = arcLength - Math.min(gap, arcLength * 0.1);
|
|
1368
1385
|
const arc = svgEl("circle", {
|
|
1369
1386
|
cx: "60",
|
|
1370
1387
|
cy: "60",
|
|
@@ -1378,7 +1395,7 @@ function renderDonut(el, opts) {
|
|
|
1378
1395
|
});
|
|
1379
1396
|
setMarkData(arc, { index: segIndex, label: seg.label, value: seg.value });
|
|
1380
1397
|
svg.appendChild(arc);
|
|
1381
|
-
offset +=
|
|
1398
|
+
offset += arcLength;
|
|
1382
1399
|
});
|
|
1383
1400
|
const legend = document.createElement("div");
|
|
1384
1401
|
legend.className = "icen-chart-legend";
|
|
@@ -1413,8 +1430,9 @@ function renderLine(el, opts) {
|
|
|
1413
1430
|
const svg = svgEl("svg", { viewBox: `0 0 ${width} ${height}`, role: "img", "aria-label": chartAriaLabel(opts.title, t("charts.type.line")) });
|
|
1414
1431
|
const defs = svgEl("defs", {});
|
|
1415
1432
|
for (let i = 0; i < 4; i++) {
|
|
1416
|
-
const y = pad + i * (height - pad * 2) / 3;
|
|
1433
|
+
const y = Math.round(pad + i * (height - pad * 2) / 3) + 0.5;
|
|
1417
1434
|
svg.appendChild(svgEl("line", {
|
|
1435
|
+
class: i === 3 ? "icen-chart-grid icen-chart-baseline" : "icen-chart-grid",
|
|
1418
1436
|
x1: String(pad),
|
|
1419
1437
|
x2: String(width - pad),
|
|
1420
1438
|
y1: String(y),
|
|
@@ -1498,7 +1516,7 @@ function renderLine(el, opts) {
|
|
|
1498
1516
|
if (defs.firstChild) svg.insertBefore(defs, svg.firstChild);
|
|
1499
1517
|
wrap.append(svg, pointLabelsRow(labelsUsed, width, pad));
|
|
1500
1518
|
body.appendChild(wrap);
|
|
1501
|
-
if (seriesList.length > 1) body.appendChild(toggleLegend(seriesList.map((s, si) => ({ key: s.name
|
|
1519
|
+
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));
|
|
1502
1520
|
});
|
|
1503
1521
|
if (el.dataset.icenChartBody == null) observeFluidWidth(el, () => renderLine(el, opts));
|
|
1504
1522
|
attachChartInteraction(el, "line");
|
|
@@ -1520,8 +1538,10 @@ function renderArea(el, opts) {
|
|
|
1520
1538
|
const max = maxOf(values);
|
|
1521
1539
|
const tone = toneVar(opts.tone);
|
|
1522
1540
|
const points = values.map((value, i) => ({
|
|
1541
|
+
i,
|
|
1523
1542
|
x: values.length <= 1 ? width / 2 : pad + i / (values.length - 1) * (width - pad * 2),
|
|
1524
|
-
|
|
1543
|
+
/* 负值钳到基线(与折线图同口径):容器 overflow:visible,反向射出会压住下方内容 */
|
|
1544
|
+
y: height - pad - Math.max(0, value) / max * (height - pad * 2),
|
|
1525
1545
|
value,
|
|
1526
1546
|
label: labels[i] ?? ""
|
|
1527
1547
|
}));
|
|
@@ -1540,8 +1560,9 @@ function renderArea(el, opts) {
|
|
|
1540
1560
|
defs.appendChild(gradient);
|
|
1541
1561
|
svg.appendChild(defs);
|
|
1542
1562
|
for (let i = 0; i < 4; i++) {
|
|
1543
|
-
const y = pad + i * (height - pad * 2) / 3;
|
|
1563
|
+
const y = Math.round(pad + i * (height - pad * 2) / 3) + 0.5;
|
|
1544
1564
|
svg.appendChild(svgEl("line", {
|
|
1565
|
+
class: i === 3 ? "icen-chart-grid icen-chart-baseline" : "icen-chart-grid",
|
|
1545
1566
|
x1: String(pad),
|
|
1546
1567
|
x2: String(width - pad),
|
|
1547
1568
|
y1: String(y),
|
|
@@ -1562,14 +1583,26 @@ function renderArea(el, opts) {
|
|
|
1562
1583
|
for (const p of points) {
|
|
1563
1584
|
const title = svgEl("title", {});
|
|
1564
1585
|
title.textContent = `${p.label}: ${fmt(opts, p.value)}`;
|
|
1565
|
-
const
|
|
1586
|
+
const dot = svgEl("circle", {
|
|
1566
1587
|
cx: p.x.toFixed(1),
|
|
1567
1588
|
cy: p.y.toFixed(1),
|
|
1568
|
-
r: "2",
|
|
1569
|
-
fill: "
|
|
1589
|
+
r: "2.6",
|
|
1590
|
+
fill: "var(--icen-token-card)",
|
|
1591
|
+
stroke: tone,
|
|
1592
|
+
"stroke-width": "1.6"
|
|
1593
|
+
});
|
|
1594
|
+
dot.appendChild(title);
|
|
1595
|
+
setMarkData(dot, { index: p.i, label: p.label, value: p.value });
|
|
1596
|
+
svg.appendChild(dot);
|
|
1597
|
+
const hit = svgEl("circle", {
|
|
1598
|
+
cx: p.x.toFixed(1),
|
|
1599
|
+
cy: p.y.toFixed(1),
|
|
1600
|
+
r: "9",
|
|
1601
|
+
fill: "transparent",
|
|
1602
|
+
"data-icen-chart-hit": "1"
|
|
1570
1603
|
});
|
|
1571
|
-
|
|
1572
|
-
svg.appendChild(
|
|
1604
|
+
copyMarkData(hit, dot);
|
|
1605
|
+
svg.appendChild(hit);
|
|
1573
1606
|
}
|
|
1574
1607
|
wrap.append(svg, pointLabelsRow(labels, width, pad));
|
|
1575
1608
|
body.appendChild(wrap);
|
|
@@ -1679,7 +1712,7 @@ function renderRadar(el, opts) {
|
|
|
1679
1712
|
setMarkData(dot, { index: i, seriesIndex: si, seriesName: s.name || void 0, label: axes[i] ?? "", value: s.values[i] ?? 0 });
|
|
1680
1713
|
svg.appendChild(dot);
|
|
1681
1714
|
}
|
|
1682
|
-
legendItems.push({ key: s.name || t("charts.seriesName", { p0: si + 1 })
|
|
1715
|
+
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 });
|
|
1683
1716
|
});
|
|
1684
1717
|
wrap.appendChild(svg);
|
|
1685
1718
|
body.appendChild(wrap);
|
|
@@ -1701,6 +1734,11 @@ function niceCeil(v) {
|
|
|
1701
1734
|
else nice = 10;
|
|
1702
1735
|
return nice * base;
|
|
1703
1736
|
}
|
|
1737
|
+
function tickPrecision(min, max, steps) {
|
|
1738
|
+
const span = Math.abs(max - min);
|
|
1739
|
+
if (!Number.isFinite(span) || span <= 0) return 0;
|
|
1740
|
+
return Math.max(0, Math.ceil(-Math.log10(span / steps)));
|
|
1741
|
+
}
|
|
1704
1742
|
function isoDate(d) {
|
|
1705
1743
|
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
1706
1744
|
const day = String(d.getDate()).padStart(2, "0");
|
|
@@ -1796,7 +1834,8 @@ function renderSparkline(el, opts) {
|
|
|
1796
1834
|
const tone = toneVar(opts.tone);
|
|
1797
1835
|
const points = values.map((value, i) => ({
|
|
1798
1836
|
x: values.length <= 1 ? width / 2 : pad + i / (values.length - 1) * (width - pad * 2),
|
|
1799
|
-
|
|
1837
|
+
/* 负值钳到基线(与折线图同口径):viewBox 仅 28 高,反向射出更刺眼 */
|
|
1838
|
+
y: height - pad - Math.max(0, value) / max * (height - pad * 2),
|
|
1800
1839
|
value
|
|
1801
1840
|
}));
|
|
1802
1841
|
const line = points.map((p, i) => `${i === 0 ? "M" : "L"}${p.x.toFixed(1)},${p.y.toFixed(1)}`).join(" ");
|
|
@@ -1921,6 +1960,7 @@ function renderCalendar(el, opts) {
|
|
|
1921
1960
|
weekdayRow.appendChild(s);
|
|
1922
1961
|
});
|
|
1923
1962
|
const max = maxOf(entries.map((e) => e.value));
|
|
1963
|
+
entries.sort((a, b) => a.date.localeCompare(b.date));
|
|
1924
1964
|
const pad = padFirstWeek(grid, entries[0].date, weekStart);
|
|
1925
1965
|
let lastMonth = -1;
|
|
1926
1966
|
entries.forEach((entry, i) => {
|
|
@@ -1979,8 +2019,9 @@ function renderScatter(el, opts) {
|
|
|
1979
2019
|
const xAt = (x) => pad + (x - xMin) / (xMax - xMin) * (width - pad * 2);
|
|
1980
2020
|
const yAt = (y) => height - pad - (y - yMin) / (yMax - yMin) * (height - pad * 2);
|
|
1981
2021
|
for (let i = 0; i <= 3; i++) {
|
|
1982
|
-
const y = pad + i * (height - pad * 2) / 3;
|
|
2022
|
+
const y = Math.round(pad + i * (height - pad * 2) / 3) + 0.5;
|
|
1983
2023
|
svg.appendChild(svgEl("line", {
|
|
2024
|
+
class: i === 3 ? "icen-chart-grid icen-chart-baseline" : "icen-chart-grid",
|
|
1984
2025
|
x1: String(pad),
|
|
1985
2026
|
x2: String(width - pad),
|
|
1986
2027
|
y1: String(y),
|
|
@@ -1996,12 +2037,13 @@ function renderScatter(el, opts) {
|
|
|
1996
2037
|
"font-size": "8",
|
|
1997
2038
|
fill: "var(--icen-token-text-faint)"
|
|
1998
2039
|
});
|
|
1999
|
-
txt.textContent = fmt(opts,
|
|
2040
|
+
txt.textContent = fmt(opts, +tv.toFixed(tickPrecision(yMin, yMax, 3)));
|
|
2000
2041
|
svg.appendChild(txt);
|
|
2001
2042
|
}
|
|
2002
2043
|
for (let i = 0; i <= 4; i++) {
|
|
2003
|
-
const x = pad + i * (width - pad * 2) / 4;
|
|
2044
|
+
const x = Math.round(pad + i * (width - pad * 2) / 4) + 0.5;
|
|
2004
2045
|
svg.appendChild(svgEl("line", {
|
|
2046
|
+
class: i === 0 ? "icen-chart-grid icen-chart-grid--v icen-chart-axis" : "icen-chart-grid icen-chart-grid--v",
|
|
2005
2047
|
x1: String(x),
|
|
2006
2048
|
x2: String(x),
|
|
2007
2049
|
y1: String(pad),
|
|
@@ -2018,7 +2060,7 @@ function renderScatter(el, opts) {
|
|
|
2018
2060
|
"font-size": "8",
|
|
2019
2061
|
fill: "var(--icen-token-text-faint)"
|
|
2020
2062
|
});
|
|
2021
|
-
txt.textContent = fmt(opts,
|
|
2063
|
+
txt.textContent = fmt(opts, +tv.toFixed(tickPrecision(xMin, xMax, 4)));
|
|
2022
2064
|
svg.appendChild(txt);
|
|
2023
2065
|
}
|
|
2024
2066
|
if (opts.yLabel) {
|
|
@@ -2255,6 +2297,14 @@ function normalizeChartSpec(raw) {
|
|
|
2255
2297
|
}
|
|
2256
2298
|
if (s.zoom === "x" || s.zoom === "brush") spec.zoom = s.zoom;
|
|
2257
2299
|
if (typeof s.loading === "boolean") spec.loading = s.loading;
|
|
2300
|
+
if (s.a11y && typeof s.a11y === "object") {
|
|
2301
|
+
const a = s.a11y;
|
|
2302
|
+
const a11y = {};
|
|
2303
|
+
if (typeof a.summary === "boolean") a11y.summary = a.summary;
|
|
2304
|
+
if (typeof a.table === "boolean") a11y.table = a.table;
|
|
2305
|
+
if (typeof a.keyboard === "boolean") a11y.keyboard = a.keyboard;
|
|
2306
|
+
if (Object.keys(a11y).length > 0) spec.a11y = a11y;
|
|
2307
|
+
}
|
|
2258
2308
|
if (Array.isArray(s.marks)) {
|
|
2259
2309
|
const marks = [];
|
|
2260
2310
|
for (const raw2 of s.marks) {
|
|
@@ -2382,6 +2432,7 @@ function renderChartSkeleton(body) {
|
|
|
2382
2432
|
body.appendChild(box);
|
|
2383
2433
|
}
|
|
2384
2434
|
var CHART_MARK_ACCENT = "var(--icen-token-accent)";
|
|
2435
|
+
var CHART_MARK_ACCENT_TEXT = "var(--icen-token-accent-text)";
|
|
2385
2436
|
function markToneVar(tone) {
|
|
2386
2437
|
switch (tone) {
|
|
2387
2438
|
case "success":
|
|
@@ -2517,7 +2568,7 @@ function paintSvgChartMarks(root, view, marks, formatValue, warned) {
|
|
|
2517
2568
|
y: String(clampNum(y - 10, 8, CHART_LINE_H - 4)),
|
|
2518
2569
|
"text-anchor": "middle",
|
|
2519
2570
|
"font-size": "8",
|
|
2520
|
-
fill:
|
|
2571
|
+
fill: CHART_MARK_ACCENT_TEXT
|
|
2521
2572
|
});
|
|
2522
2573
|
label.textContent = mark.text ?? mark.label;
|
|
2523
2574
|
g.appendChild(label);
|
|
@@ -2609,6 +2660,81 @@ function paintVBarChartMarks(root, view, spec, marks, formatValue, warned) {
|
|
|
2609
2660
|
function chartAriaLabel(title, typeName) {
|
|
2610
2661
|
return title ? `${typeName}\uFF1A${title}` : typeName;
|
|
2611
2662
|
}
|
|
2663
|
+
function summarizeChart(view, type, fmt2) {
|
|
2664
|
+
const series = view.series && view.series.length > 0 ? view.series : [{ name: "", values: view.values ?? [] }];
|
|
2665
|
+
const parts = [];
|
|
2666
|
+
if (series.length > 1) parts.push(t("charts.a11y.seriesCount", { p0: series.length }));
|
|
2667
|
+
if (type === "scatter") {
|
|
2668
|
+
const pts = view.points ?? [];
|
|
2669
|
+
if (pts.length > 0) {
|
|
2670
|
+
const xs = pts.map((p) => p.x);
|
|
2671
|
+
const ys = pts.map((p) => p.y);
|
|
2672
|
+
parts.push(t("charts.a11y.scatterRange", { p0: fmt2(Math.min(...xs)), p1: fmt2(Math.max(...xs)), p2: fmt2(Math.min(...ys)), p3: fmt2(Math.max(...ys)) }));
|
|
2673
|
+
}
|
|
2674
|
+
return parts.join("\uFF1B");
|
|
2675
|
+
}
|
|
2676
|
+
const labels = view.labels ?? [];
|
|
2677
|
+
if (labels.length > 1) parts.push(t("charts.a11y.range", { p0: labels[0], p1: labels[labels.length - 1] }));
|
|
2678
|
+
let min = Infinity;
|
|
2679
|
+
let max = -Infinity;
|
|
2680
|
+
let minAt = "";
|
|
2681
|
+
let maxAt = "";
|
|
2682
|
+
for (const s of series) {
|
|
2683
|
+
s.values.forEach((v, i) => {
|
|
2684
|
+
if (v < min) {
|
|
2685
|
+
min = v;
|
|
2686
|
+
minAt = labels[i] ?? String(i + 1);
|
|
2687
|
+
}
|
|
2688
|
+
if (v > max) {
|
|
2689
|
+
max = v;
|
|
2690
|
+
maxAt = labels[i] ?? String(i + 1);
|
|
2691
|
+
}
|
|
2692
|
+
});
|
|
2693
|
+
}
|
|
2694
|
+
if (Number.isFinite(min) && Number.isFinite(max)) {
|
|
2695
|
+
parts.push(t("charts.a11y.min", { p0: fmt2(min), p1: minAt }));
|
|
2696
|
+
parts.push(t("charts.a11y.max", { p0: fmt2(max), p1: maxAt }));
|
|
2697
|
+
}
|
|
2698
|
+
const first = series[0]?.values ?? [];
|
|
2699
|
+
if (first.length > 1) {
|
|
2700
|
+
const d = first[first.length - 1] - first[0];
|
|
2701
|
+
const key = Math.abs(d) < 1e-9 ? "charts.a11y.trendFlat" : d > 0 ? "charts.a11y.trendUp" : "charts.a11y.trendDown";
|
|
2702
|
+
parts.push(t("charts.a11y.trend", { p0: t(key) }));
|
|
2703
|
+
}
|
|
2704
|
+
return parts.join("\uFF1B");
|
|
2705
|
+
}
|
|
2706
|
+
function buildChartTable(view, spec, type, fmt2) {
|
|
2707
|
+
const table = document.createElement("table");
|
|
2708
|
+
table.className = "icen-chart-table";
|
|
2709
|
+
const caption = document.createElement("caption");
|
|
2710
|
+
caption.textContent = t("charts.a11y.tableCaption", { p0: spec.title ?? String(type) });
|
|
2711
|
+
table.appendChild(caption);
|
|
2712
|
+
const addRow = (target, cells, head) => {
|
|
2713
|
+
const tr = document.createElement("tr");
|
|
2714
|
+
for (const c of cells) {
|
|
2715
|
+
const cell = document.createElement(head ? "th" : "td");
|
|
2716
|
+
if (head) cell.scope = target.tagName === "THEAD" ? "col" : "row";
|
|
2717
|
+
cell.textContent = c;
|
|
2718
|
+
tr.appendChild(cell);
|
|
2719
|
+
}
|
|
2720
|
+
target.appendChild(tr);
|
|
2721
|
+
};
|
|
2722
|
+
const thead = table.createTHead();
|
|
2723
|
+
const tbody = table.createTBody();
|
|
2724
|
+
if (type === "scatter") {
|
|
2725
|
+
addRow(thead, ["x", "y"], true);
|
|
2726
|
+
for (const p of view.points ?? []) addRow(tbody, [fmt2(p.x), fmt2(p.y)], false);
|
|
2727
|
+
return table;
|
|
2728
|
+
}
|
|
2729
|
+
const series = view.series && view.series.length > 0 ? view.series : [{ name: "", values: view.values ?? [] }];
|
|
2730
|
+
const labels = view.labels ?? [];
|
|
2731
|
+
addRow(thead, ["", ...series.map((s, i) => s.name || String(i + 1))], true);
|
|
2732
|
+
const n = Math.max(labels.length, ...series.map((s) => s.values.length));
|
|
2733
|
+
for (let i = 0; i < n; i++) {
|
|
2734
|
+
addRow(tbody, [labels[i] ?? String(i + 1), ...series.map((s) => fmt2(s.values[i] ?? 0))], false);
|
|
2735
|
+
}
|
|
2736
|
+
return table;
|
|
2737
|
+
}
|
|
2612
2738
|
function svgDimsOf(svg) {
|
|
2613
2739
|
const vb = (svg.getAttribute("viewBox") ?? "").split(/\s+/).map(Number);
|
|
2614
2740
|
const w = Number.isFinite(vb[2]) && (vb[2] ?? 0) > 0 ? vb[2] : CHART_LINE_W;
|
|
@@ -2949,6 +3075,7 @@ function renderChart(el, raw) {
|
|
|
2949
3075
|
if (!isZoomableType(t2) || fullLength() < 2) return;
|
|
2950
3076
|
const plot = t2 === "vbar" ? root.querySelector(".icen-chart-vbar") : root.querySelector(".icen-chart-line svg");
|
|
2951
3077
|
if (!plot) return;
|
|
3078
|
+
plot.style.touchAction = current2.zoom === "x" ? "pan-y" : "none";
|
|
2952
3079
|
const on = (type, fn) => {
|
|
2953
3080
|
plot.addEventListener(type, fn);
|
|
2954
3081
|
};
|
|
@@ -3004,6 +3131,149 @@ function renderChart(el, raw) {
|
|
|
3004
3131
|
render();
|
|
3005
3132
|
});
|
|
3006
3133
|
};
|
|
3134
|
+
const KB_TYPES = /* @__PURE__ */ new Set(["line", "area", "vbar", "hbar", "scatter"]);
|
|
3135
|
+
const kbCursor = { si: 0, i: 0, active: false };
|
|
3136
|
+
let liveRegion = null;
|
|
3137
|
+
let a11ySeq = 0;
|
|
3138
|
+
const a11yOf = () => ({
|
|
3139
|
+
summary: current2.a11y?.summary !== false,
|
|
3140
|
+
table: current2.a11y?.table === true,
|
|
3141
|
+
keyboard: current2.a11y?.keyboard !== false
|
|
3142
|
+
});
|
|
3143
|
+
const seriesViewOf = (view) => view.series && view.series.length > 0 ? view.series : [{ name: "", values: view.values ?? [] }];
|
|
3144
|
+
const kbPointCount = (view) => typeOf() === "scatter" ? view.points?.length ?? 0 : Math.max(0, ...seriesViewOf(view).map((s) => s.values.length), view.labels?.length ?? 0);
|
|
3145
|
+
const kbCursorEl = () => {
|
|
3146
|
+
const t2 = typeOf();
|
|
3147
|
+
const view = viewOf();
|
|
3148
|
+
const series = seriesViewOf(view);
|
|
3149
|
+
const n = kbPointCount(view);
|
|
3150
|
+
if (n < 1) return null;
|
|
3151
|
+
const si = clampNum(kbCursor.si, 0, Math.max(0, series.length - 1));
|
|
3152
|
+
const i = clampNum(kbCursor.i, 0, n - 1);
|
|
3153
|
+
if (t2 === "line" || t2 === "area") {
|
|
3154
|
+
const svg = root.querySelector(".icen-chart-line svg");
|
|
3155
|
+
if (!svg) return null;
|
|
3156
|
+
const dots = svg.querySelectorAll("circle");
|
|
3157
|
+
let base = 0;
|
|
3158
|
+
for (let k = 0; k < si; k++) base += Math.min(series[k].values.length, n);
|
|
3159
|
+
return dots.item(base + i) ?? null;
|
|
3160
|
+
}
|
|
3161
|
+
if (t2 === "scatter") return root.querySelector(".icen-chart-scatter svg")?.querySelectorAll("circle").item(i) ?? null;
|
|
3162
|
+
if (t2 === "vbar") return root.querySelectorAll(".icen-chart-vbar-bar").item(series.length > 1 ? i * series.length + si : i) ?? null;
|
|
3163
|
+
if (t2 === "hbar") return root.querySelectorAll(".icen-chart-hbar-bar").item(i) ?? null;
|
|
3164
|
+
return null;
|
|
3165
|
+
};
|
|
3166
|
+
const announceKb = (text) => {
|
|
3167
|
+
if (!liveRegion || !liveRegion.isConnected) {
|
|
3168
|
+
liveRegion = document.createElement("div");
|
|
3169
|
+
liveRegion.className = "icen-chart-live";
|
|
3170
|
+
liveRegion.setAttribute("aria-live", "polite");
|
|
3171
|
+
root.appendChild(liveRegion);
|
|
3172
|
+
}
|
|
3173
|
+
liveRegion.textContent = "";
|
|
3174
|
+
liveRegion.textContent = text;
|
|
3175
|
+
};
|
|
3176
|
+
const applyKbCursor = () => {
|
|
3177
|
+
for (const el2 of root.querySelectorAll(".icen-chart-kb-focus")) el2.classList.remove("icen-chart-kb-focus");
|
|
3178
|
+
if (!kbCursor.active) return;
|
|
3179
|
+
kbCursorEl()?.classList.add("icen-chart-kb-focus");
|
|
3180
|
+
};
|
|
3181
|
+
const announceCursor = () => {
|
|
3182
|
+
const view = viewOf();
|
|
3183
|
+
const series = seriesViewOf(view);
|
|
3184
|
+
const n = kbPointCount(view);
|
|
3185
|
+
if (n < 1) return;
|
|
3186
|
+
const si = clampNum(kbCursor.si, 0, Math.max(0, series.length - 1));
|
|
3187
|
+
const i = clampNum(kbCursor.i, 0, Math.max(0, n - 1));
|
|
3188
|
+
const fmt2 = chartFormatValue(current2.format);
|
|
3189
|
+
if (typeOf() === "scatter") {
|
|
3190
|
+
const p = view.points?.[i];
|
|
3191
|
+
if (!p) return;
|
|
3192
|
+
announceKb(t("charts.a11y.point", { p0: `x ${fmt2(p.x)}`, p1: `y ${fmt2(p.y)}`, p2: i + 1, p3: n }));
|
|
3193
|
+
return;
|
|
3194
|
+
}
|
|
3195
|
+
const label = view.labels?.[i] ?? String(i + 1);
|
|
3196
|
+
const value = series[si]?.values[i] ?? 0;
|
|
3197
|
+
if (series.length > 1) announceKb(t("charts.a11y.pointSeries", { p0: series[si].name || String(si + 1), p1: label, p2: fmt2(value), p3: i + 1, p4: n }));
|
|
3198
|
+
else announceKb(t("charts.a11y.point", { p0: label, p1: fmt2(value), p2: i + 1, p3: n }));
|
|
3199
|
+
};
|
|
3200
|
+
const onKbKeydown = (e) => {
|
|
3201
|
+
const conf = a11yOf();
|
|
3202
|
+
if (!conf.keyboard || !KB_TYPES.has(typeOf())) return;
|
|
3203
|
+
const g = root.querySelector("[data-icen-chart-kb]");
|
|
3204
|
+
if (!g || e.target !== g) return;
|
|
3205
|
+
if (e.key === "Escape") {
|
|
3206
|
+
if (zoomWindow) {
|
|
3207
|
+
zoomWindow = null;
|
|
3208
|
+
kbCursor.active = false;
|
|
3209
|
+
render();
|
|
3210
|
+
}
|
|
3211
|
+
return;
|
|
3212
|
+
}
|
|
3213
|
+
const view = viewOf();
|
|
3214
|
+
const series = seriesViewOf(view);
|
|
3215
|
+
const n = kbPointCount(view);
|
|
3216
|
+
if (n < 1) return;
|
|
3217
|
+
const siMax = Math.max(0, series.length - 1);
|
|
3218
|
+
let moved = true;
|
|
3219
|
+
switch (e.key) {
|
|
3220
|
+
case "ArrowRight":
|
|
3221
|
+
kbCursor.i = clampNum(kbCursor.i + 1, 0, n - 1);
|
|
3222
|
+
break;
|
|
3223
|
+
case "ArrowLeft":
|
|
3224
|
+
kbCursor.i = clampNum(kbCursor.i - 1, 0, n - 1);
|
|
3225
|
+
break;
|
|
3226
|
+
case "ArrowDown":
|
|
3227
|
+
kbCursor.si = clampNum(kbCursor.si + 1, 0, siMax);
|
|
3228
|
+
break;
|
|
3229
|
+
case "ArrowUp":
|
|
3230
|
+
kbCursor.si = clampNum(kbCursor.si - 1, 0, siMax);
|
|
3231
|
+
break;
|
|
3232
|
+
case "Home":
|
|
3233
|
+
kbCursor.i = 0;
|
|
3234
|
+
break;
|
|
3235
|
+
case "End":
|
|
3236
|
+
kbCursor.i = n - 1;
|
|
3237
|
+
break;
|
|
3238
|
+
default:
|
|
3239
|
+
moved = false;
|
|
3240
|
+
}
|
|
3241
|
+
if (!moved) return;
|
|
3242
|
+
e.preventDefault();
|
|
3243
|
+
kbCursor.active = true;
|
|
3244
|
+
applyKbCursor();
|
|
3245
|
+
announceCursor();
|
|
3246
|
+
};
|
|
3247
|
+
root.addEventListener("keydown", onKbKeydown);
|
|
3248
|
+
const applyChartA11yPlus = (view, spec, type, formatValue) => {
|
|
3249
|
+
const conf = a11yOf();
|
|
3250
|
+
const graphic = root.querySelector('[role="img"]');
|
|
3251
|
+
if (!graphic) return;
|
|
3252
|
+
const body = root.querySelector(".icen-chart-body") ?? graphic.parentElement ?? root;
|
|
3253
|
+
const summaryParts = [];
|
|
3254
|
+
if (conf.summary) summaryParts.push(summarizeChart(view, type, formatValue));
|
|
3255
|
+
if (conf.keyboard && KB_TYPES.has(type)) summaryParts.push(t("charts.a11y.keyboardHint"));
|
|
3256
|
+
const summaryText = summaryParts.filter(Boolean).join("\uFF1B");
|
|
3257
|
+
if (summaryText) {
|
|
3258
|
+
const p = document.createElement("p");
|
|
3259
|
+
p.className = "icen-chart-summary";
|
|
3260
|
+
p.id = `icen-chart-a11y-${++a11ySeq}`;
|
|
3261
|
+
p.textContent = summaryText;
|
|
3262
|
+
body.appendChild(p);
|
|
3263
|
+
graphic.setAttribute("aria-describedby", p.id);
|
|
3264
|
+
} else {
|
|
3265
|
+
graphic.removeAttribute("aria-describedby");
|
|
3266
|
+
}
|
|
3267
|
+
if (conf.keyboard && KB_TYPES.has(type)) {
|
|
3268
|
+
graphic.setAttribute("tabindex", "0");
|
|
3269
|
+
graphic.setAttribute("data-icen-chart-kb", "");
|
|
3270
|
+
} else {
|
|
3271
|
+
graphic.removeAttribute("tabindex");
|
|
3272
|
+
graphic.removeAttribute("data-icen-chart-kb");
|
|
3273
|
+
}
|
|
3274
|
+
if (conf.table) body.appendChild(buildChartTable(view, spec, type, formatValue));
|
|
3275
|
+
applyKbCursor();
|
|
3276
|
+
};
|
|
3007
3277
|
const render = () => {
|
|
3008
3278
|
if (!current2.type) current2 = { ...current2, type: inferChartType(current2) };
|
|
3009
3279
|
const spec = current2;
|
|
@@ -3075,9 +3345,16 @@ function renderChart(el, raw) {
|
|
|
3075
3345
|
const graphic = root.querySelector('[role="img"]');
|
|
3076
3346
|
if (graphic && !graphic.getAttribute("aria-label")) {
|
|
3077
3347
|
graphic.setAttribute("aria-label", spec.title ? `${spec.title}\uFF08${type}\uFF09` : type);
|
|
3348
|
+
} else if (!graphic) {
|
|
3349
|
+
const dom = root.querySelector(".icen-chart-vbar, .icen-chart-hbar");
|
|
3350
|
+
if (dom) {
|
|
3351
|
+
dom.setAttribute("role", "img");
|
|
3352
|
+
dom.setAttribute("aria-label", spec.title ? `${spec.title}\uFF08${type}\uFF09` : type);
|
|
3353
|
+
}
|
|
3078
3354
|
}
|
|
3079
3355
|
}
|
|
3080
3356
|
if (loading) return;
|
|
3357
|
+
applyChartA11yPlus(view, spec, type, formatValue);
|
|
3081
3358
|
paintChartMarks(root, view, spec, formatValue, warnedMarks);
|
|
3082
3359
|
bindZoomGesture();
|
|
3083
3360
|
};
|
|
@@ -3159,6 +3436,7 @@ function renderChart(el, raw) {
|
|
|
3159
3436
|
releaseFluidWidth(root);
|
|
3160
3437
|
hiddenLegendKeys.delete(root);
|
|
3161
3438
|
zoomDragCleanup?.();
|
|
3439
|
+
root.removeEventListener("keydown", onKbKeydown);
|
|
3162
3440
|
root.textContent = "";
|
|
3163
3441
|
root.classList.remove("is-loading");
|
|
3164
3442
|
unbindEvents();
|
|
@@ -230,6 +230,7 @@ var ICEN_LOCALE_ZH_CN = {
|
|
|
230
230
|
"aiChat.roleTool": "\u5DE5",
|
|
231
231
|
"aiChat.roleUser": "\u6211",
|
|
232
232
|
"aiChat.thinking": "\u601D\u8003 {p0}",
|
|
233
|
+
"aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
|
|
233
234
|
/* ── aiComposer ── */
|
|
234
235
|
"aiComposer.attachAgent": "\u4EE3\u7406",
|
|
235
236
|
"aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
|
|
@@ -412,6 +413,19 @@ var ICEN_LOCALE_ZH_CN = {
|
|
|
412
413
|
"charts.noData": "\u6682\u65E0\u6570\u636E",
|
|
413
414
|
"charts.resetZoom": "\u91CD\u7F6E\u7F29\u653E",
|
|
414
415
|
"charts.sampled": "\u5DF2\u62BD\u6837 {p0}\u2192{p1} \u70B9",
|
|
416
|
+
"charts.a11y.keyboardHint": "\u65B9\u5411\u952E\u9010\u70B9\u6D4F\u89C8\uFF0CHome/End \u8DF3\u9996\u5C3E\uFF0CEsc \u91CD\u7F6E\u7F29\u653E",
|
|
417
|
+
"charts.a11y.max": "\u6700\u5927 {p0}\uFF08{p1}\uFF09",
|
|
418
|
+
"charts.a11y.min": "\u6700\u5C0F {p0}\uFF08{p1}\uFF09",
|
|
419
|
+
"charts.a11y.point": "{p0}\uFF1A{p1}\uFF0C\u7B2C {p2}/{p3} \u70B9",
|
|
420
|
+
"charts.a11y.pointSeries": "{p0} \xB7 {p1}\uFF1A{p2}\uFF0C\u7B2C {p3}/{p4} \u70B9",
|
|
421
|
+
"charts.a11y.range": "\u7C7B\u76EE {p0} \u81F3 {p1}",
|
|
422
|
+
"charts.a11y.scatterRange": "x \u8303\u56F4 {p0}\u2013{p1}\uFF0Cy \u8303\u56F4 {p2}\u2013{p3}",
|
|
423
|
+
"charts.a11y.seriesCount": "{p0} \u4E2A\u7CFB\u5217",
|
|
424
|
+
"charts.a11y.tableCaption": "{p0} \u6570\u636E\u8868",
|
|
425
|
+
"charts.a11y.trend": "\u9996\u7CFB\u5217\u8D8B\u52BF{p0}",
|
|
426
|
+
"charts.a11y.trendDown": "\u4E0B\u964D",
|
|
427
|
+
"charts.a11y.trendFlat": "\u6301\u5E73",
|
|
428
|
+
"charts.a11y.trendUp": "\u4E0A\u5347",
|
|
415
429
|
"charts.type.area": "\u9762\u79EF\u56FE",
|
|
416
430
|
"charts.type.donut": "\u73AF\u5F62\u56FE",
|
|
417
431
|
"charts.type.gauge": "\u4EEA\u8868\u76D8",
|
|
@@ -1435,12 +1449,19 @@ function prepareFigure(fig) {
|
|
|
1435
1449
|
if (!pre) return;
|
|
1436
1450
|
pre.tabIndex = 0;
|
|
1437
1451
|
pre.setAttribute("role", "region");
|
|
1438
|
-
if (!pre.hasAttribute("aria-label")) pre.setAttribute("aria-label", fig.querySelector(".icen-code-block-file,.icen-code-block-title,.icen-code-block-lang")?.textContent || t("codeBlock.region"));
|
|
1439
1452
|
if (!pre.id) {
|
|
1440
1453
|
do {
|
|
1441
1454
|
pre.id = "icen-code-region-" + ++regionSequence;
|
|
1442
1455
|
} while (document.getElementById(pre.id) && document.getElementById(pre.id) !== pre);
|
|
1443
1456
|
}
|
|
1457
|
+
{
|
|
1458
|
+
const base = (pre.getAttribute("aria-label") || fig.querySelector(".icen-code-block-file,.icen-code-block-title,.icen-code-block-lang")?.textContent || t("codeBlock.region")).trim();
|
|
1459
|
+
const used = /* @__PURE__ */ new Set();
|
|
1460
|
+
for (const region of document.querySelectorAll('pre[role="region"][aria-label]')) if (region !== pre) used.add(region.getAttribute("aria-label") ?? "");
|
|
1461
|
+
let label = base, n = 2;
|
|
1462
|
+
while (used.has(label)) label = `${base} ${n++}`;
|
|
1463
|
+
if (label !== base || !pre.hasAttribute("aria-label")) pre.setAttribute("aria-label", label);
|
|
1464
|
+
}
|
|
1444
1465
|
fig.querySelectorAll("[data-icen-code-block-num],[data-icen-code-block-wrap],[data-icen-code-block-fold],.icen-code-block-tail").forEach((control) => control.setAttribute("aria-controls", pre.id));
|
|
1445
1466
|
syncFold(fig, fig.classList.contains("is-folded"));
|
|
1446
1467
|
}
|
|
@@ -244,6 +244,7 @@ function openCommandPalette(id, opts) {
|
|
|
244
244
|
window.clearTimeout(closingState.timer);
|
|
245
245
|
closingState.backdrop.removeEventListener("transitionend", closingState.onEnd);
|
|
246
246
|
delete closingState.backdrop.dataset.icenState;
|
|
247
|
+
if (closingState.backdrop !== backdrop) closingState.backdrop.hidden = true;
|
|
247
248
|
closingState = null;
|
|
248
249
|
}
|
|
249
250
|
backdrop.hidden = false;
|
|
@@ -286,7 +287,6 @@ function openCommandPalette(id, opts) {
|
|
|
286
287
|
const active = panel.querySelector(".icen-command-palette-item.is-active");
|
|
287
288
|
if (active && !isDisabledItem(active)) {
|
|
288
289
|
e.preventDefault();
|
|
289
|
-
if (!programmaticCommands.has(active)) emitMenuSelect(panel, active);
|
|
290
290
|
active.click();
|
|
291
291
|
}
|
|
292
292
|
return;
|
|
@@ -300,7 +300,7 @@ function openCommandPalette(id, opts) {
|
|
|
300
300
|
els[next]?.focus();
|
|
301
301
|
}
|
|
302
302
|
};
|
|
303
|
-
window.addEventListener("keydown", keyHandler);
|
|
303
|
+
window.addEventListener("keydown", keyHandler, true);
|
|
304
304
|
emitIcen(document, "icen:command-palette-open", {});
|
|
305
305
|
}
|
|
306
306
|
function closeCommandPalette(id, opts) {
|
|
@@ -313,7 +313,7 @@ function closeCommandPalette(id, opts) {
|
|
|
313
313
|
if (openId !== id) return;
|
|
314
314
|
openId = null;
|
|
315
315
|
if (keyHandler) {
|
|
316
|
-
window.removeEventListener("keydown", keyHandler);
|
|
316
|
+
window.removeEventListener("keydown", keyHandler, true);
|
|
317
317
|
keyHandler = null;
|
|
318
318
|
}
|
|
319
319
|
document.body.style.overflow = prevBodyOverflow;
|
|
@@ -222,6 +222,7 @@ var ICEN_LOCALE_ZH_CN = {
|
|
|
222
222
|
"aiChat.roleTool": "\u5DE5",
|
|
223
223
|
"aiChat.roleUser": "\u6211",
|
|
224
224
|
"aiChat.thinking": "\u601D\u8003 {p0}",
|
|
225
|
+
"aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
|
|
225
226
|
/* ── aiComposer ── */
|
|
226
227
|
"aiComposer.attachAgent": "\u4EE3\u7406",
|
|
227
228
|
"aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
|
|
@@ -404,6 +405,19 @@ var ICEN_LOCALE_ZH_CN = {
|
|
|
404
405
|
"charts.noData": "\u6682\u65E0\u6570\u636E",
|
|
405
406
|
"charts.resetZoom": "\u91CD\u7F6E\u7F29\u653E",
|
|
406
407
|
"charts.sampled": "\u5DF2\u62BD\u6837 {p0}\u2192{p1} \u70B9",
|
|
408
|
+
"charts.a11y.keyboardHint": "\u65B9\u5411\u952E\u9010\u70B9\u6D4F\u89C8\uFF0CHome/End \u8DF3\u9996\u5C3E\uFF0CEsc \u91CD\u7F6E\u7F29\u653E",
|
|
409
|
+
"charts.a11y.max": "\u6700\u5927 {p0}\uFF08{p1}\uFF09",
|
|
410
|
+
"charts.a11y.min": "\u6700\u5C0F {p0}\uFF08{p1}\uFF09",
|
|
411
|
+
"charts.a11y.point": "{p0}\uFF1A{p1}\uFF0C\u7B2C {p2}/{p3} \u70B9",
|
|
412
|
+
"charts.a11y.pointSeries": "{p0} \xB7 {p1}\uFF1A{p2}\uFF0C\u7B2C {p3}/{p4} \u70B9",
|
|
413
|
+
"charts.a11y.range": "\u7C7B\u76EE {p0} \u81F3 {p1}",
|
|
414
|
+
"charts.a11y.scatterRange": "x \u8303\u56F4 {p0}\u2013{p1}\uFF0Cy \u8303\u56F4 {p2}\u2013{p3}",
|
|
415
|
+
"charts.a11y.seriesCount": "{p0} \u4E2A\u7CFB\u5217",
|
|
416
|
+
"charts.a11y.tableCaption": "{p0} \u6570\u636E\u8868",
|
|
417
|
+
"charts.a11y.trend": "\u9996\u7CFB\u5217\u8D8B\u52BF{p0}",
|
|
418
|
+
"charts.a11y.trendDown": "\u4E0B\u964D",
|
|
419
|
+
"charts.a11y.trendFlat": "\u6301\u5E73",
|
|
420
|
+
"charts.a11y.trendUp": "\u4E0A\u5347",
|
|
407
421
|
"charts.type.area": "\u9762\u79EF\u56FE",
|
|
408
422
|
"charts.type.donut": "\u73AF\u5F62\u56FE",
|
|
409
423
|
"charts.type.gauge": "\u4EEA\u8868\u76D8",
|