dsh-pocket 1.11.1 → 1.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/client/client.js CHANGED
@@ -209,16 +209,22 @@ function MobileNavOverlay({ toggleSidebar, t }) {
209
209
  document.addEventListener("click", onDrawerClick, true);
210
210
  return () => document.removeEventListener("click", onDrawerClick, true);
211
211
  }, [mobile, open, toggleSidebar]);
212
+ (0, import_react.useEffect)(() => {
213
+ if (!mobile || !open) return;
214
+ const onOutsideClick = (event) => {
215
+ if (document.querySelector('[aria-modal="true"]') !== null) return;
216
+ const target = event.target;
217
+ if (target === null) return;
218
+ if (target.closest('[data-mobile-nav="toggle"]') !== null) return;
219
+ const drawer = document.querySelector('[data-mobile-nav="frame"] > :first-child');
220
+ if (drawer !== null && drawer.contains(target)) return;
221
+ toggleSidebar();
222
+ };
223
+ document.addEventListener("click", onOutsideClick, true);
224
+ return () => document.removeEventListener("click", onOutsideClick, true);
225
+ }, [mobile, open, toggleSidebar]);
212
226
  if (!mobile) return null;
213
- return /* @__PURE__ */ React.createElement(React.Fragment, null, open && /* @__PURE__ */ React.createElement(
214
- "div",
215
- {
216
- "data-mobile-nav": "backdrop",
217
- role: "button",
218
- "aria-label": t("backdrop"),
219
- onClick: () => toggleSidebar()
220
- }
221
- ), fabVisible && !open && /* @__PURE__ */ React.createElement(
227
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, open && /* @__PURE__ */ React.createElement("div", { "data-mobile-nav": "backdrop" }), fabVisible && !open && /* @__PURE__ */ React.createElement(
222
228
  "button",
223
229
  {
224
230
  type: "button",
@@ -361,13 +367,16 @@ var MOBILE_CSS = `
361
367
  outline-offset: 2px;
362
368
  }
363
369
 
364
- /* Dimmed backdrop under the open drawer; above every column, below the drawer. */
370
+ /* Dimmed backdrop under the open drawer; above every column, below the drawer.
371
+ pointer-events: none \u2014\u2014 \u70B9\u51FB\u7A7F\u900F\uFF08issue #38\uFF09\uFF1Abackdrop \u53EA\u8D1F\u8D23\u89C6\u89C9\u538B\u6697\uFF0C
372
+ \u4E0D\u62A2\u70B9\u51FB\u3002\u5173\u95ED\u62BD\u5C49\u6539\u7531 MobileNavOverlay \u7684 document \u7EA7\u300C\u62BD\u5C49\u5916\u70B9\u51FB\u300D\u76D1\u542C\u5904\u7406
373
+ \uFF08\u7B49\u4EF7\u4E8E\u539F\u6765\u7684\u70B9\u51FB\u906E\u7F69\u5173\u95ED\uFF0C\u4E14\u62BD\u5C49\u5185\u70B9\u51FB\u4E0D\u518D\u88AB backdrop \u5403\u6389\uFF09\u3002 */
365
374
  [data-mobile-nav="backdrop"] {
366
375
  position: absolute;
367
376
  inset: 0;
368
377
  z-index: 30;
369
378
  background: rgba(0, 0, 0, .45);
370
- cursor: pointer;
379
+ pointer-events: none;
371
380
  animation: dsh-mobile-nav-fade .2s var(--ds-ease-in-out, ease-in-out);
372
381
  -webkit-tap-highlight-color: transparent;
373
382
  }
@@ -449,13 +458,21 @@ var MOBILE_CSS = `
449
458
  the viewport. A mere -100% leaves a sliver on screen; -105% (as used
450
459
  before) left 14px of the drawer plus a long 32px-blur shadow gradient
451
460
  visible along the left edge of the main UI. No box-shadow at all: the
452
- dimmed backdrop already separates drawer from content. */
461
+ dimmed backdrop already separates drawer from content.
462
+ Z-index note: the backdrop renders inside the shell's overlay layer
463
+ ([data-shell-overlay]), which forms its own stacking context. Third-party
464
+ plugins can force that layer up with !important (dsh-update-checker sets
465
+ it to 500), and when the layer outranks the drawer, the backdrop paints
466
+ ABOVE the drawer and swallows every tap \u2014 the drawer opens but no row
467
+ can be pressed (every tap just closes it). The drawer must therefore
468
+ outrank any such raise: 600 clears the known 500 while staying under the
469
+ fixed-position banners/toasts (z 9999) that float at the viewport level. */
453
470
  [data-mobile-nav="frame"] > :first-child {
454
471
  position: absolute !important;
455
472
  inset: 0 auto 0 0 !important;
456
473
  width: max-content !important;
457
474
  max-width: 92vw !important;
458
- z-index: 40 !important;
475
+ z-index: 600 !important;
459
476
  transform: translateX(-110%);
460
477
  transition: transform .28s var(--ds-ease-in-out, ease-in-out);
461
478
  background: var(--dsw-alias-bg-base, #ffffff);
@@ -128,16 +128,33 @@ export function MobileNavOverlay({ toggleSidebar, t }: MobileNavOverlayProps) {
128
128
  return () => document.removeEventListener('click', onDrawerClick, true)
129
129
  }, [mobile, open, toggleSidebar])
130
130
 
131
+ // Tap-outside closes the drawer (issue #38). The backdrop is now
132
+ // pointer-events: none (pure dimming layer that never steals clicks), so
133
+ // "tap the dimmed area to close" moves here: any click outside the drawer
134
+ // (and outside the header toggle) closes it, keeping the standard
135
+ // interaction while letting drawer contents receive clicks normally.
136
+ // Capture phase: the close happens before the content processes the tap
137
+ // (same first-tap-closes behaviour as before).
138
+ useEffect(() => {
139
+ if (!mobile || !open) return
140
+ const onOutsideClick = (event: MouseEvent) => {
141
+ if (document.querySelector('[aria-modal="true"]') !== null) return
142
+ const target = event.target as HTMLElement | null
143
+ if (target === null) return
144
+ if (target.closest('[data-mobile-nav="toggle"]') !== null) return
145
+ const drawer = document.querySelector<HTMLElement>('[data-mobile-nav="frame"] > :first-child')
146
+ if (drawer !== null && drawer.contains(target)) return
147
+ toggleSidebar()
148
+ }
149
+ document.addEventListener('click', onOutsideClick, true)
150
+ return () => document.removeEventListener('click', onOutsideClick, true)
151
+ }, [mobile, open, toggleSidebar])
152
+
131
153
  if (!mobile) return null
132
154
  return (
133
155
  <>
134
156
  {open && (
135
- <div
136
- data-mobile-nav="backdrop"
137
- role="button"
138
- aria-label={t('backdrop')}
139
- onClick={() => toggleSidebar()}
140
- />
157
+ <div data-mobile-nav="backdrop" />
141
158
  )}
142
159
  {fabVisible && !open && (
143
160
  <button
@@ -106,13 +106,16 @@ export const MOBILE_CSS = `
106
106
  outline-offset: 2px;
107
107
  }
108
108
 
109
- /* Dimmed backdrop under the open drawer; above every column, below the drawer. */
109
+ /* Dimmed backdrop under the open drawer; above every column, below the drawer.
110
+ pointer-events: none —— 点击穿透(issue #38):backdrop 只负责视觉压暗,
111
+ 不抢点击。关闭抽屉改由 MobileNavOverlay 的 document 级「抽屉外点击」监听处理
112
+ (等价于原来的点击遮罩关闭,且抽屉内点击不再被 backdrop 吃掉)。 */
110
113
  [data-mobile-nav="backdrop"] {
111
114
  position: absolute;
112
115
  inset: 0;
113
116
  z-index: 30;
114
117
  background: rgba(0, 0, 0, .45);
115
- cursor: pointer;
118
+ pointer-events: none;
116
119
  animation: dsh-mobile-nav-fade .2s var(--ds-ease-in-out, ease-in-out);
117
120
  -webkit-tap-highlight-color: transparent;
118
121
  }
@@ -194,13 +197,21 @@ export const MOBILE_CSS = `
194
197
  the viewport. A mere -100% leaves a sliver on screen; -105% (as used
195
198
  before) left 14px of the drawer plus a long 32px-blur shadow gradient
196
199
  visible along the left edge of the main UI. No box-shadow at all: the
197
- dimmed backdrop already separates drawer from content. */
200
+ dimmed backdrop already separates drawer from content.
201
+ Z-index note: the backdrop renders inside the shell's overlay layer
202
+ ([data-shell-overlay]), which forms its own stacking context. Third-party
203
+ plugins can force that layer up with !important (dsh-update-checker sets
204
+ it to 500), and when the layer outranks the drawer, the backdrop paints
205
+ ABOVE the drawer and swallows every tap — the drawer opens but no row
206
+ can be pressed (every tap just closes it). The drawer must therefore
207
+ outrank any such raise: 600 clears the known 500 while staying under the
208
+ fixed-position banners/toasts (z 9999) that float at the viewport level. */
198
209
  [data-mobile-nav="frame"] > :first-child {
199
210
  position: absolute !important;
200
211
  inset: 0 auto 0 0 !important;
201
212
  width: max-content !important;
202
213
  max-width: 92vw !important;
203
- z-index: 40 !important;
214
+ z-index: 600 !important;
204
215
  transform: translateX(-110%);
205
216
  transition: transform .28s var(--ds-ease-in-out, ease-in-out);
206
217
  background: var(--dsw-alias-bg-base, #ffffff);
package/package.json CHANGED
@@ -76,5 +76,5 @@
76
76
  "access": "public",
77
77
  "registry": "https://registry.npmjs.org/"
78
78
  },
79
- "version": "1.11.1"
79
+ "version": "1.11.3"
80
80
  }