agentcss 0.0.0-stage → 0.11.3
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/01-tokens/README.md +236 -0
- package/01-tokens/behavior/dismissable.js +132 -0
- package/01-tokens/behavior/emit.js +76 -0
- package/01-tokens/behavior/focus-return.js +81 -0
- package/01-tokens/behavior/roving.js +152 -0
- package/01-tokens/behavior/typeahead.js +124 -0
- package/01-tokens/focus-ring-demo.html +133 -0
- package/01-tokens/focus-ring.css +102 -0
- package/01-tokens/page.css +244 -0
- package/01-tokens/polyfill.js +116 -0
- package/01-tokens/responsive-demo.html +171 -0
- package/01-tokens/scrollbar-demo.html +194 -0
- package/01-tokens/scrollbar.css +179 -0
- package/01-tokens/theme-toggle.js +103 -0
- package/01-tokens/tokens.css +972 -0
- package/01-tokens/typography.css +156 -0
- package/02-primitives/badge/README.md +71 -0
- package/02-primitives/badge/badge.css +141 -0
- package/02-primitives/badge/demo.html +101 -0
- package/02-primitives/button/README.md +99 -0
- package/02-primitives/button/button.css +353 -0
- package/02-primitives/button/demo.html +200 -0
- package/02-primitives/card/README.md +145 -0
- package/02-primitives/card/card.css +246 -0
- package/02-primitives/card/demo.html +170 -0
- package/02-primitives/choice/README.md +161 -0
- package/02-primitives/choice/choice.css +395 -0
- package/02-primitives/choice/demo.html +277 -0
- package/02-primitives/combobox/README.md +79 -0
- package/02-primitives/combobox/combobox.css +223 -0
- package/02-primitives/combobox/combobox.js +485 -0
- package/02-primitives/combobox/demo.html +109 -0
- package/02-primitives/date-range/README.md +100 -0
- package/02-primitives/date-range/date-range.css +206 -0
- package/02-primitives/date-range/date-range.js +301 -0
- package/02-primitives/date-range/demo.html +104 -0
- package/02-primitives/input/README.md +170 -0
- package/02-primitives/input/demo.html +246 -0
- package/02-primitives/input/input.css +239 -0
- package/02-primitives/popover/README.md +80 -0
- package/02-primitives/popover/demo.html +150 -0
- package/02-primitives/popover/popover.css +187 -0
- package/02-primitives/popover/popover.js +331 -0
- package/02-primitives/progress/README.md +82 -0
- package/02-primitives/progress/demo.html +154 -0
- package/02-primitives/progress/progress.css +172 -0
- package/02-primitives/select/README.md +95 -0
- package/02-primitives/select/demo.html +121 -0
- package/02-primitives/select/select.css +151 -0
- package/02-primitives/select/select.js +549 -0
- package/02-primitives/separator/README.md +63 -0
- package/02-primitives/separator/demo.html +84 -0
- package/02-primitives/separator/separator.css +73 -0
- package/02-primitives/skeleton/README.md +69 -0
- package/02-primitives/skeleton/demo.html +110 -0
- package/02-primitives/skeleton/skeleton.css +96 -0
- package/02-primitives/switch/README.md +65 -0
- package/02-primitives/switch/demo.html +115 -0
- package/02-primitives/switch/switch.css +370 -0
- package/03-patterns/accordion/README.md +121 -0
- package/03-patterns/accordion/accordion.css +453 -0
- package/03-patterns/accordion/accordion.js +369 -0
- package/03-patterns/accordion/demo.html +223 -0
- package/03-patterns/content/README.md +103 -0
- package/03-patterns/content/content.css +286 -0
- package/03-patterns/content/demo.html +88 -0
- package/03-patterns/drawer/README.md +79 -0
- package/03-patterns/drawer/demo.html +101 -0
- package/03-patterns/drawer/drawer.css +129 -0
- package/03-patterns/drawer/drawer.js +258 -0
- package/03-patterns/dropdown/README.md +78 -0
- package/03-patterns/dropdown/demo.html +101 -0
- package/03-patterns/dropdown/dropdown.css +135 -0
- package/03-patterns/dropdown/dropdown.js +451 -0
- package/03-patterns/form-validation/README.md +147 -0
- package/03-patterns/form-validation/demo.html +280 -0
- package/03-patterns/form-validation/form-validation.css +263 -0
- package/03-patterns/list/README.md +150 -0
- package/03-patterns/list/demo.html +225 -0
- package/03-patterns/list/flip.js +201 -0
- package/03-patterns/list/list.css +162 -0
- package/03-patterns/nav/README.md +225 -0
- package/03-patterns/nav/demo.html +131 -0
- package/03-patterns/nav/nav.css +314 -0
- package/03-patterns/nav/nav.js +430 -0
- package/03-patterns/nav/toc.js +111 -0
- package/03-patterns/overlay/README.md +196 -0
- package/03-patterns/overlay/demo.html +241 -0
- package/03-patterns/overlay/overlay.css +319 -0
- package/03-patterns/overlay/overlay.js +563 -0
- package/03-patterns/pagination/README.md +114 -0
- package/03-patterns/pagination/demo.html +165 -0
- package/03-patterns/pagination/pagination.css +195 -0
- package/03-patterns/pagination/pagination.js +395 -0
- package/03-patterns/reveal/README.md +91 -0
- package/03-patterns/reveal/demo.html +106 -0
- package/03-patterns/reveal/reveal.css +93 -0
- package/03-patterns/reveal/reveal.js +172 -0
- package/03-patterns/states/README.md +141 -0
- package/03-patterns/states/demo.html +240 -0
- package/03-patterns/states/states.css +252 -0
- package/03-patterns/tabs/README.md +84 -0
- package/03-patterns/tabs/demo.html +139 -0
- package/03-patterns/tabs/tabs.css +172 -0
- package/03-patterns/tabs/tabs.js +307 -0
- package/03-patterns/tooltip/README.md +96 -0
- package/03-patterns/tooltip/demo.html +78 -0
- package/03-patterns/tooltip/tooltip.css +89 -0
- package/03-patterns/tooltip/tooltip.js +288 -0
- package/03-patterns/tree/README.md +94 -0
- package/03-patterns/tree/demo.html +138 -0
- package/03-patterns/tree/tree.css +113 -0
- package/03-patterns/tree/tree.js +456 -0
- package/04-recipes/analysis-report/README.md +80 -0
- package/04-recipes/analysis-report/analysis-report.css +187 -0
- package/04-recipes/analysis-report/demo.html +274 -0
- package/04-recipes/data-showcase/README.md +45 -0
- package/04-recipes/data-showcase/demo.html +247 -0
- package/04-recipes/detail-page/README.md +93 -0
- package/04-recipes/detail-page/demo.html +55 -0
- package/04-recipes/detail-page/detail-page.css +190 -0
- package/04-recipes/detail-page/full.html +60 -0
- package/04-recipes/detail-page/null.html +60 -0
- package/04-recipes/detail-page/partial.html +60 -0
- package/04-recipes/detail-page/verify-skeleton.py +19 -0
- package/04-recipes/longform/README.md +93 -0
- package/04-recipes/longform/agc-memory.svg +4 -0
- package/04-recipes/longform/content.html +610 -0
- package/04-recipes/longform/content.md +51 -0
- package/04-recipes/longform/longform.html +627 -0
- package/04-recipes/report/README.md +176 -0
- package/04-recipes/report/demo.html +355 -0
- package/04-recipes/report/report.css +364 -0
- package/04-recipes/table/README.md +103 -0
- package/04-recipes/table/demo.html +455 -0
- package/04-recipes/table/table.css +372 -0
- package/04-recipes/tierA-tokens.css +189 -0
- package/09-assets/README.md +74 -0
- package/09-assets/bar/README.md +94 -0
- package/09-assets/bar/bar.css +166 -0
- package/09-assets/bar/bar.js +320 -0
- package/09-assets/bar/demo.html +176 -0
- package/09-assets/echarts-adapter/demo.html +192 -0
- package/09-assets/echarts-adapter/echarts-adapter.js +277 -0
- package/09-assets/model-viewer/README.md +155 -0
- package/09-assets/model-viewer/demo.html +105 -0
- package/09-assets/model-viewer/model-viewer.css +143 -0
- package/09-assets/model-viewer/model-viewer.js +423 -0
- package/09-assets/scientific-plot/README.md +94 -0
- package/09-assets/scientific-plot/demo.html +252 -0
- package/09-assets/scientific-plot/scientific-plot.css +141 -0
- package/09-assets/scientific-plot/scientific-plot.js +610 -0
- package/09-assets/sparkline/README.md +153 -0
- package/09-assets/sparkline/demo.html +163 -0
- package/09-assets/sparkline/sparkline.css +158 -0
- package/09-assets/sparkline/sparkline.js +508 -0
- package/API.md +332 -0
- package/CHANGELOG.md +3138 -0
- package/CODE_OF_CONDUCT.md +64 -0
- package/CONTRIBUTING.md +89 -0
- package/ERRORS.md +1658 -0
- package/LICENSE +21 -0
- package/README.md +497 -2
- package/SECURITY.md +72 -0
- package/START-HERE.md +164 -0
- package/SUPPORT.md +109 -0
- package/adapters/presentation/README.md +113 -0
- package/adapters/presentation/check.js +101 -0
- package/adapters/presentation/deck.schema.json +74 -0
- package/adapters/presentation/to-doc.js +138 -0
- package/ai/START-HERE.md +104 -0
- package/ai/behaviors.json +380 -0
- package/ai/behaviors.schema.json +61 -0
- package/ai/capabilities.json +56 -0
- package/ai/cli.js +387 -0
- package/ai/components.json +1944 -0
- package/ai/components.meta.json +168 -0
- package/ai/components.schema.json +220 -0
- package/ai/contract.schema.json +147 -0
- package/ai/deprecations.json +55 -0
- package/ai/deprecations.schema.json +85 -0
- package/ai/motion-policy.json +22 -0
- package/ai/patch.js +323 -0
- package/ai/patch.schema.json +63 -0
- package/ai/profiles.json +92 -0
- package/ai/tokens.audience.json +55 -0
- package/ai/tokens.audience.schema.json +73 -0
- package/ai/tokens.json +762 -0
- package/ai/tokens.schema.json +58 -0
- package/ai/tokens.tree.json +752 -0
- package/ai/tokens.tree.schema.json +56 -0
- package/ai/validate.js +383 -0
- package/dist/01-tokens/behavior/dismissable.js +60 -0
- package/dist/01-tokens/behavior/emit.js +21 -0
- package/dist/01-tokens/behavior/focus-return.js +31 -0
- package/dist/01-tokens/behavior/roving.js +77 -0
- package/dist/01-tokens/behavior/typeahead.js +61 -0
- package/dist/01-tokens/focus-ring.css +1 -0
- package/dist/01-tokens/page.css +1 -0
- package/dist/01-tokens/polyfill.js +78 -0
- package/dist/01-tokens/scrollbar.css +1 -0
- package/dist/01-tokens/theme-toggle.js +61 -0
- package/dist/01-tokens/tokens.css +1 -0
- package/dist/01-tokens/typography.css +1 -0
- package/dist/02-primitives/badge/badge.css +1 -0
- package/dist/02-primitives/button/button.css +1 -0
- package/dist/02-primitives/card/card.css +1 -0
- package/dist/02-primitives/choice/choice.css +1 -0
- package/dist/02-primitives/combobox/combobox.css +1 -0
- package/dist/02-primitives/combobox/combobox.js +439 -0
- package/dist/02-primitives/date-range/date-range.css +1 -0
- package/dist/02-primitives/date-range/date-range.js +267 -0
- package/dist/02-primitives/input/input.css +1 -0
- package/dist/02-primitives/popover/popover.css +1 -0
- package/dist/02-primitives/popover/popover.js +257 -0
- package/dist/02-primitives/progress/progress.css +1 -0
- package/dist/02-primitives/select/select.css +1 -0
- package/dist/02-primitives/select/select.js +449 -0
- package/dist/02-primitives/separator/separator.css +1 -0
- package/dist/02-primitives/skeleton/skeleton.css +1 -0
- package/dist/02-primitives/switch/switch.css +1 -0
- package/dist/03-patterns/accordion/accordion.css +1 -0
- package/dist/03-patterns/accordion/accordion.js +219 -0
- package/dist/03-patterns/content/content.css +1 -0
- package/dist/03-patterns/drawer/drawer.css +1 -0
- package/dist/03-patterns/drawer/drawer.js +229 -0
- package/dist/03-patterns/dropdown/dropdown.css +1 -0
- package/dist/03-patterns/dropdown/dropdown.js +365 -0
- package/dist/03-patterns/form-validation/form-validation.css +1 -0
- package/dist/03-patterns/list/flip.js +117 -0
- package/dist/03-patterns/list/list.css +1 -0
- package/dist/03-patterns/nav/nav.css +1 -0
- package/dist/03-patterns/nav/nav.js +322 -0
- package/dist/03-patterns/nav/toc.js +76 -0
- package/dist/03-patterns/overlay/overlay.css +1 -0
- package/dist/03-patterns/overlay/overlay.js +398 -0
- package/dist/03-patterns/pagination/pagination.css +1 -0
- package/dist/03-patterns/pagination/pagination.js +273 -0
- package/dist/03-patterns/reveal/reveal.css +1 -0
- package/dist/03-patterns/reveal/reveal.js +138 -0
- package/dist/03-patterns/states/states.css +1 -0
- package/dist/03-patterns/tabs/tabs.css +1 -0
- package/dist/03-patterns/tabs/tabs.js +242 -0
- package/dist/03-patterns/tooltip/tooltip.css +1 -0
- package/dist/03-patterns/tooltip/tooltip.js +213 -0
- package/dist/03-patterns/tree/tree.css +1 -0
- package/dist/03-patterns/tree/tree.js +383 -0
- package/dist/04-recipes/analysis-report/analysis-report.css +1 -0
- package/dist/04-recipes/detail-page/detail-page.css +1 -0
- package/dist/04-recipes/report/report.css +1 -0
- package/dist/04-recipes/table/table.css +1 -0
- package/dist/04-recipes/tierA-tokens.css +1 -0
- package/dist/09-assets/bar/bar.css +1 -0
- package/dist/09-assets/bar/bar.js +222 -0
- package/dist/09-assets/echarts-adapter/echarts-adapter.js +185 -0
- package/dist/09-assets/model-viewer/model-viewer.css +1 -0
- package/dist/09-assets/model-viewer/model-viewer.js +320 -0
- package/dist/09-assets/scientific-plot/scientific-plot.css +1 -0
- package/dist/09-assets/scientific-plot/scientific-plot.js +568 -0
- package/dist/09-assets/sparkline/sparkline.css +1 -0
- package/dist/09-assets/sparkline/sparkline.js +265 -0
- package/dist/COSTS.md +56 -0
- package/docs/AI-CONTRACT.md +197 -0
- package/docs/BACKLOG.md +127 -0
- package/docs/BENCHMARK.md +252 -0
- package/docs/GUIDANCE.md +154 -0
- package/docs/INVARIANT.md +372 -0
- package/docs/LAYER-BASELINE.md +158 -0
- package/docs/RELEASING.md +311 -0
- package/docs/RFC-THEME-SCOPE.md +141 -0
- package/docs/ROADMAP.md +182 -0
- package/index.html +82 -0
- package/package.json +107 -4
- package/types/index.d.ts +310 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
function cssVar(name, fallback) {
|
|
5
|
+
if (typeof window.getComputedStyle !== 'function') return fallback;
|
|
6
|
+
var v = getComputedStyle(document.documentElement).getPropertyValue(name);
|
|
7
|
+
return (v && v.trim()) || fallback;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function palette() {
|
|
11
|
+
return {
|
|
12
|
+
text: cssVar('--text-primary', '#15181c'),
|
|
13
|
+
textSub: cssVar('--text-secondary', '#5b6472'),
|
|
14
|
+
textTertiary: cssVar('--text-tertiary', '#8a94a3'),
|
|
15
|
+
surface: cssVar('--surface', '#ffffff'),
|
|
16
|
+
paper: cssVar('--paper', '#f6f7f8'),
|
|
17
|
+
border: cssVar('--border-decor', '#e2e5e9'),
|
|
18
|
+
borderStrong: cssVar('--border-control', '#868b94'),
|
|
19
|
+
danger: cssVar('--danger', '#c0392b'),
|
|
20
|
+
success: cssVar('--success', '#2e7d52'),
|
|
21
|
+
warn: cssVar('--warning', '#b8860b'),
|
|
22
|
+
info: cssVar('--info', '#2b7a9e'),
|
|
23
|
+
accent: cssVar('--accent', '#1b4d8f'),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function seriesColors(n, p) {
|
|
28
|
+
var ramp = [p.accent, p.danger, p.success, p.warn, p.info];
|
|
29
|
+
if (n > ramp.length) return null;
|
|
30
|
+
return ramp.slice(0, n);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function theme(name, p) {
|
|
34
|
+
p = p || palette();
|
|
35
|
+
var isDark = document.documentElement.getAttribute('data-theme-current') === 'dark'
|
|
36
|
+
|| cssVar('--paper', '#fff') !== '#f6f7f8';
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
color: [p.accent, p.danger, p.success, p.warn, p.info],
|
|
40
|
+
backgroundColor: 'transparent',
|
|
41
|
+
textStyle: {
|
|
42
|
+
color: p.text,
|
|
43
|
+
fontFamily: cssVar('--sans', 'system-ui, sans-serif'),
|
|
44
|
+
},
|
|
45
|
+
title: {
|
|
46
|
+
textStyle: { color: p.text, fontWeight: 600 },
|
|
47
|
+
subtextStyle: { color: p.textSub },
|
|
48
|
+
},
|
|
49
|
+
legend: { textStyle: { color: p.textSub } },
|
|
50
|
+
tooltip: {
|
|
51
|
+
backgroundColor: isDark ? '#1c2024' : '#ffffff',
|
|
52
|
+
borderColor: p.border,
|
|
53
|
+
borderWidth: 1,
|
|
54
|
+
textStyle: { color: p.text, fontSize: 12 },
|
|
55
|
+
|
|
56
|
+
extraCssText: isDark
|
|
57
|
+
? 'box-shadow:0 2px 8px rgba(0,0,0,.5);'
|
|
58
|
+
: 'box-shadow:0 2px 8px rgba(0,0,0,.1);',
|
|
59
|
+
},
|
|
60
|
+
categoryAxis: axisCommon(p, isDark),
|
|
61
|
+
valueAxis: axisCommon(p, isDark),
|
|
62
|
+
logAxis: axisCommon(p, isDark),
|
|
63
|
+
timeAxis: axisCommon(p, isDark),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function axisCommon(p, isDark) {
|
|
68
|
+
return {
|
|
69
|
+
axisLine: { lineStyle: { color: p.border } },
|
|
70
|
+
axisTick: { show: false },
|
|
71
|
+
axisLabel: { color: p.textSub, fontSize: 11 },
|
|
72
|
+
splitLine: { lineStyle: { color: p.border, type: 'dashed' } },
|
|
73
|
+
|
|
74
|
+
splitNumber: 4,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function defaults(option) {
|
|
79
|
+
var p = palette();
|
|
80
|
+
var o = option || {};
|
|
81
|
+
|
|
82
|
+
o.textStyle = merge(o.textStyle, {
|
|
83
|
+
fontFamily: cssVar('--mono', 'ui-monospace, monospace'),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
o.grid = merge(o.grid, { left: 56, right: 24, top: 32, bottom: 32, containLabel: false });
|
|
87
|
+
|
|
88
|
+
o.series = (o.series || []).map(function (s) {
|
|
89
|
+
if (s.type === 'line') {
|
|
90
|
+
return merge(s, {
|
|
91
|
+
smooth: false,
|
|
92
|
+
showSymbol: (s.data || []).length <= 7,
|
|
93
|
+
symbolSize: 5,
|
|
94
|
+
lineStyle: merge(s.lineStyle, { width: 2 }),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
if (s.type === 'bar') {
|
|
98
|
+
return merge(s, {
|
|
99
|
+
barMaxWidth: 28,
|
|
100
|
+
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (s.type === 'area') {
|
|
104
|
+
return merge(s, {
|
|
105
|
+
areaStyle: merge(s.areaStyle, { opacity: 0.14 }),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return s;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
var isBar = o.series.some(function (s) { return s.type === 'bar'; });
|
|
112
|
+
if (isBar && o.yAxis) {
|
|
113
|
+
var y = Array.isArray(o.yAxis) ? o.yAxis[0] : o.yAxis;
|
|
114
|
+
if (y && y.min === undefined) y.min = 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (o.series.length > 5) {
|
|
118
|
+
if (typeof console !== 'undefined' && console.warn) {
|
|
119
|
+
console.warn('[frontend-lib] 系列数 ' + o.series.length +
|
|
120
|
+
' 超过 5 —— 请改图表类型或分屏,见 charter 10。配色循环会让颜色撞车。');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return o;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function currentThemeName() {
|
|
128
|
+
return 'fe-' +
|
|
129
|
+
(document.documentElement.getAttribute('data-theme-current') || 'light');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function create(dom, opt) {
|
|
133
|
+
if (typeof window.echarts === 'undefined') {
|
|
134
|
+
if (typeof console !== 'undefined' && console.warn) {
|
|
135
|
+
console.warn('[frontend-lib] 未检测到 ECharts —— ' +
|
|
136
|
+
'请在主项目里自行引入(前端库本身零依赖)。');
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
var name = currentThemeName();
|
|
141
|
+
|
|
142
|
+
if (typeof window.echarts.registerTheme === 'function') {
|
|
143
|
+
window.echarts.registerTheme(name, theme(name));
|
|
144
|
+
}
|
|
145
|
+
var inst = window.echarts.init(dom, name);
|
|
146
|
+
inst.__feDom = dom;
|
|
147
|
+
inst.__feOpts = opt || {};
|
|
148
|
+
inst.__feTheme = name;
|
|
149
|
+
inst.setOption(defaults(inst.__feOpts));
|
|
150
|
+
return inst;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function merge(a, b) {
|
|
154
|
+
var o = {}, k;
|
|
155
|
+
if (a) for (k in a) if (a.hasOwnProperty(k)) o[k] = a[k];
|
|
156
|
+
if (b) for (k in b) if (b.hasOwnProperty(k)) o[k] = b[k];
|
|
157
|
+
return o;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
var ChartAdapter = {
|
|
161
|
+
cssVar: cssVar,
|
|
162
|
+
palette: palette,
|
|
163
|
+
seriesColors: seriesColors,
|
|
164
|
+
theme: theme,
|
|
165
|
+
defaults: defaults,
|
|
166
|
+
create: create,
|
|
167
|
+
|
|
168
|
+
refresh: function (inst) {
|
|
169
|
+
if (!inst) return;
|
|
170
|
+
var name = currentThemeName();
|
|
171
|
+
if (typeof window.echarts !== 'undefined' && window.echarts.registerTheme) {
|
|
172
|
+
window.echarts.registerTheme(name, theme(name));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (inst.__feDom) {
|
|
176
|
+
var opt = inst.__feOpts;
|
|
177
|
+
inst.dispose();
|
|
178
|
+
return create(inst.__feDom, opt);
|
|
179
|
+
}
|
|
180
|
+
inst.setOption(defaults(inst.__feOpts), name);
|
|
181
|
+
return inst;
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
if (typeof window !== 'undefined') window.ChartAdapter = ChartAdapter;
|
|
185
|
+
})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.mv {position:relative;display:block;width:100%;box-sizing:border-box;border:1px solid var(--border-decor);border-radius:var(--r-md);background:var(--surface);overflow:hidden;}.mv__stage {display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--sp-2);min-height:180px;padding:var(--sp-5) var(--sp-4);background:var(--surface-sunken);text-align:center;}.mv__stage--err {border-inline-start:3px solid var(--danger);}.mv__ph {font-size:var(--fs-sm);color:var(--text-tertiary);letter-spacing:0.08em;text-transform:uppercase;}.mv__status, .mv__err {margin:0;font-size:var(--fs-sm);color:var(--text-secondary);line-height:1.6;}.mv__err {color:var(--danger);}.mv__btn {display:block;width:calc(100% - var(--sp-6));margin:var(--sp-3) var(--sp-3) 0;min-height:44px;padding:var(--sp-2) var(--sp-4);font:inherit;font-size:var(--fs-sm);font-weight:500;color:var(--text-on-accent);background:var(--accent);border:0;border-radius:var(--r-sm);cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background var(--dur-fast) var(--ease-out);}.mv__btn:hover:not(:disabled) {background:var(--accent-hover);}.mv__btn:disabled {opacity:0.5;cursor:not-allowed;}.mv__btn:focus-visible {outline:2px solid var(--accent);outline-offset:2px;}.mv__hint {margin:0;padding:0 var(--sp-3) var(--sp-3);font-size:var(--fs-xs);color:var(--text-tertiary);line-height:1.6;}.mv__hint code {font-family:var(--mono);font-size:1em;color:var(--text-secondary);}.mv canvas {display:block;width:100% !important;height:auto !important;touch-action:none;background:transparent;}.mv__cap {margin:0;padding:var(--sp-2) var(--sp-3);font-size:var(--fs-xs);color:var(--text-secondary);background:var(--surface);border-top:1px solid var(--border-decor);line-height:1.6;}.mv__cap b {font-family:var(--mono);font-weight:600;color:var(--text-primary);font-variant-numeric:tabular-nums;}@media (prefers-reduced-motion:reduce) {.mv__btn {transition:none;}}@media print {.mv__btn, .mv__hint {display:none;}}@media (hover:hover) and (pointer:fine) {.mv__btn:hover:not(:disabled) {background:var(--accent-hover);}}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
function el(tag, cls, text) {
|
|
5
|
+
var n = document.createElement(tag);
|
|
6
|
+
if (cls) n.className = cls;
|
|
7
|
+
if (text !== undefined && text !== null) n.textContent = text;
|
|
8
|
+
return n;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function hasWebGL() {
|
|
12
|
+
try {
|
|
13
|
+
var c = document.createElement('canvas');
|
|
14
|
+
return !!(c.getContext('webgl2') || c.getContext('webgl') ||
|
|
15
|
+
c.getContext('experimental-webgl'));
|
|
16
|
+
} catch (e) { return false; }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function loadScript(src) {
|
|
20
|
+
return new Promise(function (resolve, reject) {
|
|
21
|
+
if (!src) { resolve(); return; }
|
|
22
|
+
var s = document.createElement('script');
|
|
23
|
+
s.src = src;
|
|
24
|
+
s.async = false;
|
|
25
|
+
s.onload = function () { resolve(); };
|
|
26
|
+
s.onerror = function () {
|
|
27
|
+
reject(new Error('脚本加载失败:' + src));
|
|
28
|
+
};
|
|
29
|
+
document.head.appendChild(s);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function fmtKB(bytes) {
|
|
34
|
+
return Math.round(bytes / 1024) + ' KB';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function Viewer(node) {
|
|
38
|
+
this.node = node;
|
|
39
|
+
|
|
40
|
+
var q = (location.search || '').replace(/^\?/, '');
|
|
41
|
+
function qp(k, dflt) {
|
|
42
|
+
var m = new RegExp('(?:^|&)' + k + '=([^&]*)').exec(q);
|
|
43
|
+
return m ? decodeURIComponent(m[1]) : dflt;
|
|
44
|
+
}
|
|
45
|
+
this.qOverride = !!q;
|
|
46
|
+
this.src = qp('mv', node.getAttribute('data-mv') || '');
|
|
47
|
+
this.h = parseInt(node.getAttribute('data-mv-height') || '320', 10);
|
|
48
|
+
this.threeSrc = qp('three', node.getAttribute('data-mv-three') || '');
|
|
49
|
+
this.gltfSrc = qp('gltf', node.getAttribute('data-mv-gltf') || '');
|
|
50
|
+
this.orbitSrc = qp('orbit', node.getAttribute('data-mv-orbit') || '');
|
|
51
|
+
this.instances = {};
|
|
52
|
+
this.state = 'idle';
|
|
53
|
+
this.build();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Viewer.prototype.build = function () {
|
|
57
|
+
var self = this;
|
|
58
|
+
var n = this.node;
|
|
59
|
+
n.classList.add('mv');
|
|
60
|
+
|
|
61
|
+
this.ui = el('div', 'mv__ui');
|
|
62
|
+
this.ui.appendChild(this.makeIdle());
|
|
63
|
+
n.appendChild(this.ui);
|
|
64
|
+
|
|
65
|
+
this.btn = el('button', 'mv__btn', '加载 3D 模型');
|
|
66
|
+
this.btn.type = 'button';
|
|
67
|
+
this.btn.addEventListener('click', function () { self.load(); });
|
|
68
|
+
this.ui.appendChild(this.btn);
|
|
69
|
+
|
|
70
|
+
this.hint = el('p', 'mv__hint');
|
|
71
|
+
this.hint.innerHTML = '模型 <code>' + (this.src.split('/').pop() || '—') +
|
|
72
|
+
'</code> 会<b>点击后才下载</b>,首屏不占流量。';
|
|
73
|
+
this.ui.appendChild(this.hint);
|
|
74
|
+
|
|
75
|
+
if (!hasWebGL()) {
|
|
76
|
+
this.fail('这台设备的浏览器不支持 WebGL,无法显示 3D 模型。');
|
|
77
|
+
this.btn.disabled = true;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
Viewer.prototype.makeIdle = function () {
|
|
82
|
+
var box = el('div', 'mv__stage');
|
|
83
|
+
box.appendChild(el('div', 'mv__ph', '3D 模型'));
|
|
84
|
+
return box;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
Viewer.prototype.fail = function (msg) {
|
|
88
|
+
if (this.timer) { clearTimeout(this.timer); this.timer = null; }
|
|
89
|
+
this.state = 'error';
|
|
90
|
+
this.ui.innerHTML = '';
|
|
91
|
+
var s = el('div', 'mv__stage mv__stage--err');
|
|
92
|
+
s.appendChild(el('div', 'mv__ph', '3D 模型'));
|
|
93
|
+
var p = el('p', 'mv__err', msg);
|
|
94
|
+
s.appendChild(p);
|
|
95
|
+
this.ui.appendChild(s);
|
|
96
|
+
if (this.btn) this.ui.appendChild(this.btn);
|
|
97
|
+
if (this.btn) {
|
|
98
|
+
this.btn.disabled = false;
|
|
99
|
+
this.btn.textContent = '重试';
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
Viewer.prototype.status = function (msg) {
|
|
104
|
+
if (this.statusNode) { this.statusNode.textContent = msg; }
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
Viewer.prototype.load = function () {
|
|
108
|
+
var self = this;
|
|
109
|
+
if (this.state === 'loading' || this.state === 'ok') return;
|
|
110
|
+
this.state = 'loading';
|
|
111
|
+
|
|
112
|
+
this.ui.innerHTML = '';
|
|
113
|
+
var stage = el('div', 'mv__stage');
|
|
114
|
+
this.statusNode = el('p', 'mv__status', '正在准备…');
|
|
115
|
+
stage.appendChild(this.statusNode);
|
|
116
|
+
this.ui.appendChild(stage);
|
|
117
|
+
|
|
118
|
+
var t0 = (window.performance && performance.now) ? performance.now() : Date.now();
|
|
119
|
+
this.status('正在准备 3D 引擎…');
|
|
120
|
+
this.boot(null, t0, 0);
|
|
121
|
+
|
|
122
|
+
var self0 = this;
|
|
123
|
+
this.timer = setTimeout(function () {
|
|
124
|
+
if (self0.state === 'loading') {
|
|
125
|
+
self0.fail('加载超时(20 秒)。请检查:' +
|
|
126
|
+
'① 模型路径是否正确:'+ self0.src +
|
|
127
|
+
'② 服务器是否能返回该文件(404 时也应给明确提示)');
|
|
128
|
+
}
|
|
129
|
+
}, 20000);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
Viewer.prototype.boot = function (buf, t0, bytes) {
|
|
133
|
+
var self = this;
|
|
134
|
+
|
|
135
|
+
loadScript(this.threeSrc)
|
|
136
|
+
.then(function () { return loadScript(self.gltfSrc); })
|
|
137
|
+
.then(function () { return loadScript(self.orbitSrc); })
|
|
138
|
+
.then(function () { self.initScene(buf, t0, bytes); })
|
|
139
|
+
.catch(function (err) {
|
|
140
|
+
self.fail('3D 引擎加载失败:' + (err && err.message ? err.message : err) +
|
|
141
|
+
'。请检查 three.js / GLTFLoader.js / OrbitControls.js 的路径。');
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
Viewer.prototype.initScene = function (buf, t0, bytes) {
|
|
146
|
+
var self = this;
|
|
147
|
+
if (typeof window.THREE === 'undefined') {
|
|
148
|
+
this.fail('three.js 没有正确加载(THREE 未定义)。请检查 data-mv-three 的路径。');
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
var W = this.node.clientWidth || 320;
|
|
153
|
+
var H = this.h;
|
|
154
|
+
|
|
155
|
+
var scene = new THREE.Scene();
|
|
156
|
+
var camera = new THREE.PerspectiveCamera(45, W / H, 0.1, 100);
|
|
157
|
+
camera.position.set(0, 0.6, 2.4);
|
|
158
|
+
|
|
159
|
+
var renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
|
160
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
|
|
161
|
+
renderer.setSize(W, H);
|
|
162
|
+
renderer.setClearColor(0x000000, 0);
|
|
163
|
+
this.ui.innerHTML = '';
|
|
164
|
+
this.node.appendChild(renderer.domElement);
|
|
165
|
+
this.statusNode = null;
|
|
166
|
+
|
|
167
|
+
scene.add(new THREE.AmbientLight(0xffffff, 0.45));
|
|
168
|
+
var key = new THREE.DirectionalLight(0xffffff, 0.9);
|
|
169
|
+
key.position.set(1, 1.6, 1.4);
|
|
170
|
+
scene.add(key);
|
|
171
|
+
var rim = new THREE.DirectionalLight(0xffffff, 0.35);
|
|
172
|
+
rim.position.set(-1.2, 0.4, -1);
|
|
173
|
+
scene.add(rim);
|
|
174
|
+
|
|
175
|
+
var OrbitCtor = (window.THREE && window.THREE.OrbitControls) || window.OrbitControls;
|
|
176
|
+
var controls = null;
|
|
177
|
+
if (OrbitCtor) {
|
|
178
|
+
controls = new OrbitCtor(camera, renderer.domElement);
|
|
179
|
+
controls.enableDamping = true;
|
|
180
|
+
controls.dampingFactor = 0.08;
|
|
181
|
+
controls.enablePan = false;
|
|
182
|
+
controls.minDistance = 1.1;
|
|
183
|
+
controls.maxDistance = 4.5;
|
|
184
|
+
controls.target.set(0, 0.35, 0);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
var GLCtor = (window.THREE && window.THREE.GLTFLoader) || window.GLTFLoader;
|
|
188
|
+
if (!GLCtor) {
|
|
189
|
+
this.fail('GLTFLoader 没有正确加载(THREE.GLTFLoader 未定义)。请检查 data-mv-gltf 的路径。');
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
var loader = new GLCtor();
|
|
194
|
+
|
|
195
|
+
var self1 = this;
|
|
196
|
+
var xhr = new XMLHttpRequest();
|
|
197
|
+
xhr.responseType = 'arraybuffer';
|
|
198
|
+
xhr.open('GET', this.src, true);
|
|
199
|
+
xhr.onprogress = function (e) {
|
|
200
|
+
if (e.lengthComputable && e.total) {
|
|
201
|
+
self1.lastBytes = e.total;
|
|
202
|
+
self1.status('正在下载模型 ' + Math.round(e.loaded / e.total * 100) + '%');
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
xhr.onload = function () {
|
|
206
|
+
if (xhr.status >= 400) {
|
|
207
|
+
self1.fail('模型不存在(HTTP ' + xhr.status + '):' + self1.src);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
var buf = xhr.response;
|
|
211
|
+
|
|
212
|
+
if (!buf || buf.byteLength < 12) {
|
|
213
|
+
self1.fail('模型文件是空的或损坏了:' + self1.src);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
var b0 = new Uint8Array(buf, 0, 4);
|
|
218
|
+
var head = String.fromCharCode(b0[0], b0[1], b0[2], b0[3]);
|
|
219
|
+
if (head !== 'glTF') {
|
|
220
|
+
self1.fail('这不是 glb 文件(缺少 glTF 标识,收到的是「' + head + '」)。' +
|
|
221
|
+
'服务器可能返回了 HTML 错误页。');
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
doLoad(buf);
|
|
225
|
+
};
|
|
226
|
+
xhr.onerror = function () { self1.fail('无法访问模型:' + self1.src); };
|
|
227
|
+
xhr.send();
|
|
228
|
+
|
|
229
|
+
function doLoad(buf) {
|
|
230
|
+
loader.parse(buf, '', function (gltf) {
|
|
231
|
+
var model = gltf.scene;
|
|
232
|
+
|
|
233
|
+
var box = new THREE.Box3().setFromObject(model);
|
|
234
|
+
var size = box.getSize(new THREE.Vector3());
|
|
235
|
+
var center = box.getCenter(new THREE.Vector3());
|
|
236
|
+
model.position.sub(center);
|
|
237
|
+
var maxDim = Math.max(size.x, size.y, size.z) || 1;
|
|
238
|
+
model.scale.setScalar(1.6 / maxDim);
|
|
239
|
+
box.setFromObject(model);
|
|
240
|
+
var c2 = box.getCenter(new THREE.Vector3());
|
|
241
|
+
model.position.sub(new THREE.Vector3(c2.x, box.min.y + (box.max.y - box.min.y) * 0.45, c2.z));
|
|
242
|
+
scene.add(model);
|
|
243
|
+
|
|
244
|
+
if (self.timer) { clearTimeout(self.timer); self.timer = null; }
|
|
245
|
+
self.state = 'ok';
|
|
246
|
+
self.instances = { scene: scene, camera: camera, renderer: renderer,
|
|
247
|
+
model: model, controls: controls };
|
|
248
|
+
|
|
249
|
+
var last = 0;
|
|
250
|
+
function loop(t) {
|
|
251
|
+
self.raf = requestAnimationFrame(loop);
|
|
252
|
+
|
|
253
|
+
if (document.hidden) return;
|
|
254
|
+
if (controls) controls.update();
|
|
255
|
+
renderer.render(scene, camera);
|
|
256
|
+
last = t;
|
|
257
|
+
}
|
|
258
|
+
self.raf = requestAnimationFrame(loop);
|
|
259
|
+
|
|
260
|
+
self.ui.innerHTML = '';
|
|
261
|
+
var cap = el('p', 'mv__cap');
|
|
262
|
+
var dt = Math.round(((window.performance && performance.now) ? performance.now() : Date.now()) - t0);
|
|
263
|
+
cap.innerHTML = '模型 <b>' + fmtKB(bytes || self.lastBytes || 0) + '</b> · 引擎就绪耗时 <b>' + dt + 'ms</b>' +
|
|
264
|
+
(controls ? ' · 拖动可旋转,滚轮/双指可缩放' : ' · 未加载控制器,无法拖动');
|
|
265
|
+
self.node.appendChild(cap);
|
|
266
|
+
},
|
|
267
|
+
|
|
268
|
+
function (evt) {
|
|
269
|
+
if (evt && evt.lengthComputable && evt.total) {
|
|
270
|
+
self.lastBytes = evt.total;
|
|
271
|
+
self.status('正在下载模型 ' + Math.round(evt.loaded / evt.total * 100) + '%');
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
|
|
275
|
+
function (err) {
|
|
276
|
+
var msg = (err && err.message) ? err.message : (err || '未知错误');
|
|
277
|
+
|
|
278
|
+
if (msg.indexOf('fetch') > -1 || msg.indexOf('Failed') > -1) {
|
|
279
|
+
self.fail('模型加载失败:服务器的 Content-Security-Policy 缺少 blob:,' +
|
|
280
|
+
'内嵌贴图被浏览器拦下了。需要在 CSP 的 img-src 与 connect-src 里加上 blob:。');
|
|
281
|
+
} else {
|
|
282
|
+
self.fail('模型加载失败:' + msg + '。请确认 ' + self.src + ' 已部署且可访问。');
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
var ModelViewer = {
|
|
289
|
+
|
|
290
|
+
update: function (root) {
|
|
291
|
+
var list = (root || document).querySelectorAll('[data-mv]');
|
|
292
|
+
for (var i = 0; i < list.length; i++) {
|
|
293
|
+
if (list[i].__mv) continue;
|
|
294
|
+
list[i].__mv = new Viewer(list[i]);
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
refresh: function (root) {
|
|
299
|
+
var list = (root || document).querySelectorAll('[data-mv]');
|
|
300
|
+
for (var i = 0; i < list.length; i++) {
|
|
301
|
+
var v = list[i].__mv;
|
|
302
|
+
if (!v || v.state !== 'ok') continue;
|
|
303
|
+
if (v.raf) cancelAnimationFrame(v.raf);
|
|
304
|
+
if (v.instances && v.instances.renderer) {
|
|
305
|
+
try { v.instances.renderer.dispose(); } catch (e) {}
|
|
306
|
+
}
|
|
307
|
+
list[i].innerHTML = '';
|
|
308
|
+
list[i].__mv = new Viewer(list[i]);
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
if (typeof window !== 'undefined') window.ModelViewer = ModelViewer;
|
|
314
|
+
|
|
315
|
+
if (document.readyState === 'loading') {
|
|
316
|
+
document.addEventListener('DOMContentLoaded', function () { ModelViewer.update(); });
|
|
317
|
+
} else {
|
|
318
|
+
ModelViewer.update();
|
|
319
|
+
}
|
|
320
|
+
})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.splot {display:block;max-width:100%;height:auto;font-family:var(--sans);}.splot__s0 {--splot-c:var(--accent);}.splot__s1 {--splot-c:var(--danger);}.splot__s2 {--splot-c:var(--success);}.splot__s3 {--splot-c:var(--warning);}.splot__s4 {--splot-c:var(--info);}.splot__grid {stroke:var(--border-decor);stroke-width:1;}.splot__axis {stroke:var(--border-decor-str);stroke-width:1;}.splot__tick {stroke:var(--border-decor-str);stroke-width:1;}.splot__tick-label {fill:var(--text-tertiary);font-size:var(--fs-xs);font-variant-numeric:tabular-nums;}.splot__axis-label {fill:var(--text-secondary);font-size:var(--fs-xs);font-weight:500;}.splot__line {fill:none;stroke:var(--splot-c, var(--accent));stroke-width:2;stroke-linejoin:round;stroke-linecap:round;}.splot__pt {fill:var(--splot-c, var(--accent));stroke:var(--surface);stroke-width:1;}.splot__err {stroke:var(--splot-c, var(--accent));stroke-width:1.5;stroke-linecap:round;}.splot__band {fill:var(--splot-c, var(--accent));fill-opacity:.14;stroke:none;}.splot__legend {display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-4, 1rem);margin:var(--sp-2) 0 0;padding:0;list-style:none;font-size:var(--fs-xs);color:var(--text-secondary);}.splot__legend-item {display:inline-flex;align-items:center;gap:var(--sp-1);}.splot__legend-mark {flex:0 0 auto;overflow:visible;}.splot__legend-mark line {stroke:var(--splot-c, var(--accent));}.splot__ref {stroke:var(--text-tertiary);stroke-width:1;stroke-dasharray:4 4;}.splot__ref-label {fill:var(--text-tertiary);font-size:var(--fs-xs);}.splot__anno-dot {fill:var(--text-primary);}.splot__anno {fill:var(--text-primary);font-size:var(--fs-xs);font-weight:600;}.splot__note {fill:var(--warning);font-size:var(--fs-xs);}@media (prefers-contrast:more) {.splot__axis, .splot__tick {stroke:var(--text-primary);}.splot__line {stroke-width:3;}}@media print {.splot__grid {stroke:var(--border-decor);}.splot__band {fill-opacity:.22;}}
|