dsh-plugin-core 0.10.1 → 0.12.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/README.md +4 -3
- package/dist/explorer/FileBrowser.d.ts.map +1 -1
- package/dist/explorer/FileBrowser.js +3 -2
- package/dist/explorer/FileBrowser.js.map +1 -1
- package/dist/explorer/open.d.ts.map +1 -1
- package/dist/explorer/open.js +7 -3
- package/dist/explorer/open.js.map +1 -1
- package/dist/explorer/preview/BytesPreview.d.ts.map +1 -1
- package/dist/explorer/preview/BytesPreview.js +3 -2
- package/dist/explorer/preview/BytesPreview.js.map +1 -1
- package/dist/explorer/preview/HtmlPreview.d.ts.map +1 -1
- package/dist/explorer/preview/HtmlPreview.js +3 -2
- package/dist/explorer/preview/HtmlPreview.js.map +1 -1
- package/dist/explorer/preview/OfficePreview.d.ts.map +1 -1
- package/dist/explorer/preview/OfficePreview.js +3 -2
- package/dist/explorer/preview/OfficePreview.js.map +1 -1
- package/dist/explorer/preview/TextPreview.d.ts.map +1 -1
- package/dist/explorer/preview/TextPreview.js +3 -2
- package/dist/explorer/preview/TextPreview.js.map +1 -1
- package/dist/session/SessionViewModal.d.ts.map +1 -1
- package/dist/session/SessionViewModal.js +3 -2
- package/dist/session/SessionViewModal.js.map +1 -1
- package/dist/session/mirror/ChatView.d.ts.map +1 -1
- package/dist/session/mirror/ChatView.js +3 -0
- package/dist/session/mirror/ChatView.js.map +1 -1
- package/dist/ui/AlertModal.d.ts.map +1 -1
- package/dist/ui/AlertModal.js +3 -0
- package/dist/ui/AlertModal.js.map +1 -1
- package/dist/ui/BackToTop.d.ts.map +1 -1
- package/dist/ui/BackToTop.js +4 -3
- package/dist/ui/BackToTop.js.map +1 -1
- package/dist/ui/Button.d.ts.map +1 -1
- package/dist/ui/Button.js +8 -17
- package/dist/ui/Button.js.map +1 -1
- package/dist/ui/Card.d.ts.map +1 -1
- package/dist/ui/Card.js +3 -2
- package/dist/ui/Card.js.map +1 -1
- package/dist/ui/Chip.d.ts.map +1 -1
- package/dist/ui/Chip.js +3 -2
- package/dist/ui/Chip.js.map +1 -1
- package/dist/ui/CodeViewer.d.ts.map +1 -1
- package/dist/ui/CodeViewer.js +3 -0
- package/dist/ui/CodeViewer.js.map +1 -1
- package/dist/ui/DateTimePicker.d.ts.map +1 -1
- package/dist/ui/DateTimePicker.js +4 -2
- package/dist/ui/DateTimePicker.js.map +1 -1
- package/dist/ui/Field.d.ts +10 -0
- package/dist/ui/Field.d.ts.map +1 -1
- package/dist/ui/Field.js +5 -4
- package/dist/ui/Field.js.map +1 -1
- package/dist/ui/FieldHint.d.ts.map +1 -1
- package/dist/ui/FieldHint.js +3 -2
- package/dist/ui/FieldHint.js.map +1 -1
- package/dist/ui/Loader.d.ts +49 -0
- package/dist/ui/Loader.d.ts.map +1 -0
- package/dist/ui/Loader.js +75 -0
- package/dist/ui/Loader.js.map +1 -0
- package/dist/ui/LoaderBar.d.ts +38 -0
- package/dist/ui/LoaderBar.d.ts.map +1 -0
- package/dist/ui/LoaderBar.js +73 -0
- package/dist/ui/LoaderBar.js.map +1 -0
- package/dist/ui/Loading.d.ts +22 -0
- package/dist/ui/Loading.d.ts.map +1 -1
- package/dist/ui/Loading.js +16 -18
- package/dist/ui/Loading.js.map +1 -1
- package/dist/ui/MarqueeText.d.ts.map +1 -1
- package/dist/ui/MarqueeText.js +3 -0
- package/dist/ui/MarqueeText.js.map +1 -1
- package/dist/ui/Modal.d.ts.map +1 -1
- package/dist/ui/Modal.js +3 -2
- package/dist/ui/Modal.js.map +1 -1
- package/dist/ui/ModelPicker.d.ts.map +1 -1
- package/dist/ui/ModelPicker.js +3 -2
- package/dist/ui/ModelPicker.js.map +1 -1
- package/dist/ui/PanelDock.d.ts.map +1 -1
- package/dist/ui/PanelDock.js +5 -2
- package/dist/ui/PanelDock.js.map +1 -1
- package/dist/ui/Picker.d.ts.map +1 -1
- package/dist/ui/Picker.js +5 -2
- package/dist/ui/Picker.js.map +1 -1
- package/dist/ui/Segmented.d.ts +24 -0
- package/dist/ui/Segmented.d.ts.map +1 -1
- package/dist/ui/Segmented.js +4 -27
- package/dist/ui/Segmented.js.map +1 -1
- package/dist/ui/SplitGroup.d.ts.map +1 -1
- package/dist/ui/SplitGroup.js +3 -2
- package/dist/ui/SplitGroup.js.map +1 -1
- package/dist/ui/Textarea.d.ts.map +1 -1
- package/dist/ui/Textarea.js +3 -2
- package/dist/ui/Textarea.js.map +1 -1
- package/dist/ui/controls/button-css.generated.d.ts +1 -1
- package/dist/ui/controls/button-css.generated.d.ts.map +1 -1
- package/dist/ui/controls/button-css.generated.js +1 -1
- package/dist/ui/controls/button-css.generated.js.map +1 -1
- package/dist/ui/controls/loader-bar-css.generated.d.ts +2 -0
- package/dist/ui/controls/loader-bar-css.generated.d.ts.map +1 -0
- package/dist/ui/controls/loader-bar-css.generated.js +4 -0
- package/dist/ui/controls/loader-bar-css.generated.js.map +1 -0
- package/dist/ui/controls/loader-css.generated.d.ts +2 -0
- package/dist/ui/controls/loader-css.generated.d.ts.map +1 -0
- package/dist/ui/controls/loader-css.generated.js +4 -0
- package/dist/ui/controls/loader-css.generated.js.map +1 -0
- package/dist/ui/controls/loading-css.generated.d.ts +1 -1
- package/dist/ui/controls/loading-css.generated.d.ts.map +1 -1
- package/dist/ui/controls/loading-css.generated.js +1 -1
- package/dist/ui/controls/loading-css.generated.js.map +1 -1
- package/dist/ui/controls-css.d.ts +2 -0
- package/dist/ui/controls-css.d.ts.map +1 -1
- package/dist/ui/controls-css.js +2 -0
- package/dist/ui/controls-css.js.map +1 -1
- package/dist/ui/css.d.ts +28 -5
- package/dist/ui/css.d.ts.map +1 -1
- package/dist/ui/css.js +31 -34
- package/dist/ui/css.js.map +1 -1
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +5 -2
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/loader-bar-art.d.ts +6 -0
- package/dist/ui/loader-bar-art.d.ts.map +1 -0
- package/dist/ui/loader-bar-art.js +6 -0
- package/dist/ui/loader-bar-art.js.map +1 -0
- package/dist/ui/loading-host.d.ts +5 -0
- package/dist/ui/loading-host.d.ts.map +1 -1
- package/dist/ui/loading-host.js +8 -0
- package/dist/ui/loading-host.js.map +1 -1
- package/docs/design/architecture.md +9 -5
- package/docs/design/structure.md +4 -2
- package/docs/design/style.md +50 -0
- package/docs/help/integration.doc.ts +2 -2
- package/docs/help/integration.md +2 -2
- package/docs/help/style.md +35 -0
- package/docs/help/ui.doc.ts +14 -3
- package/docs/help/ui.md +14 -3
- package/docs/requirements.md +20 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loading-host.js","sourceRoot":"","sources":["../../src/ui/loading-host.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,EAAE;AACF,oDAAoD;AACpD,6DAA6D;AAC7D,6CAA6C;AAC7C,2CAA2C;
|
|
1
|
+
{"version":3,"file":"loading-host.js","sourceRoot":"","sources":["../../src/ui/loading-host.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,EAAE;AACF,oDAAoD;AACpD,6DAA6D;AAC7D,6CAA6C;AAC7C,2CAA2C;AAG3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,8CAA8C;AAC9C,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAA;AAE1E,0CAA0C;AAC1C,MAAM,UAAU,gBAAgB,CAAI,MAAe;IACjD,MAAM,CAAC,GAAG,UAA2C,CAAA;IACrD,MAAM,QAAQ,GAAG,CAAC,CAAC,gBAAgB,CAAC,CAAA;IACpC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAA;IAC3C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAA;IACxB,CAAC,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAAA;IAC7B,OAAO,OAAO,CAAA;AAChB,CAAC;AAeD,qCAAqC;AACrC;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAyB;IAC3D,qBAAqB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IAC7C,OAAO,gDAAgD,QAAQ,EAAE,CAAA;AACnE,CAAC;AA6BD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAI/B,IAAI,GAAG,GAAG,CAAC,CAAA;IACX,IAAI,OAAO,GAA4B,IAAI,CAAA;IAC3C,OAAO;QACL,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO;QACtB,IAAI,CAAC,OAAuB;YAC1B,MAAM,EAAE,GAAG,EAAE,GAAG,CAAA;YAChB,OAAO,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,CAAA;YACzB,IAAI,MAAM,GAAG,KAAK,CAAA;YAClB,OAAO;gBACL,KAAK;oBACH,qCAAqC;oBACrC,IAAI,MAAM,IAAI,OAAO,EAAE,EAAE,KAAK,EAAE;wBAAE,OAAM;oBACxC,MAAM,GAAG,IAAI,CAAA;oBACb,OAAO,GAAG,IAAI,CAAA;gBAChB,CAAC;aACF,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -44,8 +44,11 @@ utils(谁都不依赖,谁都可以用)
|
|
|
44
44
|
插件启动 ──▶ setStyleKit(createStyleKit({ id }))
|
|
45
45
|
│
|
|
46
46
|
▼
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
用到的控件首次渲染 ──▶ 自注入自己那份 CSS(幂等)
|
|
48
|
+
│
|
|
49
|
+
▼
|
|
50
|
+
往 <head> 插/更新一个 <style id="{id}">
|
|
51
|
+
内容 = tokens 域 + 各「已用到」的控件域拼成的 CSS 文本
|
|
49
52
|
```
|
|
50
53
|
|
|
51
54
|
为什么必须运行时注入:DSH 客户端产物是 `window.__ModuleLoader__.load({ id, factory })` 的
|
|
@@ -107,7 +110,8 @@ dist/** 产物形态不变,仍由 createStyleKit 拼成一份
|
|
|
107
110
|
|
|
108
111
|
## 触发关系
|
|
109
112
|
|
|
110
|
-
- `setStyleKit()
|
|
111
|
-
-
|
|
112
|
-
|
|
113
|
+
- `setStyleKit()`:插件启动时调一次;不调则走默认 kit(多插件同页会互相覆盖,务必调)。
|
|
114
|
+
- 控件样式**按需**:各控件首次渲染时自注入自己那份 CSS(幂等),没用到的控件其 CSS 不进包。
|
|
115
|
+
`ensureControls()` 现只剩「登记 token」一件事,是可选预热而非必需步骤。
|
|
116
|
+
- 自注入无 `document` 时静默跳过(SSR / 单测不炸)。
|
|
113
117
|
- `showToast()` 无 `document` 时静默跳过。
|
package/docs/design/structure.md
CHANGED
|
@@ -41,8 +41,10 @@ dsh-plugin-core/
|
|
|
41
41
|
│ │ Checkbox / Segmented / Picker(下拉选择)/
|
|
42
42
|
│ │ DateTimePicker(日期时间:单值 / 时间段 × 精度到秒)
|
|
43
43
|
│ ├── 动作 ✅ Button / IconButton
|
|
44
|
-
│ ├── 反馈 ✅ Modal / Toast
|
|
45
|
-
│ │
|
|
44
|
+
│ ├── 反馈 ✅ Modal / Toast / Loader 家族(2026-10-30):
|
|
45
|
+
│ │ │ Loader(ring / blocks × 五档尺寸)、LoaderBar(胶囊不定进度);
|
|
46
|
+
│ │ │ 两者都只画图形,无背景无定位,背景与位置归调用方
|
|
47
|
+
│ │ └── Loading ✅ 旧复合浮层(贴右下角的 pill + 两种加载卡),保留、已标 deprecated
|
|
46
48
|
│ ├── 展示 ✅ Card / StripCard / Chip / MarqueeText /
|
|
47
49
|
│ │ SectionHead / FieldHint / LiveText / BackToTop
|
|
48
50
|
│ ├── 选择 ✅ WorkspacePicker(选工作区,自取宿主快照)
|
package/docs/design/style.md
CHANGED
|
@@ -17,6 +17,56 @@ What stays here is what you must honour when **changing styles in this repo**.
|
|
|
17
17
|
EN: The client bundle is a CJS closure loaded by `window.__ModuleLoader__.load`, so `import './x.css'` produces a
|
|
18
18
|
separate asset the kernel never loads — CSS must be injected at runtime as a TS string.
|
|
19
19
|
|
|
20
|
+
## 控件样式按需:每个控件只注入自己那份
|
|
21
|
+
|
|
22
|
+
> EN: Per-control styles: every control injects only its own
|
|
23
|
+
|
|
24
|
+
(2026-10-30 起)**注入是按控件的,不是一把全量**:每个控件在 render 里调
|
|
25
|
+
`ensureComponentStyles('<域>', <自己那份 CSS>)`(幂等,每次 render 调都安全),用不到的控件其 CSS
|
|
26
|
+
不进消费方的包 —— 实测只用 `Button` 时样式文本从 71.7 KB 降到 9.4 KB。
|
|
27
|
+
|
|
28
|
+
EN: Injection is per control, not one big blob. Each control calls `ensureComponentStyles('<domain>', <its own CSS>)`
|
|
29
|
+
during render (idempotent); CSS of controls you never use never reaches your bundle.
|
|
30
|
+
|
|
31
|
+
新增控件照做:import 自己那份 `*_CSS` 常量 + 在组件里调一次 `ensureComponentStyles`。
|
|
32
|
+
|
|
33
|
+
1. **不要顺手把别人的 CSS 一起传进去** —— 传了就退化成全量,包体省不下来。
|
|
34
|
+
2. **跨控件的修饰一律用更高特异性表达**(`.dshpc-split .dshpc-seg`),由提供上下文的那个控件
|
|
35
|
+
负责它自己那份;**绝不靠注入顺序** —— 顺序 = 控件首次渲染顺序,不固定。
|
|
36
|
+
有自检盯着:`test/css-contract.test.mjs` 禁止跨常量出现同名选择器(含 `@media` 内)。
|
|
37
|
+
3. **CSS 必须是 `export const X_CSS` 的字符串常量**(被显式引用的值):`package.json` 的
|
|
38
|
+
`sideEffects: false` 既不会误删它、又能让用不到的那份被摇掉。
|
|
39
|
+
**绝不能退回 `import './x.css'`** —— 那是副作用式导入,webpack 官方点名它会在 `sideEffects:false`
|
|
40
|
+
下被连样式一起摇掉(组件渲染出来没样式)。
|
|
41
|
+
|
|
42
|
+
EN: (1) never bundle someone else's CSS into your call; (2) express cross-control overrides with higher
|
|
43
|
+
specificity, never with injection order (order = first-render order, not fixed) — the contract test forbids
|
|
44
|
+
same-name selectors across constants; (3) keep CSS as exported string constants — never go back to
|
|
45
|
+
`import './x.css'`, which `sideEffects:false` would drop along with the styles.
|
|
46
|
+
|
|
47
|
+
### 为什么不用 `@layer` 分层(评估过,有意不做)
|
|
48
|
+
|
|
49
|
+
> EN: Why we deliberately do not use `@layer`
|
|
50
|
+
|
|
51
|
+
`@layer`(CSS Cascading and Inheritance L5,Baseline 2022-03)能让层序显式固定、不受注入时机影响,
|
|
52
|
+
听上去正好治「顺序不确定」。**但它在这里会适得其反**:
|
|
53
|
+
|
|
54
|
+
- **未分层样式压过任何层**:层级裁决优先于特异性。一旦把 dshpc 样式包进 `@layer dshpc`,
|
|
55
|
+
宿主任何**未分层的元素级重置**(`button { font-size: 14px }` 之类)就会反过来压过我们,
|
|
56
|
+
层内特异性再高也没用 ⇒ 控件被宿主皮肤吃掉。
|
|
57
|
+
- **不分层反而更稳**:现状下我们的 `.dshpc-btn`(0,1,0)靠特异性就能压过宿主的 `button`(0,0,1)。
|
|
58
|
+
|
|
59
|
+
所以「不分层」是**有意为之,不是遗漏**。真要分层,必须先把宿主的元素级样式摸清楚;而且只能整套一层
|
|
60
|
+
(`@layer dshpc`),**不能按组件拆层** —— 层间忽略特异性会直接打掉 `.dshpc-split .dshpc-seg` 这类
|
|
61
|
+
靠特异性生效的拼接定制。
|
|
62
|
+
|
|
63
|
+
EN: `@layer` would let layer order be explicit and immune to injection timing, but here it backfires:
|
|
64
|
+
unlayered styles beat anything inside a layer, and layer judgement precedes specificity. Wrapping our styles
|
|
65
|
+
in `@layer dshpc` would let the host's unlayered element resets (`button { font-size }`) override our rules no
|
|
66
|
+
matter how specific they are. Staying unlayered is deliberate — `.dshpc-btn` (0,1,0) already beats the host's
|
|
67
|
+
`button` (0,0,1) on specificity. If layering ever becomes necessary: one layer for the whole kit, never per
|
|
68
|
+
control.
|
|
69
|
+
|
|
20
70
|
## 交互态颜色(hover / active)
|
|
21
71
|
|
|
22
72
|
> EN: Interaction colors (hover / active)
|
|
@@ -4,11 +4,11 @@ import type { DocTopic } from '../design/doc-format.js'
|
|
|
4
4
|
const install = `pnpm add dsh-plugin-core`
|
|
5
5
|
const initStyle = `// 插件 client 入口
|
|
6
6
|
import { createStyleKit } from 'dsh-plugin-core/design'
|
|
7
|
-
import {
|
|
7
|
+
import { setStyleKit } from 'dsh-plugin-core/ui'
|
|
8
8
|
|
|
9
9
|
const kit = createStyleKit({ id: 'dsh-task-reminder-ui' })
|
|
10
10
|
setStyleKit(kit)
|
|
11
|
-
|
|
11
|
+
// 只需这一行:控件首次渲染时自注入自己那份 CSS,token 也一并登记。`
|
|
12
12
|
const useControl = `import { Button, Input, Picker, showToast } from 'dsh-plugin-core/ui'
|
|
13
13
|
|
|
14
14
|
h(Input, { value: name, onChange: setName, placeholder: '任务名', error: nameError })
|
package/docs/help/integration.md
CHANGED
|
@@ -47,11 +47,11 @@ pnpm add dsh-plugin-core
|
|
|
47
47
|
```ts id="integration-init-style"
|
|
48
48
|
// 插件 client 入口
|
|
49
49
|
import { createStyleKit } from 'dsh-plugin-core/design'
|
|
50
|
-
import {
|
|
50
|
+
import { setStyleKit } from 'dsh-plugin-core/ui'
|
|
51
51
|
|
|
52
52
|
const kit = createStyleKit({ id: 'dsh-task-reminder-ui' })
|
|
53
53
|
setStyleKit(kit)
|
|
54
|
-
|
|
54
|
+
// 只需这一行:控件首次渲染时自注入自己那份 CSS,token 也一并登记。
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
```tsx id="integration-use-control"
|
package/docs/help/style.md
CHANGED
|
@@ -78,3 +78,38 @@ or by grepping `tokens-css.ts`.
|
|
|
78
78
|
EN: Reskin by reassigning the same variables inside your own style domain (no fork needed). Add a domain with
|
|
79
79
|
`kit.registerStyle('widget', css)`; re-registering a domain overwrites it. The `tokens` domain always comes
|
|
80
80
|
first — core maintains that ordering. Skin lives in the caller’s domain; components only read tokens.
|
|
81
|
+
|
|
82
|
+
## 怎么应用:样式是按需的
|
|
83
|
+
|
|
84
|
+
> EN: How to apply it: styles are on demand
|
|
85
|
+
|
|
86
|
+
(2026-10-30 起)插件入口**只需 `setStyleKit` 一行**;控件首次渲染时自注入自己那份 CSS(幂等),
|
|
87
|
+
没用到的控件其 CSS 不进你的包。`ensureControls()` 现只登记 token,是**可选**预热,不必再调。
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { createStyleKit } from 'dsh-plugin-core/design'
|
|
91
|
+
import { setStyleKit } from 'dsh-plugin-core/ui'
|
|
92
|
+
|
|
93
|
+
setStyleKit(createStyleKit({ id: 'dsh-task-reminder-ui' }))
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
EN: Since 2026-10-30 the entry needs only `setStyleKit`; each control self-injects its own CSS on first render,
|
|
97
|
+
and CSS of controls you never use stays out of your bundle. `ensureControls()` now only registers tokens and is
|
|
98
|
+
optional.
|
|
99
|
+
|
|
100
|
+
## 避免什么
|
|
101
|
+
|
|
102
|
+
> EN: What to avoid
|
|
103
|
+
|
|
104
|
+
1. **不要 `import * as core from 'dsh-plugin-core/ui'` / `require('dsh-plugin-core/ui')`** —— 打包器无法摇树,
|
|
105
|
+
所有控件 CSS 全进你的包(实测差 62.3 KB)。一律**具名导入**。
|
|
106
|
+
2. **不要把多份 CSS 自己拼起来注册成一个域** —— 那等于重建全量注入,按需收益归零。
|
|
107
|
+
要加自己的皮肤,用 `kit.registerStyle('你的域', css)` 单独注册。
|
|
108
|
+
3. **不要写「靠注入顺序才对」的规则** —— 顺序 = 控件首次渲染顺序,不固定。
|
|
109
|
+
要覆盖就用更高特异性(多加一个类限定),跨来源的层次用 `@layer`。
|
|
110
|
+
4. **不要退回 `import './x.css'`** —— 客户端产物是 JS 闭包,`.css` 内核不加载;且在
|
|
111
|
+
`sideEffects: false` 下会被连样式一起摇掉。
|
|
112
|
+
|
|
113
|
+
EN: (1) Never namespace-import or `require` the barrel − it defeats tree-shaking (62.3 KB difference); use named
|
|
114
|
+
imports. (2) Do not concatenate several CSS constants into one domain − that rebuilds full injection. (3) Never
|
|
115
|
+
rely on injection order; override with higher specificity. (4) Never go back to `import './x.css'`.
|
package/docs/help/ui.doc.ts
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
import type { DocTopic } from '../design/doc-format.js'
|
|
3
3
|
|
|
4
4
|
const setup = `import { createStyleKit } from 'dsh-plugin-core/design'
|
|
5
|
-
import {
|
|
5
|
+
import { setStyleKit } from 'dsh-plugin-core/ui'
|
|
6
6
|
|
|
7
7
|
setStyleKit(createStyleKit({ id: 'dsh-task-reminder-ui' }))
|
|
8
|
-
|
|
8
|
+
// 控件样式不用你挂:每个控件首次渲染时自注入自己那份 CSS(幂等),
|
|
9
|
+
// 用不到的控件其 CSS 也不会进你的包。`
|
|
9
10
|
|
|
10
11
|
const cardExample = `import { Card, Chip, StripCard } from 'dsh-plugin-core/ui'
|
|
11
12
|
|
|
@@ -75,7 +76,7 @@ const doc: DocTopic = {
|
|
|
75
76
|
'Button', 'IconButton', 'Segmented', 'SplitGroup', 'Input', 'PrefixedInput', 'NumberInput', 'Textarea',
|
|
76
77
|
'Checkbox', 'fieldMetricsOf', 'Picker', 'WorkspacePicker', 'ModelPicker', 'DateTimePicker', 'Card', 'StripCard',
|
|
77
78
|
'Chip', 'Modal', 'FieldHint', 'setTooltipRenderer', 'showToast', 'notify', 'showHostToast',
|
|
78
|
-
'Loading', 'RunningBlocks', 'SectionHead', 'MarqueeText', 'LiveText',
|
|
79
|
+
'Loader', 'LoaderBar', 'Loading', 'RunningBlocks', 'SectionHead', 'MarqueeText', 'LiveText',
|
|
79
80
|
'BackToTop', 'startResizeLayoutWidth', 'PanelDock', 'createPanelDock', 'DockPanel',
|
|
80
81
|
'ensureControls', 'setStyleKit',
|
|
81
82
|
],
|
|
@@ -369,6 +370,14 @@ const doc: DocTopic = {
|
|
|
369
370
|
zh: '三条取舍(照用别改):① 样式取首个副本;② position 全局共享;③ 不做卸载回收。无 document 的环境静默跳过。',
|
|
370
371
|
en: 'Three trade-offs (accept them): ① styling comes from the first copy; ② position is shared per screen; ③ no unload reclamation. Environments without document skip silently.',
|
|
371
372
|
},
|
|
373
|
+
{
|
|
374
|
+
zh: '`Loader` 是通用加载**图标**:只画图标,不带背景、不带内距、不带定位 —— 胶囊 / 圆角面这类背景、按钮内 / 标签内 / 漂浮这类位置,全归调用方自己包。两轴正交:`variant`(`ring` 默认开口弧旋转 / `blocks` 三块脉动)× `size`(`xs` 12 / `sm` 16 / `md` 24 / `lg` 32 / `xl` 48),几何画在 24×24 viewBox 里随尺寸等比缩放,描边与方块的视觉重量各档一致。颜色走 `currentColor`,跟着所在文字自动变色。默认 `aria-hidden`(纯装饰,语义由旁边文字或外层 `role="status"` 承担);要它自己播报就传 `label`。新形态加在库里(枚举 + 一段 CSS),不要在插件里另造一套转圈。',
|
|
375
|
+
en: '`Loader` is the generic loading **icon**: it draws the icon and nothing else — no background, no padding, no positioning. Pills / rounded surfaces belong to you, and so does placement (inside a button, inside a tag, floating). Two orthogonal axes: `variant` (`ring` default — a rotating open arc / `blocks` — three pulsing squares) × `size` (`xs` 12 / `sm` 16 / `md` 24 / `lg` 32 / `xl` 48). The geometry lives in a 24×24 viewBox and scales proportionally, so stroke and square weights match across tiers. Colour is `currentColor`, inheriting the surrounding text. It is `aria-hidden` by default (pure decoration — semantics come from nearby text or an outer `role="status"`); pass `label` to have it announce itself. New variants go into the library (one enum value plus one CSS block), never a second spinner built in a plugin.',
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
zh: '同族还有一个**具象** loading,边界与 `Loader` 一样(只画图形,背景与定位归调用方):`LoaderBar` 是胶囊不定进度 —— 蓝色半截固定不动、只有它上面的细斜纹单向流动(0.55 秒走一个条纹周期),不表示任何百分比;尺寸档按**高度**给、宽固定 4:1。要停住(截图 / 打印)传 `animated={false}`。',
|
|
379
|
+
en: 'One **concrete** loader in the same family, with the same boundary as `Loader` (graphics only — background and placement belong to the caller): `LoaderBar` is a capsule indeterminate bar — the blue half stays put while the thin stripes on it flow in one direction (one stripe period every 0.55s), encoding no percentage; sizes set the **height**, width is a fixed 4:1. Pass `animated={false}` to freeze it (screenshots / print).',
|
|
380
|
+
},
|
|
372
381
|
{
|
|
373
382
|
zh: '加载提示两种样式:`LoadingToast` 横排卡(转圈在左、文字在右,灰底与 notify 的 info 卡同色)、`LoadingBlock` 方块卡(转圈在上、文字在下,内距更大)。默认文案走内置字典「数据加载中」/「Loading」,传 `text` 覆盖。',
|
|
374
383
|
en: 'Two loading styles: `LoadingToast` — a horizontal card (spinner left, text right, same grey as the notify info card) — and `LoadingBlock` — a square card (spinner above text, roomier padding). The default copy comes from the built-in dictionary (“数据加载中” / “Loading”); pass `text` to override.',
|
|
@@ -394,6 +403,8 @@ const doc: DocTopic = {
|
|
|
394
403
|
{ name: 'notify(message, opts?)', type: '', def: '', desc: { zh: '默认用这个。opts: `{ variant?, description?, durationMs?, position?, actions? }`,actions 用自带 Button(1–2 个)', en: 'Use this by default. opts `{ variant?, description?, durationMs?, position?, actions? }`, actions use our own Button (1–2)' } },
|
|
395
404
|
{ name: 'showHostToast(message, opts?)', type: '', def: '', desc: { zh: '宿主原生 Toast,走 `dsh-plugin-core/ui/host` 子路径。opts: `{ tone?, holdMs?, actions?, onDismiss? }`', en: 'Host-native Toast from the `dsh-plugin-core/ui/host` subpath. opts `{ tone?, holdMs?, actions?, onDismiss? }`' } },
|
|
396
405
|
{ name: 'showLoading(opts?)', type: '', def: '', desc: { zh: '全局加载提示(全局唯一一处),返回 `{ close() }`。opts: `{ text?, variant?: \'toast\' | \'block\', position?, mask?, maskOpacity?, translate? }`;position 默认 bottom-center', en: 'Global loading hint (one spot globally) returning `{ close() }`. opts `{ text?, variant?: \'toast\' | \'block\', position?, mask?, maskOpacity?, translate? }`; position defaults to bottom-center' } },
|
|
406
|
+
{ name: 'Loader({ variant?, size?, label?, className? })', type: '', def: '', desc: { zh: '通用加载图标:variant 两形态 × size 五档;无背景无定位,颜色走 currentColor', en: 'Generic loading icon: two variants × five sizes; no background or positioning, colour via currentColor' } },
|
|
407
|
+
{ name: 'LoaderBar({ size?, animated?, label?, className? })', type: '', def: '', desc: { zh: '胶囊不定进度:蓝色段固定、斜纹单向流动;尺寸按高度给,宽固定 4:1', en: 'Capsule indeterminate bar: the blue segment stays put while its stripes flow; sizes set height, width is a fixed 4:1' } },
|
|
397
408
|
{ name: 'LoadingToast({ text? })', type: '', def: '', desc: { zh: '就地渲染的横排加载卡(转圈在左)', en: 'In-place horizontal loading card (spinner left)' } },
|
|
398
409
|
{ name: 'LoadingBlock({ text? })', type: '', def: '', desc: { zh: '就地渲染的方块加载卡(转圈在上、文字在下)', en: 'In-place square loading card (spinner above text)' } },
|
|
399
410
|
{ name: 'Loading({ anchorId? })', type: '', def: '', desc: { zh: '贴到主内容容器右下角的加载指示;anchorId 默认 dshpc-main', en: 'Loading indicator pinned to the main container’s bottom-right; anchorId defaults to dshpc-main' } },
|
package/docs/help/ui.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
> EN: ui — base controls
|
|
6
6
|
|
|
7
|
-
导出:Button、IconButton、Segmented、SplitGroup、Input、PrefixedInput、NumberInput、Textarea、Checkbox、fieldMetricsOf、Picker、WorkspacePicker、ModelPicker、DateTimePicker、Card、StripCard、Chip、Modal、FieldHint、setTooltipRenderer、showToast、notify、showHostToast、Loading、RunningBlocks、SectionHead、MarqueeText、LiveText、BackToTop、startResizeLayoutWidth、PanelDock、createPanelDock、DockPanel、ensureControls、setStyleKit
|
|
7
|
+
导出:Button、IconButton、Segmented、SplitGroup、Input、PrefixedInput、NumberInput、Textarea、Checkbox、fieldMetricsOf、Picker、WorkspacePicker、ModelPicker、DateTimePicker、Card、StripCard、Chip、Modal、FieldHint、setTooltipRenderer、showToast、notify、showHostToast、Loader、LoaderBar、Loading、RunningBlocks、SectionHead、MarqueeText、LiveText、BackToTop、startResizeLayoutWidth、PanelDock、createPanelDock、DockPanel、ensureControls、setStyleKit
|
|
8
8
|
|
|
9
9
|
## 概览
|
|
10
10
|
|
|
@@ -24,10 +24,11 @@
|
|
|
24
24
|
|
|
25
25
|
```ts id="ui-setup"
|
|
26
26
|
import { createStyleKit } from 'dsh-plugin-core/design'
|
|
27
|
-
import {
|
|
27
|
+
import { setStyleKit } from 'dsh-plugin-core/ui'
|
|
28
28
|
|
|
29
29
|
setStyleKit(createStyleKit({ id: 'dsh-task-reminder-ui' }))
|
|
30
|
-
|
|
30
|
+
// 控件样式不用你挂:每个控件首次渲染时自注入自己那份 CSS(幂等),
|
|
31
|
+
// 用不到的控件其 CSS 也不会进你的包。
|
|
31
32
|
```
|
|
32
33
|
|
|
33
34
|
## Button / IconButton / Segmented
|
|
@@ -307,6 +308,14 @@ h(StripCard, {
|
|
|
307
308
|
|
|
308
309
|
> EN: Three trade-offs (accept them): ① styling comes from the first copy; ② position is shared per screen; ③ no unload reclamation. Environments without document skip silently.
|
|
309
310
|
|
|
311
|
+
`Loader` 是通用加载**图标**:只画图标,不带背景、不带内距、不带定位 —— 胶囊 / 圆角面这类背景、按钮内 / 标签内 / 漂浮这类位置,全归调用方自己包。两轴正交:`variant`(`ring` 默认开口弧旋转 / `blocks` 三块脉动)× `size`(`xs` 12 / `sm` 16 / `md` 24 / `lg` 32 / `xl` 48),几何画在 24×24 viewBox 里随尺寸等比缩放,描边与方块的视觉重量各档一致。颜色走 `currentColor`,跟着所在文字自动变色。默认 `aria-hidden`(纯装饰,语义由旁边文字或外层 `role="status"` 承担);要它自己播报就传 `label`。新形态加在库里(枚举 + 一段 CSS),不要在插件里另造一套转圈。
|
|
312
|
+
|
|
313
|
+
> EN: `Loader` is the generic loading **icon**: it draws the icon and nothing else — no background, no padding, no positioning. Pills / rounded surfaces belong to you, and so does placement (inside a button, inside a tag, floating). Two orthogonal axes: `variant` (`ring` default — a rotating open arc / `blocks` — three pulsing squares) × `size` (`xs` 12 / `sm` 16 / `md` 24 / `lg` 32 / `xl` 48). The geometry lives in a 24×24 viewBox and scales proportionally, so stroke and square weights match across tiers. Colour is `currentColor`, inheriting the surrounding text. It is `aria-hidden` by default (pure decoration — semantics come from nearby text or an outer `role="status"`); pass `label` to have it announce itself. New variants go into the library (one enum value plus one CSS block), never a second spinner built in a plugin.
|
|
314
|
+
|
|
315
|
+
同族还有一个**具象** loading,边界与 `Loader` 一样(只画图形,背景与定位归调用方):`LoaderBar` 是胶囊不定进度 —— 蓝色半截固定不动、只有它上面的细斜纹单向流动(0.55 秒走一个条纹周期),不表示任何百分比;尺寸档按**高度**给、宽固定 4:1。要停住(截图 / 打印)传 `animated={false}`。
|
|
316
|
+
|
|
317
|
+
> EN: One **concrete** loader in the same family, with the same boundary as `Loader` (graphics only — background and placement belong to the caller): `LoaderBar` is a capsule indeterminate bar — the blue half stays put while the thin stripes on it flow in one direction (one stripe period every 0.55s), encoding no percentage; sizes set the **height**, width is a fixed 4:1. Pass `animated={false}` to freeze it (screenshots / print).
|
|
318
|
+
|
|
310
319
|
加载提示两种样式:`LoadingToast` 横排卡(转圈在左、文字在右,灰底与 notify 的 info 卡同色)、`LoadingBlock` 方块卡(转圈在上、文字在下,内距更大)。默认文案走内置字典「数据加载中」/「Loading」,传 `text` 覆盖。
|
|
311
320
|
|
|
312
321
|
> EN: Two loading styles: `LoadingToast` — a horizontal card (spinner left, text right, same grey as the notify info card) — and `LoadingBlock` — a square card (spinner above text, roomier padding). The default copy comes from the built-in dictionary (“数据加载中” / “Loading”); pass `text` to override.
|
|
@@ -329,6 +338,8 @@ Modal 是自绘 overlay,不走 react-dom portal。
|
|
|
329
338
|
| `notify(message, opts?)` | `` | | 默认用这个。opts: `{ variant?, description?, durationMs?, position?, actions? }`,actions 用自带 Button(1–2 个) | Use this by default. opts `{ variant?, description?, durationMs?, position?, actions? }`, actions use our own Button (1–2) |
|
|
330
339
|
| `showHostToast(message, opts?)` | `` | | 宿主原生 Toast,走 `dsh-plugin-core/ui/host` 子路径。opts: `{ tone?, holdMs?, actions?, onDismiss? }` | Host-native Toast from the `dsh-plugin-core/ui/host` subpath. opts `{ tone?, holdMs?, actions?, onDismiss? }` |
|
|
331
340
|
| `showLoading(opts?)` | `` | | 全局加载提示(全局唯一一处),返回 `{ close() }`。opts: `{ text?, variant?: 'toast' \| 'block', position?, mask?, maskOpacity?, translate? }`;position 默认 bottom-center | Global loading hint (one spot globally) returning `{ close() }`. opts `{ text?, variant?: 'toast' \| 'block', position?, mask?, maskOpacity?, translate? }`; position defaults to bottom-center |
|
|
341
|
+
| `Loader({ variant?, size?, label?, className? })` | `` | | 通用加载图标:variant 两形态 × size 五档;无背景无定位,颜色走 currentColor | Generic loading icon: two variants × five sizes; no background or positioning, colour via currentColor |
|
|
342
|
+
| `LoaderBar({ size?, animated?, label?, className? })` | `` | | 胶囊不定进度:蓝色段固定、斜纹单向流动;尺寸按高度给,宽固定 4:1 | Capsule indeterminate bar: the blue segment stays put while its stripes flow; sizes set height, width is a fixed 4:1 |
|
|
332
343
|
| `LoadingToast({ text? })` | `` | | 就地渲染的横排加载卡(转圈在左) | In-place horizontal loading card (spinner left) |
|
|
333
344
|
| `LoadingBlock({ text? })` | `` | | 就地渲染的方块加载卡(转圈在上、文字在下) | In-place square loading card (spinner above text) |
|
|
334
345
|
| `Loading({ anchorId? })` | `` | | 贴到主内容容器右下角的加载指示;anchorId 默认 dshpc-main | Loading indicator pinned to the main container’s bottom-right; anchorId defaults to dshpc-main |
|
package/docs/requirements.md
CHANGED
|
@@ -52,7 +52,19 @@ dsh-plugin-core/
|
|
|
52
52
|
- 日期时间:`DateTimePicker`(2026-10-24 新增:单值 / 时间段 × 精度 day/hour/minute/second;
|
|
53
53
|
数据恒完整本地 ISO 到毫秒、**显示只到精度**;起始端 floor、结束端 ceil)
|
|
54
54
|
- 「统一某类元素」的控件:`SectionHead` 等
|
|
55
|
-
- 反馈件:`Modal` / `Loading` / `toast` / 空态
|
|
55
|
+
- 反馈件:`Modal` / `Loader` 家族 / `Loading` / `toast` / 空态
|
|
56
|
+
- Loader 家族按「一个前缀 + 具象名」命名(2026-10-30 用户定):`Loader`(通用图标)/
|
|
57
|
+
`LoaderBar`(胶囊不定进度)。两者的边界完全一致 —— **只画图形,不带背景、内距、定位**,
|
|
58
|
+
背景与位置归调用方;尺寸轴共用 `LoaderSize`。
|
|
59
|
+
- `LoaderWhale`(品牌鲸鱼)同日实现后又按用户要求**删除**(2026-10-30:动效与形态都不合适):
|
|
60
|
+
删掉的是源码、CSS、转录的路径数据与源素材 `鲸鱼.svg`,不要把鲸鱼图形再搬回来。
|
|
61
|
+
- `Loader`(2026-10-30 拍板新增):**通用加载图标**,只画图标 —— 无背景、无内距、无定位,
|
|
62
|
+
背景(胶囊 / 圆角面)与位置(按钮内 / 标签内 / 漂浮)归调用方。两轴正交:`variant`
|
|
63
|
+
(`ring` / `blocks`)× `size`(`xs` 12 / `sm` 16 / `md` 24 / `lg` 32 / `xl` 48),
|
|
64
|
+
几何画在 24×24 viewBox 内等比缩放;颜色走 `currentColor`;默认 `aria-hidden`,传 `label` 才播报。
|
|
65
|
+
新形态加在库里(枚举 + 一段 CSS),不在插件里另造转圈。Button 的 loading 与 `LoadingToast` /
|
|
66
|
+
`LoadingBlock` 的转圈改为复用它(环的画法与 keyframes 只剩 `controls/loader.css` 一份)。
|
|
67
|
+
- `Loading` 是旧的「自带定位 + 自带 pill 背景」复合件,**保留不删**但标 `@deprecated`,新代码用 `Loader`。
|
|
56
68
|
- 布局基础:`PanelDock` / `DockPanel` / `createPanelDock`(**可停靠分栏容器**:多面板并存、按组名寻址、拖拽拉栏、宽度记忆;2026-10-20 拍板用此名,替代早先的 `SidebarLayout` / `SplitPane`)。只做右侧;组名与窗口一对一;默认上限 3,超限拒绝新开;不做 tab 切换 / 自动淘汰 / 多份同名;**面板本身始终是布局成员,不做面板浮层**(2026-10-28 补:**收起** = 面板退出布局、另出右侧一只独立的 `position: fixed` 耳朵,点耳朵展开并还原宽度;关闭不留耳朵——耳朵是独立浮层,不是把面板变浮层)。**结构照成熟库口径写 children,`open/close` 只传 id,不把页面树塞进调用参数**
|
|
57
69
|
- **通用控件是纯零件,数据由调用方传入**;**领域选择器例外**(2026-10-20 用户拍板反转):
|
|
58
70
|
`ModelPicker` / `WorkspacePicker` 是「现成的包」,接线后**自己取数自己显示**,消费方不再拿数组传 props。
|
|
@@ -120,6 +132,12 @@ dsh-plugin-core/
|
|
|
120
132
|
|
|
121
133
|
⇒ 必须是 `createStyleKit({ id })`:每个插件调一次领一套自己的(`<style>` 标签 id 按插件唯一)。
|
|
122
134
|
|
|
135
|
+
**(2026-10-30)注入按控件粒度**:每个控件自注入自己那份 CSS(`ensureComponentStyles(domain, css)`,幂等),
|
|
136
|
+
**不许再聚合成一把全量**。全量聚合会让入口模块静态依赖所有 CSS,打包器无法摇树 —— 插件只用 Button 也会
|
|
137
|
+
背上全部 71.7 KB 样式文本。`ensureControls()` 因此收敛为「只登记 token」的可选预热。
|
|
138
|
+
配套约束:消费方须**具名导入**(`import * as` / CJS `require` 会让按需收益归零);跨控件修饰只许用
|
|
139
|
+
更高特异性表达,不许依赖注入顺序。
|
|
140
|
+
|
|
123
141
|
### 5.3 明暗色判据(别跟错)
|
|
124
142
|
|
|
125
143
|
- 判据 = **`body[data-ds-dark-theme]`**(宿主启动脚本 `toggleAttribute` 写入,
|
|
@@ -175,6 +193,7 @@ dsh-plugin-core/
|
|
|
175
193
|
| v2 | `explorer`(用户拍板要抽) | ✅ 已完成(浏览面板 + 预览;**选择器后移至 ui**,见 §2.4) |
|
|
176
194
|
| v2+ | `explorer` 重做(2026-10-20) | ✅ 已完成(FileBrowser 面板 + `openFilePreview` / `pickWorkspaceFile` 两能力 + 全量预览:md / 代码高亮 / HTML / PDF / Office;官方件经 `./ui/official` 子路径) |
|
|
177
195
|
| v3 | `session` | ⚠️ **半完成**:契约与三种承载已好,**官方会话 UI 镜像未搬**(只做最简渲染) |
|
|
196
|
+
| v3+ | 控件样式按需注入(2026-10-30) | ✅ 已完成(`css.ts` 停全量聚合;27 个组件各自注入自己那份;只 `import { Button }` 时 CSS 文本 71.7 KB → 9.4 KB。**不采用 `@layer`**:未分层样式压过任何层且层级裁决优先于特异性,包进层会被宿主元素级重置反压) |
|
|
178
197
|
| 文档 | README 接入指南 | ✅ 已完成 |
|
|
179
198
|
|
|
180
199
|
**未做**(按重要性):消费者插件接入 / 会话 UI 镜像 / 类名隔离 /
|
package/package.json
CHANGED