@dshtrading/client-ui-settings 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +75 -0
- package/lib/client/locales.d.ts +17 -0
- package/lib/client/locales.js +203 -0
- package/lib/client.js +1329 -0
- package/lib/client.js.map +1 -0
- package/lib/index.d.ts +13 -0
- package/lib/index.js +13 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":["useId","useRef","useState","css","useState","css","useMemo","resolveSlotLabel"],"sources":["../src/client/trading-settings-controller.ts","../src/client/TradingSettingsSection.tsx","../src/client/MarketProviderPanel.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * Trading settings controller: a SnapshotStore over the dshtrading namespace\n * view (markets map + provider presence), with the write methods supplied as\n * plain inject fields (官方模式: hooks = 可观察状态, 普通字段 = 写操作)。\n * The Host (dsh-trading/router) owns the namespace and its schema; this\n * controller binds the client settings scope and translates user choices\n * into revision-fenced path mutations.\n */\nimport type {\n SnapshotStore,\n} from '@deepseek-ai/dsh-client-store'\nimport type {\n SettingsScope,\n SettingsScopeSnapshot,\n} from '@deepseek-ai/dsh-client-ui-settings/client'\n\nexport interface ProviderMeta {\n id: string\n /** 显示名词典键(dshtrading.settings,渲染处 t() 解析)。 */\n label: string\n url?: string\n env?: string\n type: 'public' | 'commercial' | 'gateway'\n markets: readonly string[]\n}\n\n/** provider 候选显示名与指引(词典键 + 官网/API Key 申请链接 + 环境变量 + 支持市场;值与 router PROVIDER_VOCABULARY 对齐)。 */\nexport const PROVIDER_LABELS: readonly Readonly<ProviderMeta>[] = [\n { id: 'binance', label: 'provider.binance', url: 'https://binance.com/en/binance-api', env: 'BINANCE_API_KEY', type: 'public', markets: ['crypto'] },\n { id: 'okx', label: 'provider.okx', url: 'https://okx.com/docs-v5/zh/', env: 'OKX_API_KEY', type: 'public', markets: ['crypto'] },\n { id: 'bybit', label: 'provider.bybit', url: 'https://bybit.com/en/api-overview', env: 'BYBIT_API_KEY', type: 'public', markets: ['crypto'] },\n { id: 'ccxt', label: 'provider.ccxt', url: 'https://ccxt.com', env: 'CCXT_API_KEY', type: 'public', markets: ['crypto'] },\n { id: 'yahoo', label: 'provider.yahoo', url: 'https://finance.yahoo.com', type: 'public', markets: ['us', 'hk'] },\n { id: 'alpaca', label: 'provider.alpaca', url: 'https://alpaca.markets', env: 'ALPACA_API_KEY', type: 'commercial', markets: ['us'] },\n { id: 'fmp', label: 'provider.fmp', url: 'https://site.financialmodelingprep.com/developer', env: 'FMP_API_KEY', type: 'commercial', markets: ['us'] },\n { id: 'finnhub', label: 'provider.finnhub', url: 'https://finnhub.io/register', env: 'FINNHUB_API_KEY', type: 'commercial', markets: ['us'] },\n { id: 'polygon', label: 'provider.polygon', url: 'https://polygon.io', env: 'POLYGON_API_KEY', type: 'commercial', markets: ['us'] },\n { id: 'ibkr', label: 'provider.ibkr', url: 'https://interactivebrokers.com/campus/ibkr-api-page/cpapi/', env: 'IBKR_GATEWAY_URL', type: 'gateway', markets: ['us', 'hk'] },\n { id: 'stooq', label: 'provider.stooq', url: 'https://stooq.com', type: 'public', markets: ['us'] },\n { id: 'tencent', label: 'provider.tencent', url: 'https://finance.qq.com', type: 'public', markets: ['cn', 'hk'] },\n { id: 'eastmoney', label: 'provider.eastmoney', url: 'https://eastmoney.com', type: 'public', markets: ['cn', 'hk'] },\n { id: 'tushare', label: 'provider.tushare', url: 'https://tushare.pro/register', env: 'TUSHARE_TOKEN', type: 'commercial', markets: ['cn', 'hk', 'us'] },\n { id: 'akshare', label: 'provider.akshare', url: 'https://akshare.xyz', env: 'AKSHARE_API_URL', type: 'public', markets: ['cn', 'hk'] },\n { id: 'qmt', label: 'provider.qmt', url: 'http://127.0.0.1:5800', env: 'QMT_GATEWAY_URL', type: 'gateway', markets: ['cn'] },\n { id: 'futu', label: 'provider.futu', url: 'https://futunn.com/download/open-api', env: 'FUTU_HOST', type: 'gateway', markets: ['hk', 'us', 'cn'] },\n { id: 'longbridge', label: 'provider.longbridge', url: 'https://open.longportapp.com', env: 'LONGBRIDGE_APP_KEY', type: 'commercial', markets: ['hk', 'us'] },\n { id: 'tiger', label: 'provider.tiger', url: 'https://developer.itigerup.com', env: 'TIGER_ID', type: 'commercial', markets: ['hk', 'us', 'cn'] },\n { id: 'hithink', label: 'provider.hithink', url: 'https://fuyao.aicubes.cn', env: 'HITHINK_FINANCE_API_KEY', type: 'commercial', markets: ['cn'] },\n]\n\nexport interface CredentialField {\n key: string\n /** 字段显示名词典键(dshtrading.settings,渲染处 t() 解析)。 */\n label: string\n /** 输入框占位词典键(可缺省;渲染处 t() 解析)。 */\n placeholder?: string\n secret?: boolean\n}\n\nexport const PROVIDER_CREDENTIAL_SPECS: Record<string, readonly CredentialField[]> = {\n binance: [\n { key: 'apiKey', label: 'field.label.apiKey', placeholder: 'field.placeholder.binanceKey', secret: true },\n { key: 'apiSecret', label: 'field.label.apiSecret', placeholder: 'field.placeholder.binanceSecret', secret: true },\n ],\n okx: [\n { key: 'apiKey', label: 'field.label.apiKey', placeholder: 'field.placeholder.okxKey', secret: true },\n { key: 'secretKey', label: 'field.label.secretKey', placeholder: 'field.placeholder.okxSecret', secret: true },\n { key: 'passphrase', label: 'field.label.passphrase', placeholder: 'field.placeholder.okxPassphrase', secret: true },\n ],\n bybit: [\n { key: 'apiKey', label: 'field.label.apiKey', placeholder: 'field.placeholder.bybitKey', secret: true },\n { key: 'apiSecret', label: 'field.label.apiSecret', placeholder: 'field.placeholder.bybitSecret', secret: true },\n ],\n ccxt: [\n { key: 'apiKey', label: 'field.label.apiKey', placeholder: 'field.placeholder.ccxtKey', secret: true },\n { key: 'apiSecret', label: 'field.label.apiSecret', placeholder: 'field.placeholder.ccxtSecret', secret: true },\n ],\n alpaca: [\n { key: 'apiKey', label: 'field.label.apiKey', placeholder: 'field.placeholder.alpacaKey', secret: true },\n { key: 'secretKey', label: 'field.label.secretKey', placeholder: 'field.placeholder.alpacaSecret', secret: true },\n ],\n fmp: [\n { key: 'apiKey', label: 'field.label.apiKey', placeholder: 'field.placeholder.fmpKey', secret: true },\n ],\n finnhub: [\n { key: 'apiKey', label: 'field.label.apiKey', placeholder: 'field.placeholder.finnhubKey', secret: true },\n ],\n polygon: [\n { key: 'apiKey', label: 'field.label.apiKey', placeholder: 'field.placeholder.polygonKey', secret: true },\n ],\n tushare: [\n { key: 'token', label: 'field.label.token', placeholder: 'field.placeholder.tushareToken', secret: true },\n ],\n akshare: [\n { key: 'apiUrl', label: 'field.label.apiUrl', placeholder: 'field.placeholder.akshareUrl' },\n ],\n qmt: [\n { key: 'gatewayUrl', label: 'field.label.qmtUrl', placeholder: 'field.placeholder.qmtUrl' },\n ],\n futu: [\n { key: 'host', label: 'field.label.futuHost', placeholder: 'field.placeholder.futuHost' },\n { key: 'port', label: 'field.label.futuPort', placeholder: 'field.placeholder.futuPort' },\n ],\n ibkr: [\n { key: 'gatewayUrl', label: 'field.label.ibkrUrl', placeholder: 'field.placeholder.ibkrUrl' },\n ],\n longbridge: [\n { key: 'appKey', label: 'field.label.appKey', placeholder: 'field.placeholder.longbridgeAppKey', secret: true },\n { key: 'appSecret', label: 'field.label.appSecret', placeholder: 'field.placeholder.longbridgeAppSecret', secret: true },\n { key: 'accessToken', label: 'field.label.accessToken', placeholder: 'field.placeholder.longbridgeAccessToken', secret: true },\n ],\n tiger: [\n { key: 'tigerId', label: 'field.label.tigerId', placeholder: 'field.placeholder.tigerId' },\n { key: 'privateKey', label: 'field.label.tigerPrivateKey', placeholder: 'field.placeholder.tigerPrivateKey', secret: true },\n ],\n hithink: [\n { key: 'apiKey', label: 'field.label.apiKey', placeholder: 'HITHINK_FINANCE_API_KEY', secret: true },\n ],\n}\n\n/** dshtrading namespace 下的值形状(router 侧同步;窄化后的子集契约)。 */\nexport interface TradingSettings {\n markets: Record<string, { provider?: string; tradeProvider?: string }>\n /** 各提供方 API 凭证。 */\n credentials?: Record<string, Record<string, string>>\n /** WS2c:新闻相关设置(CryptoPanic API token,可选)。 */\n news?: { cryptoPanicKey?: string }\n /** 涨跌配色模式:red-up = 红涨绿跌(国内),green-up = 绿涨红跌(国际)。 */\n colorMode?: 'red-up' | 'green-up'\n}\n\n/** 组件的可观察状态(SnapshotStore 值):已解析 value + 覆盖标记。 */\nexport interface TradingSettingsState {\n status: 'loading' | 'ready' | 'unavailable'\n /** market id → 已解析 provider(undefined = 未解析到)。 */\n resolved: Record<string, string | undefined>\n /** market id → 用户是否覆盖(user 层 presence)。 */\n overridden: Record<string, boolean>\n /** provider id → credentials 字典。 */\n credentials: Record<string, Record<string, string>>\n /** WS2c:已解析 CryptoPanic key(undefined = 无 key = 新闻走公共源)。 */\n newsKey: string | undefined\n /** WS2c:用户是否覆盖了 CryptoPanic key。 */\n newsOverridden: boolean\n /** 涨跌配色模式。 */\n colorMode: 'red-up' | 'green-up'\n /** 表单可写(mode=host 且 writable)。 */\n writable: boolean\n}\n\n/** 写路径(普通 inject 字段)。 */\nexport interface TradingSettingsActions {\n setProvider(market: string, provider: string): Promise<void>\n resetProvider(market: string): Promise<void>\n setCredential(provider: string, fields: Record<string, string>): Promise<void>\n deleteCredential(provider: string): Promise<void>\n /** WS2c:设置/清除 CryptoPanic key(空串 = 清除回公共源)。 */\n setNewsKey(value: string): Promise<void>\n resetNewsKey(): Promise<void>\n /** 设置涨跌配色模式。 */\n setColorMode(mode: 'red-up' | 'green-up'): Promise<void>\n}\n\n/** 状态转化:从 settings 快照投射为组件的可观察视图。 */\nexport function projectSnapshot(snap: SettingsScopeSnapshot<TradingSettings>): TradingSettingsState {\n const value = snap.value ?? (snap.base as TradingSettings | undefined)\n const user = (snap.user ?? {}) as { markets?: Record<string, unknown>; credentials?: Record<string, unknown> }\n // 市场键 = value/base/user 的实际键并集(dict 开放:新市场的键出现即进入,无需改码)。\n const marketIds = new Set<string>([\n ...Object.keys(value?.markets ?? {}),\n ...Object.keys((snap.base as TradingSettings | undefined)?.markets ?? {}),\n ...Object.keys(user.markets ?? {}),\n ])\n const resolved: Record<string, string | undefined> = {}\n const overridden: Record<string, boolean> = {}\n const baseMarkets = (snap.base as TradingSettings | undefined)?.markets ?? {}\n for (const marketId of marketIds) {\n // 逐市场 value 优先、base 兜底:value 缺该市场键时(部分合并)仍能解析到实际 provider。\n resolved[marketId] = value?.markets?.[marketId]?.provider ?? baseMarkets[marketId]?.provider\n overridden[marketId] = user.markets?.[marketId] !== undefined\n }\n\n // 凭证字典\n const credentials = value?.credentials ?? {}\n\n // WS2c:新闻 key 同理(value 优先、base 兜底;user 层 presence 判 overridden)。\n const baseNews = (snap.base as TradingSettings | undefined)?.news\n const news = value?.news ?? baseNews\n const userNews = ((snap.user ?? {}) as { news?: { cryptoPanicKey?: string } }).news\n return {\n status: snap.status,\n resolved,\n overridden,\n credentials,\n newsKey: news?.cryptoPanicKey,\n newsOverridden: userNews?.cryptoPanicKey !== undefined,\n colorMode: value?.colorMode === 'green-up' ? 'green-up' : 'red-up',\n writable: snap.writable && snap.mode === 'host',\n }\n}\n\n/** 从 settings scope 构建 SnapshotStore(getSnapshot 稳定引用 + subscribe 转发)。 */\nexport function createTradingSettingsStore(scope: SettingsScope<TradingSettings>): SnapshotStore<TradingSettingsState> {\n let cached: TradingSettingsState = projectSnapshot(scope.getSnapshot())\n return {\n getSnapshot: () => {\n const current = projectSnapshot(scope.getSnapshot())\n // 引用稳定:值未变则复用缓存(bindSnapshotSelector 依赖引用稳定性做浅比较)。\n if (JSON.stringify(current) !== JSON.stringify(cached)) cached = current\n return cached\n },\n subscribe: (listener) => scope.subscribe(listener),\n }\n}\n","/**\n * Trading settings section (tab container): the '交易' 一级菜单 host. The\n * section chrome is a tab bar projected from the dshtrading.market.tab slot\n * ledger; each market contributes its own panel (id = market id) and the\n * section renders it through the child slot. New market = new tab registration,\n * no section changes (官方 settings.plugins.tab 模式).\n */\nimport { useEffect, useId, useRef, useState } from 'react'\nimport type {} from './contract/locale-keys.ts'\nimport type {\n HostObservable, InjectFace, PropsLocale, PropsRenderSlots, PropsRuntime,\n} from '@deepseek-ai/dsh-client-ui-slots'\nimport type { TradingSettingsState } from './trading-settings-controller.ts'\nimport css from './trading-settings.module.css'\n\n/** One tab projected from a dshtrading.market.tab contribution. */\nexport interface TradingMarketTabEntry {\n id: string\n order: number\n label: string\n}\n\n/** SnapshotStore face for subscribing to controller state. */\ninterface ControllerStore {\n getSnapshot: () => TradingSettingsState\n subscribe: (listener: () => void) => () => void\n}\n\n/** Registration-side business face for the section. */\nexport interface TradingSettingsSectionInjected {\n hooks: {\n /** Ordered, locale-aware projection of the market tab ledger. */\n tabs: HostObservable<readonly TradingMarketTabEntry[]>\n /** Shared dshtrading controller (for colorMode state). */\n controller: ControllerStore\n }\n /** Write action: set global color mode. */\n setColorMode: (mode: 'red-up' | 'green-up') => Promise<void>\n}\n\n/** Props the renderer binds for the section. */\nexport type TradingSettingsSectionProps =\n PropsRuntime<'settings.section'>\n & PropsLocale<'dshtrading.settings'>\n & PropsRenderSlots<'dshtrading.market.tab'>\n & InjectFace<TradingSettingsSectionInjected>\n\n/** Render the Trading page: color mode selector + market tab bar + active market provider panel. */\nexport function TradingSettingsSection({ t, renderSlot, useTabs, useController, setColorMode }: TradingSettingsSectionProps) {\n const tabsId = useId()\n const tabRefs = useRef<Array<HTMLButtonElement | null>>([])\n const rows = useTabs(value => value)\n const controllerState = useController((value: TradingSettingsState) => value)\n const [activeId, setActiveId] = useState<string>()\n const [visitedIds, setVisitedIds] = useState<ReadonlySet<string>>(() => new Set())\n const active = rows.find(row => row.id === activeId)?.id ?? rows[0]?.id\n\n // 首次选中即挂载,切换后保持挂载(draft 存活)。\n useEffect(() => {\n if (active === undefined) return\n setVisitedIds((previous) => {\n if (previous.has(active)) return previous\n return new Set([...previous, active])\n })\n }, [active])\n\n const currentColorMode = controllerState.colorMode ?? 'red-up'\n\n return (\n <div className={css.root}>\n <p className={css.lead}>{t('lead')}</p>\n\n {/* 涨跌配色选择 */}\n <fieldset className={css.colorModeFieldset}>\n <legend className={css.colorModeLabel}>{t('colorMode.label')}</legend>\n <div className={css.colorModeOptions}>\n <label className={css.colorModeOption} data-active={currentColorMode === 'red-up' ? 'true' : undefined}>\n <input\n type=\"radio\"\n name=\"dshtrading-color-mode\"\n value=\"red-up\"\n checked={currentColorMode === 'red-up'}\n onChange={() => { void setColorMode('red-up') }}\n className={css.colorModeRadio}\n />\n <span className={css.colorModeSwatch} style={{ background: '#e64545' }} />\n <span className={css.colorModeSwatchDown} style={{ background: '#2ba471' }} />\n <span>{t('colorMode.redUp')}</span>\n </label>\n <label className={css.colorModeOption} data-active={currentColorMode === 'green-up' ? 'true' : undefined}>\n <input\n type=\"radio\"\n name=\"dshtrading-color-mode\"\n value=\"green-up\"\n checked={currentColorMode === 'green-up'}\n onChange={() => { void setColorMode('green-up') }}\n className={css.colorModeRadio}\n />\n <span className={css.colorModeSwatch} style={{ background: '#2ba471' }} />\n <span className={css.colorModeSwatchDown} style={{ background: '#e64545' }} />\n <span>{t('colorMode.greenUp')}</span>\n </label>\n </div>\n </fieldset>\n\n {rows.length === 0 ? <p className={css.empty}>{t('empty')}</p> : (\n <>\n <div className={css.tabList} role=\"tablist\" aria-label={t('tabs')}>\n {rows.map((row, index) => {\n const selected = row.id === active\n return (\n <button\n key={row.id}\n ref={(element) => { tabRefs.current[index] = element }}\n id={`${tabsId}-tab-${row.id}`}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n aria-controls={`${tabsId}-panel-${row.id}`}\n data-active={selected ? 'true' : undefined}\n tabIndex={selected ? 0 : -1}\n className={css.tab}\n onClick={() => { setActiveId(row.id) }}\n onKeyDown={(event) => {\n let nextIndex: number\n switch (event.key) {\n case 'ArrowRight': nextIndex = (index + 1) % rows.length; break\n case 'ArrowLeft': nextIndex = (index - 1 + rows.length) % rows.length; break\n case 'Home': nextIndex = 0; break\n case 'End': nextIndex = rows.length - 1; break\n default: return\n }\n event.preventDefault()\n const nextRow = rows[nextIndex] as TradingMarketTabEntry\n const nextTab = tabRefs.current[nextIndex] as HTMLButtonElement\n setActiveId(nextRow.id)\n nextTab.focus()\n }}\n >\n {row.label}\n </button>\n )\n })}\n </div>\n {rows\n .filter(row => row.id === active || visitedIds.has(row.id))\n .map((row) => {\n const selected = row.id === active\n return (\n <div\n key={row.id}\n id={`${tabsId}-panel-${row.id}`}\n role=\"tabpanel\"\n aria-labelledby={`${tabsId}-tab-${row.id}`}\n className={css.tabPanel}\n hidden={!selected}\n >\n {renderSlot('dshtrading.market.tab', {}, { only: row.id })}\n </div>\n )\n })}\n </>\n )}\n </div>\n )\n}\n\nexport type { TradingSettingsSectionProps as TradingSettingsSectionPropsType }\n","import { useEffect, useMemo, useState } from 'react'\nimport type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from './contract/slots.ts'\nimport type {\n CredentialField,\n TradingSettingsState,\n} from './trading-settings-controller.ts'\nimport { PROVIDER_CREDENTIAL_SPECS, PROVIDER_LABELS } from './trading-settings-controller.ts'\nimport type {} from './contract/locale-keys.ts'\nimport css from './market-provider-panel.module.css'\n\n/** SnapshotStore 面(hooks 注入)。 */\nexport interface MarketPanelStateStore {\n getSnapshot: () => TradingSettingsState\n subscribe: (listener: () => void) => () => void\n}\n\nexport interface MarketProviderPanelInjected {\n hooks: {\n /** Shared dshtrading view (all markets); the panel reads its own market only. */\n controller: MarketPanelStateStore\n }\n /** This panel's market id (crypto/us/cn/hk/...). */\n market: string\n /** Write path: store this market's provider selection. */\n setProvider: (market: string, provider: string) => Promise<void>\n /** Write path: clear this market's provider (re-inherit base default). */\n resetProvider: (market: string) => Promise<void>\n /** Write path: set credentials for a provider. */\n setCredential: (provider: string, fields: Record<string, string>) => Promise<void>\n /** Write path: delete/clear credentials for a provider. */\n deleteCredential: (provider: string) => Promise<void>\n /** WS2c: write/clear the CryptoPanic news API key (empty = clear → public sources). */\n setNewsKey: (value: string) => Promise<void>\n /** WS2c: clear the CryptoPanic news API key back to base (public sources). */\n resetNewsKey: () => Promise<void>\n}\n\nexport type MarketProviderPanelProps =\n PropsRuntime<'dshtrading.market.tab'>\n & PropsLocale<'dshtrading.settings'>\n & InjectFace<MarketProviderPanelInjected>\n\n/** PropsLocale 在无宿主 merge 的独立编译里不落 t 座位(既有债),本地兜底。 */\ntype PanelT = (key: string, params?: Record<string, unknown>) => string\n\nconst TYPE_LABEL: Record<string, string> = {\n public: 'type.public',\n gateway: 'type.gateway',\n commercial: 'type.commercial',\n}\n\nfunction ProviderCredentialCard(props: {\n providerId: string\n spec: readonly CredentialField[]\n currentValues?: Record<string, string>\n writable: boolean\n onSave: (fields: Record<string, string>) => Promise<void>\n onDelete: () => Promise<void>\n t: (key: string, params?: Record<string, unknown>) => string\n}) {\n const { providerId, spec, currentValues = {}, writable, onSave, onDelete, t } = props\n const [open, setOpen] = useState(false)\n const [fields, setFields] = useState<Record<string, string>>(() => ({ ...currentValues }))\n const [showSecret, setShowSecret] = useState<Record<string, boolean>>({})\n const [saving, setSaving] = useState(false)\n const [msg, setMsg] = useState<string | null>(null)\n\n useEffect(() => {\n setFields({ ...currentValues })\n }, [currentValues])\n\n const isConfigured = Object.values(currentValues).some((v) => Boolean(v && v.trim()))\n const isDirty = spec.some((s) => (fields[s.key] ?? '') !== (currentValues[s.key] ?? ''))\n\n const handleSave = async (e: React.MouseEvent) => {\n e.stopPropagation()\n setSaving(true)\n setMsg(null)\n try {\n await onSave(fields)\n setMsg(t('credential.saved'))\n } catch (err) {\n setMsg(`${t('credential.saveFailed')}: ${String(err)}`)\n } finally {\n setSaving(false)\n }\n }\n\n const handleDelete = async (e: React.MouseEvent) => {\n e.stopPropagation()\n setSaving(true)\n setMsg(null)\n try {\n await onDelete()\n setFields({})\n setMsg(t('credential.deleted'))\n } catch (err) {\n setMsg(`${t('credential.deleteFailed')}: ${String(err)}`)\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <div className={css.credentialBlock} onClick={(e) => e.stopPropagation()}>\n <div className={css.credentialHeader}>\n <span className={css.credentialStatus} data-configured={isConfigured ? 'true' : 'false'}>\n <span>{isConfigured ? '●' : '○'}</span>\n <span>{isConfigured ? t('credential.configured') : t('credential.notConfigured')}</span>\n </span>\n <button\n type=\"button\"\n className={css.credentialToggleBtn}\n onClick={() => {\n setOpen(!open)\n setMsg(null)\n }}\n >\n {open ? t('credential.btnFold') : t('credential.btn')}\n </button>\n </div>\n\n {open && (\n <div className={css.credentialDrawer}>\n <div className={css.credentialFields}>\n {spec.map((field) => {\n const isPass = field.secret && !showSecret[field.key]\n return (\n <div key={field.key} className={css.fieldRow}>\n <label className={css.fieldLabel}>{t(field.label)}</label>\n <div className={css.inputWrapper}>\n <input\n type={isPass ? 'password' : 'text'}\n className={css.credInput}\n value={fields[field.key] ?? ''}\n placeholder={field.placeholder !== undefined ? t(field.placeholder) : undefined}\n disabled={!writable || saving}\n onChange={(e) => setFields({ ...fields, [field.key]: e.target.value })}\n />\n {field.secret && (\n <button\n type=\"button\"\n className={css.eyeBtn}\n onClick={() => setShowSecret((prev) => ({ ...prev, [field.key]: !prev[field.key] }))}\n title={showSecret[field.key] ? t('field.action.hide') : t('field.action.show')}\n >\n {showSecret[field.key] ? '🙈' : '👁️'}\n </button>\n )}\n </div>\n </div>\n )\n })}\n </div>\n <div className={css.credActions}>\n <button\n type=\"button\"\n className={css.credSaveBtn}\n disabled={!isDirty || saving || !writable}\n onClick={handleSave}\n >\n {t('credential.save')}\n </button>\n {isConfigured && (\n <button\n type=\"button\"\n className={css.credDeleteBtn}\n disabled={saving || !writable}\n onClick={handleDelete}\n >\n {t('credential.delete')}\n </button>\n )}\n {msg && <span className={css.credMsg}>{msg}</span>}\n </div>\n </div>\n )}\n </div>\n )\n}\n\n/** Render one market's provider radio group with save/reset (+ WS2c news key, crypto only). */\nexport function MarketProviderPanel({\n t: tProp,\n useController,\n market,\n setProvider,\n resetProvider,\n setCredential,\n deleteCredential,\n setNewsKey,\n resetNewsKey,\n}: MarketProviderPanelProps) {\n // PropsLocale 的 t 座位在无宿主 merge 的独立编译下解析为 never(既有债 20 处\n // TS2349 的根因)。本地遮蔽:运行时框架注入 t,签名与 SDK Translate 对齐。\n const t = tProp as unknown as PanelT\n const state = useController((value: TradingSettingsState) => value)\n const resolved = state.resolved[market]\n const overridden = state.overridden[market]\n const [draft, setDraft] = useState<string | undefined>(undefined)\n const [saving, setSaving] = useState(false)\n const [message, setMessage] = useState<string | undefined>(undefined)\n\n // 首次进入或切换市场时,以当前市场的解析值初始化\n useEffect(() => {\n setDraft(resolved)\n setMessage(undefined)\n }, [market, resolved])\n\n const dirty = useMemo(() => {\n const chosen = draft ?? resolved\n if (chosen === undefined) return overridden\n return chosen !== resolved\n }, [draft, resolved, overridden])\n\n const writable = state.writable\n\n // WS2c:CryptoPanic key\n const [newsDraft, setNewsDraft] = useState<string | undefined>(undefined)\n const [newsSaving, setNewsSaving] = useState(false)\n const [newsMessage, setNewsMessage] = useState<string | undefined>(undefined)\n useEffect(() => {\n if (newsDraft === undefined && state.status === 'ready') {\n setNewsDraft(state.newsKey)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.status, state.newsKey])\n\n async function saveNews() {\n setNewsSaving(true)\n setNewsMessage(undefined)\n try {\n const next = (newsDraft ?? '').trim()\n const current = state.newsKey ?? ''\n if (next !== current) {\n await setNewsKey(next)\n } else if (state.newsOverridden) {\n await resetNewsKey()\n }\n setNewsMessage(t('newsSaved'))\n } catch (error) {\n setNewsMessage(`${t('newsSaveFailed')}: ${String((error as { message?: string })?.message ?? error)}`)\n } finally {\n setNewsSaving(false)\n }\n }\n\n const newsDirty = (newsDraft === undefined ? state.newsKey ?? '' : newsDraft.trim()) !== (state.newsKey ?? '')\n\n const options = useMemo(() => {\n const matched = PROVIDER_LABELS.filter((p) => p.markets.includes(market))\n const known = new Set(matched.map((p) => p.id))\n const extras: { id: string; label: string; url?: string; env?: string; type?: string }[] = []\n for (const slug of [resolved, draft]) {\n if (slug !== undefined && !known.has(slug) && !extras.some((e) => e.id === slug)) {\n extras.push({ id: slug, label: t('custom', { provider: slug }) })\n }\n }\n return [...matched, ...extras]\n }, [market, resolved, draft, t])\n\n async function save() {\n setSaving(true)\n setMessage(undefined)\n try {\n const chosen = draft ?? resolved\n if (chosen === undefined) {\n if (overridden) await resetProvider(market)\n } else if (chosen !== resolved || !overridden) {\n await setProvider(market, chosen)\n }\n setMessage(t('saved'))\n } catch (error) {\n setMessage(`${t('saveFailed')}: ${String((error as { message?: string })?.message ?? error)}`)\n } finally {\n setSaving(false)\n }\n }\n\n const activeProvider = draft ?? resolved\n\n return (\n <div className={css.panel}>\n <div className={css.currentHeader}>\n <span>{t('current', { provider: '' })}</span>\n <span className={css.currentBadge}>{resolved ?? t('default')}</span>\n </div>\n\n <div className={css.grid}>\n {options.map((provider) => {\n const selected = (draft === undefined ? resolved === provider.id : draft === provider.id)\n const credSpec = PROVIDER_CREDENTIAL_SPECS[provider.id]\n const currentCreds = state.credentials?.[provider.id]\n return (\n <div\n key={`${market}-${provider.id}`}\n className={css.card}\n data-selected={selected ? 'true' : undefined}\n onClick={() => { if (writable && !saving) setDraft(provider.id) }}\n >\n <div className={css.cardHeader}>\n <input\n type=\"radio\"\n name={`provider-${market}`}\n checked={selected}\n disabled={!writable || saving}\n onChange={() => setDraft(provider.id)}\n />\n <span className={css.cardTitle}>{t(provider.label)}</span>\n {provider.type && (\n <span className={css.typeBadge}>{t(TYPE_LABEL[provider.type] ?? provider.type)}</span>\n )}\n </div>\n\n {(provider.url || provider.env) && (\n <div className={css.cardMeta}>\n {provider.url && (\n <div>\n <a\n href={provider.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={css.link}\n onClick={(e) => e.stopPropagation()}\n >\n {t('provider.docsLink')} ↗\n </a>\n </div>\n )}\n {provider.env && (\n <div className={css.envBox}>\n {t('provider.envPrefix')}<code>{provider.env}</code>\n </div>\n )}\n </div>\n )}\n\n {credSpec && credSpec.length > 0 && (\n <ProviderCredentialCard\n providerId={provider.id}\n spec={credSpec}\n currentValues={currentCreds}\n writable={writable}\n onSave={(fields) => setCredential(provider.id, fields)}\n onDelete={() => deleteCredential(provider.id)}\n t={t as (k: string) => string}\n />\n )}\n </div>\n )\n })}\n </div>\n\n <div className={css.actions}>\n <button\n type=\"button\"\n className={css.saveBtn}\n disabled={!dirty || saving || !writable}\n onClick={() => void save()}\n >\n {t('save')}\n </button>\n <button\n type=\"button\"\n className={css.discardBtn}\n disabled={saving || !dirty}\n onClick={() => { setDraft(undefined); setMessage(undefined) }}\n >\n {t('discard')}\n </button>\n {message !== undefined ? <span className={css.message}>{message}</span> : null}\n </div>\n\n {market === 'crypto' && (\n <div className={css.newsSection}>\n <label className={css.newsLabel}>{t('newsKeyLabel')}</label>\n <input\n type=\"password\"\n className={css.newsInput}\n value={newsDraft ?? ''}\n disabled={!writable || newsSaving}\n onChange={(event) => setNewsDraft(event.target.value)}\n placeholder={t('newsKeyPlaceholder')}\n />\n <div className={css.actions}>\n <button\n type=\"button\"\n className={css.saveBtn}\n disabled={!newsDirty || newsSaving || !writable}\n onClick={() => void saveNews()}\n >\n {t('save')}\n </button>\n <button\n type=\"button\"\n className={css.discardBtn}\n disabled={newsSaving || !newsDirty}\n onClick={() => { setNewsDraft(undefined); setNewsMessage(undefined) }}\n >\n {t('discard')}\n </button>\n {newsMessage !== undefined ? <span className={css.message}>{newsMessage}</span> : null}\n </div>\n </div>\n )}\n </div>\n )\n}\n","/**\n * client-ui-settings client 词典(纯数据模块:零运行时依赖)。\n *\n * 单一来源:本包 client apply 注册 zh/en(typed register 编译期校验键位);\n * packages/dsh-i18n 语言包构建期 import 本模块注册 zh-CN;scripts/i18n-audit.mjs\n * 静态加载本模块做 zh/en 键对齐与占位符对齐门禁。\n */\n/**\n * dshtrading.settings locale keys(单一来源 = locales.ts zh 块;contract/locale-keys.ts\n * 据此 augment LocaleNamespaceMap,PropsLocale 落 t 座位)。\n */\nexport type SettingsLocaleKey =\n | 'nav'\n | 'lead'\n | 'tabs'\n | 'empty'\n | 'save'\n | 'discard'\n | 'saved'\n | 'saveFailed'\n | 'current'\n | 'default'\n | 'custom'\n | 'newsKeyLabel'\n | 'newsKeyPlaceholder'\n | 'newsSaved'\n | 'newsSaveFailed'\n | 'colorMode.label'\n | 'colorMode.redUp'\n | 'colorMode.greenUp'\n | 'market.crypto'\n | 'market.us'\n | 'market.cn'\n | 'market.hk'\n | 'credential.btn'\n | 'credential.btnFold'\n | 'credential.configured'\n | 'credential.notConfigured'\n | 'credential.save'\n | 'credential.delete'\n | 'credential.saved'\n | 'credential.deleted'\n | 'credential.saveFailed'\n | 'credential.deleteFailed'\n | 'type.public'\n | 'type.gateway'\n | 'type.commercial'\n | 'field.action.hide'\n | 'field.action.show'\n | 'provider.docsLink'\n | 'provider.envPrefix'\n | 'provider.binance'\n | 'provider.okx'\n | 'provider.bybit'\n | 'provider.ccxt'\n | 'provider.yahoo'\n | 'provider.alpaca'\n | 'provider.fmp'\n | 'provider.finnhub'\n | 'provider.polygon'\n | 'provider.ibkr'\n | 'provider.stooq'\n | 'provider.tencent'\n | 'provider.eastmoney'\n | 'provider.tushare'\n | 'provider.akshare'\n | 'provider.qmt'\n | 'provider.futu'\n | 'provider.longbridge'\n | 'provider.tiger'\n | 'field.label.apiKey'\n | 'field.label.apiSecret'\n | 'field.label.secretKey'\n | 'field.label.passphrase'\n | 'field.label.token'\n | 'field.label.apiUrl'\n | 'field.label.qmtUrl'\n | 'field.label.futuHost'\n | 'field.label.futuPort'\n | 'field.label.ibkrUrl'\n | 'field.label.appKey'\n | 'field.label.appSecret'\n | 'field.label.accessToken'\n | 'field.label.tigerId'\n | 'field.label.tigerPrivateKey'\n | 'field.placeholder.binanceKey'\n | 'field.placeholder.binanceSecret'\n | 'field.placeholder.okxKey'\n | 'field.placeholder.okxSecret'\n | 'field.placeholder.okxPassphrase'\n | 'field.placeholder.bybitKey'\n | 'field.placeholder.bybitSecret'\n | 'field.placeholder.ccxtKey'\n | 'field.placeholder.ccxtSecret'\n | 'field.placeholder.alpacaKey'\n | 'field.placeholder.alpacaSecret'\n | 'field.placeholder.fmpKey'\n | 'field.placeholder.finnhubKey'\n | 'field.placeholder.polygonKey'\n | 'field.placeholder.tushareToken'\n | 'field.placeholder.akshareUrl'\n | 'field.placeholder.qmtUrl'\n | 'field.placeholder.futuHost'\n | 'field.placeholder.futuPort'\n | 'field.placeholder.ibkrUrl'\n | 'field.placeholder.longbridgeAppKey'\n | 'field.placeholder.longbridgeAppSecret'\n | 'field.placeholder.longbridgeAccessToken'\n | 'field.placeholder.tigerId'\n | 'field.placeholder.tigerPrivateKey'\n\nexport const zh: Record<SettingsLocaleKey, string> = {\n 'nav': '交易',\n 'lead': '选择每个市场使用的数据/交易所提供方。行情面板保存即生效;Agent 会话于新建会话生效(切换不中断当前会话)。',\n 'tabs': '市场',\n 'empty': '没有可配置的市场。',\n 'save': '保存',\n 'discard': '放弃',\n 'saved': '已保存',\n 'saveFailed': '保存失败',\n 'current': '当前:{provider}',\n 'default': '默认',\n 'custom': '自定义({provider},由第三方连接器提供)',\n 'newsKeyLabel': 'CryptoPanic API Key(可选)——新闻工具 crypto_get_news 的 B 增强源;留空则用公共源。',\n 'newsKeyPlaceholder': '粘贴 CryptoPanic free API token(私钥,仅本地存储)',\n 'newsSaved': '已保存',\n 'newsSaveFailed': '保存失败',\n 'colorMode.label': '涨跌配色',\n 'colorMode.redUp': '红涨绿跌(国内习惯)',\n 'colorMode.greenUp': '绿涨红跌(国际习惯)',\n 'market.crypto': '加密货币',\n 'market.us': '美国股票',\n 'market.cn': '中国 A 股',\n 'market.hk': '香港股票',\n 'credential.btn': '配置 API 凭证',\n 'credential.btnFold': '收起配置',\n 'credential.configured': '已配置凭证',\n 'credential.notConfigured': '未配置',\n 'credential.save': '保存凭证',\n 'credential.delete': '清除/删除凭证',\n 'credential.saved': 'API 凭证已保存',\n 'credential.deleted': 'API 凭证已删除',\n 'credential.saveFailed': '凭证保存失败',\n 'credential.deleteFailed': '凭证清除失败',\n 'type.public': '免密公共源',\n 'type.gateway': '本地网关',\n 'type.commercial': '商业 API',\n 'field.action.hide': '隐藏',\n 'field.action.show': '显示',\n 'provider.docsLink': '官方指引与文档',\n 'provider.envPrefix': '环境变量:',\n 'provider.binance': 'Binance (币安)',\n 'provider.okx': 'OKX (欧易)',\n 'provider.bybit': 'Bybit',\n 'provider.ccxt': 'CCXT (跨所聚合 100+)',\n 'provider.yahoo': 'Yahoo Finance',\n 'provider.alpaca': 'Alpaca',\n 'provider.fmp': 'FMP (Financial Modeling Prep)',\n 'provider.finnhub': 'Finnhub',\n 'provider.polygon': 'Polygon.io (Massive)',\n 'provider.ibkr': 'IBKR (盈透证券)',\n 'provider.stooq': 'Stooq',\n 'provider.tencent': '腾讯 (Tencent)',\n 'provider.eastmoney': '东方财富 (Eastmoney)',\n 'provider.tushare': 'Tushare Pro',\n 'provider.akshare': 'AkShare (宏观/另类量化)',\n 'provider.qmt': 'MiniQMT (迅投券商实盘)',\n 'provider.futu': 'Futu (富途 OpenD)',\n 'provider.longbridge': 'Longbridge (长桥)',\n 'provider.tiger': 'Tiger Trade (老虎证券)',\n 'field.label.apiKey': 'API Key',\n 'field.label.apiSecret': 'API Secret',\n 'field.label.secretKey': 'Secret Key',\n 'field.label.passphrase': 'Passphrase',\n 'field.label.token': 'Pro Token',\n 'field.label.apiUrl': 'HTTP 服务地址',\n 'field.label.qmtUrl': 'MiniQMT 服务地址',\n 'field.label.futuHost': 'OpenD IP',\n 'field.label.futuPort': 'OpenD 端口',\n 'field.label.ibkrUrl': 'CP Gateway 地址',\n 'field.label.appKey': 'App Key',\n 'field.label.appSecret': 'App Secret',\n 'field.label.accessToken': 'Access Token',\n 'field.label.tigerId': 'Tiger ID',\n 'field.label.tigerPrivateKey': 'RSA 私钥',\n 'field.placeholder.binanceKey': 'BINANCE_API_KEY (留空走免密公共行情)',\n 'field.placeholder.binanceSecret': 'BINANCE_API_SECRET',\n 'field.placeholder.okxKey': 'OKX_API_KEY (留空走免密公共行情)',\n 'field.placeholder.okxSecret': 'OKX_SECRET_KEY',\n 'field.placeholder.okxPassphrase': 'OKX_PASSPHRASE',\n 'field.placeholder.bybitKey': 'BYBIT_API_KEY (留空走免密公共行情)',\n 'field.placeholder.bybitSecret': 'BYBIT_API_SECRET',\n 'field.placeholder.ccxtKey': 'CCXT_API_KEY',\n 'field.placeholder.ccxtSecret': 'CCXT_API_SECRET',\n 'field.placeholder.alpacaKey': 'ALPACA_API_KEY',\n 'field.placeholder.alpacaSecret': 'ALPACA_SECRET_KEY',\n 'field.placeholder.fmpKey': 'FMP_API_KEY',\n 'field.placeholder.finnhubKey': 'FINNHUB_API_KEY',\n 'field.placeholder.polygonKey': 'POLYGON_API_KEY',\n 'field.placeholder.tushareToken': 'TUSHARE_TOKEN',\n 'field.placeholder.akshareUrl': 'http://127.0.0.1:8080 (默认内置)',\n 'field.placeholder.qmtUrl': 'http://127.0.0.1:5800',\n 'field.placeholder.futuHost': '127.0.0.1',\n 'field.placeholder.futuPort': '11111',\n 'field.placeholder.ibkrUrl': 'https://localhost:5000',\n 'field.placeholder.longbridgeAppKey': 'LONGBRIDGE_APP_KEY',\n 'field.placeholder.longbridgeAppSecret': 'LONGBRIDGE_APP_SECRET',\n 'field.placeholder.longbridgeAccessToken': 'LONGBRIDGE_ACCESS_TOKEN',\n 'field.placeholder.tigerId': 'TIGER_ID',\n 'field.placeholder.tigerPrivateKey': 'TIGER_PRIVATE_KEY',\n}\n\nexport const en: Record<SettingsLocaleKey, string> = {\n 'nav': 'Trading',\n 'lead': 'Choose the data/exchange provider for each market. Quote panels take effect immediately; agent sessions pick it up in new sessions (running sessions are not interrupted).',\n 'tabs': 'Markets',\n 'empty': 'No configurable markets.',\n 'save': 'Save',\n 'discard': 'Discard',\n 'saved': 'Saved',\n 'saveFailed': 'Save failed',\n 'current': 'Current: {provider}',\n 'default': 'default',\n 'custom': 'Custom ({provider}, provided by a third-party connector)',\n 'newsKeyLabel': 'CryptoPanic API key (optional) — B-source enrichment for the crypto_get_news tool; leave empty to use public sources.',\n 'newsKeyPlaceholder': 'Paste a CryptoPanic free API token (stored locally only)',\n 'newsSaved': 'Saved',\n 'newsSaveFailed': 'Save failed',\n 'colorMode.label': 'Price Color Scheme',\n 'colorMode.redUp': 'Red Up / Green Down (Chinese)',\n 'colorMode.greenUp': 'Green Up / Red Down (International)',\n 'market.crypto': 'Crypto',\n 'market.us': 'US Stocks',\n 'market.cn': 'China A-shares',\n 'market.hk': 'Hong Kong',\n 'credential.btn': 'Configure API Credentials',\n 'credential.btnFold': 'Hide Configuration',\n 'credential.configured': 'Configured',\n 'credential.notConfigured': 'Not Configured',\n 'credential.save': 'Save Credentials',\n 'credential.delete': 'Clear / Delete Credentials',\n 'credential.saved': 'API Credentials saved',\n 'credential.deleted': 'API Credentials cleared',\n 'credential.saveFailed': 'Failed to save credentials',\n 'credential.deleteFailed': 'Failed to clear credentials',\n 'type.public': 'Public source',\n 'type.gateway': 'Local gateway',\n 'type.commercial': 'Commercial API',\n 'field.action.hide': 'Hide',\n 'field.action.show': 'Show',\n 'provider.docsLink': 'Official docs & guides',\n 'provider.envPrefix': 'Env var: ',\n 'provider.binance': 'Binance',\n 'provider.okx': 'OKX',\n 'provider.bybit': 'Bybit',\n 'provider.ccxt': 'CCXT (100+ exchanges)',\n 'provider.yahoo': 'Yahoo Finance',\n 'provider.alpaca': 'Alpaca',\n 'provider.fmp': 'FMP (Financial Modeling Prep)',\n 'provider.finnhub': 'Finnhub',\n 'provider.polygon': 'Polygon.io (Massive)',\n 'provider.ibkr': 'IBKR (Interactive Brokers)',\n 'provider.stooq': 'Stooq',\n 'provider.tencent': 'Tencent',\n 'provider.eastmoney': 'Eastmoney',\n 'provider.tushare': 'Tushare Pro',\n 'provider.akshare': 'AkShare (macro / alt-data)',\n 'provider.qmt': 'MiniQMT (broker gateway)',\n 'provider.futu': 'Futu (OpenD)',\n 'provider.longbridge': 'Longbridge',\n 'provider.tiger': 'Tiger Trade',\n 'field.label.apiKey': 'API Key',\n 'field.label.apiSecret': 'API Secret',\n 'field.label.secretKey': 'Secret Key',\n 'field.label.passphrase': 'Passphrase',\n 'field.label.token': 'Pro Token',\n 'field.label.apiUrl': 'HTTP endpoint',\n 'field.label.qmtUrl': 'MiniQMT endpoint',\n 'field.label.futuHost': 'OpenD IP',\n 'field.label.futuPort': 'OpenD port',\n 'field.label.ibkrUrl': 'CP Gateway URL',\n 'field.label.appKey': 'App Key',\n 'field.label.appSecret': 'App Secret',\n 'field.label.accessToken': 'Access Token',\n 'field.label.tigerId': 'Tiger ID',\n 'field.label.tigerPrivateKey': 'RSA private key',\n 'field.placeholder.binanceKey': 'BINANCE_API_KEY (leave empty for public quotes)',\n 'field.placeholder.binanceSecret': 'BINANCE_API_SECRET',\n 'field.placeholder.okxKey': 'OKX_API_KEY (leave empty for public quotes)',\n 'field.placeholder.okxSecret': 'OKX_SECRET_KEY',\n 'field.placeholder.okxPassphrase': 'OKX_PASSPHRASE',\n 'field.placeholder.bybitKey': 'BYBIT_API_KEY (leave empty for public quotes)',\n 'field.placeholder.bybitSecret': 'BYBIT_API_SECRET',\n 'field.placeholder.ccxtKey': 'CCXT_API_KEY',\n 'field.placeholder.ccxtSecret': 'CCXT_API_SECRET',\n 'field.placeholder.alpacaKey': 'ALPACA_API_KEY',\n 'field.placeholder.alpacaSecret': 'ALPACA_SECRET_KEY',\n 'field.placeholder.fmpKey': 'FMP_API_KEY',\n 'field.placeholder.finnhubKey': 'FINNHUB_API_KEY',\n 'field.placeholder.polygonKey': 'POLYGON_API_KEY',\n 'field.placeholder.tushareToken': 'TUSHARE_TOKEN',\n 'field.placeholder.akshareUrl': 'http://127.0.0.1:8080 (built-in default)',\n 'field.placeholder.qmtUrl': 'http://127.0.0.1:5800',\n 'field.placeholder.futuHost': '127.0.0.1',\n 'field.placeholder.futuPort': '11111',\n 'field.placeholder.ibkrUrl': 'https://localhost:5000',\n 'field.placeholder.longbridgeAppKey': 'LONGBRIDGE_APP_KEY',\n 'field.placeholder.longbridgeAppSecret': 'LONGBRIDGE_APP_SECRET',\n 'field.placeholder.longbridgeAccessToken': 'LONGBRIDGE_ACCESS_TOKEN',\n 'field.placeholder.tigerId': 'TIGER_ID',\n 'field.placeholder.tigerPrivateKey': 'TIGER_PRIVATE_KEY',\n}\n","/**\n * Trading settings surface, browser half — one 'settings.section' entry\n * (交易) hosting per-market tabs (dshtrading.market.tab keyed slot).\n *\n * The section is a tab container over the market tab ledger; each market is\n * one tab registration (MarketProviderPanel). A new market = a new tab\n * registration, no section changes; a new exchange = a provider candidate\n * line in trading-settings-controller. The dshtrading namespace is owned by\n * @dshtrading/router on the Host.\n */\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport { resolveSlotLabel } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from './contract/locale-keys.ts'\nimport type { SettingsSectionInjected } from './contract/slots.ts'\nimport {\n createTradingSettingsStore,\n type TradingSettings,\n type TradingSettingsActions,\n type TradingSettingsState,\n} from './trading-settings-controller.ts'\nimport { TradingSettingsSection, type TradingSettingsSectionInjected, type TradingMarketTabEntry } from './TradingSettingsSection.tsx'\nimport { MarketProviderPanel } from './MarketProviderPanel.tsx'\n\nimport { en, zh } from './locales.ts'\n/** 本面板/字符串翻译的 locale namespace。 */\nconst NS = 'dshtrading.settings'\n\n/** Required services (cordis fiber inject). */\nexport const inject = ['slots', 'locale', 'settingsScope']\n\n/** 市场 tab 注册清单(id = market slug;新市场 = 加一行 + 加 slot 注册,section 零改)。 */\nconst MARKET_TABS: readonly { id: string; order: number; key: string }[] = [\n { id: 'crypto', order: 0, key: 'crypto' },\n { id: 'us', order: 1, key: 'us' },\n { id: 'cn', order: 2, key: 'cn' },\n { id: 'hk', order: 3, key: 'hk' },\n]\n\n/** 注册『交易』设置一级菜单(tab 容器)+ 每市场面板。 */\nexport function apply(ctx: ClientContext): void {\n const t = ctx.locale.bind(NS)\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-trading-settings: dictionaries')\n\n const scope = ctx.settingsScope.bind<TradingSettings>({ namespace: 'dshtrading' })\n const store = createTradingSettingsStore(scope)\n const actions: TradingSettingsActions = {\n async setProvider(market, provider) {\n const rev = scope.getSnapshot().revision\n await scope.mutate([{ op: 'set', path: ['markets', market, 'provider'], value: provider }], rev)\n },\n async resetProvider(market) {\n const rev = scope.getSnapshot().revision\n await scope.mutate([{ op: 'unset', path: ['markets', market, 'provider'] }], rev)\n },\n async setCredential(provider, fields) {\n const rev = scope.getSnapshot().revision\n await scope.mutate([{ op: 'set', path: ['credentials', provider], value: fields }], rev)\n },\n async deleteCredential(provider) {\n const rev = scope.getSnapshot().revision\n await scope.mutate([{ op: 'unset', path: ['credentials', provider] }], rev)\n },\n async setNewsKey(value) {\n const rev = scope.getSnapshot().revision\n // 空串 = 清除(unset 回 base 默认):无 key = 新闻走公共源。\n const op = value.trim()\n ? { op: 'set' as const, path: ['news', 'cryptoPanicKey'], value: value.trim() }\n : { op: 'unset' as const, path: ['news', 'cryptoPanicKey'] }\n await scope.mutate([op], rev)\n },\n async resetNewsKey() {\n const rev = scope.getSnapshot().revision\n await scope.mutate([{ op: 'unset', path: ['news', 'cryptoPanicKey'] }], rev)\n },\n async setColorMode(mode) {\n const rev = scope.getSnapshot().revision\n await scope.mutate([{ op: 'set', path: ['colorMode'], value: mode }], rev)\n // 同步 localStorage + dispatch 事件,通知 client-ui-trading 的 colorModeStore 热切换。\n try { localStorage.setItem('dshtrading.color_mode.v1', JSON.stringify(mode)) } catch { /* unavailable */ }\n try { window.dispatchEvent(new Event('dshtrading-color-mode-changed')) } catch { /* SSR guard */ }\n },\n }\n\n // Tab ledger read + locale revision (官方 sectionInjected 模式).\n let tabsVersion = -1\n let tabsRevision = -1\n let tabs: readonly TradingMarketTabEntry[] = []\n const sectionInjected = (): TradingSettingsSectionInjected => ({\n hooks: {\n tabs: {\n getSnapshot: () => {\n const version = ctx.slots.getVersion('dshtrading.market.tab')\n const revision = ctx.locale.getSnapshot().revision\n if (version !== tabsVersion || revision !== tabsRevision) {\n tabsVersion = version\n tabsRevision = revision\n tabs = ctx.slots.entries('dshtrading.market.tab')\n .map((entry) => ({\n id: entry.options.id ?? '',\n order: entry.options.order ?? 0,\n label: resolveSlotLabel(entry.options.label) ?? '',\n }))\n .sort((a, b) => a.order - b.order)\n }\n return tabs\n },\n subscribe: (listener) => {\n const offLedger = ctx.slots.subscribe('dshtrading.market.tab', listener)\n const offLocale = ctx.locale.subscribe(listener)\n return () => {\n offLedger()\n offLocale()\n }\n },\n },\n },\n })\n\n // 一级菜单:交易(tab 容器)。\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'trading',\n order: 8,\n label: () => t('nav'),\n locale: NS,\n inject: () => ({\n ...sectionInjected(),\n hooks: {\n ...sectionInjected().hooks,\n controller: store,\n },\n setColorMode: actions.setColorMode,\n }),\n children: { 'dshtrading.market.tab': { kind: 'list', scope: 'root' } },\n }, TradingSettingsSection))\n\n // 每个市场一个 tab(list:id=market slug,only=market 时渲染对应面板,官方 settings.plugins.tab 模式)。\n ctx.slots.inject('dshtrading.market.tab', function* () {\n for (const market of MARKET_TABS) {\n yield ctx.slots.register({\n name: 'dshtrading.market.tab',\n id: market.id,\n order: market.order,\n label: () => t('market.' + market.key),\n locale: NS,\n inject: () => ({\n hooks: {\n controller: store,\n },\n market: market.id,\n ...actions,\n }),\n }, MarketProviderPanel)\n }\n })\n}\n"],"mappings":";;;;;;;;;;;EA2BA,MAAa,kBAAqD;GAChE;IAAE,IAAI;IAAW,OAAO;IAAoB,KAAK;IAAsC,KAAK;IAAmB,MAAM;IAAU,SAAS,CAAC,QAAQ;GAAE;GACnJ;IAAE,IAAI;IAAO,OAAO;IAAgB,KAAK;IAA+B,KAAK;IAAe,MAAM;IAAU,SAAS,CAAC,QAAQ;GAAE;GAChI;IAAE,IAAI;IAAS,OAAO;IAAkB,KAAK;IAAqC,KAAK;IAAiB,MAAM;IAAU,SAAS,CAAC,QAAQ;GAAE;GAC5I;IAAE,IAAI;IAAQ,OAAO;IAAiB,KAAK;IAAoB,KAAK;IAAgB,MAAM;IAAU,SAAS,CAAC,QAAQ;GAAE;GACxH;IAAE,IAAI;IAAS,OAAO;IAAkB,KAAK;IAA6B,MAAM;IAAU,SAAS,CAAC,MAAM,IAAI;GAAE;GAChH;IAAE,IAAI;IAAU,OAAO;IAAmB,KAAK;IAA0B,KAAK;IAAkB,MAAM;IAAc,SAAS,CAAC,IAAI;GAAE;GACpI;IAAE,IAAI;IAAO,OAAO;IAAgB,KAAK;IAAoD,KAAK;IAAe,MAAM;IAAc,SAAS,CAAC,IAAI;GAAE;GACrJ;IAAE,IAAI;IAAW,OAAO;IAAoB,KAAK;IAA+B,KAAK;IAAmB,MAAM;IAAc,SAAS,CAAC,IAAI;GAAE;GAC5I;IAAE,IAAI;IAAW,OAAO;IAAoB,KAAK;IAAsB,KAAK;IAAmB,MAAM;IAAc,SAAS,CAAC,IAAI;GAAE;GACnI;IAAE,IAAI;IAAQ,OAAO;IAAiB,KAAK;IAA8D,KAAK;IAAoB,MAAM;IAAW,SAAS,CAAC,MAAM,IAAI;GAAE;GACzK;IAAE,IAAI;IAAS,OAAO;IAAkB,KAAK;IAAqB,MAAM;IAAU,SAAS,CAAC,IAAI;GAAE;GAClG;IAAE,IAAI;IAAW,OAAO;IAAoB,KAAK;IAA0B,MAAM;IAAU,SAAS,CAAC,MAAM,IAAI;GAAE;GACjH;IAAE,IAAI;IAAa,OAAO;IAAsB,KAAK;IAAyB,MAAM;IAAU,SAAS,CAAC,MAAM,IAAI;GAAE;GACpH;IAAE,IAAI;IAAW,OAAO;IAAoB,KAAK;IAAgC,KAAK;IAAiB,MAAM;IAAc,SAAS;KAAC;KAAM;KAAM;IAAI;GAAE;GACvJ;IAAE,IAAI;IAAW,OAAO;IAAoB,KAAK;IAAuB,KAAK;IAAmB,MAAM;IAAU,SAAS,CAAC,MAAM,IAAI;GAAE;GACtI;IAAE,IAAI;IAAO,OAAO;IAAgB,KAAK;IAAyB,KAAK;IAAmB,MAAM;IAAW,SAAS,CAAC,IAAI;GAAE;GAC3H;IAAE,IAAI;IAAQ,OAAO;IAAiB,KAAK;IAAwC,KAAK;IAAa,MAAM;IAAW,SAAS;KAAC;KAAM;KAAM;IAAI;GAAE;GAClJ;IAAE,IAAI;IAAc,OAAO;IAAuB,KAAK;IAAgC,KAAK;IAAsB,MAAM;IAAc,SAAS,CAAC,MAAM,IAAI;GAAE;GAC5J;IAAE,IAAI;IAAS,OAAO;IAAkB,KAAK;IAAkC,KAAK;IAAY,MAAM;IAAc,SAAS;KAAC;KAAM;KAAM;IAAI;GAAE;GAChJ;IAAE,IAAI;IAAW,OAAO;IAAoB,KAAK;IAA4B,KAAK;IAA2B,MAAM;IAAc,SAAS,CAAC,IAAI;GAAE;EACnJ;EAWA,MAAa,4BAAwE;GACnF,SAAS,CACP;IAAE,KAAK;IAAU,OAAO;IAAsB,aAAa;IAAgC,QAAQ;GAAK,GACxG;IAAE,KAAK;IAAa,OAAO;IAAyB,aAAa;IAAmC,QAAQ;GAAK,CACnH;GACA,KAAK;IACH;KAAE,KAAK;KAAU,OAAO;KAAsB,aAAa;KAA4B,QAAQ;IAAK;IACpG;KAAE,KAAK;KAAa,OAAO;KAAyB,aAAa;KAA+B,QAAQ;IAAK;IAC7G;KAAE,KAAK;KAAc,OAAO;KAA0B,aAAa;KAAmC,QAAQ;IAAK;GACrH;GACA,OAAO,CACL;IAAE,KAAK;IAAU,OAAO;IAAsB,aAAa;IAA8B,QAAQ;GAAK,GACtG;IAAE,KAAK;IAAa,OAAO;IAAyB,aAAa;IAAiC,QAAQ;GAAK,CACjH;GACA,MAAM,CACJ;IAAE,KAAK;IAAU,OAAO;IAAsB,aAAa;IAA6B,QAAQ;GAAK,GACrG;IAAE,KAAK;IAAa,OAAO;IAAyB,aAAa;IAAgC,QAAQ;GAAK,CAChH;GACA,QAAQ,CACN;IAAE,KAAK;IAAU,OAAO;IAAsB,aAAa;IAA+B,QAAQ;GAAK,GACvG;IAAE,KAAK;IAAa,OAAO;IAAyB,aAAa;IAAkC,QAAQ;GAAK,CAClH;GACA,KAAK,CACH;IAAE,KAAK;IAAU,OAAO;IAAsB,aAAa;IAA4B,QAAQ;GAAK,CACtG;GACA,SAAS,CACP;IAAE,KAAK;IAAU,OAAO;IAAsB,aAAa;IAAgC,QAAQ;GAAK,CAC1G;GACA,SAAS,CACP;IAAE,KAAK;IAAU,OAAO;IAAsB,aAAa;IAAgC,QAAQ;GAAK,CAC1G;GACA,SAAS,CACP;IAAE,KAAK;IAAS,OAAO;IAAqB,aAAa;IAAkC,QAAQ;GAAK,CAC1G;GACA,SAAS,CACP;IAAE,KAAK;IAAU,OAAO;IAAsB,aAAa;GAA+B,CAC5F;GACA,KAAK,CACH;IAAE,KAAK;IAAc,OAAO;IAAsB,aAAa;GAA2B,CAC5F;GACA,MAAM,CACJ;IAAE,KAAK;IAAQ,OAAO;IAAwB,aAAa;GAA6B,GACxF;IAAE,KAAK;IAAQ,OAAO;IAAwB,aAAa;GAA6B,CAC1F;GACA,MAAM,CACJ;IAAE,KAAK;IAAc,OAAO;IAAuB,aAAa;GAA4B,CAC9F;GACA,YAAY;IACV;KAAE,KAAK;KAAU,OAAO;KAAsB,aAAa;KAAsC,QAAQ;IAAK;IAC9G;KAAE,KAAK;KAAa,OAAO;KAAyB,aAAa;KAAyC,QAAQ;IAAK;IACvH;KAAE,KAAK;KAAe,OAAO;KAA2B,aAAa;KAA2C,QAAQ;IAAK;GAC/H;GACA,OAAO,CACL;IAAE,KAAK;IAAW,OAAO;IAAuB,aAAa;GAA4B,GACzF;IAAE,KAAK;IAAc,OAAO;IAA+B,aAAa;IAAqC,QAAQ;GAAK,CAC5H;GACA,SAAS,CACP;IAAE,KAAK;IAAU,OAAO;IAAsB,aAAa;IAA2B,QAAQ;GAAK,CACrG;EACF;;EA8CA,SAAgB,gBAAgB,MAAoE;GAClG,MAAM,QAAQ,KAAK,SAAU,KAAK;GAClC,MAAM,OAAQ,KAAK,QAAQ,CAAC;GAE5B,MAAM,4BAAY,IAAI,IAAY;IAChC,GAAG,OAAO,KAAK,OAAO,WAAW,CAAC,CAAC;IACnC,GAAG,OAAO,KAAM,KAAK,MAAsC,WAAW,CAAC,CAAC;IACxE,GAAG,OAAO,KAAK,KAAK,WAAW,CAAC,CAAC;GACnC,CAAC;GACD,MAAM,WAA+C,CAAC;GACtD,MAAM,aAAsC,CAAC;GAC7C,MAAM,cAAe,KAAK,MAAsC,WAAW,CAAC;GAC5E,KAAK,MAAM,YAAY,WAAW;IAEhC,SAAS,YAAY,OAAO,UAAU,SAAS,EAAE,YAAY,YAAY,SAAS,EAAE;IACpF,WAAW,YAAY,KAAK,UAAU,cAAc,KAAA;GACtD;GAGA,MAAM,cAAc,OAAO,eAAe,CAAC;GAG3C,MAAM,WAAY,KAAK,MAAsC;GAC7D,MAAM,OAAO,OAAO,QAAQ;GAC5B,MAAM,YAAa,KAAK,QAAQ,CAAC,EAAA,CAA8C;GAC/E,OAAO;IACL,QAAQ,KAAK;IACb;IACA;IACA;IACA,SAAS,MAAM;IACf,gBAAgB,UAAU,mBAAmB,KAAA;IAC7C,WAAW,OAAO,cAAc,aAAa,aAAa;IAC1D,UAAU,KAAK,YAAY,KAAK,SAAS;GAC3C;EACF;;EAGA,SAAgB,2BAA2B,OAA4E;GACrH,IAAI,SAA+B,gBAAgB,MAAM,YAAY,CAAC;GACtE,OAAO;IACL,mBAAmB;KACjB,MAAM,UAAU,gBAAgB,MAAM,YAAY,CAAC;KAEnD,IAAI,KAAK,UAAU,OAAO,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS;KACjE,OAAO;IACT;IACA,YAAY,aAAa,MAAM,UAAU,QAAQ;GACnD;EACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECrKA,SAAgB,uBAAuB,EAAE,GAAG,YAAY,SAAS,eAAe,gBAA6C;GAC3H,MAAM,UAAA,GAASA,MAAAA,MAAAA,CAAM;GACrB,MAAM,WAAA,GAAUC,MAAAA,OAAAA,CAAwC,CAAC,CAAC;GAC1D,MAAM,OAAO,SAAQ,UAAS,KAAK;GACnC,MAAM,kBAAkB,eAAe,UAAgC,KAAK;GAC5E,MAAM,CAAC,UAAU,gBAAA,GAAeC,MAAAA,SAAAA,CAAiB;GACjD,MAAM,CAAC,YAAY,kBAAA,GAAiBA,MAAAA,SAAAA,uBAAoC,IAAI,IAAI,CAAC;GACjF,MAAM,SAAS,KAAK,MAAK,QAAO,IAAI,OAAO,QAAQ,CAAC,EAAE,MAAM,KAAK,EAAE,EAAE;GAGrE,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,WAAW,KAAA,GAAW;IAC1B,eAAe,aAAa;KAC1B,IAAI,SAAS,IAAI,MAAM,GAAG,OAAO;KACjC,uBAAO,IAAI,IAAI,CAAC,GAAG,UAAU,MAAM,CAAC;IACtC,CAAC;GACH,GAAG,CAAC,MAAM,CAAC;GAEX,MAAM,mBAAmB,gBAAgB,aAAa;GAEtD,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAWC,oCAAI;IAApB,UAAA;KACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;MAAG,WAAWA,oCAAI;MAAO,UAAA,EAAE,MAAM;KAAK,CAAA;KAGtC,iBAAA,GAAA,kBAAA,KAAA,CAAC,YAAD;MAAU,WAAWA,oCAAI;MAAzB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;OAAQ,WAAWA,oCAAI;OAAiB,UAAA,EAAE,iBAAiB;MAAU,CAAA,GACrE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,WAAWA,oCAAI;OAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,SAAD;QAAO,WAAWA,oCAAI;QAAiB,eAAa,qBAAqB,WAAW,SAAS,KAAA;QAA7F,UAAA;SACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;UACE,MAAK;UACL,MAAK;UACL,OAAM;UACN,SAAS,qBAAqB;UAC9B,gBAAgB;WAAE,aAAkB,QAAQ;UAAE;UAC9C,WAAWA,oCAAI;SAChB,CAAA;SACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;UAAM,WAAWA,oCAAI;UAAiB,OAAO,EAAE,YAAY,UAAU;SAAI,CAAA;SACzE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;UAAM,WAAWA,oCAAI;UAAqB,OAAO,EAAE,YAAY,UAAU;SAAI,CAAA;SAC7E,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,iBAAiB,EAAQ,CAAA;QAC7B;OACP,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,SAAD;QAAO,WAAWA,oCAAI;QAAiB,eAAa,qBAAqB,aAAa,SAAS,KAAA;QAA/F,UAAA;SACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;UACE,MAAK;UACL,MAAK;UACL,OAAM;UACN,SAAS,qBAAqB;UAC9B,gBAAgB;WAAE,aAAkB,UAAU;UAAE;UAChD,WAAWA,oCAAI;SAChB,CAAA;SACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;UAAM,WAAWA,oCAAI;UAAiB,OAAO,EAAE,YAAY,UAAU;SAAI,CAAA;SACzE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;UAAM,WAAWA,oCAAI;UAAqB,OAAO,EAAE,YAAY,UAAU;SAAI,CAAA;SAC7E,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,mBAAmB,EAAQ,CAAA;QAC/B;OACJ,CAAA,CAAA;MACG,CAAA,CAAA;;KAET,KAAK,WAAW,IAAI,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;MAAG,WAAWA,oCAAI;MAAQ,UAAA,EAAE,OAAO;KAAK,CAAA,IAC3D,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAWA,oCAAI;MAAS,MAAK;MAAU,cAAY,EAAE,MAAM;MAC7D,UAAA,KAAK,KAAK,KAAK,UAAU;OACxB,MAAM,WAAW,IAAI,OAAO;OAC5B,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAEE,MAAM,YAAY;SAAE,QAAQ,QAAQ,SAAS;QAAQ;QACrD,IAAI,GAAG,OAAO,OAAO,IAAI;QACzB,MAAK;QACL,MAAK;QACL,iBAAe;QACf,iBAAe,GAAG,OAAO,SAAS,IAAI;QACtC,eAAa,WAAW,SAAS,KAAA;QACjC,UAAU,WAAW,IAAI;QACzB,WAAWA,oCAAI;QACf,eAAe;SAAE,YAAY,IAAI,EAAE;QAAE;QACrC,YAAY,UAAU;SACpB,IAAI;SACJ,QAAQ,MAAM,KAAd;UACE,KAAK;WAAc,aAAa,QAAQ,KAAK,KAAK;WAAQ;UAC1D,KAAK;WAAa,aAAa,QAAQ,IAAI,KAAK,UAAU,KAAK;WAAQ;UACvE,KAAK;WAAQ,YAAY;WAAG;UAC5B,KAAK;WAAO,YAAY,KAAK,SAAS;WAAG;UACzC,SAAS;SACX;SACA,MAAM,eAAe;SACrB,MAAM,UAAU,KAAK;SACrB,MAAM,UAAU,QAAQ,QAAQ;SAChC,YAAY,QAAQ,EAAE;SACtB,QAAQ,MAAM;QAChB;QAEC,UAAA,IAAI;OACC,GA5BD,IAAI,EA4BH;MAEZ,CAAC;KACE,CAAA,GACJ,KACE,QAAO,QAAO,IAAI,OAAO,UAAU,WAAW,IAAI,IAAI,EAAE,CAAC,CAAC,CAC1D,KAAK,QAAQ;MACZ,MAAM,WAAW,IAAI,OAAO;MAC5B,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAEE,IAAI,GAAG,OAAO,SAAS,IAAI;OAC3B,MAAK;OACL,mBAAiB,GAAG,OAAO,OAAO,IAAI;OACtC,WAAWA,oCAAI;OACf,QAAQ,CAAC;OAER,UAAA,WAAW,yBAAyB,CAAC,GAAG,EAAE,MAAM,IAAI,GAAG,CAAC;MACtD,GARE,IAAI,EAQN;KAET,CAAC,CACH,EAAA,CAAA;IAED;;EAET;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECtHA,MAAM,aAAqC;GACzC,QAAQ;GACR,SAAS;GACT,YAAY;EACd;EAEA,SAAS,uBAAuB,OAQ7B;GACD,MAAM,EAAE,YAAY,MAAM,gBAAgB,CAAC,GAAG,UAAU,QAAQ,UAAU,MAAM;GAChF,MAAM,CAAC,MAAM,YAAA,GAAWC,MAAAA,SAAAA,CAAS,KAAK;GACtC,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,QAAwC,EAAE,GAAG,cAAc,EAAE;GACzF,MAAM,CAAC,YAAY,kBAAA,GAAiBA,MAAAA,SAAAA,CAAkC,CAAC,CAAC;GACxE,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAAS,KAAK;GAC1C,MAAM,CAAC,KAAK,WAAA,GAAUA,MAAAA,SAAAA,CAAwB,IAAI;GAElD,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,UAAU,EAAE,GAAG,cAAc,CAAC;GAChC,GAAG,CAAC,aAAa,CAAC;GAElB,MAAM,eAAe,OAAO,OAAO,aAAa,CAAC,CAAC,MAAM,MAAM,QAAQ,KAAK,EAAE,KAAK,CAAC,CAAC;GACpF,MAAM,UAAU,KAAK,MAAM,OAAO,OAAO,EAAE,QAAQ,SAAS,cAAc,EAAE,QAAQ,GAAG;GAEvF,MAAM,aAAa,OAAO,MAAwB;IAChD,EAAE,gBAAgB;IAClB,UAAU,IAAI;IACd,OAAO,IAAI;IACX,IAAI;KACF,MAAM,OAAO,MAAM;KACnB,OAAO,EAAE,kBAAkB,CAAC;IAC9B,SAAS,KAAK;KACZ,OAAO,GAAG,EAAE,uBAAuB,EAAE,IAAI,OAAO,GAAG,GAAG;IACxD,UAAU;KACR,UAAU,KAAK;IACjB;GACF;GAEA,MAAM,eAAe,OAAO,MAAwB;IAClD,EAAE,gBAAgB;IAClB,UAAU,IAAI;IACd,OAAO,IAAI;IACX,IAAI;KACF,MAAM,SAAS;KACf,UAAU,CAAC,CAAC;KACZ,OAAO,EAAE,oBAAoB,CAAC;IAChC,SAAS,KAAK;KACZ,OAAO,GAAG,EAAE,yBAAyB,EAAE,IAAI,OAAO,GAAG,GAAG;IAC1D,UAAU;KACR,UAAU,KAAK;IACjB;GACF;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAWC,yCAAI;IAAiB,UAAU,MAAM,EAAE,gBAAgB;IAAvE,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAWA,yCAAI;KAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;MAAM,WAAWA,yCAAI;MAAkB,mBAAiB,eAAe,SAAS;MAAhF,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,eAAe,MAAM,IAAU,CAAA,GACtC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,eAAe,EAAE,uBAAuB,IAAI,EAAE,0BAA0B,EAAQ,CAAA,CACnF;KACN,CAAA,GAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;MACE,MAAK;MACL,WAAWA,yCAAI;MACf,eAAe;OACb,QAAQ,CAAC,IAAI;OACb,OAAO,IAAI;MACb;MAEC,UAAA,OAAO,EAAE,oBAAoB,IAAI,EAAE,gBAAgB;KAC9C,CAAA,CACL;IAEJ,CAAA,GAAA,QACC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAWA,yCAAI;KAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAWA,yCAAI;MACjB,UAAA,KAAK,KAAK,UAAU;OACnB,MAAM,SAAS,MAAM,UAAU,CAAC,WAAW,MAAM;OACjD,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;QAAqB,WAAWA,yCAAI;QAApC,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;SAAO,WAAWA,yCAAI;SAAa,UAAA,EAAE,MAAM,KAAK;QAAS,CAAA,GACzD,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;SAAK,WAAWA,yCAAI;SAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;UACE,MAAM,SAAS,aAAa;UAC5B,WAAWA,yCAAI;UACf,OAAO,OAAO,MAAM,QAAQ;UAC5B,aAAa,MAAM,gBAAgB,KAAA,IAAY,EAAE,MAAM,WAAW,IAAI,KAAA;UACtE,UAAU,CAAC,YAAY;UACvB,WAAW,MAAM,UAAU;WAAE,GAAG;YAAS,MAAM,MAAM,EAAE,OAAO;UAAM,CAAC;SACtE,CAAA,GACA,MAAM,UACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;UACE,MAAK;UACL,WAAWA,yCAAI;UACf,eAAe,eAAe,UAAU;WAAE,GAAG;YAAO,MAAM,MAAM,CAAC,KAAK,MAAM;UAAK,EAAE;UACnF,OAAO,WAAW,MAAM,OAAO,EAAE,mBAAmB,IAAI,EAAE,mBAAmB;UAE5E,UAAA,WAAW,MAAM,OAAO,OAAO;SAC1B,CAAA,CAEP;QACF,CAAA,CAAA;OAtBK,GAAA,MAAM,GAsBX;MAET,CAAC;KACE,CAAA,GACL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,yCAAI;MAApB,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QACE,MAAK;QACL,WAAWA,yCAAI;QACf,UAAU,CAAC,WAAW,UAAU,CAAC;QACjC,SAAS;QAER,UAAA,EAAE,iBAAiB;OACd,CAAA;OACP,gBACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QACE,MAAK;QACL,WAAWA,yCAAI;QACf,UAAU,UAAU,CAAC;QACrB,SAAS;QAER,UAAA,EAAE,mBAAmB;OAChB,CAAA;OAET,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAWA,yCAAI;QAAU,UAAA;OAAU,CAAA;MAC9C;KACF,CAAA,CAAA;IAEJ,CAAA,CAAA;;EAET;;EAGA,SAAgB,oBAAoB,EAClC,GAAG,OACH,eACA,QACA,aACA,eACA,eACA,kBACA,YACA,gBAC2B;GAG3B,MAAM,IAAI;GACV,MAAM,QAAQ,eAAe,UAAgC,KAAK;GAClE,MAAM,WAAW,MAAM,SAAS;GAChC,MAAM,aAAa,MAAM,WAAW;GACpC,MAAM,CAAC,OAAO,aAAA,GAAYD,MAAAA,SAAAA,CAA6B,KAAA,CAAS;GAChE,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAAS,KAAK;GAC1C,MAAM,CAAC,SAAS,eAAA,GAAcA,MAAAA,SAAAA,CAA6B,KAAA,CAAS;GAGpE,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,SAAS,QAAQ;IACjB,WAAW,KAAA,CAAS;GACtB,GAAG,CAAC,QAAQ,QAAQ,CAAC;GAErB,MAAM,SAAA,GAAQE,MAAAA,QAAAA,OAAc;IAC1B,MAAM,SAAS,SAAS;IACxB,IAAI,WAAW,KAAA,GAAW,OAAO;IACjC,OAAO,WAAW;GACpB,GAAG;IAAC;IAAO;IAAU;GAAU,CAAC;GAEhC,MAAM,WAAW,MAAM;GAGvB,MAAM,CAAC,WAAW,iBAAA,GAAgBF,MAAAA,SAAAA,CAA6B,KAAA,CAAS;GACxE,MAAM,CAAC,YAAY,kBAAA,GAAiBA,MAAAA,SAAAA,CAAS,KAAK;GAClD,MAAM,CAAC,aAAa,mBAAA,GAAkBA,MAAAA,SAAAA,CAA6B,KAAA,CAAS;GAC5E,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,cAAc,KAAA,KAAa,MAAM,WAAW,SAC9C,aAAa,MAAM,OAAO;GAG9B,GAAG,CAAC,MAAM,QAAQ,MAAM,OAAO,CAAC;GAEhC,eAAe,WAAW;IACxB,cAAc,IAAI;IAClB,eAAe,KAAA,CAAS;IACxB,IAAI;KACF,MAAM,QAAQ,aAAa,GAAA,CAAI,KAAK;KAEpC,IAAI,UADY,MAAM,WAAW,KAE/B,MAAM,WAAW,IAAI;UAChB,IAAI,MAAM,gBACf,MAAM,aAAa;KAErB,eAAe,EAAE,WAAW,CAAC;IAC/B,SAAS,OAAO;KACd,eAAe,GAAG,EAAE,gBAAgB,EAAE,IAAI,OAAQ,OAAgC,WAAW,KAAK,GAAG;IACvG,UAAU;KACR,cAAc,KAAK;IACrB;GACF;GAEA,MAAM,aAAa,cAAc,KAAA,IAAY,MAAM,WAAW,KAAK,UAAU,KAAK,QAAQ,MAAM,WAAW;GAE3G,MAAM,WAAA,GAAUE,MAAAA,QAAAA,OAAc;IAC5B,MAAM,UAAU,gBAAgB,QAAQ,MAAM,EAAE,QAAQ,SAAS,MAAM,CAAC;IACxE,MAAM,QAAQ,IAAI,IAAI,QAAQ,KAAK,MAAM,EAAE,EAAE,CAAC;IAC9C,MAAM,SAAqF,CAAC;IAC5F,KAAK,MAAM,QAAQ,CAAC,UAAU,KAAK,GACjC,IAAI,SAAS,KAAA,KAAa,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,MAAM,MAAM,EAAE,OAAO,IAAI,GAC7E,OAAO,KAAK;KAAE,IAAI;KAAM,OAAO,EAAE,UAAU,EAAE,UAAU,KAAK,CAAC;IAAE,CAAC;IAGpE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM;GAC/B,GAAG;IAAC;IAAQ;IAAU;IAAO;GAAC,CAAC;GAE/B,eAAe,OAAO;IACpB,UAAU,IAAI;IACd,WAAW,KAAA,CAAS;IACpB,IAAI;KACF,MAAM,SAAS,SAAS;KACxB,IAAI,WAAW,KAAA,GACT;UAAA,YAAY,MAAM,cAAc,MAAM;KAAA,OACrC,IAAI,WAAW,YAAY,CAAC,YACjC,MAAM,YAAY,QAAQ,MAAM;KAElC,WAAW,EAAE,OAAO,CAAC;IACvB,SAAS,OAAO;KACd,WAAW,GAAG,EAAE,YAAY,EAAE,IAAI,OAAQ,OAAgC,WAAW,KAAK,GAAG;IAC/F,UAAU;KACR,UAAU,KAAK;IACjB;GACF;GAIA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAWD,yCAAI;IAApB,UAAA;KACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,yCAAI;MAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,WAAW,EAAE,UAAU,GAAG,CAAC,EAAQ,CAAA,GAC5C,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAWA,yCAAI;OAAe,UAAA,YAAY,EAAE,SAAS;MAAQ,CAAA,CAChE;;KAEL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAWA,yCAAI;MACjB,UAAA,QAAQ,KAAK,aAAa;OACzB,MAAM,WAAY,UAAU,KAAA,IAAY,aAAa,SAAS,KAAK,UAAU,SAAS;OACtF,MAAM,WAAW,0BAA0B,SAAS;OACpD,MAAM,eAAe,MAAM,cAAc,SAAS;OAClD,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;QAEE,WAAWA,yCAAI;QACf,iBAAe,WAAW,SAAS,KAAA;QACnC,eAAe;SAAE,IAAI,YAAY,CAAC,QAAQ,SAAS,SAAS,EAAE;QAAE;QAJlE,UAAA;SAME,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;UAAK,WAAWA,yCAAI;UAApB,UAAA;WACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;YACE,MAAK;YACL,MAAM,YAAY;YAClB,SAAS;YACT,UAAU,CAAC,YAAY;YACvB,gBAAgB,SAAS,SAAS,EAAE;WACrC,CAAA;WACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;YAAM,WAAWA,yCAAI;YAAY,UAAA,EAAE,SAAS,KAAK;WAAQ,CAAA;WACxD,SAAS,QACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;YAAM,WAAWA,yCAAI;YAAY,UAAA,EAAE,WAAW,SAAS,SAAS,SAAS,IAAI;WAAQ,CAAA;UAEpF;;UAEH,SAAS,OAAO,SAAS,QACzB,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;UAAK,WAAWA,yCAAI;UAApB,UAAA,CACG,SAAS,OACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,KAAD;WACE,MAAM,SAAS;WACf,QAAO;WACP,KAAI;WACJ,WAAWA,yCAAI;WACf,UAAU,MAAM,EAAE,gBAAgB;WALpC,UAAA,CAOG,EAAE,mBAAmB,GAAE,IACvB;UACA,CAAA,EAAA,CAAA,GAEN,SAAS,OACR,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;WAAK,WAAWA,yCAAI;WAApB,UAAA,CACG,EAAE,oBAAoB,GAAE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,SAAS,IAAU,CAAA,CAChD;UAEJ,CAAA,CAAA;;SAGN,YAAY,SAAS,SAAS,KAC7B,iBAAA,GAAA,kBAAA,IAAA,CAAC,wBAAD;UACE,YAAY,SAAS;UACrB,MAAM;UACN,eAAe;UACL;UACV,SAAS,WAAW,cAAc,SAAS,IAAI,MAAM;UACrD,gBAAgB,iBAAiB,SAAS,EAAE;UACzC;SACJ,CAAA;QAEA;OArDE,GAAA,GAAG,OAAO,GAAG,SAAS,IAqDxB;MAET,CAAC;KACE,CAAA;KAEL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,yCAAI;MAApB,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QACE,MAAK;QACL,WAAWA,yCAAI;QACf,UAAU,CAAC,SAAS,UAAU,CAAC;QAC/B,eAAe,KAAK,KAAK;QAExB,UAAA,EAAE,MAAM;OACH,CAAA;OACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QACE,MAAK;QACL,WAAWA,yCAAI;QACf,UAAU,UAAU,CAAC;QACrB,eAAe;SAAE,SAAS,KAAA,CAAS;SAAG,WAAW,KAAA,CAAS;QAAE;QAE3D,UAAA,EAAE,SAAS;OACN,CAAA;OACP,YAAY,KAAA,IAAY,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAWA,yCAAI;QAAU,UAAA;OAAc,CAAA,IAAI;MACvE;;KAEJ,WAAW,YACV,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,yCAAI;MAApB,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;QAAO,WAAWA,yCAAI;QAAY,UAAA,EAAE,cAAc;OAAS,CAAA;OAC3D,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;QACE,MAAK;QACL,WAAWA,yCAAI;QACf,OAAO,aAAa;QACpB,UAAU,CAAC,YAAY;QACvB,WAAW,UAAU,aAAa,MAAM,OAAO,KAAK;QACpD,aAAa,EAAE,oBAAoB;OACpC,CAAA;OACD,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;QAAK,WAAWA,yCAAI;QAApB,UAAA;SACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;UACE,MAAK;UACL,WAAWA,yCAAI;UACf,UAAU,CAAC,aAAa,cAAc,CAAC;UACvC,eAAe,KAAK,SAAS;UAE5B,UAAA,EAAE,MAAM;SACH,CAAA;SACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;UACE,MAAK;UACL,WAAWA,yCAAI;UACf,UAAU,cAAc,CAAC;UACzB,eAAe;WAAE,aAAa,KAAA,CAAS;WAAG,eAAe,KAAA,CAAS;UAAE;UAEnE,UAAA,EAAE,SAAS;SACN,CAAA;SACP,gBAAgB,KAAA,IAAY,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;UAAM,WAAWA,yCAAI;UAAU,UAAA;SAAkB,CAAA,IAAI;QAC/E;;MACF;;IAEJ;;EAET;;;EC1SA,MAAa,KAAwC;GAC/C,OAAO;GACP,QAAQ;GACR,QAAQ;GACR,SAAS;GACT,QAAQ;GACR,WAAW;GACX,SAAS;GACT,cAAc;GACd,WAAW;GACX,WAAW;GACX,UAAU;GACV,gBAAgB;GAChB,sBAAsB;GACtB,aAAa;GACb,kBAAkB;GAClB,mBAAmB;GACnB,mBAAmB;GACnB,qBAAqB;GACrB,iBAAiB;GACjB,aAAa;GACb,aAAa;GACb,aAAa;GACb,kBAAkB;GAClB,sBAAsB;GACtB,yBAAyB;GACzB,4BAA4B;GAC5B,mBAAmB;GACnB,qBAAqB;GACrB,oBAAoB;GACpB,sBAAsB;GACtB,yBAAyB;GACzB,2BAA2B;GAC3B,eAAe;GACf,gBAAgB;GAChB,mBAAmB;GACnB,qBAAqB;GACrB,qBAAqB;GACrB,qBAAqB;GACrB,sBAAsB;GACtB,oBAAoB;GACpB,gBAAgB;GAChB,kBAAkB;GAClB,iBAAiB;GACjB,kBAAkB;GAClB,mBAAmB;GACnB,gBAAgB;GAChB,oBAAoB;GACpB,oBAAoB;GACpB,iBAAiB;GACjB,kBAAkB;GAClB,oBAAoB;GACpB,sBAAsB;GACtB,oBAAoB;GACpB,oBAAoB;GACpB,gBAAgB;GAChB,iBAAiB;GACjB,uBAAuB;GACvB,kBAAkB;GAClB,sBAAsB;GACtB,yBAAyB;GACzB,yBAAyB;GACzB,0BAA0B;GAC1B,qBAAqB;GACrB,sBAAsB;GACtB,sBAAsB;GACtB,wBAAwB;GACxB,wBAAwB;GACxB,uBAAuB;GACvB,sBAAsB;GACtB,yBAAyB;GACzB,2BAA2B;GAC3B,uBAAuB;GACvB,+BAA+B;GAC/B,gCAAgC;GAChC,mCAAmC;GACnC,4BAA4B;GAC5B,+BAA+B;GAC/B,mCAAmC;GACnC,8BAA8B;GAC9B,iCAAiC;GACjC,6BAA6B;GAC7B,gCAAgC;GAChC,+BAA+B;GAC/B,kCAAkC;GAClC,4BAA4B;GAC5B,gCAAgC;GAChC,gCAAgC;GAChC,kCAAkC;GAClC,gCAAgC;GAChC,4BAA4B;GAC5B,8BAA8B;GAC9B,8BAA8B;GAC9B,6BAA6B;GAC7B,sCAAsC;GACtC,yCAAyC;GACzC,2CAA2C;GAC3C,6BAA6B;GAC7B,qCAAqC;EAC3C;EAEA,MAAa,KAAwC;GAC/C,OAAO;GACP,QAAQ;GACR,QAAQ;GACR,SAAS;GACT,QAAQ;GACR,WAAW;GACX,SAAS;GACT,cAAc;GACd,WAAW;GACX,WAAW;GACX,UAAU;GACV,gBAAgB;GAChB,sBAAsB;GACtB,aAAa;GACb,kBAAkB;GAClB,mBAAmB;GACnB,mBAAmB;GACnB,qBAAqB;GACrB,iBAAiB;GACjB,aAAa;GACb,aAAa;GACb,aAAa;GACb,kBAAkB;GAClB,sBAAsB;GACtB,yBAAyB;GACzB,4BAA4B;GAC5B,mBAAmB;GACnB,qBAAqB;GACrB,oBAAoB;GACpB,sBAAsB;GACtB,yBAAyB;GACzB,2BAA2B;GAC3B,eAAe;GACf,gBAAgB;GAChB,mBAAmB;GACnB,qBAAqB;GACrB,qBAAqB;GACrB,qBAAqB;GACrB,sBAAsB;GACtB,oBAAoB;GACpB,gBAAgB;GAChB,kBAAkB;GAClB,iBAAiB;GACjB,kBAAkB;GAClB,mBAAmB;GACnB,gBAAgB;GAChB,oBAAoB;GACpB,oBAAoB;GACpB,iBAAiB;GACjB,kBAAkB;GAClB,oBAAoB;GACpB,sBAAsB;GACtB,oBAAoB;GACpB,oBAAoB;GACpB,gBAAgB;GAChB,iBAAiB;GACjB,uBAAuB;GACvB,kBAAkB;GAClB,sBAAsB;GACtB,yBAAyB;GACzB,yBAAyB;GACzB,0BAA0B;GAC1B,qBAAqB;GACrB,sBAAsB;GACtB,sBAAsB;GACtB,wBAAwB;GACxB,wBAAwB;GACxB,uBAAuB;GACvB,sBAAsB;GACtB,yBAAyB;GACzB,2BAA2B;GAC3B,uBAAuB;GACvB,+BAA+B;GAC/B,gCAAgC;GAChC,mCAAmC;GACnC,4BAA4B;GAC5B,+BAA+B;GAC/B,mCAAmC;GACnC,8BAA8B;GAC9B,iCAAiC;GACjC,6BAA6B;GAC7B,gCAAgC;GAChC,+BAA+B;GAC/B,kCAAkC;GAClC,4BAA4B;GAC5B,gCAAgC;GAChC,gCAAgC;GAChC,kCAAkC;GAClC,gCAAgC;GAChC,4BAA4B;GAC5B,8BAA8B;GAC9B,8BAA8B;GAC9B,6BAA6B;GAC7B,sCAAsC;GACtC,yCAAyC;GACzC,2CAA2C;GAC3C,6BAA6B;GAC7B,qCAAqC;EAC3C;;;;EC1RA,MAAM,KAAK;;EAGX,MAAa,SAAS;GAAC;GAAS;GAAU;EAAe;;EAGzD,MAAM,cAAqE;GACzE;IAAE,IAAI;IAAU,OAAO;IAAG,KAAK;GAAS;GACxC;IAAE,IAAI;IAAM,OAAO;IAAG,KAAK;GAAK;GAChC;IAAE,IAAI;IAAM,OAAO;IAAG,KAAK;GAAK;GAChC;IAAE,IAAI;IAAM,OAAO;IAAG,KAAK;GAAK;EAClC;;EAGA,SAAgB,MAAM,KAA0B;GAC9C,MAAM,IAAI,IAAI,OAAO,KAAK,EAAE;GAC5B,IAAI,aAAa,IAAI,OAAO,SAAS,IAAI;IAAE;IAAI;GAAG,CAAC,GAAG,oCAAoC;GAE1F,MAAM,QAAQ,IAAI,cAAc,KAAsB,EAAE,WAAW,aAAa,CAAC;GACjF,MAAM,QAAQ,2BAA2B,KAAK;GAC9C,MAAM,UAAkC;IACtC,MAAM,YAAY,QAAQ,UAAU;KAClC,MAAM,MAAM,MAAM,YAAY,CAAC,CAAC;KAChC,MAAM,MAAM,OAAO,CAAC;MAAE,IAAI;MAAO,MAAM;OAAC;OAAW;OAAQ;MAAU;MAAG,OAAO;KAAS,CAAC,GAAG,GAAG;IACjG;IACA,MAAM,cAAc,QAAQ;KAC1B,MAAM,MAAM,MAAM,YAAY,CAAC,CAAC;KAChC,MAAM,MAAM,OAAO,CAAC;MAAE,IAAI;MAAS,MAAM;OAAC;OAAW;OAAQ;MAAU;KAAE,CAAC,GAAG,GAAG;IAClF;IACA,MAAM,cAAc,UAAU,QAAQ;KACpC,MAAM,MAAM,MAAM,YAAY,CAAC,CAAC;KAChC,MAAM,MAAM,OAAO,CAAC;MAAE,IAAI;MAAO,MAAM,CAAC,eAAe,QAAQ;MAAG,OAAO;KAAO,CAAC,GAAG,GAAG;IACzF;IACA,MAAM,iBAAiB,UAAU;KAC/B,MAAM,MAAM,MAAM,YAAY,CAAC,CAAC;KAChC,MAAM,MAAM,OAAO,CAAC;MAAE,IAAI;MAAS,MAAM,CAAC,eAAe,QAAQ;KAAE,CAAC,GAAG,GAAG;IAC5E;IACA,MAAM,WAAW,OAAO;KACtB,MAAM,MAAM,MAAM,YAAY,CAAC,CAAC;KAEhC,MAAM,KAAK,MAAM,KAAK,IAClB;MAAE,IAAI;MAAgB,MAAM,CAAC,QAAQ,gBAAgB;MAAG,OAAO,MAAM,KAAK;KAAE,IAC5E;MAAE,IAAI;MAAkB,MAAM,CAAC,QAAQ,gBAAgB;KAAE;KAC7D,MAAM,MAAM,OAAO,CAAC,EAAE,GAAG,GAAG;IAC9B;IACA,MAAM,eAAe;KACnB,MAAM,MAAM,MAAM,YAAY,CAAC,CAAC;KAChC,MAAM,MAAM,OAAO,CAAC;MAAE,IAAI;MAAS,MAAM,CAAC,QAAQ,gBAAgB;KAAE,CAAC,GAAG,GAAG;IAC7E;IACA,MAAM,aAAa,MAAM;KACvB,MAAM,MAAM,MAAM,YAAY,CAAC,CAAC;KAChC,MAAM,MAAM,OAAO,CAAC;MAAE,IAAI;MAAO,MAAM,CAAC,WAAW;MAAG,OAAO;KAAK,CAAC,GAAG,GAAG;KAEzE,IAAI;MAAE,aAAa,QAAQ,4BAA4B,KAAK,UAAU,IAAI,CAAC;KAAE,QAAQ,CAAoB;KACzG,IAAI;MAAE,OAAO,cAAc,IAAI,MAAM,+BAA+B,CAAC;KAAE,QAAQ,CAAkB;IACnG;GACF;GAGA,IAAI,cAAc;GAClB,IAAI,eAAe;GACnB,IAAI,OAAyC,CAAC;GAC9C,MAAM,yBAAyD,EAC7D,OAAO,EACL,MAAM;IACJ,mBAAmB;KACjB,MAAM,UAAU,IAAI,MAAM,WAAW,uBAAuB;KAC5D,MAAM,WAAW,IAAI,OAAO,YAAY,CAAC,CAAC;KAC1C,IAAI,YAAY,eAAe,aAAa,cAAc;MACxD,cAAc;MACd,eAAe;MACf,OAAO,IAAI,MAAM,QAAQ,uBAAuB,CAAC,CAC9C,KAAK,WAAW;OACf,IAAI,MAAM,QAAQ,MAAM;OACxB,OAAO,MAAM,QAAQ,SAAS;OAC9B,QAAA,GAAOE,iCAAAA,iBAAAA,CAAiB,MAAM,QAAQ,KAAK,KAAK;MAClD,EAAE,CAAC,CACF,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;KACrC;KACA,OAAO;IACT;IACA,YAAY,aAAa;KACvB,MAAM,YAAY,IAAI,MAAM,UAAU,yBAAyB,QAAQ;KACvE,MAAM,YAAY,IAAI,OAAO,UAAU,QAAQ;KAC/C,aAAa;MACX,UAAU;MACV,UAAU;KACZ;IACF;GACF,EACF,EACF;GAGA,IAAI,MAAM,OAAO,0BAA0B,IAAI,MAAM,SAAS;IAC5D,MAAM;IACN,IAAI;IACJ,OAAO;IACP,aAAa,EAAE,KAAK;IACpB,QAAQ;IACR,eAAe;KACb,GAAG,gBAAgB;KACnB,OAAO;MACL,GAAG,gBAAgB,CAAC,CAAC;MACrB,YAAY;KACd;KACA,cAAc,QAAQ;IACxB;IACA,UAAU,EAAE,yBAAyB;KAAE,MAAM;KAAQ,OAAO;IAAO,EAAE;GACvE,GAAG,sBAAsB,CAAC;GAG1B,IAAI,MAAM,OAAO,yBAAyB,aAAa;IACrD,KAAK,MAAM,UAAU,aACnB,MAAM,IAAI,MAAM,SAAS;KACvB,MAAM;KACN,IAAI,OAAO;KACX,OAAO,OAAO;KACd,aAAa,EAAE,YAAY,OAAO,GAAG;KACrC,QAAQ;KACR,eAAe;MACb,OAAO,EACL,YAAY,MACd;MACA,QAAQ,OAAO;MACf,GAAG;KACL;IACF,GAAG,mBAAmB;GAE1B,CAAC;EACH"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/index.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Trading settings surface, node half. The empty apply exists so the plugin
|
|
4
|
+
* appears in the host cordis.yml / Loader; the browser half owns the section
|
|
5
|
+
* through exports["./client"], discovered from the package.json dsh.client
|
|
6
|
+
* declaration. The page edits the dshtrading namespace owned by
|
|
7
|
+
* @dshtrading/router (registered on the Host), so this package registers no
|
|
8
|
+
* namespace of its own.
|
|
9
|
+
*/
|
|
10
|
+
/** Host plugin body — no host-side behavior for this surface plugin. */
|
|
11
|
+
declare function apply(): void;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { apply };
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/index.ts
|
|
2
|
+
/**
|
|
3
|
+
* Trading settings surface, node half. The empty apply exists so the plugin
|
|
4
|
+
* appears in the host cordis.yml / Loader; the browser half owns the section
|
|
5
|
+
* through exports["./client"], discovered from the package.json dsh.client
|
|
6
|
+
* declaration. The page edits the dshtrading namespace owned by
|
|
7
|
+
* @dshtrading/router (registered on the Host), so this package registers no
|
|
8
|
+
* namespace of its own.
|
|
9
|
+
*/
|
|
10
|
+
/** Host plugin body — no host-side behavior for this surface plugin. */
|
|
11
|
+
function apply() {}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { apply };
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dshtrading/client-ui-settings",
|
|
3
|
+
"description": "Trading settings section for the dsh web client: market → provider routing (dshtrading namespace). Browser half is a dsh.client bundle; node half is the host row placeholder.",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "./lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./client": {
|
|
14
|
+
"types": "./lib/types/client/index.d.ts",
|
|
15
|
+
"default": "./lib/client.js"
|
|
16
|
+
},
|
|
17
|
+
"./locales": {
|
|
18
|
+
"types": "./lib/client/locales.d.ts",
|
|
19
|
+
"default": "./lib/client/locales.js"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"lib"
|
|
25
|
+
],
|
|
26
|
+
"license": "PolyForm-Noncommercial-1.0.0",
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@dshtrading/router": "^0.1.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@deepseek-ai/cordis": ">=4.0.0",
|
|
32
|
+
"@deepseek-ai/dsh-client-connection": ">=0.1.2-alpha.1",
|
|
33
|
+
"@deepseek-ai/dsh-client-locale": ">=0.1.2-alpha.1",
|
|
34
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.2-alpha.1",
|
|
35
|
+
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.2-alpha.1",
|
|
36
|
+
"@deepseek-ai/dsh-client-ui-renderer": ">=0.1.2-alpha.1",
|
|
37
|
+
"@deepseek-ai/dsh-api-remotes": ">=0.1.2-alpha.1",
|
|
38
|
+
"@deepseek-ai/dsh-client-store": ">=0.1.2-alpha.1",
|
|
39
|
+
"react": "^18.2.0",
|
|
40
|
+
"@types/react": "~18.3.1"
|
|
41
|
+
},
|
|
42
|
+
"dsh": {
|
|
43
|
+
"client": {
|
|
44
|
+
"inject": [
|
|
45
|
+
"@deepseek-ai/dsh-client-connection",
|
|
46
|
+
"@deepseek-ai/dsh-client-locale",
|
|
47
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
48
|
+
"@deepseek-ai/dsh-client-ui-slots",
|
|
49
|
+
"@deepseek-ai/dsh-api-remotes"
|
|
50
|
+
],
|
|
51
|
+
"platform": "web"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"tsdown": "^0.22.0",
|
|
56
|
+
"vitest": "^3.0.0",
|
|
57
|
+
"lightningcss": "^1.0.0",
|
|
58
|
+
"react": "^18.2.0",
|
|
59
|
+
"@types/react": "~18.3.1"
|
|
60
|
+
},
|
|
61
|
+
"scripts": {
|
|
62
|
+
"bundle": "tsdown && tsdown --config tsdown.client.config.mjs",
|
|
63
|
+
"build": "tsdown && tsdown --config tsdown.client.config.mjs",
|
|
64
|
+
"test": "vitest run"
|
|
65
|
+
}
|
|
66
|
+
}
|