Files
wangjia 40760aa884
ci / server (push) Failing after 14s
ci / design-tokens (push) Failing after 11s
dudu MVP:五端语音输入法初始提交
- server:Go 网关(WS 流式识别中继/计费配额/微信登录支付 mock/反馈/埋点),gummy provider 已真实联调
- desktop:Tauri 2(全局快捷键 push-to-talk/浮层/托盘/设置/登录购买/反馈/首启引导)
- android:Compose 主 App + IME(键盘内录音直传)
- ios:App + 键盘扩展(1A spike 实证键盘内不可录音,走 deep link 听写)
- design/design-pipeline:设计系统 + token 导出 iOS/Android 主题
- doc:前后端设计文档(HTML);web:官网宣传页;todo:任务看板

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 00:38:37 +08:00

2536 lines
86 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* @ds-bundle: {"format":3,"namespace":"DuduDesignSystem_2e0172","components":[{"name":"Badge","sourcePath":"components/core/Badge.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Card","sourcePath":"components/core/Card.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Kbd","sourcePath":"components/core/Kbd.jsx"},{"name":"HotkeyCombo","sourcePath":"components/core/Kbd.jsx"},{"name":"ProgressBar","sourcePath":"components/core/ProgressBar.jsx"},{"name":"Input","sourcePath":"components/forms/Input.jsx"},{"name":"SettingRow","sourcePath":"components/forms/SettingRow.jsx"},{"name":"Switch","sourcePath":"components/forms/Switch.jsx"},{"name":"MicBar","sourcePath":"components/voice/MicBar.jsx"},{"name":"RecognitionOverlay","sourcePath":"components/voice/RecognitionOverlay.jsx"},{"name":"Waveform","sourcePath":"components/voice/Waveform.jsx"}],"sourceHashes":{"components/core/Badge.jsx":"d5433a1dda15","components/core/Button.jsx":"4b31f273e96b","components/core/Card.jsx":"9c6e3ffd97c3","components/core/IconButton.jsx":"48e88946ef2f","components/core/Kbd.jsx":"3bf363d1e58f","components/core/ProgressBar.jsx":"3fc99fb6d122","components/forms/Input.jsx":"f155fb819be6","components/forms/SettingRow.jsx":"7dde4fa7a2d6","components/forms/Switch.jsx":"2ee4051b56cf","components/voice/MicBar.jsx":"fc199b567222","components/voice/RecognitionOverlay.jsx":"d9bcf80d92e9","components/voice/Waveform.jsx":"e1c4a0aab25c","ui_kits/desktop/DesktopShared.jsx":"a4c508056a42","ui_kits/desktop/LoginPurchase.jsx":"022475732fde","ui_kits/desktop/OverlayDemo.jsx":"c20232f9bec3","ui_kits/desktop/SettingsTray.jsx":"5448b0778969","ui_kits/mobile/AppScreens.jsx":"13aaca8c53d1","ui_kits/mobile/KeyboardScreen.jsx":"13f81b790a9f","ui_kits/mobile/MobileShared.jsx":"bfd297452e3e"},"inlinedExternals":[],"unexposedExports":[]} */
(() => {
const __ds_ns = (window.DuduDesignSystem_2e0172 = window.DuduDesignSystem_2e0172 || {});
const __ds_scope = {};
(__ds_ns.__errors = __ds_ns.__errors || []);
// components/core/Badge.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const ddBadgeCss = `
.dd-badge {
display: inline-flex; align-items: center; gap: 4px;
font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--weight-semibold);
padding: 2px 10px; border-radius: var(--radius-full); line-height: var(--leading-normal);
}
.dd-badge--neutral { background: var(--surface-2); color: var(--text-2); }
.dd-badge--blue { background: var(--accent-soft); color: var(--accent-text); }
.dd-badge--green { background: var(--positive-soft); color: var(--positive); }
.dd-badge--orange { background: var(--warning-soft); color: var(--warning); }
.dd-badge--red { background: var(--danger-soft); color: var(--danger); }
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-badge-css')) {
const s = document.createElement('style');
s.id = 'dd-badge-css';
s.textContent = ddBadgeCss;
document.head.appendChild(s);
}
function Badge({
tone = 'neutral',
children,
...rest
}) {
return /*#__PURE__*/React.createElement("span", _extends({
className: `dd-badge dd-badge--${tone}`
}, rest), children);
}
Object.assign(__ds_scope, { Badge });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/Badge.jsx", error: String((e && e.message) || e) }); }
// components/core/Button.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const ddButtonCss = `
.dd-btn {
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
font-family: var(--font-sans); font-weight: var(--weight-medium);
border-radius: var(--radius-sm); border: 1px solid transparent;
cursor: pointer; white-space: nowrap; user-select: none;
transition: background var(--dur-fast) var(--ease-out),
border-color var(--dur-fast) var(--ease-out),
color var(--dur-fast) var(--ease-out);
}
.dd-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.dd-btn--sm { height: var(--control-sm); padding: 0 12px; font-size: var(--text-sm); }
.dd-btn--md { height: var(--control-md); padding: 0 16px; font-size: var(--text-base); }
.dd-btn--lg { height: var(--control-lg); padding: 0 20px; font-size: var(--text-md); }
.dd-btn--block { width: 100%; }
.dd-btn--primary { background: var(--accent); color: var(--text-on-accent); }
.dd-btn--primary:hover { background: var(--accent-hover); }
.dd-btn--primary:active { background: var(--accent-press); }
.dd-btn--secondary { background: var(--surface-card); border-color: var(--border-2); color: var(--text-1); }
.dd-btn--secondary:hover { background: var(--surface-2); }
.dd-btn--secondary:active { background: var(--surface-3); }
.dd-btn--ghost { background: transparent; color: var(--accent-text); }
.dd-btn--ghost:hover { background: var(--accent-soft); }
.dd-btn--ghost:active { background: var(--accent-soft-2); }
.dd-btn--danger { background: var(--danger); color: #fff; }
.dd-btn--danger:hover { filter: brightness(0.94); }
.dd-btn[disabled] { opacity: 0.45; pointer-events: none; }
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-button-css')) {
const s = document.createElement('style');
s.id = 'dd-button-css';
s.textContent = ddButtonCss;
document.head.appendChild(s);
}
function Button({
variant = 'primary',
size = 'md',
block = false,
disabled = false,
children,
...rest
}) {
const cls = `dd-btn dd-btn--${variant} dd-btn--${size}${block ? ' dd-btn--block' : ''}`;
return /*#__PURE__*/React.createElement("button", _extends({
type: "button",
className: cls,
disabled: disabled
}, rest), children);
}
Object.assign(__ds_scope, { Button });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/Button.jsx", error: String((e && e.message) || e) }); }
// components/core/Card.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const ddCardCss = `
.dd-card {
background: var(--surface-card); border: 1px solid var(--border-1);
border-radius: var(--radius-md); box-shadow: var(--shadow-card);
}
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-card-css')) {
const s = document.createElement('style');
s.id = 'dd-card-css';
s.textContent = ddCardCss;
document.head.appendChild(s);
}
function Card({
padding = 'var(--space-5)',
style,
children,
...rest
}) {
return /*#__PURE__*/React.createElement("div", _extends({
className: "dd-card",
style: {
padding,
...style
}
}, rest), children);
}
Object.assign(__ds_scope, { Card });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/Card.jsx", error: String((e && e.message) || e) }); }
// components/core/IconButton.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const ddIconBtnCss = `
.dd-iconbtn {
display: inline-flex; align-items: center; justify-content: center;
border: none; background: transparent; color: var(--text-2);
border-radius: var(--radius-sm); cursor: pointer;
transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.dd-iconbtn:hover { background: var(--surface-2); color: var(--text-1); }
.dd-iconbtn:active { background: var(--surface-3); }
.dd-iconbtn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.dd-iconbtn[disabled] { opacity: 0.45; pointer-events: none; }
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-iconbtn-css')) {
const s = document.createElement('style');
s.id = 'dd-iconbtn-css';
s.textContent = ddIconBtnCss;
document.head.appendChild(s);
}
function IconButton({
size = 32,
label,
disabled = false,
children,
...rest
}) {
return /*#__PURE__*/React.createElement("button", _extends({
type: "button",
className: "dd-iconbtn",
"aria-label": label,
title: label,
style: {
width: size,
height: size
},
disabled: disabled
}, rest), children);
}
Object.assign(__ds_scope, { IconButton });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/IconButton.jsx", error: String((e && e.message) || e) }); }
// components/core/Kbd.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const ddKbdCss = `
.dd-kbd {
display: inline-block; background: var(--surface-2);
border: 1px solid var(--border-2); border-bottom-width: 2px;
border-radius: var(--radius-xs); padding: 1px 7px;
font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-1);
line-height: 1.5;
}
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-kbd-css')) {
const s = document.createElement('style');
s.id = 'dd-kbd-css';
s.textContent = ddKbdCss;
document.head.appendChild(s);
}
function Kbd({
children,
...rest
}) {
return /*#__PURE__*/React.createElement("kbd", _extends({
className: "dd-kbd"
}, rest), children);
}
function HotkeyCombo({
keys = [],
gap = 4
}) {
return /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
gap,
alignItems: 'center'
}
}, keys.map((k, i) => /*#__PURE__*/React.createElement(Kbd, {
key: i
}, k)));
}
Object.assign(__ds_scope, { Kbd, HotkeyCombo });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/Kbd.jsx", error: String((e && e.message) || e) }); }
// components/core/ProgressBar.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const ddProgressCss = `
.dd-progress { background: var(--surface-3); border-radius: var(--radius-full); overflow: hidden; }
.dd-progress i { display: block; height: 100%; border-radius: var(--radius-full);
background: var(--accent); transition: width var(--dur-slow) var(--ease-out); }
.dd-progress--warning i { background: var(--warning); }
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-progress-css')) {
const s = document.createElement('style');
s.id = 'dd-progress-css';
s.textContent = ddProgressCss;
document.head.appendChild(s);
}
function ProgressBar({
value = 0,
max = 100,
height = 6,
warnAt = 0.9,
style,
...rest
}) {
const ratio = Math.min(1, max > 0 ? value / max : 0);
const warning = ratio >= warnAt;
return /*#__PURE__*/React.createElement("div", _extends({
className: `dd-progress${warning ? ' dd-progress--warning' : ''}`,
style: {
height,
...style
},
role: "progressbar",
"aria-valuenow": value,
"aria-valuemax": max
}, rest), /*#__PURE__*/React.createElement("i", {
style: {
width: `${ratio * 100}%`
}
}));
}
Object.assign(__ds_scope, { ProgressBar });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/core/ProgressBar.jsx", error: String((e && e.message) || e) }); }
// components/forms/Input.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const ddInputCss = `
.dd-input {
display: block; width: 100%; box-sizing: border-box;
height: var(--control-md); padding: 0 12px;
font-family: var(--font-sans); font-size: var(--text-base); color: var(--text-1);
background: var(--surface-card); border: 1px solid var(--border-2);
border-radius: var(--radius-sm);
transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.dd-input::placeholder { color: var(--text-3); }
.dd-input:hover { border-color: var(--gray-400); }
.dd-input:focus { outline: none; border-color: var(--accent); box-shadow: var(--focus-ring); }
.dd-input[disabled] { opacity: 0.45; pointer-events: none; }
.dd-input--lg { height: var(--control-lg); font-size: var(--text-md); border-radius: var(--radius-sm); }
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-input-css')) {
const s = document.createElement('style');
s.id = 'dd-input-css';
s.textContent = ddInputCss;
document.head.appendChild(s);
}
function Input({
size = 'md',
style,
...rest
}) {
return /*#__PURE__*/React.createElement("input", _extends({
className: `dd-input${size === 'lg' ? ' dd-input--lg' : ''}`,
style: style
}, rest));
}
Object.assign(__ds_scope, { Input });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/Input.jsx", error: String((e && e.message) || e) }); }
// components/forms/SettingRow.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const ddSettingRowCss = `
.dd-setrow {
display: flex; align-items: center; justify-content: space-between; gap: 16px;
padding: 12px 0; border-bottom: 1px solid var(--border-1);
font-family: var(--font-sans); font-size: var(--text-base);
}
.dd-setrow:last-child { border-bottom: none; }
.dd-setrow__label { color: var(--text-1); }
.dd-setrow__desc { font-size: var(--text-xs); color: var(--text-3); margin-top: 2px; }
.dd-setrow__control { display: flex; align-items: center; gap: 8px; color: var(--text-2); font-size: var(--text-sm); }
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-setrow-css')) {
const s = document.createElement('style');
s.id = 'dd-setrow-css';
s.textContent = ddSettingRowCss;
document.head.appendChild(s);
}
function SettingRow({
label,
description,
children,
...rest
}) {
return /*#__PURE__*/React.createElement("div", _extends({
className: "dd-setrow"
}, rest), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
className: "dd-setrow__label"
}, label), description ? /*#__PURE__*/React.createElement("div", {
className: "dd-setrow__desc"
}, description) : null), /*#__PURE__*/React.createElement("div", {
className: "dd-setrow__control"
}, children));
}
Object.assign(__ds_scope, { SettingRow });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/SettingRow.jsx", error: String((e && e.message) || e) }); }
// components/forms/Switch.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const ddSwitchCss = `
.dd-switch {
position: relative; display: inline-block; width: 40px; height: 24px;
border-radius: var(--radius-full); background: var(--surface-3);
border: none; cursor: pointer; padding: 0; flex: none;
transition: background var(--dur-base) var(--ease-out);
}
.dd-switch::after {
content: ''; position: absolute; top: 3px; left: 3px;
width: 18px; height: 18px; border-radius: 50%;
background: #fff; box-shadow: 0 1px 3px rgba(17,19,26,0.25);
transition: transform var(--dur-base) var(--ease-out);
}
.dd-switch[aria-checked="true"] { background: var(--accent); }
.dd-switch[aria-checked="true"]::after { transform: translateX(16px); }
.dd-switch:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.dd-switch[disabled] { opacity: 0.45; pointer-events: none; }
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-switch-css')) {
const s = document.createElement('style');
s.id = 'dd-switch-css';
s.textContent = ddSwitchCss;
document.head.appendChild(s);
}
function Switch({
checked = false,
onChange,
disabled = false,
...rest
}) {
return /*#__PURE__*/React.createElement("button", _extends({
type: "button",
role: "switch",
className: "dd-switch",
"aria-checked": checked ? 'true' : 'false',
disabled: disabled,
onClick: () => onChange && onChange(!checked)
}, rest));
}
Object.assign(__ds_scope, { Switch });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/forms/Switch.jsx", error: String((e && e.message) || e) }); }
// components/voice/Waveform.jsx
try { (() => {
const ddWaveCss = `
.dd-wave { display: inline-flex; align-items: center; gap: 3px; }
.dd-wave i { display: block; width: 3px; border-radius: 2px; background: currentColor; }
.dd-wave--active i { animation: dd-wave-bounce 0.9s var(--ease-in-out) infinite alternate; }
@keyframes dd-wave-bounce {
from { transform: scaleY(0.35); }
to { transform: scaleY(1); }
}
@media (prefers-reduced-motion: reduce) {
.dd-wave--active i { animation: none; }
}
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-wave-css')) {
const s = document.createElement('style');
s.id = 'dd-wave-css';
s.textContent = ddWaveCss;
document.head.appendChild(s);
}
const DD_WAVE_PATTERN = [0.3, 0.55, 0.85, 0.45, 0.7, 1, 0.4, 0.6, 0.25, 0.8, 0.5, 0.35];
function Waveform({
bars = 12,
active = false,
height = 26,
color = 'var(--accent)',
style
}) {
const items = [];
for (let i = 0; i < bars; i++) {
const h = Math.round(DD_WAVE_PATTERN[i % DD_WAVE_PATTERN.length] * height);
items.push(/*#__PURE__*/React.createElement("i", {
key: i,
style: {
height: Math.max(4, h),
animationDelay: `${i % 6 * 0.07}s`
}
}));
}
return /*#__PURE__*/React.createElement("span", {
className: `dd-wave${active ? ' dd-wave--active' : ''}`,
style: {
height,
color,
...style
},
"aria-hidden": "true"
}, items);
}
Object.assign(__ds_scope, { Waveform });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/voice/Waveform.jsx", error: String((e && e.message) || e) }); }
// components/voice/MicBar.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const ddMicBarCss = `
.dd-micbar {
display: flex; align-items: center; justify-content: center; gap: 8px;
width: 100%; height: var(--control-xl); border: none; cursor: pointer;
border-radius: var(--radius-full);
font-family: var(--font-sans); font-size: var(--text-md); font-weight: var(--weight-semibold);
user-select: none; -webkit-user-select: none; touch-action: none;
transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.dd-micbar--idle { background: var(--accent); color: var(--text-on-accent); }
.dd-micbar--idle:active { background: var(--accent-press); }
.dd-micbar--recording { background: var(--positive); color: #fff; }
.dd-micbar--disabled { background: var(--surface-3); color: var(--text-3); cursor: default; }
.dd-micbar--quota { background: var(--warning); color: #fff; }
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-micbar-css')) {
const s = document.createElement('style');
s.id = 'dd-micbar-css';
s.textContent = ddMicBarCss;
document.head.appendChild(s);
}
function DdMicIcon({
size = 20
}) {
return /*#__PURE__*/React.createElement("svg", {
width: size,
height: size,
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
strokeWidth: "2",
strokeLinecap: "round",
strokeLinejoin: "round",
"aria-hidden": "true"
}, /*#__PURE__*/React.createElement("path", {
d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"
}), /*#__PURE__*/React.createElement("path", {
d: "M19 10v2a7 7 0 0 1-14 0v-2"
}), /*#__PURE__*/React.createElement("line", {
x1: "12",
x2: "12",
y1: "19",
y2: "22"
}));
}
const DD_MICBAR_LABELS = {
idle: '按住说话',
recording: '松开完成 · 上滑取消',
disabled: '打开 dudu App 登录',
quota: '今日试用已用完,去购买时长'
};
function MicBar({
state = 'idle',
label,
...rest
}) {
const text = label || DD_MICBAR_LABELS[state] || DD_MICBAR_LABELS.idle;
return /*#__PURE__*/React.createElement("button", _extends({
type: "button",
className: `dd-micbar dd-micbar--${state}`
}, rest), state === 'recording' ? /*#__PURE__*/React.createElement(__ds_scope.Waveform, {
active: true,
bars: 9,
height: 18,
color: "rgba(255,255,255,0.95)"
}) : /*#__PURE__*/React.createElement(DdMicIcon, null), /*#__PURE__*/React.createElement("span", null, text));
}
Object.assign(__ds_scope, { MicBar });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/voice/MicBar.jsx", error: String((e && e.message) || e) }); }
// components/voice/RecognitionOverlay.jsx
try { (() => {
const ddOverlayCss = `
.dd-overlay {
box-sizing: border-box; width: 340px;
background: var(--overlay-bg); color: var(--overlay-text);
border-radius: var(--radius-lg); padding: 14px 18px;
box-shadow: var(--shadow-overlay);
font-family: var(--font-sans);
backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
}
.dd-overlay__status {
display: flex; align-items: center; gap: 8px;
color: var(--overlay-text-2); font-size: var(--text-base); margin-top: 8px;
}
.dd-overlay__text { font-size: var(--text-md); line-height: 1.6; margin-top: 8px; min-height: 24px; }
.dd-overlay__text .dd-partial { color: var(--overlay-text-2); }
.dd-overlay__hint { font-size: 11px; color: var(--overlay-text-3); margin-top: 8px; text-align: right; }
`;
if (typeof document !== 'undefined' && !document.getElementById('dd-overlay-css')) {
const s = document.createElement('style');
s.id = 'dd-overlay-css';
s.textContent = ddOverlayCss;
document.head.appendChild(s);
}
function RecognitionOverlay({
state = 'listening',
finalText = '',
partialText = '',
hint = '松开 ⌘⇧Space 完成输入',
width = 340,
style
}) {
return /*#__PURE__*/React.createElement("div", {
className: "dd-overlay",
style: {
width,
...style
},
role: "status"
}, /*#__PURE__*/React.createElement(__ds_scope.Waveform, {
active: true,
bars: 12,
height: 24,
color: "#7C9BFF"
}), state === 'listening' ? /*#__PURE__*/React.createElement("div", {
className: "dd-overlay__status"
}, /*#__PURE__*/React.createElement("svg", {
width: "16",
height: "16",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
strokeWidth: "2",
strokeLinecap: "round",
strokeLinejoin: "round",
"aria-hidden": "true"
}, /*#__PURE__*/React.createElement("path", {
d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"
}), /*#__PURE__*/React.createElement("path", {
d: "M19 10v2a7 7 0 0 1-14 0v-2"
}), /*#__PURE__*/React.createElement("line", {
x1: "12",
x2: "12",
y1: "19",
y2: "22"
})), /*#__PURE__*/React.createElement("span", null, "\u8046\u542C\u4E2D\u2026")) : /*#__PURE__*/React.createElement("div", {
className: "dd-overlay__text"
}, finalText, partialText ? /*#__PURE__*/React.createElement("span", {
className: "dd-partial"
}, partialText) : null), /*#__PURE__*/React.createElement("div", {
className: "dd-overlay__hint"
}, hint));
}
Object.assign(__ds_scope, { RecognitionOverlay });
})(); } catch (e) { __ds_ns.__errors.push({ path: "components/voice/RecognitionOverlay.jsx", error: String((e && e.message) || e) }); }
// ui_kits/desktop/DesktopShared.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
// dudu 桌面端 UI kit · 共享元素:Lucide 图标子集、mac 窗口框、伪二维码
// 通过 window 共享给其余 text/babel 脚本
function DuduIcon({
d,
size = 16,
sw = 2,
children,
...rest
}) {
return /*#__PURE__*/React.createElement("svg", _extends({
width: size,
height: size,
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
strokeWidth: sw,
strokeLinecap: "round",
strokeLinejoin: "round",
"aria-hidden": "true"
}, rest), children);
}
const DuIcons = {
Mic: p => /*#__PURE__*/React.createElement(DuduIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"
}), /*#__PURE__*/React.createElement("path", {
d: "M19 10v2a7 7 0 0 1-14 0v-2"
}), /*#__PURE__*/React.createElement("line", {
x1: "12",
x2: "12",
y1: "19",
y2: "22"
})),
Settings: p => /*#__PURE__*/React.createElement(DuduIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"
}), /*#__PURE__*/React.createElement("circle", {
cx: "12",
cy: "12",
r: "3"
})),
Check: p => /*#__PURE__*/React.createElement(DuduIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M20 6 9 17l-5-5"
})),
X: p => /*#__PURE__*/React.createElement(DuduIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M18 6 6 18"
}), /*#__PURE__*/React.createElement("path", {
d: "m6 6 12 12"
})),
ChevronDown: p => /*#__PURE__*/React.createElement(DuduIcon, p, /*#__PURE__*/React.createElement("path", {
d: "m6 9 6 6 6-6"
})),
ChevronRight: p => /*#__PURE__*/React.createElement(DuduIcon, p, /*#__PURE__*/React.createElement("path", {
d: "m9 18 6-6-6-6"
})),
Sun: p => /*#__PURE__*/React.createElement(DuduIcon, p, /*#__PURE__*/React.createElement("circle", {
cx: "12",
cy: "12",
r: "4"
}), /*#__PURE__*/React.createElement("path", {
d: "M12 2v2"
}), /*#__PURE__*/React.createElement("path", {
d: "M12 20v2"
}), /*#__PURE__*/React.createElement("path", {
d: "m4.93 4.93 1.41 1.41"
}), /*#__PURE__*/React.createElement("path", {
d: "m17.66 17.66 1.41 1.41"
}), /*#__PURE__*/React.createElement("path", {
d: "M2 12h2"
}), /*#__PURE__*/React.createElement("path", {
d: "M20 12h2"
}), /*#__PURE__*/React.createElement("path", {
d: "m6.34 17.66-1.41 1.41"
}), /*#__PURE__*/React.createElement("path", {
d: "m19.07 4.93-1.41 1.41"
})),
Moon: p => /*#__PURE__*/React.createElement(DuduIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"
})),
AudioLines: p => /*#__PURE__*/React.createElement(DuduIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M2 10v3"
}), /*#__PURE__*/React.createElement("path", {
d: "M6 6v11"
}), /*#__PURE__*/React.createElement("path", {
d: "M10 3v18"
}), /*#__PURE__*/React.createElement("path", {
d: "M14 8v7"
}), /*#__PURE__*/React.createElement("path", {
d: "M18 5v13"
}), /*#__PURE__*/React.createElement("path", {
d: "M22 10v3"
})),
User: p => /*#__PURE__*/React.createElement(DuduIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"
}), /*#__PURE__*/React.createElement("circle", {
cx: "12",
cy: "7",
r: "4"
})),
LogOut: p => /*#__PURE__*/React.createElement(DuduIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"
}), /*#__PURE__*/React.createElement("polyline", {
points: "16 17 21 12 16 7"
}), /*#__PURE__*/React.createElement("line", {
x1: "21",
x2: "9",
y1: "12",
y2: "12"
}))
};
// dudu 圆嘴 logocurrentColor 线条版)
function DuduLogo({
size = 20,
sw = 3.5
}) {
return /*#__PURE__*/React.createElement("svg", {
width: size,
height: size,
viewBox: "0 0 48 48",
fill: "none",
stroke: "currentColor",
strokeWidth: sw,
strokeLinecap: "round",
"aria-hidden": "true"
}, /*#__PURE__*/React.createElement("circle", {
cx: "24",
cy: "24",
r: "18"
}), /*#__PURE__*/React.createElement("path", {
d: "M17 20.5v7"
}), /*#__PURE__*/React.createElement("path", {
d: "M24 16.5v15"
}), /*#__PURE__*/React.createElement("path", {
d: "M31 20.5v7"
}));
}
// mac 风格窗口(红绿灯 + 标题)
function MacWindow({
title,
width = 460,
children,
style
}) {
return /*#__PURE__*/React.createElement("div", {
style: {
width,
background: 'var(--surface-card)',
borderRadius: 'var(--radius-md)',
border: '1px solid var(--border-1)',
boxShadow: 'var(--shadow-window)',
overflow: 'hidden',
fontFamily: 'var(--font-sans)',
...style
}
}, /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
alignItems: 'center',
gap: 7,
padding: '10px 14px',
background: 'var(--surface-2)',
borderBottom: '1px solid var(--border-1)'
}
}, /*#__PURE__*/React.createElement("span", {
style: {
width: 11,
height: 11,
borderRadius: '50%',
background: '#FF5F57'
}
}), /*#__PURE__*/React.createElement("span", {
style: {
width: 11,
height: 11,
borderRadius: '50%',
background: '#FEBC2E'
}
}), /*#__PURE__*/React.createElement("span", {
style: {
width: 11,
height: 11,
borderRadius: '50%',
background: '#28C840'
}
}), /*#__PURE__*/React.createElement("span", {
style: {
marginLeft: 10,
fontSize: 'var(--text-xs)',
color: 'var(--text-2)',
whiteSpace: 'nowrap'
}
}, title)), children);
}
// 伪二维码占位(确定性图案,仅作占位 — 接入后端 /v1/auth/qr 后替换)
function FakeQr({
size = 148,
seed = 7
}) {
const n = 17;
const cells = [];
let s = seed;
const rnd = () => {
s = s * 16807 % 2147483647;
return s / 2147483647;
};
for (let y = 0; y < n; y++) {
for (let x = 0; x < n; x++) {
const corner = x < 5 && y < 5 || x > n - 6 && y < 5 || x < 5 && y > n - 6;
let on;
if (corner) {
const cx = x > n - 6 ? x - (n - 5) : x,
cy = y > n - 6 ? y - (n - 5) : y;
on = cx === 0 || cx === 4 || cy === 0 || cy === 4 || cx > 1 && cx < 3 + 1 && cy > 1 && cy < 3 + 1;
} else {
on = rnd() > 0.52;
}
if (on) cells.push(/*#__PURE__*/React.createElement("span", {
key: x + '-' + y,
style: {
gridColumn: x + 1,
gridRow: y + 1,
background: '#1B1E26',
borderRadius: 1
}
}));
}
}
return /*#__PURE__*/React.createElement("div", {
style: {
width: size,
height: size,
padding: 10,
boxSizing: 'border-box',
background: '#fff',
borderRadius: 'var(--radius-md)',
border: '1px solid var(--border-1)',
display: 'grid',
gridTemplateColumns: `repeat(${n}, 1fr)`,
gridTemplateRows: `repeat(${n}, 1fr)`,
gap: 1
},
"aria-label": "\u4E8C\u7EF4\u7801\u5360\u4F4D"
}, cells);
}
Object.assign(window, {
DuduIcon,
DuIcons,
DuduLogo,
MacWindow,
FakeQr
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/desktop/DesktopShared.jsx", error: String((e && e.message) || e) }); }
// ui_kits/desktop/LoginPurchase.jsx
try { (() => {
// dudu 桌面端 · 登录 / 购买窗口(点击走完整流程:扫码登录 → 选时长包 → 支付 → 完成)
function LoginPurchaseWindow() {
const {
Button,
Badge
} = window.DuduDesignSystem_2e0172;
const [step, setStep] = React.useState('login'); // login | plans | pay | done
const [plan, setPlan] = React.useState('m');
const PACKS = {
s: {
label: '100 分钟',
price: 9,
desc: '约 ¥0.09 / 分钟',
tag: ''
},
m: {
label: '500 分钟',
price: 39,
desc: '约 ¥0.078 / 分钟',
tag: '省 13%'
},
l: {
label: '2000 分钟',
price: 129,
desc: '约 ¥0.065 / 分钟',
tag: '省 28%'
}
};
const Center = ({
children
}) => /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 14,
padding: '26px 24px 30px',
fontFamily: 'var(--font-sans)'
}
}, children);
return /*#__PURE__*/React.createElement(MacWindow, {
title: step === 'login' ? 'dudu — 登录' : 'dudu — 购买时长',
width: 400
}, step === 'login' && /*#__PURE__*/React.createElement(Center, null, /*#__PURE__*/React.createElement("span", {
style: {
color: 'var(--accent)'
}
}, /*#__PURE__*/React.createElement(DuduLogo, {
size: 40
})), /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-lg)',
fontWeight: 'var(--weight-semibold)',
color: 'var(--text-1)'
}
}, "\u5FAE\u4FE1\u626B\u7801\u767B\u5F55"), /*#__PURE__*/React.createElement(FakeQr, {
seed: 7
}), /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-sm)',
color: 'var(--text-2)',
textAlign: 'center',
lineHeight: 'var(--leading-normal)'
}
}, "\u6253\u5F00\u5FAE\u4FE1\u626B\u4E00\u626B\uFF0C\u786E\u8BA4\u540E\u81EA\u52A8\u767B\u5F55"), /*#__PURE__*/React.createElement(Button, {
variant: "ghost",
size: "sm",
onClick: () => setStep('plans')
}, "\u6A21\u62DF\uFF1A\u624B\u673A\u5DF2\u786E\u8BA4 \u2192")), step === 'plans' && /*#__PURE__*/React.createElement(Center, null, /*#__PURE__*/React.createElement("div", {
style: {
alignSelf: 'stretch',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}
}, /*#__PURE__*/React.createElement("span", {
style: {
fontSize: 'var(--text-lg)',
fontWeight: 'var(--weight-semibold)',
color: 'var(--text-1)'
}
}, "\u8D2D\u4E70\u65F6\u957F"), /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 8,
fontSize: 'var(--text-sm)',
color: 'var(--text-2)'
}
}, "wang*** ", /*#__PURE__*/React.createElement(Badge, {
tone: "blue"
}, "\u8BD5\u7528\u4E2D"))), /*#__PURE__*/React.createElement("div", {
style: {
alignSelf: 'stretch',
display: 'flex',
flexDirection: 'column',
gap: 10
}
}, Object.entries(PACKS).map(([key, p]) => {
const active = plan === key;
return /*#__PURE__*/React.createElement("button", {
key: key,
type: "button",
onClick: () => setPlan(key),
style: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
textAlign: 'left',
padding: '13px 16px',
borderRadius: 'var(--radius-md)',
cursor: 'pointer',
border: active ? '1.5px solid var(--accent)' : '1px solid var(--border-1)',
background: active ? 'var(--accent-soft)' : 'var(--surface-card)',
fontFamily: 'var(--font-sans)',
transition: 'border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out)'
}
}, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 8
}
}, /*#__PURE__*/React.createElement("span", {
style: {
fontSize: 'var(--text-base)',
fontWeight: 'var(--weight-medium)',
color: 'var(--text-1)'
}
}, p.label), p.tag && /*#__PURE__*/React.createElement("span", {
style: {
fontSize: 10,
padding: '1px 7px',
borderRadius: 'var(--radius-full)',
background: 'var(--warning-soft)',
color: 'var(--warning)',
fontWeight: 'var(--weight-medium)'
}
}, p.tag)), /*#__PURE__*/React.createElement("span", {
style: {
display: 'block',
fontSize: 'var(--text-xs)',
color: 'var(--text-2)',
marginTop: 3
}
}, p.desc)), /*#__PURE__*/React.createElement("span", {
style: {
color: active ? 'var(--accent-text)' : 'var(--text-1)',
whiteSpace: 'nowrap'
}
}, /*#__PURE__*/React.createElement("span", {
style: {
fontSize: 'var(--text-2xl)',
fontWeight: 'var(--weight-bold)'
}
}, "\xA5", p.price)));
})), /*#__PURE__*/React.createElement("div", {
style: {
alignSelf: 'stretch',
fontSize: 'var(--text-xs)',
color: 'var(--text-3)',
lineHeight: 'var(--leading-normal)'
}
}, "\u65F6\u957F\u4E0D\u8FC7\u671F \xB7 \u6BCF\u5929\u53E6\u6709 3 \u5206\u949F\u514D\u8D39\u8BD5\u7528"), /*#__PURE__*/React.createElement(Button, {
variant: "primary",
block: true,
onClick: () => setStep('pay')
}, "\u5FAE\u4FE1\u652F\u4ED8 \xA5", PACKS[plan].price)), step === 'pay' && /*#__PURE__*/React.createElement(Center, null, /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-lg)',
fontWeight: 'var(--weight-semibold)',
color: 'var(--text-1)'
}
}, "\u5FAE\u4FE1\u626B\u7801\u652F\u4ED8"), /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-3xl)',
fontWeight: 'var(--weight-bold)',
color: 'var(--text-1)',
fontFamily: 'var(--font-sans)'
}
}, "\xA5", PACKS[plan].price, /*#__PURE__*/React.createElement("span", {
style: {
fontSize: 'var(--text-sm)',
fontWeight: 'var(--weight-regular)',
color: 'var(--text-3)'
}
}, " \xB7 ", PACKS[plan].label, "\u65F6\u957F\u5305")), /*#__PURE__*/React.createElement(FakeQr, {
seed: 23
}), /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-sm)',
color: 'var(--text-2)'
}
}, "\u652F\u4ED8\u5B8C\u6210\u540E\u81EA\u52A8\u5F00\u901A"), /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
gap: 10
}
}, /*#__PURE__*/React.createElement(Button, {
variant: "secondary",
size: "sm",
onClick: () => setStep('plans')
}, "\u8FD4\u56DE"), /*#__PURE__*/React.createElement(Button, {
variant: "ghost",
size: "sm",
onClick: () => setStep('done')
}, "\u6A21\u62DF\uFF1A\u652F\u4ED8\u6210\u529F \u2192"))), step === 'done' && /*#__PURE__*/React.createElement(Center, null, /*#__PURE__*/React.createElement("span", {
style: {
width: 56,
height: 56,
borderRadius: '50%',
background: 'var(--positive-soft)',
color: 'var(--positive)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
}, /*#__PURE__*/React.createElement(DuIcons.Check, {
size: 28,
sw: 2.5
})), /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-lg)',
fontWeight: 'var(--weight-semibold)',
color: 'var(--text-1)'
}
}, "\u5DF2\u5230\u8D26 ", PACKS[plan].label), /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-sm)',
color: 'var(--text-2)',
textAlign: 'center'
}
}, "\u65F6\u957F\u4F59\u989D 472 \u5206\u949F \xB7 \u4E0D\u8FC7\u671F \xB7 \u73B0\u5728\u5C31\u6309\u4F4F \u2318\u21E7Space \u8BD5\u8BD5"), /*#__PURE__*/React.createElement(Button, {
variant: "primary",
onClick: () => setStep('login')
}, "\u5F00\u59CB\u4F7F\u7528")));
}
Object.assign(window, {
LoginPurchaseWindow
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/desktop/LoginPurchase.jsx", error: String((e && e.message) || e) }); }
// ui_kits/desktop/OverlayDemo.jsx
try { (() => {
// dudu 桌面端 · 识别浮层演示
// 在仿真备忘录窗口上方演示完整 push-to-talk 流程:
// 按住按钮(= 按住 ⌘⇧Space)→ 聆听中 → partial 流式 → 松开 → final 注入输入框
const DEMO_SENTENCES = ['帮我把这份周报整理一下,重点突出本周的进展和下周的计划。', '好的,我马上把文件发给你,大概十分钟之内。', '明天上午十点的会改到下午三点,记得同步给项目组。'];
function OverlayDemo() {
const {
RecognitionOverlay
} = window.DuduDesignSystem_2e0172;
const [phase, setPhase] = React.useState('idle'); // idle | listening | streaming
const [finalText, setFinalText] = React.useState('');
const [partialText, setPartialText] = React.useState('');
const [docText, setDocText] = React.useState('');
const [sentenceIdx, setSentenceIdx] = React.useState(0);
const timerRef = React.useRef(null);
const stateRef = React.useRef({});
stateRef.current = {
finalText,
partialText,
sentenceIdx
};
const stop = React.useCallback(() => {
clearInterval(timerRef.current);
const {
finalText: f,
partialText: p,
sentenceIdx: idx
} = stateRef.current;
const committed = f + p;
if (committed) {
setDocText(d => d + committed);
setSentenceIdx((idx + 1) % DEMO_SENTENCES.length);
}
setFinalText('');
setPartialText('');
setPhase('idle');
}, []);
const start = React.useCallback(() => {
if (timerRef.current) clearInterval(timerRef.current);
setPhase('listening');
setFinalText('');
setPartialText('');
const sentence = DEMO_SENTENCES[stateRef.current.sentenceIdx];
let i = 0;
setTimeout(() => setPhase(ph => ph === 'listening' ? 'streaming' : ph), 420);
timerRef.current = setInterval(() => {
i += 1;
if (i >= sentence.length) {
clearInterval(timerRef.current);
setFinalText(sentence);
setPartialText('');
return;
}
// 模拟流式:句读处定稿(final),其余为 partial
const lastPunct = Math.max(sentence.lastIndexOf('', i), sentence.lastIndexOf('。', i));
setFinalText(sentence.slice(0, lastPunct + 1));
setPartialText(sentence.slice(lastPunct + 1, i));
}, 90);
}, []);
React.useEffect(() => () => clearInterval(timerRef.current), []);
const overlayState = phase === 'streaming' && (finalText || partialText) ? 'text' : 'listening';
return /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 28
}
}, /*#__PURE__*/React.createElement("div", {
style: {
position: 'relative'
}
}, /*#__PURE__*/React.createElement(MacWindow, {
title: "\u5907\u5FD8\u5F55 \u2014 \u5468\u62A5\u8349\u7A3F",
width: 560
}, /*#__PURE__*/React.createElement("div", {
style: {
padding: '18px 20px',
minHeight: 150
}
}, /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-md)',
lineHeight: 'var(--leading-loose)',
color: 'var(--text-1)',
minHeight: 96
}
}, docText || /*#__PURE__*/React.createElement("span", {
style: {
color: 'var(--text-3)'
}
}, "\u5149\u6807\u5728\u8FD9\u91CC \u2014 \u5728\u4EFB\u610F\u5E94\u7528\u4E2D\u6309\u4F4F\u5FEB\u6377\u952E\u5373\u53EF\u8BED\u97F3\u8F93\u5165"), /*#__PURE__*/React.createElement("span", {
style: {
color: 'var(--accent)',
animation: 'dd-caret 1.1s steps(1) infinite'
}
}, "\u258F")))), phase !== 'idle' && /*#__PURE__*/React.createElement("div", {
style: {
position: 'absolute',
left: '50%',
top: '100%',
transform: 'translate(-50%, -22px)',
animation: 'dd-rise var(--dur-base) var(--ease-out)'
}
}, /*#__PURE__*/React.createElement(RecognitionOverlay, {
state: overlayState,
finalText: finalText,
partialText: partialText,
hint: "\u677E\u5F00 \u2318\u21E7Space \u5B8C\u6210\u8F93\u5165"
}))), /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
alignItems: 'center',
gap: 14,
marginTop: phase === 'idle' ? 0 : 40
}
}, /*#__PURE__*/React.createElement("button", {
type: "button",
onPointerDown: start,
onPointerUp: stop,
onPointerLeave: () => phase !== 'idle' && stop(),
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 8,
height: 'var(--control-lg)',
padding: '0 22px',
borderRadius: 'var(--radius-full)',
border: 'none',
cursor: 'pointer',
background: phase === 'idle' ? 'var(--accent)' : 'var(--positive)',
color: 'var(--text-on-accent)',
fontSize: 'var(--text-base)',
fontWeight: 'var(--weight-semibold)',
fontFamily: 'var(--font-sans)',
userSelect: 'none',
WebkitUserSelect: 'none',
transition: 'background var(--dur-fast) var(--ease-out)'
}
}, /*#__PURE__*/React.createElement(DuIcons.Mic, {
size: 17
}), phase === 'idle' ? '按住试一试(模拟按住 ⌘⇧Space)' : '松开完成输入'), docText && /*#__PURE__*/React.createElement("button", {
type: "button",
onClick: () => setDocText(''),
style: {
height: 'var(--control-lg)',
padding: '0 16px',
borderRadius: 'var(--radius-full)',
border: '1px solid var(--border-1)',
background: 'var(--surface-card)',
color: 'var(--text-2)',
fontSize: 'var(--text-sm)',
cursor: 'pointer',
fontFamily: 'var(--font-sans)'
}
}, "\u6E05\u7A7A")));
}
Object.assign(window, {
OverlayDemo
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/desktop/OverlayDemo.jsx", error: String((e && e.message) || e) }); }
// ui_kits/desktop/SettingsTray.jsx
try { (() => {
// dudu 桌面端 · 系统托盘菜单 + 设置窗口
function TrayMenu() {
const {
Badge
} = window.DuduDesignSystem_2e0172;
const Item = ({
children,
right,
accent,
onClick
}) => {
const [hover, setHover] = React.useState(false);
return /*#__PURE__*/React.createElement("div", {
onMouseEnter: () => setHover(true),
onMouseLeave: () => setHover(false),
onClick: onClick,
style: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
gap: 18,
padding: '7px 14px',
cursor: 'default',
fontSize: 'var(--text-sm)',
background: hover ? 'var(--accent)' : 'transparent',
color: hover ? 'var(--text-on-accent)' : accent ? 'var(--text-1)' : 'var(--text-1)',
transition: 'background var(--dur-fast) var(--ease-out)'
}
}, /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 8,
whiteSpace: 'nowrap'
}
}, children), right && /*#__PURE__*/React.createElement("span", {
style: {
fontSize: 'var(--text-xs)',
color: hover ? 'rgba(255,255,255,0.8)' : 'var(--text-3)',
whiteSpace: 'nowrap'
}
}, right));
};
const Sep = () => /*#__PURE__*/React.createElement("div", {
style: {
height: 1,
background: 'var(--border-1)',
margin: '4px 0'
}
});
return /*#__PURE__*/React.createElement("div", {
style: {
width: 248,
padding: '5px 0',
fontFamily: 'var(--font-sans)',
background: 'color-mix(in srgb, var(--surface-card) 96%, transparent)',
backdropFilter: 'blur(20px)',
WebkitBackdropFilter: 'blur(20px)',
border: '1px solid var(--border-1)',
borderRadius: 'var(--radius-md)',
boxShadow: 'var(--shadow-menu)'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '8px 14px 6px'
}
}, /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 8,
fontSize: 'var(--text-sm)',
fontWeight: 'var(--weight-medium)',
color: 'var(--text-1)',
whiteSpace: 'nowrap'
}
}, /*#__PURE__*/React.createElement(DuduLogo, {
size: 17
}), " dudu \u8BED\u97F3\u8F93\u5165"), /*#__PURE__*/React.createElement(Badge, {
tone: "green"
}, "\u5DF2\u5C31\u7EEA")), /*#__PURE__*/React.createElement(Sep, null), /*#__PURE__*/React.createElement(Item, {
right: /*#__PURE__*/React.createElement(DuIcons.Check, {
size: 13
})
}, "\u542F\u7528\u5FEB\u6377\u952E"), /*#__PURE__*/React.createElement(Item, {
right: "\u2318\u21E7Space"
}, "\u6309\u4F4F\u8BF4\u8BDD"), /*#__PURE__*/React.createElement(Item, null, "\u8BBE\u7F6E\u2026"), /*#__PURE__*/React.createElement(Item, {
right: "472 \u5206\u949F"
}, "\u65F6\u957F\u4F59\u989D"), /*#__PURE__*/React.createElement(Sep, null), /*#__PURE__*/React.createElement(Item, {
right: "\u5DF2\u767B\u5F55"
}, "\u8D26\u53F7 wang***"), /*#__PURE__*/React.createElement(Item, null, "\u68C0\u67E5\u66F4\u65B0"), /*#__PURE__*/React.createElement(Sep, null), /*#__PURE__*/React.createElement(Item, null, "\u9000\u51FA dudu"));
}
function SettingsWindow({
theme,
onThemeChange
}) {
const {
Switch,
SettingRow,
HotkeyCombo,
Button,
Badge,
ProgressBar
} = window.DuduDesignSystem_2e0172;
const [autostart, setAutostart] = React.useState(true);
const [sound, setSound] = React.useState(false);
const [mic, setMic] = React.useState('MacBook Pro 麦克风');
const Section = ({
title,
children
}) => /*#__PURE__*/React.createElement("div", {
style: {
padding: '4px 18px 8px'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-xs)',
color: 'var(--text-3)',
fontWeight: 'var(--weight-medium)',
margin: '10px 0 2px',
letterSpacing: 'var(--tracking-wide)'
}
}, title), children);
const themeOptions = [['system', '跟随系统'], ['light', '浅色'], ['dark', '深色']];
return /*#__PURE__*/React.createElement(MacWindow, {
title: "dudu \u8BBE\u7F6E",
width: 440
}, /*#__PURE__*/React.createElement(Section, {
title: "\u8F93\u5165"
}, /*#__PURE__*/React.createElement(SettingRow, {
label: "\u8BF4\u8BDD\u5FEB\u6377\u952E",
description: "\u6309\u4F4F\u8BF4\u8BDD\uFF0C\u677E\u5F00\u4E0A\u5C4F"
}, /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 10
}
}, /*#__PURE__*/React.createElement(HotkeyCombo, {
keys: ['⌘', '⇧', 'Space']
}), /*#__PURE__*/React.createElement(Button, {
variant: "ghost",
size: "sm"
}, "\u4FEE\u6539"))), /*#__PURE__*/React.createElement(SettingRow, {
label: "\u9EA6\u514B\u98CE"
}, /*#__PURE__*/React.createElement("span", {
style: {
position: 'relative',
display: 'inline-flex',
alignItems: 'center'
}
}, /*#__PURE__*/React.createElement("select", {
value: mic,
onChange: e => setMic(e.target.value),
style: {
appearance: 'none',
WebkitAppearance: 'none',
height: 'var(--control-sm)',
padding: '0 30px 0 10px',
borderRadius: 'var(--radius-sm)',
border: '1px solid var(--border-1)',
background: 'var(--surface-card)',
color: 'var(--text-1)',
fontSize: 'var(--text-sm)',
fontFamily: 'var(--font-sans)',
cursor: 'pointer'
}
}, /*#__PURE__*/React.createElement("option", null, "MacBook Pro \u9EA6\u514B\u98CE"), /*#__PURE__*/React.createElement("option", null, "AirPods Pro"), /*#__PURE__*/React.createElement("option", null, "\u5916\u63A5 USB \u9EA6\u514B\u98CE")), /*#__PURE__*/React.createElement("span", {
style: {
position: 'absolute',
right: 8,
pointerEvents: 'none',
color: 'var(--text-3)',
display: 'inline-flex'
}
}, /*#__PURE__*/React.createElement(DuIcons.ChevronDown, {
size: 13
})))), /*#__PURE__*/React.createElement(SettingRow, {
label: "\u63D0\u793A\u97F3",
description: "\u5F00\u59CB / \u5B8C\u6210\u65F6\u64AD\u653E\u8F7B\u63D0\u793A\u97F3"
}, /*#__PURE__*/React.createElement(Switch, {
checked: sound,
onChange: setSound
}))), /*#__PURE__*/React.createElement("div", {
style: {
height: 1,
background: 'var(--border-1)'
}
}), /*#__PURE__*/React.createElement(Section, {
title: "\u901A\u7528"
}, /*#__PURE__*/React.createElement(SettingRow, {
label: "\u5F00\u673A\u81EA\u542F"
}, /*#__PURE__*/React.createElement(Switch, {
checked: autostart,
onChange: setAutostart
})), /*#__PURE__*/React.createElement(SettingRow, {
label: "\u5916\u89C2"
}, /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
background: 'var(--surface-2)',
borderRadius: 'var(--radius-sm)',
padding: 2,
gap: 2
}
}, themeOptions.map(([val, lab]) => /*#__PURE__*/React.createElement("button", {
key: val,
type: "button",
onClick: () => onThemeChange(val),
style: {
height: 24,
padding: '0 10px',
borderRadius: 4,
border: 'none',
cursor: 'pointer',
fontSize: 'var(--text-xs)',
fontFamily: 'var(--font-sans)',
background: theme === val ? 'var(--surface-card)' : 'transparent',
color: theme === val ? 'var(--text-1)' : 'var(--text-2)',
boxShadow: theme === val ? 'var(--shadow-card)' : 'none',
transition: 'background var(--dur-fast) var(--ease-out)'
}
}, lab))))), /*#__PURE__*/React.createElement("div", {
style: {
height: 1,
background: 'var(--border-1)'
}
}), /*#__PURE__*/React.createElement(Section, {
title: "\u8D26\u53F7\u4E0E\u65F6\u957F"
}, /*#__PURE__*/React.createElement(SettingRow, {
label: "\u767B\u5F55\u72B6\u6001",
description: "\u5FAE\u4FE1\u5DF2\u767B\u5F55"
}, /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 8,
fontSize: 'var(--text-sm)',
color: 'var(--text-1)'
}
}, "wang*** ", /*#__PURE__*/React.createElement(Badge, {
tone: "green"
}, "\u4F59\u989D\u5145\u8DB3"))), /*#__PURE__*/React.createElement(SettingRow, {
label: "\u65F6\u957F\u4F59\u989D",
description: "\u65F6\u957F\u4E0D\u8FC7\u671F \xB7 \u6BCF\u5929\u53E6\u6709 3 \u5206\u949F\u514D\u8D39\u8BD5\u7528"
}, /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 10
}
}, /*#__PURE__*/React.createElement("span", {
style: {
fontSize: 'var(--text-base)',
fontWeight: 'var(--weight-semibold)',
color: 'var(--text-1)',
fontFamily: 'var(--font-sans)'
}
}, "472 \u5206\u949F"), /*#__PURE__*/React.createElement(Button, {
variant: "secondary",
size: "sm"
}, "\u8D2D\u4E70\u65F6\u957F"))), /*#__PURE__*/React.createElement("div", {
style: {
padding: '10px 0 12px'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
justifyContent: 'space-between',
fontSize: 'var(--text-xs)',
color: 'var(--text-2)',
marginBottom: 7
}
}, /*#__PURE__*/React.createElement("span", null, "\u4ECA\u65E5\u514D\u8D39\u8BD5\u7528"), /*#__PURE__*/React.createElement("span", {
style: {
fontFamily: 'var(--font-mono)'
}
}, "1 / 3 \u5206\u949F")), /*#__PURE__*/React.createElement(ProgressBar, {
value: 1,
max: 3
}))));
}
Object.assign(window, {
TrayMenu,
SettingsWindow
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/desktop/SettingsTray.jsx", error: String((e && e.message) || e) }); }
// ui_kits/mobile/AppScreens.jsx
try { (() => {
// dudu 移动端 · 主 App 四屏:启用引导 / 登录 / 购买时长 / 我的
function MAppHeader({
title
}) {
return /*#__PURE__*/React.createElement("div", {
style: {
textAlign: 'center',
fontSize: 'var(--text-md)',
fontWeight: 'var(--weight-medium)',
color: 'var(--text-1)',
padding: '4px 0 10px'
}
}, title);
}
/* ---------- ① 启用引导 ---------- */
function OnboardingScreen() {
const {
Button
} = window.DuduDesignSystem_2e0172;
const [step, setStep] = React.useState(0);
const steps = [{
title: '添加键盘',
desc: '设置 → 通用 → 键盘 → 添加新键盘,选择 dudu',
icon: /*#__PURE__*/React.createElement(DuMIcons.Keyboard, {
size: 26
})
}, {
title: '开启完全访问',
desc: '语音识别需要联网,请允许完全访问',
icon: /*#__PURE__*/React.createElement(DuMIcons.Shield, {
size: 26
})
}, {
title: '试一试',
desc: '在下面的输入框按住麦克风说一句话',
icon: /*#__PURE__*/React.createElement(DuMIcons.Mic, {
size: 26
})
}];
return /*#__PURE__*/React.createElement("div", {
style: {
flex: 1,
display: 'flex',
flexDirection: 'column',
padding: '4px 18px 18px'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 8,
padding: '18px 0 6px'
}
}, /*#__PURE__*/React.createElement("span", {
style: {
color: 'var(--accent)'
}
}, /*#__PURE__*/React.createElement(DuduMLogo, {
size: 44
})), /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-xl)',
fontWeight: 'var(--weight-semibold)',
color: 'var(--text-1)',
whiteSpace: 'nowrap'
}
}, "\u4E09\u6B65\u5F00\u542F dudu"), /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-sm)',
color: 'var(--text-2)'
}
}, "\u6309\u4F4F\u8BF4\u8BDD\uFF0C\u677E\u5F00\u4E0A\u5C4F")), /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
flexDirection: 'column',
gap: 10,
marginTop: 14
}
}, steps.map((s, i) => {
const state = i < step ? 'done' : i === step ? 'active' : 'todo';
return /*#__PURE__*/React.createElement("div", {
key: i,
style: {
display: 'flex',
alignItems: 'center',
gap: 12,
padding: '13px 14px',
borderRadius: 'var(--radius-lg)',
background: 'var(--surface-card)',
border: state === 'active' ? '1.5px solid var(--accent)' : '1px solid var(--border-1)',
opacity: state === 'todo' ? 0.62 : 1,
transition: 'border-color var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out)'
}
}, /*#__PURE__*/React.createElement("span", {
style: {
width: 40,
height: 40,
borderRadius: 'var(--radius-md)',
flex: 'none',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
background: state === 'done' ? 'var(--positive-soft)' : 'var(--accent-soft)',
color: state === 'done' ? 'var(--positive)' : 'var(--accent-text)'
}
}, state === 'done' ? /*#__PURE__*/React.createElement(DuMIcons.Check, {
size: 20
}) : s.icon), /*#__PURE__*/React.createElement("span", {
style: {
minWidth: 0
}
}, /*#__PURE__*/React.createElement("span", {
style: {
display: 'block',
fontSize: 'var(--text-base)',
fontWeight: 'var(--weight-medium)',
color: 'var(--text-1)'
}
}, i + 1, ". ", s.title), /*#__PURE__*/React.createElement("span", {
style: {
display: 'block',
fontSize: 'var(--text-xs)',
color: 'var(--text-2)',
marginTop: 2,
lineHeight: 'var(--leading-normal)'
}
}, s.desc)));
})), /*#__PURE__*/React.createElement("div", {
style: {
marginTop: 'auto'
}
}, /*#__PURE__*/React.createElement(Button, {
variant: "primary",
size: "lg",
block: true,
onClick: () => setStep(s => (s + 1) % 4)
}, step >= 3 ? '完成' : step === 2 ? '我说完了' : '去设置')));
}
/* ---------- ② 登录 ---------- */
function LoginScreen() {
return /*#__PURE__*/React.createElement("div", {
style: {
flex: 1,
display: 'flex',
flexDirection: 'column',
padding: '4px 22px 22px'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
flex: 1,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: 12
}
}, /*#__PURE__*/React.createElement("span", {
style: {
color: 'var(--accent)'
}
}, /*#__PURE__*/React.createElement(DuduMLogo, {
size: 64,
sw: 3.2
})), /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-2xl)',
fontWeight: 'var(--weight-semibold)',
color: 'var(--text-1)',
letterSpacing: 'var(--tracking-wide)'
}
}, "dudu"), /*#__PURE__*/React.createElement("div", {
style: {
fontSize: 'var(--text-sm)',
color: 'var(--text-2)'
}
}, "\u5927\u6A21\u578B\u8BED\u97F3\u8F93\u5165 \xB7 \u8BF4\u8BDD\u5373\u4E0A\u5C4F")), /*#__PURE__*/React.createElement("button", {
type: "button",
style: {
height: 'var(--control-xl)',
borderRadius: 'var(--radius-full)',
border: 'none',
cursor: 'pointer',
background: '#07C160',
color: '#fff',
fontSize: 'var(--text-md)',
fontWeight: 'var(--weight-semibold)',
fontFamily: 'var(--font-sans)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: 8,
width: '100%'
}
}, /*#__PURE__*/React.createElement(DuMIcons.Wechat, {
size: 19
}), " \u5FAE\u4FE1\u4E00\u952E\u767B\u5F55"), /*#__PURE__*/React.createElement("div", {
style: {
textAlign: 'center',
fontSize: 'var(--text-xs)',
color: 'var(--text-3)',
marginTop: 12,
lineHeight: 'var(--leading-normal)'
}
}, "\u767B\u5F55\u5373\u540C\u610F\u300A\u7528\u6237\u534F\u8BAE\u300B\u4E0E\u300A\u9690\u79C1\u653F\u7B56\u300B"));
}
/* ---------- ③ 购买时长 ---------- */
function PaywallScreen() {
const {
Button
} = window.DuduDesignSystem_2e0172;
const [pack, setPack] = React.useState('m');
const PACKS = [['s', '100 分钟', 9, '约 ¥0.09 / 分钟', ''], ['m', '500 分钟', 39, '约 ¥0.078 / 分钟', '省 13%'], ['l', '2000 分钟', 129, '约 ¥0.065 / 分钟', '省 28%']];
const price = PACKS.find(p => p[0] === pack)[2];
return /*#__PURE__*/React.createElement("div", {
style: {
flex: 1,
display: 'flex',
flexDirection: 'column',
padding: '4px 16px 16px',
minHeight: 0,
overflow: 'auto'
}
}, /*#__PURE__*/React.createElement(MAppHeader, {
title: "\u8D2D\u4E70\u65F6\u957F"
}), /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '14px 16px',
background: 'var(--surface-card)',
border: '1px solid var(--border-1)',
borderRadius: 'var(--radius-lg)',
flex: 'none'
}
}, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("span", {
style: {
display: 'block',
fontSize: 'var(--text-xs)',
color: 'var(--text-2)'
}
}, "\u65F6\u957F\u4F59\u989D"), /*#__PURE__*/React.createElement("span", {
style: {
display: 'block',
marginTop: 2,
fontSize: 'var(--text-2xl)',
fontWeight: 'var(--weight-bold)',
color: 'var(--text-1)',
fontFamily: 'var(--font-sans)'
}
}, "472 ", /*#__PURE__*/React.createElement("span", {
style: {
fontSize: 'var(--text-xs)',
fontWeight: 'var(--weight-regular)',
color: 'var(--text-3)'
}
}, "\u5206\u949F"))), /*#__PURE__*/React.createElement("span", {
style: {
fontSize: 'var(--text-xs)',
color: 'var(--text-3)',
textAlign: 'right',
lineHeight: 'var(--leading-normal)'
}
}, "\u65F6\u957F\u4E0D\u8FC7\u671F", /*#__PURE__*/React.createElement("br", null), "\u6BCF\u5929\u53E6\u6709 3 \u5206\u949F\u514D\u8D39\u8BD5\u7528")), /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
flexDirection: 'column',
gap: 10,
marginTop: 12
}
}, PACKS.map(([key, lab, p, desc, tag]) => {
const active = pack === key;
return /*#__PURE__*/React.createElement("button", {
key: key,
type: "button",
onClick: () => setPack(key),
style: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
textAlign: 'left',
padding: '12px 14px',
cursor: 'pointer',
borderRadius: 'var(--radius-lg)',
fontFamily: 'var(--font-sans)',
border: active ? '1.5px solid var(--accent)' : '1px solid var(--border-1)',
background: active ? 'var(--accent-soft)' : 'var(--surface-card)',
transition: 'border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out)'
}
}, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 7
}
}, /*#__PURE__*/React.createElement("span", {
style: {
fontSize: 'var(--text-base)',
fontWeight: 'var(--weight-medium)',
color: 'var(--text-1)'
}
}, lab), tag && /*#__PURE__*/React.createElement("span", {
style: {
fontSize: 10,
padding: '1px 7px',
borderRadius: 'var(--radius-full)',
background: 'var(--warning-soft)',
color: 'var(--warning)',
fontWeight: 'var(--weight-medium)',
whiteSpace: 'nowrap'
}
}, tag)), /*#__PURE__*/React.createElement("span", {
style: {
display: 'block',
fontSize: 'var(--text-xs)',
color: 'var(--text-2)',
marginTop: 2
}
}, desc)), /*#__PURE__*/React.createElement("span", {
style: {
whiteSpace: 'nowrap',
fontSize: 'var(--text-xl)',
fontWeight: 'var(--weight-bold)',
color: active ? 'var(--accent-text)' : 'var(--text-1)'
}
}, "\xA5", p));
})), /*#__PURE__*/React.createElement("div", {
style: {
marginTop: 'auto',
paddingTop: 14
}
}, /*#__PURE__*/React.createElement(Button, {
variant: "primary",
size: "lg",
block: true
}, "\u5FAE\u4FE1\u652F\u4ED8 \xA5", price), /*#__PURE__*/React.createElement("div", {
style: {
textAlign: 'center',
fontSize: 'var(--text-xs)',
color: 'var(--text-3)',
marginTop: 8
}
}, "\u652F\u4ED8\u540E\u7ACB\u5373\u5230\u8D26 \xB7 \u65F6\u957F\u4E0D\u8FC7\u671F")));
}
/* ---------- ④ 我的 ---------- */
function ProfileScreen() {
const {
Badge,
ProgressBar
} = window.DuduDesignSystem_2e0172;
const perms = [{
label: '麦克风权限',
ok: true
}, {
label: '键盘已添加',
ok: true
}, {
label: '完全访问',
ok: false,
hint: '去开启'
}];
return /*#__PURE__*/React.createElement("div", {
style: {
flex: 1,
display: 'flex',
flexDirection: 'column',
gap: 12,
padding: '4px 16px 16px',
minHeight: 0,
overflow: 'auto'
}
}, /*#__PURE__*/React.createElement(MAppHeader, {
title: "\u6211\u7684"
}), /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
alignItems: 'center',
gap: 12,
padding: '14px 14px',
background: 'var(--surface-card)',
border: '1px solid var(--border-1)',
borderRadius: 'var(--radius-lg)'
}
}, /*#__PURE__*/React.createElement("span", {
style: {
width: 46,
height: 46,
borderRadius: '50%',
background: 'var(--accent-soft)',
color: 'var(--accent-text)',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
flex: 'none'
}
}, /*#__PURE__*/React.createElement(DuMIcons.User, {
size: 22
})), /*#__PURE__*/React.createElement("span", {
style: {
minWidth: 0,
flex: 1
}
}, /*#__PURE__*/React.createElement("span", {
style: {
display: 'block',
fontSize: 'var(--text-md)',
fontWeight: 'var(--weight-medium)',
color: 'var(--text-1)'
}
}, "wang***"), /*#__PURE__*/React.createElement("span", {
style: {
display: 'block',
fontSize: 'var(--text-xs)',
color: 'var(--text-2)',
marginTop: 2
}
}, "\u65F6\u957F\u4F59\u989D 472 \u5206\u949F \xB7 \u4E0D\u8FC7\u671F")), /*#__PURE__*/React.createElement(Badge, {
tone: "green"
}, "\u4F59\u989D\u5145\u8DB3")), /*#__PURE__*/React.createElement("div", {
style: {
padding: '14px 14px 16px',
background: 'var(--surface-card)',
border: '1px solid var(--border-1)',
borderRadius: 'var(--radius-lg)'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
justifyContent: 'space-between',
fontSize: 'var(--text-xs)',
color: 'var(--text-2)',
marginBottom: 8
}
}, /*#__PURE__*/React.createElement("span", null, "\u4ECA\u65E5\u514D\u8D39\u8BD5\u7528"), /*#__PURE__*/React.createElement("span", {
style: {
fontFamily: 'var(--font-mono)'
}
}, "1 / 3 \u5206\u949F")), /*#__PURE__*/React.createElement(ProgressBar, {
value: 1,
max: 3
})), /*#__PURE__*/React.createElement("div", {
style: {
background: 'var(--surface-card)',
border: '1px solid var(--border-1)',
borderRadius: 'var(--radius-lg)',
overflow: 'hidden'
}
}, perms.map((p, i) => /*#__PURE__*/React.createElement("div", {
key: i,
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '12px 14px',
borderBottom: i < perms.length - 1 ? '1px solid var(--border-2)' : 'none',
fontSize: 'var(--text-base)',
color: 'var(--text-1)'
}
}, /*#__PURE__*/React.createElement("span", null, p.label), p.ok ? /*#__PURE__*/React.createElement("span", {
style: {
color: 'var(--positive)',
display: 'inline-flex'
}
}, /*#__PURE__*/React.createElement(DuMIcons.Check, {
size: 16
})) : /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 2,
fontSize: 'var(--text-sm)',
color: 'var(--danger)'
}
}, p.hint, " ", /*#__PURE__*/React.createElement(DuMIcons.ChevronRight, {
size: 14
}))))));
}
Object.assign(window, {
OnboardingScreen,
LoginScreen,
PaywallScreen,
ProfileScreen
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/mobile/AppScreens.jsx", error: String((e && e.message) || e) }); }
// ui_kits/mobile/KeyboardScreen.jsx
try { (() => {
// dudu 移动端 · 语音键盘(键盘扩展)
// 微信聊天上下文 + 以语音为主的键盘:工具条 / partial 文本条 / 功能键行 / 大麦克风条
// 按住麦克风条:partial 流式显示 → 松开 final 上屏到宿主输入框
const KB_SENTENCES = ['好的,我马上把文件发给你,大概十分钟之内。', '今晚的聚餐改到八点,地址我发你定位。'];
function KeyboardScreen({
account = 'ok'
}) {
// account: ok(有余额) | trial(试用中) | guest(未登录) | quota(今日试用已用完)
const {
MicBar
} = window.DuduDesignSystem_2e0172;
const [recording, setRecording] = React.useState(false);
const [finalText, setFinalText] = React.useState('');
const [partialText, setPartialText] = React.useState('');
const [inputText, setInputText] = React.useState('');
const [seconds, setSeconds] = React.useState(0);
const [idx, setIdx] = React.useState(0);
const timers = React.useRef({});
const ref = React.useRef({});
ref.current = {
finalText,
partialText,
idx
};
const stop = () => {
clearInterval(timers.current.t);
clearInterval(timers.current.s);
const {
finalText: f,
partialText: p,
idx: i
} = ref.current;
const committed = f + p;
if (committed) {
setInputText(v => v + committed);
setIdx((i + 1) % KB_SENTENCES.length);
}
setFinalText('');
setPartialText('');
setSeconds(0);
setRecording(false);
};
const start = () => {
if (account === 'guest' || account === 'quota') return;
setRecording(true);
setFinalText('');
setPartialText('');
setSeconds(0);
const sentence = KB_SENTENCES[ref.current.idx];
let i = 0;
timers.current.t = setInterval(() => {
i += 1;
if (i >= sentence.length) {
clearInterval(timers.current.t);
setFinalText(sentence);
setPartialText('');
return;
}
const lastPunct = Math.max(sentence.lastIndexOf('', i), sentence.lastIndexOf('。', i));
setFinalText(sentence.slice(0, lastPunct + 1));
setPartialText(sentence.slice(lastPunct + 1, i));
}, 95);
timers.current.s = setInterval(() => setSeconds(s => s + 1), 1000);
};
React.useEffect(() => () => {
clearInterval(timers.current.t);
clearInterval(timers.current.s);
}, []);
const micState = account === 'guest' ? 'disabled' : account === 'quota' ? 'quota' : recording ? 'recording' : 'idle';
const fmt = s => `00:${String(s).padStart(2, '0')}`;
const FnKey = ({
children,
label,
flex = 1,
onClick
}) => /*#__PURE__*/React.createElement("button", {
type: "button",
onClick: onClick,
"aria-label": label,
style: {
flex,
height: 40,
border: 'none',
borderRadius: 'var(--radius-sm)',
cursor: 'pointer',
background: 'var(--surface-card)',
color: 'var(--text-1)',
boxShadow: 'var(--shadow-key)',
fontFamily: 'var(--font-sans)',
fontSize: 'var(--text-md)',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
gap: 4
}
}, children);
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
style: {
flex: 1,
display: 'flex',
flexDirection: 'column',
minHeight: 0
}
}, /*#__PURE__*/React.createElement("div", {
style: {
textAlign: 'center',
fontSize: 'var(--text-sm)',
color: 'var(--text-2)',
padding: '4px 0 8px',
borderBottom: '1px solid var(--border-1)'
}
}, "\u5F20\u4E09"), /*#__PURE__*/React.createElement("div", {
style: {
flex: 1,
padding: '12px 12px 8px',
display: 'flex',
flexDirection: 'column',
gap: 8,
overflow: 'hidden',
justifyContent: 'flex-end'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
alignSelf: 'flex-start',
maxWidth: '78%',
background: 'var(--surface-card)',
border: '1px solid var(--border-1)',
borderRadius: '4px 12px 12px 12px',
padding: '8px 11px',
fontSize: 'var(--text-base)',
color: 'var(--text-1)',
lineHeight: 'var(--leading-normal)'
}
}, "\u4E0A\u6B21\u8BF4\u7684\u90A3\u4EFD\u6750\u6599\u65B9\u4FBF\u53D1\u6211\u4E00\u4E0B\u5417"), /*#__PURE__*/React.createElement("div", {
style: {
alignSelf: 'flex-end',
maxWidth: '78%',
background: 'var(--accent)',
color: 'var(--text-on-accent)',
borderRadius: '12px 4px 12px 12px',
padding: '8px 11px',
fontSize: 'var(--text-base)',
lineHeight: 'var(--leading-normal)'
}
}, "\u7A0D\u7B49\uFF0C\u6211\u770B\u4E00\u4E0B")), /*#__PURE__*/React.createElement("div", {
style: {
padding: '0 10px 10px'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
minHeight: 38,
boxSizing: 'border-box',
padding: '8px 12px',
borderRadius: 'var(--radius-md)',
background: 'var(--surface-card)',
border: recording ? '1.5px solid var(--accent)' : '1px solid var(--border-1)',
fontSize: 'var(--text-base)',
color: inputText ? 'var(--text-1)' : 'var(--text-3)',
lineHeight: 'var(--leading-normal)'
}
}, inputText || '发消息…', /*#__PURE__*/React.createElement("span", {
style: {
color: 'var(--accent)',
animation: 'dd-caret 1.1s steps(1) infinite'
}
}, "\u258F")))), /*#__PURE__*/React.createElement("div", {
style: {
flex: 'none',
background: 'var(--surface-2)',
borderTop: '1px solid var(--border-1)',
padding: '6px 8px 10px'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: '2px 6px 8px'
}
}, /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 6,
fontSize: 'var(--text-xs)',
color: 'var(--text-2)'
}
}, /*#__PURE__*/React.createElement(DuduMLogo, {
size: 13
}), " dudu \u8BED\u97F3\u8F93\u5165"), /*#__PURE__*/React.createElement("span", {
style: {
display: 'inline-flex',
alignItems: 'center',
gap: 4,
fontSize: 'var(--text-xs)',
fontFamily: recording ? 'var(--font-mono)' : 'var(--font-sans)',
color: recording ? 'var(--positive)' : account === 'quota' ? 'var(--warning)' : 'var(--text-3)'
}
}, account === 'guest' ? '未登录' : account === 'quota' ? '今日试用已用完' : recording ? fmt(seconds) : account === 'trial' ? '试用 · 今日剩 2 分钟' : /*#__PURE__*/React.createElement(React.Fragment, null, "\u4F59\u989D 472 \u5206\u949F ", /*#__PURE__*/React.createElement(DuMIcons.Check, {
size: 11
})))), recording ? /*#__PURE__*/React.createElement("div", {
style: {
margin: '0 2px 8px',
minHeight: 40,
boxSizing: 'border-box',
padding: '9px 12px',
background: 'var(--surface-card)',
border: '1px solid var(--border-1)',
borderRadius: 'var(--radius-md)',
fontSize: 'var(--text-base)',
lineHeight: 'var(--leading-normal)',
color: 'var(--text-1)'
}
}, finalText, /*#__PURE__*/React.createElement("span", {
style: {
color: 'var(--text-3)'
}
}, partialText)) : /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
gap: 6,
margin: '0 2px 8px'
}
}, /*#__PURE__*/React.createElement(FnKey, {
label: "\u5207\u6362\u952E\u76D8",
flex: 1.3
}, /*#__PURE__*/React.createElement(DuMIcons.Globe, {
size: 17
})), /*#__PURE__*/React.createElement(FnKey, {
label: "\u9017\u53F7",
onClick: () => setInputText(v => v + '')
}, "\uFF0C"), /*#__PURE__*/React.createElement(FnKey, {
label: "\u53E5\u53F7",
onClick: () => setInputText(v => v + '。')
}, "\u3002"), /*#__PURE__*/React.createElement(FnKey, {
label: "\u9000\u683C",
flex: 1.3,
onClick: () => setInputText(v => v.slice(0, -1))
}, /*#__PURE__*/React.createElement(DuMIcons.Backspace, {
size: 17
})), /*#__PURE__*/React.createElement(FnKey, {
label: "\u53D1\u9001",
flex: 1.3,
onClick: () => setInputText('')
}, /*#__PURE__*/React.createElement(DuMIcons.Enter, {
size: 16
}))), /*#__PURE__*/React.createElement("div", {
style: {
padding: '0 2px'
}
}, /*#__PURE__*/React.createElement(MicBar, {
state: micState,
onPointerDown: start,
onPointerUp: stop,
onPointerLeave: () => recording && stop()
})), recording && /*#__PURE__*/React.createElement("div", {
style: {
textAlign: 'center',
fontSize: 'var(--text-xs)',
color: 'var(--text-3)',
paddingTop: 6,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: 4
}
}, /*#__PURE__*/React.createElement(DuMIcons.ArrowUp, {
size: 11
}), " \u4E0A\u6ED1\u53D6\u6D88")));
}
Object.assign(window, {
KeyboardScreen
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/mobile/KeyboardScreen.jsx", error: String((e && e.message) || e) }); }
// ui_kits/mobile/MobileShared.jsx
try { (() => {
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
// dudu 移动端 UI kit · 共享:Lucide 图标子集、DuduLogo、手机框
function DuMIcon({
size = 16,
sw = 2,
children,
...rest
}) {
return /*#__PURE__*/React.createElement("svg", _extends({
width: size,
height: size,
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
strokeWidth: sw,
strokeLinecap: "round",
strokeLinejoin: "round",
"aria-hidden": "true"
}, rest), children);
}
const DuMIcons = {
Mic: p => /*#__PURE__*/React.createElement(DuMIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"
}), /*#__PURE__*/React.createElement("path", {
d: "M19 10v2a7 7 0 0 1-14 0v-2"
}), /*#__PURE__*/React.createElement("line", {
x1: "12",
x2: "12",
y1: "19",
y2: "22"
})),
Globe: p => /*#__PURE__*/React.createElement(DuMIcon, p, /*#__PURE__*/React.createElement("circle", {
cx: "12",
cy: "12",
r: "10"
}), /*#__PURE__*/React.createElement("path", {
d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"
}), /*#__PURE__*/React.createElement("path", {
d: "M2 12h20"
})),
Backspace: p => /*#__PURE__*/React.createElement(DuMIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M20 5H9l-7 7 7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2Z"
}), /*#__PURE__*/React.createElement("line", {
x1: "18",
x2: "12",
y1: "9",
y2: "15"
}), /*#__PURE__*/React.createElement("line", {
x1: "12",
x2: "18",
y1: "9",
y2: "15"
})),
Enter: p => /*#__PURE__*/React.createElement(DuMIcon, p, /*#__PURE__*/React.createElement("polyline", {
points: "9 10 4 15 9 20"
}), /*#__PURE__*/React.createElement("path", {
d: "M20 4v7a4 4 0 0 1-4 4H4"
})),
Check: p => /*#__PURE__*/React.createElement(DuMIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M20 6 9 17l-5-5"
})),
ChevronRight: p => /*#__PURE__*/React.createElement(DuMIcon, p, /*#__PURE__*/React.createElement("path", {
d: "m9 18 6-6-6-6"
})),
User: p => /*#__PURE__*/React.createElement(DuMIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"
}), /*#__PURE__*/React.createElement("circle", {
cx: "12",
cy: "7",
r: "4"
})),
Keyboard: p => /*#__PURE__*/React.createElement(DuMIcon, p, /*#__PURE__*/React.createElement("rect", {
width: "20",
height: "16",
x: "2",
y: "4",
rx: "2"
}), /*#__PURE__*/React.createElement("path", {
d: "M6 8h.01"
}), /*#__PURE__*/React.createElement("path", {
d: "M10 8h.01"
}), /*#__PURE__*/React.createElement("path", {
d: "M14 8h.01"
}), /*#__PURE__*/React.createElement("path", {
d: "M18 8h.01"
}), /*#__PURE__*/React.createElement("path", {
d: "M6 12h.01"
}), /*#__PURE__*/React.createElement("path", {
d: "M10 12h.01"
}), /*#__PURE__*/React.createElement("path", {
d: "M14 12h.01"
}), /*#__PURE__*/React.createElement("path", {
d: "M18 12h.01"
}), /*#__PURE__*/React.createElement("path", {
d: "M7 16h10"
})),
Shield: p => /*#__PURE__*/React.createElement(DuMIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"
})),
ArrowUp: p => /*#__PURE__*/React.createElement(DuMIcon, p, /*#__PURE__*/React.createElement("path", {
d: "m5 12 7-7 7 7"
}), /*#__PURE__*/React.createElement("path", {
d: "M12 19V5"
})),
Wechat: p =>
/*#__PURE__*/
/* 简化对话气泡(代微信图标占位,正式包内用官方资源)*/
React.createElement(DuMIcon, p, /*#__PURE__*/React.createElement("path", {
d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z"
}))
};
function DuduMLogo({
size = 20,
sw = 3.5
}) {
return /*#__PURE__*/React.createElement("svg", {
width: size,
height: size,
viewBox: "0 0 48 48",
fill: "none",
stroke: "currentColor",
strokeWidth: sw,
strokeLinecap: "round",
"aria-hidden": "true"
}, /*#__PURE__*/React.createElement("circle", {
cx: "24",
cy: "24",
r: "18"
}), /*#__PURE__*/React.createElement("path", {
d: "M17 20.5v7"
}), /*#__PURE__*/React.createElement("path", {
d: "M24 16.5v15"
}), /*#__PURE__*/React.createElement("path", {
d: "M31 20.5v7"
}));
}
// 中性手机框:深色边框 + 打孔/刘海,内容区由调用方填充
function PhoneFrame({
width = 312,
height = 596,
children
}) {
return /*#__PURE__*/React.createElement("div", {
style: {
width,
height,
boxSizing: 'border-box',
background: '#0B0C10',
borderRadius: 38,
padding: 9,
boxShadow: 'var(--shadow-window)',
flex: 'none'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
width: '100%',
height: '100%',
boxSizing: 'border-box',
background: 'var(--bg-app)',
borderRadius: 30,
overflow: 'hidden',
display: 'flex',
flexDirection: 'column',
position: 'relative'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
height: 30,
flex: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
}, /*#__PURE__*/React.createElement("div", {
style: {
width: 84,
height: 18,
background: '#0B0C10',
borderRadius: 10
}
})), children));
}
Object.assign(window, {
DuMIcon,
DuMIcons,
DuduMLogo,
PhoneFrame
});
})(); } catch (e) { __ds_ns.__errors.push({ path: "ui_kits/mobile/MobileShared.jsx", error: String((e && e.message) || e) }); }
__ds_ns.Badge = __ds_scope.Badge;
__ds_ns.Button = __ds_scope.Button;
__ds_ns.Card = __ds_scope.Card;
__ds_ns.IconButton = __ds_scope.IconButton;
__ds_ns.Kbd = __ds_scope.Kbd;
__ds_ns.HotkeyCombo = __ds_scope.HotkeyCombo;
__ds_ns.ProgressBar = __ds_scope.ProgressBar;
__ds_ns.Input = __ds_scope.Input;
__ds_ns.SettingRow = __ds_scope.SettingRow;
__ds_ns.Switch = __ds_scope.Switch;
__ds_ns.MicBar = __ds_scope.MicBar;
__ds_ns.RecognitionOverlay = __ds_scope.RecognitionOverlay;
__ds_ns.Waveform = __ds_scope.Waveform;
})();