@sparkelf/dsh-patch-composer-popover-boundaries 0.2.0-rc.2 → 0.2.0-rc.20
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/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"file": "./patches/composer-popover-boundaries.patch",
|
|
9
9
|
"id": "composer-popover-center-boundaries",
|
|
10
10
|
"target": {
|
|
11
|
-
"baseRevision": "
|
|
11
|
+
"baseRevision": "ddefc45fbc7f8e46dd73185e68295696d1297887",
|
|
12
12
|
"kind": "dsh-source",
|
|
13
13
|
"paths": [
|
|
14
14
|
"apps/web/tests/",
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"url": "git+https://github.com/SparkElf/deepseek-harness-plus.git"
|
|
36
36
|
},
|
|
37
37
|
"type": "module",
|
|
38
|
-
"version": "0.2.0-rc.
|
|
38
|
+
"version": "0.2.0-rc.20"
|
|
39
39
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
diff --git a/apps/web/tests/access-confirmation.e2e.ts b/apps/web/tests/access-confirmation.e2e.ts
|
|
2
|
-
index
|
|
2
|
+
index 2b2ba0e..bd61e45 100644
|
|
3
3
|
--- a/apps/web/tests/access-confirmation.e2e.ts
|
|
4
4
|
+++ b/apps/web/tests/access-confirmation.e2e.ts
|
|
5
|
-
@@ -
|
|
5
|
+
@@ -150,6 +150,12 @@ describe('web e2e: experimental Auto and Full access confirmation', () => {
|
|
6
6
|
expect(await access.getAttribute('aria-label')).toBe('访问模式,当前:工作区内修改')
|
|
7
7
|
|
|
8
8
|
await access.click()
|
|
@@ -16,7 +16,7 @@ index cd64d98110..f513b1114a 100644
|
|
|
16
16
|
const dialog = page.getByRole('dialog', { name: '确认启用完全权限?' })
|
|
17
17
|
await dialog.waitFor({ timeout: 10_000 })
|
|
18
18
|
diff --git a/apps/web/tests/default-model.e2e.ts b/apps/web/tests/default-model.e2e.ts
|
|
19
|
-
index
|
|
19
|
+
index 304bdb9..0e820ee 100644
|
|
20
20
|
--- a/apps/web/tests/default-model.e2e.ts
|
|
21
21
|
+++ b/apps/web/tests/default-model.e2e.ts
|
|
22
22
|
@@ -105,6 +105,12 @@ describe('web e2e: the composer model switch is the default for later sessions',
|
|
@@ -32,44 +32,11 @@ index 304bdb97f6..0e820ee757 100644
|
|
|
32
32
|
await page.getByRole('menuitem', { name: /模型/ }).click()
|
|
33
33
|
await page.getByRole('menuitemradio', { name: 'Acme Large' }).click()
|
|
34
34
|
|
|
35
|
-
diff --git a/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx b/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx
|
|
36
|
-
index 1736fd8..efd2496 100644
|
|
37
|
-
--- a/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx
|
|
38
|
-
+++ b/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx
|
|
39
|
-
@@ -1,4 +1,4 @@
|
|
40
|
-
-import { useEffect, useState } from 'react'
|
|
41
|
-
+import { useEffect, useRef, useState } from 'react'
|
|
42
|
-
import type { ReactNode } from 'react'
|
|
43
|
-
import clsx from 'clsx'
|
|
44
|
-
import {
|
|
45
|
-
@@ -100,6 +100,8 @@ export function PermissionSelect({
|
|
46
|
-
const catalog = usePermissionCatalog(state => state.value)
|
|
47
|
-
const [pick, setPick] = useState<string | null>(null)
|
|
48
|
-
const [open, setOpen] = useState(false)
|
|
49
|
-
+ const triggerRef = useRef<HTMLButtonElement | null>(null)
|
|
50
|
-
+ const boundaryRef = useRef<HTMLElement | null>(null)
|
|
51
|
-
const [confirmation, setConfirmation] = useState<string | null>(null)
|
|
52
|
-
const [acknowledged, setAcknowledged] = useState(false)
|
|
53
|
-
|
|
54
|
-
@@ -192,8 +194,13 @@ export function PermissionSelect({
|
|
55
|
-
onClose={() => { setOpen(false) }}
|
|
56
|
-
side="top"
|
|
57
|
-
portal
|
|
58
|
-
+ boundaryRef={boundaryRef}
|
|
59
|
-
anchor={
|
|
60
|
-
<button
|
|
61
|
-
+ ref={(node) => {
|
|
62
|
-
+ triggerRef.current = node
|
|
63
|
-
+ boundaryRef.current = node?.closest<HTMLElement>('[data-dsh-center-col]') ?? null
|
|
64
|
-
+ }}
|
|
65
|
-
type="button"
|
|
66
|
-
className={css.trigger}
|
|
67
|
-
aria-label={t('mode', { name: currentAccessibleLabel })}
|
|
68
35
|
diff --git a/packages/client/ui-layout/README.md b/packages/client/ui-layout/README.md
|
|
69
|
-
index
|
|
36
|
+
index 582c5fb..bc4dc41 100644
|
|
70
37
|
--- a/packages/client/ui-layout/README.md
|
|
71
38
|
+++ b/packages/client/ui-layout/README.md
|
|
72
|
-
@@ -
|
|
39
|
+
@@ -45,7 +45,7 @@ The presenter consumes resolved theme snapshots and projects them onto the docum
|
|
73
40
|
|
|
74
41
|
`selectPanel(id)` checks the live `main` registry before changing selection; an absent key throws and leaves the current panel intact. `beginNavigation()` returns an abort signal for an asynchronous UI navigation. A later call, a valid panel selection (including repeated selection), or layout disposal aborts that signal without cancelling underlying Session creation. Consumers check the signal before committing navigation or moving drafts.
|
|
75
42
|
|
|
@@ -79,7 +46,7 @@ index 4fe19fb9ec..976a4dad8c 100644
|
|
|
79
46
|
</details>
|
|
80
47
|
|
|
81
48
|
diff --git a/packages/client/ui-layout/src/client/AppFrame.tsx b/packages/client/ui-layout/src/client/AppFrame.tsx
|
|
82
|
-
index
|
|
49
|
+
index 323318f..86a33a3 100644
|
|
83
50
|
--- a/packages/client/ui-layout/src/client/AppFrame.tsx
|
|
84
51
|
+++ b/packages/client/ui-layout/src/client/AppFrame.tsx
|
|
85
52
|
@@ -33,7 +33,7 @@ export type AppFrameProps =
|
|
@@ -92,7 +59,7 @@ index 05bb4b9494..c156255193 100644
|
|
|
92
59
|
|
|
93
60
|
/** Subscribe to the main key without subscribing the column frame to each panel id. */
|
|
94
61
|
diff --git a/packages/client/ui-model-selection/src/client/ModelSelect.module.css b/packages/client/ui-model-selection/src/client/ModelSelect.module.css
|
|
95
|
-
index
|
|
62
|
+
index b2cb715..968d000 100644
|
|
96
63
|
--- a/packages/client/ui-model-selection/src/client/ModelSelect.module.css
|
|
97
64
|
+++ b/packages/client/ui-model-selection/src/client/ModelSelect.module.css
|
|
98
65
|
@@ -104,7 +104,9 @@
|
|
@@ -107,10 +74,10 @@ index b2cb715287..968d000bc5 100644
|
|
|
107
74
|
min-width: min(240px, calc(100vw - 32px));
|
|
108
75
|
max-width: min(420px, calc(100vw - 32px));
|
|
109
76
|
diff --git a/packages/client/ui-model-selection/src/client/ModelSelect.tsx b/packages/client/ui-model-selection/src/client/ModelSelect.tsx
|
|
110
|
-
index
|
|
77
|
+
index b5a55f5..7252e44 100644
|
|
111
78
|
--- a/packages/client/ui-model-selection/src/client/ModelSelect.tsx
|
|
112
79
|
+++ b/packages/client/ui-model-selection/src/client/ModelSelect.tsx
|
|
113
|
-
@@ -
|
|
80
|
+
@@ -167,13 +167,22 @@ export function ModelSelect(
|
|
114
81
|
const rect = triggerRef.current?.getBoundingClientRect()
|
|
115
82
|
if (rect === undefined) return
|
|
116
83
|
const MARGIN = 12
|
|
@@ -137,10 +104,10 @@ index e9fc0195ef..637ecb5601 100644
|
|
|
137
104
|
// First run measures the hidden pre-render (same commit as `open`), so
|
|
138
105
|
// the card lands placed before anything paints.
|
|
139
106
|
diff --git a/packages/client/ui-model-selection/tests/model-select.client.spec.tsx b/packages/client/ui-model-selection/tests/model-select.client.spec.tsx
|
|
140
|
-
index
|
|
107
|
+
index 4a5ee43..a70e88d 100644
|
|
141
108
|
--- a/packages/client/ui-model-selection/tests/model-select.client.spec.tsx
|
|
142
109
|
+++ b/packages/client/ui-model-selection/tests/model-select.client.spec.tsx
|
|
143
|
-
@@ -
|
|
110
|
+
@@ -213,23 +213,28 @@ describe('ModelSelect reasoning effort', () => {
|
|
144
111
|
Object.defineProperty(HTMLElement.prototype, 'offsetWidth', { configurable: true, get: () => 200 })
|
|
145
112
|
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { configurable: true, get: () => 300 })
|
|
146
113
|
try {
|
|
@@ -150,7 +117,7 @@ index 3b8c92d8bf..53b1f03c39 100644
|
|
|
150
117
|
available
|
|
151
118
|
directory={createSnapshotStore(state())}
|
|
152
119
|
load={vi.fn()}
|
|
153
|
-
select={vi.fn().mockResolvedValue(true)}
|
|
120
|
+
select={vi.fn().mockResolvedValue({ ok: true, value: undefined })}
|
|
154
121
|
t={t}
|
|
155
122
|
- />)
|
|
156
123
|
+ /></div>)
|
|
@@ -174,34 +141,67 @@ index 3b8c92d8bf..53b1f03c39 100644
|
|
|
174
141
|
expect(menu.style.top).toBe('12px')
|
|
175
142
|
// Interactions inside the trigger subtree or the portaled card stay open.
|
|
176
143
|
fireEvent.mouseDown(menu)
|
|
144
|
+
diff --git a/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx b/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx
|
|
145
|
+
index 1736fd8..efd2496 100644
|
|
146
|
+
--- a/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx
|
|
147
|
+
+++ b/packages/client/ui-permission-presets/src/client/PermissionSelect.tsx
|
|
148
|
+
@@ -1,4 +1,4 @@
|
|
149
|
+
-import { useEffect, useState } from 'react'
|
|
150
|
+
+import { useEffect, useRef, useState } from 'react'
|
|
151
|
+
import type { ReactNode } from 'react'
|
|
152
|
+
import clsx from 'clsx'
|
|
153
|
+
import {
|
|
154
|
+
@@ -100,6 +100,8 @@ export function PermissionSelect({
|
|
155
|
+
const catalog = usePermissionCatalog(state => state.value)
|
|
156
|
+
const [pick, setPick] = useState<string | null>(null)
|
|
157
|
+
const [open, setOpen] = useState(false)
|
|
158
|
+
+ const triggerRef = useRef<HTMLButtonElement | null>(null)
|
|
159
|
+
+ const boundaryRef = useRef<HTMLElement | null>(null)
|
|
160
|
+
const [confirmation, setConfirmation] = useState<string | null>(null)
|
|
161
|
+
const [acknowledged, setAcknowledged] = useState(false)
|
|
162
|
+
|
|
163
|
+
@@ -192,8 +194,13 @@ export function PermissionSelect({
|
|
164
|
+
onClose={() => { setOpen(false) }}
|
|
165
|
+
side="top"
|
|
166
|
+
portal
|
|
167
|
+
+ boundaryRef={boundaryRef}
|
|
168
|
+
anchor={
|
|
169
|
+
<button
|
|
170
|
+
+ ref={(node) => {
|
|
171
|
+
+ triggerRef.current = node
|
|
172
|
+
+ boundaryRef.current = node?.closest<HTMLElement>('[data-dsh-center-col]') ?? null
|
|
173
|
+
+ }}
|
|
174
|
+
type="button"
|
|
175
|
+
className={css.trigger}
|
|
176
|
+
aria-label={t('mode', { name: currentAccessibleLabel })}
|
|
177
177
|
diff --git a/packages/client/ui-primitives/README.md b/packages/client/ui-primitives/README.md
|
|
178
|
-
index
|
|
178
|
+
index cefa67e..915e570 100644
|
|
179
179
|
--- a/packages/client/ui-primitives/README.md
|
|
180
180
|
+++ b/packages/client/ui-primitives/README.md
|
|
181
|
-
@@ -
|
|
182
|
-
| `Button` | Clickable action; `variant` selects `primary`, `ghost`, `outline`, or `toolbar`. |
|
|
181
|
+
@@ -40,7 +40,7 @@ Check this table before writing a control in a feature package. A plugin cannot
|
|
183
182
|
| `Switch` | Two-state toggle, 36×20. `label` is required, so the control cannot ship unnamed. |
|
|
183
|
+
| `Checkbox` | Labeled native checkbox with controlled state, keyboard interaction, and disabled styling; the caller supplies localized `label` text. |
|
|
184
184
|
| `Input` | Single-line text entry for search boxes and inline forms. |
|
|
185
|
-
-| `Menu` | Dropdown of items, separators, and group labels, with nested submenus. |
|
|
186
|
-
+| `Menu` | Dropdown of items, separators, and group labels, with nested submenus;
|
|
185
|
+
-| `Menu` | Dropdown of items, separators, and group labels, with nested submenus. While open, ↑/↓ (with Home and End) walk the list, Tab settles the focused row, and Escape or Shift+Tab close back to the anchor; selecting a row also returns the keyboard to the anchor unless the owner moved it itself. Only a keyboard on the anchor or inside the list is intercepted, and `autoFocus` decides solely whether opening focuses the first row. |
|
|
186
|
+
+| `Menu` | Dropdown of items, separators, and group labels, with nested submenus. While open, ↑/↓ (with Home and End) walk the list, Tab settles the focused row, and Escape or Shift+Tab close back to the anchor; selecting a row also returns the keyboard to the anchor unless the owner moved it itself. Only a keyboard on the anchor or inside the list is intercepted, and `autoFocus` decides solely whether opening focuses the first row. Portaled menus may intersect viewport clamping with an owner boundary. |
|
|
187
187
|
| `Pill` | Selectable capsule button for view switchers and filters; takes `active` and `onClick`. |
|
|
188
188
|
| `Tag` | Read-only capsule badge; `tone` selects one of eight palettes. |
|
|
189
189
|
| `StateDot` | Status mark: `done`, `warning`, `ongoing`, `error`, or `idle`. `aria-hidden`, so the render site owns the name. |
|
|
190
190
|
diff --git a/packages/client/ui-primitives/README.zh.md b/packages/client/ui-primitives/README.zh.md
|
|
191
|
-
index
|
|
191
|
+
index 3c069d0..39eeb5f 100644
|
|
192
192
|
--- a/packages/client/ui-primitives/README.zh.md
|
|
193
193
|
+++ b/packages/client/ui-primitives/README.zh.md
|
|
194
|
-
@@ -
|
|
195
|
-
| `Button` | 可点击操作;`variant` 选择 `primary`、`ghost`、`outline` 或 `toolbar`。 |
|
|
194
|
+
@@ -40,7 +40,7 @@ kind: "package-library"
|
|
196
195
|
| `Switch` | 36×20 的双态开关。`label` 必填,控件不可能在没有名称的情况下发布。 |
|
|
196
|
+
| `Checkbox` | 带标签的原生复选框,支持受控状态、键盘交互和禁用样式;调用方提供本地化的 `label` 文本。 |
|
|
197
197
|
| `Input` | 单行文本输入,用于搜索框与行内表单。 |
|
|
198
|
-
-| `Menu` |
|
|
199
|
-
+| `Menu` |
|
|
198
|
+
-| `Menu` | 由条目、分隔线与分组标题构成的下拉菜单,支持嵌套子菜单。打开期间 `↑`/`↓`(以及 Home、End)在列表中走位,Tab 选定聚焦行,Escape 或 Shift+Tab 关闭并把焦点还给锚点;选定一行同样把键盘还给锚点——除非拥有者自己移动了焦点。只拦截位于锚点或列表内的键盘,`autoFocus` 仅决定打开时是否聚焦首行。 |
|
|
199
|
+
+| `Menu` | 由条目、分隔线与分组标题构成的下拉菜单,支持嵌套子菜单。打开期间 `↑`/`↓`(以及 Home、End)在列表中走位,Tab 选定聚焦行,Escape 或 Shift+Tab 关闭并把焦点还给锚点;选定一行同样把键盘还给锚点——除非拥有者自己移动了焦点。只拦截位于锚点或列表内的键盘,`autoFocus` 仅决定打开时是否聚焦首行。portal菜单可将视口clamp与owner boundary取交集。 |
|
|
200
200
|
| `Pill` | 可选中的胶囊按钮,用于视图切换与筛选器;接受 `active` 与 `onClick`。 |
|
|
201
201
|
| `Tag` | 只读胶囊徽章;`tone` 选择八种配色之一。 |
|
|
202
202
|
| `StateDot` | 状态标记:`done`、`warning`、`ongoing`、`error` 或 `idle`。它是 `aria-hidden` 的,名称由渲染点提供。 |
|
|
203
203
|
diff --git a/packages/client/ui-primitives/src/Menu.tsx b/packages/client/ui-primitives/src/Menu.tsx
|
|
204
|
-
index
|
|
204
|
+
index bb04912..1e1e1c7 100644
|
|
205
205
|
--- a/packages/client/ui-primitives/src/Menu.tsx
|
|
206
206
|
+++ b/packages/client/ui-primitives/src/Menu.tsx
|
|
207
207
|
@@ -1,5 +1,5 @@
|
|
@@ -211,7 +211,7 @@ index db8b5588fe..cff56df8dc 100644
|
|
|
211
211
|
import { createPortal } from 'react-dom'
|
|
212
212
|
import clsx from 'clsx'
|
|
213
213
|
import { IconCheckOutline16 } from './icons/index.tsx'
|
|
214
|
-
@@ -
|
|
214
|
+
@@ -75,6 +75,7 @@ const MEASURE_STYLE: CSSProperties = { visibility: 'hidden', left: 0, top: 0 }
|
|
215
215
|
* gap and a brief overshoot survivable; coming back cancels the close.
|
|
216
216
|
* @param props.dense - reduce vertical row spacing without changing the standard typography or card width.
|
|
217
217
|
* @param props.compact - use reduced menu typography and spacing.
|
|
@@ -219,7 +219,7 @@ index db8b5588fe..cff56df8dc 100644
|
|
|
219
219
|
* @param props.getAnchorRect - portal mode only: supply the anchor rect
|
|
220
220
|
* directly (e.g. from a host-owned trigger button) instead of measuring the
|
|
221
221
|
* Menu's own wrapper span. Required when the wrapper isn't itself laid out at
|
|
222
|
-
@@ -
|
|
222
|
+
@@ -89,7 +90,7 @@ const MEASURE_STYLE: CSSProperties = { visibility: 'hidden', left: 0, top: 0 }
|
|
223
223
|
* crowds the cell).
|
|
224
224
|
* @returns anchor wrapper with the conditional list.
|
|
225
225
|
*/
|
|
@@ -228,7 +228,7 @@ index db8b5588fe..cff56df8dc 100644
|
|
|
228
228
|
open: boolean
|
|
229
229
|
autoFocus?: boolean
|
|
230
230
|
anchor: ReactNode
|
|
231
|
-
@@ -
|
|
231
|
+
@@ -107,6 +108,7 @@ export function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, o
|
|
232
232
|
compact?: boolean
|
|
233
233
|
selection?: 'check' | 'fill'
|
|
234
234
|
getAnchorRect?: () => DOMRect | null
|
|
@@ -236,7 +236,7 @@ index db8b5588fe..cff56df8dc 100644
|
|
|
236
236
|
className?: string | undefined
|
|
237
237
|
}) {
|
|
238
238
|
const rootRef = useRef<HTMLSpanElement>(null)
|
|
239
|
-
@@ -
|
|
239
|
+
@@ -174,8 +176,13 @@ export function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, o
|
|
240
240
|
const MARGIN = 12
|
|
241
241
|
const vw = window.innerWidth
|
|
242
242
|
const vh = window.innerHeight
|
|
@@ -250,7 +250,7 @@ index db8b5588fe..cff56df8dc 100644
|
|
|
250
250
|
const lh = listEl?.offsetHeight ?? 0
|
|
251
251
|
|
|
252
252
|
let x: number
|
|
253
|
-
@@ -
|
|
253
|
+
@@ -187,14 +194,18 @@ export function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, o
|
|
254
254
|
x = r.left
|
|
255
255
|
y = side === 'bottom' ? r.bottom + 4 : r.top - lh - 4
|
|
256
256
|
} else {
|
|
@@ -272,20 +272,20 @@ index db8b5588fe..cff56df8dc 100644
|
|
|
272
272
|
}
|
|
273
273
|
// First run measures the hidden pre-render (same commit as `open`), so
|
|
274
274
|
// end/top alignment and clamping use real dimensions before anything
|
|
275
|
-
@@ -
|
|
275
|
+
@@ -206,7 +217,7 @@ export function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, o
|
|
276
276
|
window.removeEventListener('scroll', place, true)
|
|
277
277
|
window.removeEventListener('resize', place)
|
|
278
278
|
}
|
|
279
279
|
- }, [open, portal, align, side, getAnchorRect])
|
|
280
280
|
+ }, [open, portal, align, side, getAnchorRect, boundaryRef])
|
|
281
281
|
|
|
282
|
-
|
|
283
|
-
|
|
282
|
+
// Opening remembers where the keyboard was, so closing can hand it back to
|
|
283
|
+
// that control — an anchor wrapping several (a split button) cannot be asked
|
|
284
284
|
diff --git a/packages/client/ui-primitives/tests/atoms.client.spec.tsx b/packages/client/ui-primitives/tests/atoms.client.spec.tsx
|
|
285
|
-
index
|
|
285
|
+
index a2f6b70..458c825 100644
|
|
286
286
|
--- a/packages/client/ui-primitives/tests/atoms.client.spec.tsx
|
|
287
287
|
+++ b/packages/client/ui-primitives/tests/atoms.client.spec.tsx
|
|
288
|
-
@@ -
|
|
288
|
+
@@ -416,6 +416,32 @@ describe('Menu', () => {
|
|
289
289
|
expect(menu.style.top).toBe('132px')
|
|
290
290
|
})
|
|
291
291
|
|