dsh-width-tiers 2.0.1 → 2.0.2
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 +7 -4
- package/README.zh.md +7 -3
- package/lib/client.js +45 -8
- package/locale/de.json +6 -0
- package/locale/en.json +6 -0
- package/locale/es.json +6 -0
- package/locale/fr.json +6 -0
- package/locale/ja.json +6 -0
- package/locale/pt.json +6 -0
- package/locale/ru.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -28,14 +28,15 @@
|
|
|
28
28
|
Fixed and custom widths are clamped by the app to
|
|
29
29
|
`max(640px, column − 176px)`; the standard tier follows the app default
|
|
30
30
|
(680–920px). On a narrow window a wider fixed tier therefore behaves like
|
|
31
|
-
`full
|
|
31
|
+
`full`, and the menu shows the reachable maximum for fixed tiers (1280px
|
|
32
|
+
reads 640px on an 800px column).
|
|
32
33
|
|
|
33
34
|
## Features
|
|
34
35
|
|
|
35
36
|
- Uses the app's native width axis (`--dsh-chat-user-width` and
|
|
36
37
|
`dsh.conversation.contentWidth`), so the built-in drag handles keep working.
|
|
37
38
|
- Persists the selected tier and restores it on the next visit.
|
|
38
|
-
- Follows **Settings → Language** (中文 / English / 日本語 / Español / Français / Deutsch / Русский / Português).
|
|
39
|
+
- Follows **Settings → Language** (中文 / English / 日本語 / Español / Français / Deutsch / Русский / Português), including the Settings plugin card's title and summary (`locale/<lang>.json`).
|
|
39
40
|
- Menu supports ArrowUp/Down, Home/End, Escape and Tab, with focus restoration.
|
|
40
41
|
- Tier changes sync across tabs.
|
|
41
42
|
- Respects `prefers-reduced-motion`.
|
|
@@ -86,8 +87,10 @@ dsh plugin --profile web add link:/path/to/dsh-width-tiers
|
|
|
86
87
|
## Compatibility
|
|
87
88
|
|
|
88
89
|
- DSH Web 0.2.x with a `web` profile (`shell.overlay` slot and `slots` service).
|
|
89
|
-
- Width axis checked against DSH 0.2.
|
|
90
|
-
`--dsh-chat-*` variables, `data-width-handle`, layout/locale services.
|
|
90
|
+
- Width axis checked against DSH 0.2.2-alpha.3: 640px floor, 176px handle
|
|
91
|
+
budget, `--dsh-chat-*` variables, `data-width-handle`, layout/locale services.
|
|
92
|
+
- Narrow screens: the picker hides while alpha.3's sidebar drawer
|
|
93
|
+
(`data-sidebar-drawer`) is open and follows the on-screen keyboard.
|
|
91
94
|
|
|
92
95
|
## Development
|
|
93
96
|
|
package/README.zh.md
CHANGED
|
@@ -26,14 +26,16 @@
|
|
|
26
26
|
| 自定义 | 原生拖拽记录的宽度 | 不动 |
|
|
27
27
|
|
|
28
28
|
固定档和自定义宽度会被应用钳制到 `max(640px, 列宽 − 176px)`;标准档
|
|
29
|
-
使用应用默认的 680–920px
|
|
29
|
+
使用应用默认的 680–920px。窄窗口下较宽的固定档等同「全宽」,菜单中的
|
|
30
|
+
固定档数值也按可达上限显示(例如 800px 列宽下「宽」显示 640px)。
|
|
30
31
|
|
|
31
32
|
## 特性
|
|
32
33
|
|
|
33
34
|
- 走应用原生宽度通道(`--dsh-chat-user-width` 与
|
|
34
35
|
`dsh.conversation.contentWidth`),自带拖拽手柄始终可用。
|
|
35
36
|
- 记住当前档位,下次打开自动恢复。
|
|
36
|
-
- 跟随 **设置 → 语言**(中文 / English / 日本語 / Español / Français / Deutsch / Русский / Português
|
|
37
|
+
- 跟随 **设置 → 语言**(中文 / English / 日本語 / Español / Français / Deutsch / Русский / Português),
|
|
38
|
+
包括设置页插件卡片的标题与简介(`locale/<lang>.json`)。
|
|
37
39
|
- 菜单支持方向键、Home/End、Esc、Tab,并恢复焦点。
|
|
38
40
|
- 档位选择跨标签页同步。
|
|
39
41
|
- 支持 `prefers-reduced-motion`。
|
|
@@ -77,8 +79,10 @@ dsh plugin --profile web add link:/path/to/dsh-width-tiers
|
|
|
77
79
|
## 兼容性
|
|
78
80
|
|
|
79
81
|
- DSH Web 0.2.x,带 `web` profile(`shell.overlay` 插槽与 `slots` 服务)。
|
|
80
|
-
- 宽度轴已按 DSH 0.2.
|
|
82
|
+
- 宽度轴已按 DSH 0.2.2-alpha.3 对照:640px 下限、176px 手柄预留、
|
|
81
83
|
`--dsh-chat-*` 变量、`data-width-handle`、layout/locale 服务。
|
|
84
|
+
- 窄屏适配 alpha.3 的侧栏抽屉(`data-sidebar-drawer`):抽屉打开时隐藏
|
|
85
|
+
选择器;软键盘弹出时按钮与菜单随之上移。
|
|
82
86
|
|
|
83
87
|
## 开发
|
|
84
88
|
|
package/lib/client.js
CHANGED
|
@@ -30,6 +30,8 @@ window.__ModuleLoader__.load({
|
|
|
30
30
|
const TIER_ATTR = "data-dsh-width";
|
|
31
31
|
/** Attribute the plugin sets on <body> while the custom-drag guide is open. */
|
|
32
32
|
const GUIDE_ATTR = "data-dsh-width-guide";
|
|
33
|
+
/** Body custom property carrying the on-screen-keyboard inset (px). */
|
|
34
|
+
const KEYBOARD_INSET_VAR = "--dsh-width-keyboard-inset";
|
|
33
35
|
// src/client/model.ts
|
|
34
36
|
const TIERS = [
|
|
35
37
|
{
|
|
@@ -151,8 +153,8 @@ window.__ModuleLoader__.load({
|
|
|
151
153
|
* dark palettes; every selector is scoped to this plugin's own ids and classes.
|
|
152
154
|
*/
|
|
153
155
|
const css = [
|
|
154
|
-
"#dsh-wide-toggle{position:fixed;right:10px;bottom:216px;z-index:999;display:flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid var(--dsw-alias-border-l2);border-radius:50%;overflow:hidden;background:var(--dsw-alias-button-floating-fill);color:var(--dsw-alias-label-secondary);box-shadow:0 2px 8px rgba(0,0,0,.18);cursor:pointer;opacity:.72;transition:opacity .2s ease,width .2s ease,border-radius .2s ease,background .2s ease,color .2s ease}",
|
|
155
|
-
"#dsh-wide-toggle::after{content:'';position:fixed;right:10px;bottom:216px;width:36px;height:36px;pointer-events:auto}",
|
|
156
|
+
"#dsh-wide-toggle{position:fixed;right:10px;bottom:calc(216px + var(--dsh-width-keyboard-inset,0px) + env(safe-area-inset-bottom,0px));z-index:999;display:flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid var(--dsw-alias-border-l2);border-radius:50%;overflow:hidden;background:var(--dsw-alias-button-floating-fill);color:var(--dsw-alias-label-secondary);box-shadow:0 2px 8px rgba(0,0,0,.18);cursor:pointer;opacity:.72;transition:opacity .2s ease,width .2s ease,border-radius .2s ease,background .2s ease,color .2s ease}",
|
|
157
|
+
"#dsh-wide-toggle::after{content:'';position:fixed;right:10px;bottom:calc(216px + var(--dsh-width-keyboard-inset,0px) + env(safe-area-inset-bottom,0px));width:36px;height:36px;pointer-events:auto}",
|
|
156
158
|
"#dsh-wide-toggle:hover{opacity:1}",
|
|
157
159
|
"#dsh-wide-toggle:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px;width:36px;border-radius:50%}",
|
|
158
160
|
"#dsh-wide-toggle:not(:hover):not(:focus-visible){width:10px;border-radius:6px}",
|
|
@@ -161,9 +163,9 @@ window.__ModuleLoader__.load({
|
|
|
161
163
|
"#dsh-wide-toggle.pulse{animation:dsh-wide-pulse .65s ease-out}",
|
|
162
164
|
"@media (prefers-reduced-motion:reduce){#dsh-wide-toggle{transition:none}#dsh-wide-toggle.pulse{animation:none}}",
|
|
163
165
|
"@keyframes dsh-wide-pulse{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--dsw-alias-state-business-primary) 60%,transparent)}100%{box-shadow:0 0 0 14px transparent}}",
|
|
164
|
-
"#dsh-width-menu{position:fixed;right:20px;bottom:264px;z-index:1000;min-width:196px;padding:6px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-specific-menu);box-shadow:0 8px 28px rgba(0,0,0,.24);display:flex;flex-direction:column;gap:2px}",
|
|
166
|
+
"#dsh-width-menu{position:fixed;right:20px;bottom:calc(264px + var(--dsh-width-keyboard-inset,0px) + env(safe-area-inset-bottom,0px));z-index:1000;min-width:196px;max-height:calc(100vh - 280px);max-height:calc(100dvh - 280px);overflow-y:auto;overscroll-behavior:contain;padding:6px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-specific-menu);box-shadow:0 8px 28px rgba(0,0,0,.24);display:flex;flex-direction:column;gap:2px}",
|
|
165
167
|
"#dsh-width-menu[hidden]{display:none}",
|
|
166
|
-
"#dsh-width-menu button{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 12px;border:none;border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:18px;text-align:left;cursor:pointer}",
|
|
168
|
+
"#dsh-width-menu button{display:flex;flex:none;align-items:center;justify-content:space-between;gap:12px;padding:8px 12px;border:none;border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:18px;text-align:left;cursor:pointer}",
|
|
167
169
|
"#dsh-width-menu button:hover{background:var(--dsw-alias-interactive-bg-hover)}",
|
|
168
170
|
"#dsh-width-menu button:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}",
|
|
169
171
|
"#dsh-width-menu button.selected{background:var(--dsw-alias-interactive-bg-hover-solid);color:var(--dsw-alias-state-business-primary)}",
|
|
@@ -174,7 +176,8 @@ window.__ModuleLoader__.load({
|
|
|
174
176
|
"#dsh-width-guide svg{flex:none;color:var(--dsw-alias-state-business-primary)}",
|
|
175
177
|
"#dsh-width-guide[data-mode=live]{font-size:13px;font-weight:600;font-variant-numeric:tabular-nums}",
|
|
176
178
|
"body[data-dsh-width-guide] [data-width-handle]{background:linear-gradient(to bottom,transparent calc(50% - 64px),color-mix(in srgb,var(--dsw-alias-state-business-primary) 18%,transparent) calc(50% - 64px),color-mix(in srgb,var(--dsw-alias-state-business-primary) 18%,transparent) calc(50% + 64px),transparent calc(50% + 64px));border-radius:3px}",
|
|
177
|
-
"body[data-dsh-width-guide] [data-width-handle]::after{opacity:1}"
|
|
179
|
+
"body[data-dsh-width-guide] [data-width-handle]::after{opacity:1}",
|
|
180
|
+
"body:has([data-sidebar-drawer]:not([data-sidebar-collapsed])) #dsh-wide-toggle,body:has([data-sidebar-drawer]:not([data-sidebar-collapsed])) #dsh-width-menu,body:has([data-sidebar-drawer]:not([data-sidebar-collapsed])) #dsh-width-guide{opacity:0;visibility:hidden;pointer-events:none}"
|
|
178
181
|
].join("");
|
|
179
182
|
/**
|
|
180
183
|
* Install the plugin stylesheet and return its removal disposer.
|
|
@@ -324,6 +327,15 @@ window.__ModuleLoader__.load({
|
|
|
324
327
|
let guideHideTimer = null;
|
|
325
328
|
let guideWidth = GUIDE_WIDTH_PX;
|
|
326
329
|
let tierBeforeGuide = "standard";
|
|
330
|
+
let keyboardInset = 0;
|
|
331
|
+
function syncKeyboardInset() {
|
|
332
|
+
const viewport = window.visualViewport;
|
|
333
|
+
const next = viewport == null ? 0 : Math.max(0, Math.round(window.innerHeight - viewport.height - viewport.offsetTop));
|
|
334
|
+
keyboardInset = next;
|
|
335
|
+
if (next > 0) body().style.setProperty(KEYBOARD_INSET_VAR, `${next}px`);
|
|
336
|
+
else body().style.removeProperty(KEYBOARD_INSET_VAR);
|
|
337
|
+
if (guideActive) updateGuideStyle();
|
|
338
|
+
}
|
|
327
339
|
let preferenceOwned = false;
|
|
328
340
|
let preferenceWritten = null;
|
|
329
341
|
let collapsedByTier = false;
|
|
@@ -364,7 +376,12 @@ window.__ModuleLoader__.load({
|
|
|
364
376
|
}
|
|
365
377
|
case "medium":
|
|
366
378
|
case "wide":
|
|
367
|
-
case "ultra":
|
|
379
|
+
case "ultra": {
|
|
380
|
+
const nominal = NOMINAL_WIDTH_PX[tierId];
|
|
381
|
+
const root = roots.find();
|
|
382
|
+
if (root === null || root.offsetWidth <= 0) return `${nominal}px`;
|
|
383
|
+
return `${Math.round(Math.min(nominal, fullWidthPx(root.offsetWidth)))}px`;
|
|
384
|
+
}
|
|
368
385
|
case "full": {
|
|
369
386
|
const root = roots.find();
|
|
370
387
|
if (root === null) return "—";
|
|
@@ -478,13 +495,22 @@ window.__ModuleLoader__.load({
|
|
|
478
495
|
pulseSeq += 1;
|
|
479
496
|
emit();
|
|
480
497
|
}
|
|
498
|
+
function fallbackGuideStyle() {
|
|
499
|
+
if (keyboardInset <= 0) return GUIDE_FALLBACK;
|
|
500
|
+
return {
|
|
501
|
+
left: "auto",
|
|
502
|
+
right: "24px",
|
|
503
|
+
top: `${Math.max(24, Math.round((window.innerHeight - keyboardInset) / 2))}px`
|
|
504
|
+
};
|
|
505
|
+
}
|
|
481
506
|
function computeGuideStyle() {
|
|
482
507
|
const handle = guideHandle !== null && document.contains(guideHandle) ? guideHandle : document.querySelector("[data-width-handle=\"right\"]");
|
|
483
508
|
const viewport = window.innerWidth || 0;
|
|
484
|
-
if (handle === null || typeof handle.getBoundingClientRect !== "function" || viewport === 0) return
|
|
509
|
+
if (handle === null || typeof handle.getBoundingClientRect !== "function" || viewport === 0) return fallbackGuideStyle();
|
|
485
510
|
const rect = handle.getBoundingClientRect();
|
|
486
511
|
const gap = 10;
|
|
487
|
-
const
|
|
512
|
+
const visibleBottom = (window.innerHeight || 0) - keyboardInset;
|
|
513
|
+
const top = `${Math.max(8, Math.min(rect.top + rect.height / 2, visibleBottom - 24))}px`;
|
|
488
514
|
if (viewport - rect.right >= guideWidth + gap) return {
|
|
489
515
|
left: `${rect.right + gap}px`,
|
|
490
516
|
right: "auto",
|
|
@@ -801,6 +827,12 @@ window.__ModuleLoader__.load({
|
|
|
801
827
|
});
|
|
802
828
|
};
|
|
803
829
|
window.addEventListener("resize", onWindowResize);
|
|
830
|
+
const visualViewport = window.visualViewport ?? null;
|
|
831
|
+
if (visualViewport !== null) {
|
|
832
|
+
visualViewport.addEventListener("resize", syncKeyboardInset);
|
|
833
|
+
visualViewport.addEventListener("scroll", syncKeyboardInset);
|
|
834
|
+
}
|
|
835
|
+
syncKeyboardInset();
|
|
804
836
|
snapshot = buildSnapshot();
|
|
805
837
|
const unsubscribeLocale = options.locale.subscribe(() => {
|
|
806
838
|
if (guideActive && !guideDragging && guideMode === "hint") guideText = t("guide.hint");
|
|
@@ -849,6 +881,11 @@ window.__ModuleLoader__.load({
|
|
|
849
881
|
window.removeEventListener("resize", onWindowResize);
|
|
850
882
|
window.removeEventListener("load", attach);
|
|
851
883
|
window.removeEventListener("storage", onStorage);
|
|
884
|
+
if (visualViewport !== null) {
|
|
885
|
+
visualViewport.removeEventListener("resize", syncKeyboardInset);
|
|
886
|
+
visualViewport.removeEventListener("scroll", syncKeyboardInset);
|
|
887
|
+
}
|
|
888
|
+
body().style.removeProperty(KEYBOARD_INSET_VAR);
|
|
852
889
|
if (observer !== null) observer.disconnect();
|
|
853
890
|
document.removeEventListener("pointerdown", onHandlePointerDown, true);
|
|
854
891
|
document.removeEventListener("pointerup", onHandlePointerUp, true);
|
package/locale/de.json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"title": "Breitenstufen (dsh-width-tiers)",
|
|
4
|
+
"description": "Breitenstufen für Chat-Inhalte (Standard / Mittel / Breit / Sehr breit / Volle Breite / Benutzerdefiniert) mit schwebender Auswahl; nutzt die native Breitenachse der App, sodass die integrierten Ziehpunkte weiter funktionieren."
|
|
5
|
+
}
|
|
6
|
+
}
|
package/locale/en.json
ADDED
package/locale/es.json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"title": "Niveles de ancho (dsh-width-tiers)",
|
|
4
|
+
"description": "Niveles de ancho del contenido del chat (estándar / medio / ancho / muy ancho / completo / personalizado) con un selector flotante; usa el eje de ancho nativo de la app, así que los tiradores de arrastre integrados siguen funcionando."
|
|
5
|
+
}
|
|
6
|
+
}
|
package/locale/fr.json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"title": "Paliers de largeur (dsh-width-tiers)",
|
|
4
|
+
"description": "Paliers de largeur du contenu du chat (standard / moyen / large / très large / pleine largeur / personnalisé) avec un sélecteur flottant ; s'appuie sur l'axe de largeur natif de l'application, donc les poignées de redimensionnement intégrées restent utilisables."
|
|
5
|
+
}
|
|
6
|
+
}
|
package/locale/ja.json
ADDED
package/locale/pt.json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"title": "Níveis de largura (dsh-width-tiers)",
|
|
4
|
+
"description": "Níveis de largura do conteúdo do chat (padrão / médio / largo / muito largo / largura total / personalizado) com um seletor flutuante; usa o eixo de largura nativo do app, então as alças de redimensionamento integradas continuam funcionando."
|
|
5
|
+
}
|
|
6
|
+
}
|
package/locale/ru.json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"title": "Уровни ширины (dsh-width-tiers)",
|
|
4
|
+
"description": "Уровни ширины содержимого чата (стандартная / средняя / широкая / очень широкая / на всю ширину / своя) с плавающим переключателем; использует нативную ось ширины приложения, поэтому встроенные маркеры изменения ширины продолжают работать."
|
|
5
|
+
}
|
|
6
|
+
}
|
package/locale/zh.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-width-tiers",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "DSH Web client plugin: chat content width tiers (standard / medium / wide / ultra / full / custom) with a floating picker button. Mounts into the app's shell.overlay slot on DSH 0.2.x and drives the native width axis, so the built-in drag handles keep working. UI copy follows the app language (zh / en / ja / es / fr / de / ru / pt).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "aaronlei",
|
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
"exports": {
|
|
13
13
|
".": "./lib/index.js",
|
|
14
14
|
"./client": "./lib/client.js",
|
|
15
|
-
"./package.json": "./package.json"
|
|
15
|
+
"./package.json": "./package.json",
|
|
16
|
+
"./locale/*.json": "./locale/*.json"
|
|
16
17
|
},
|
|
17
18
|
"files": [
|
|
18
19
|
"lib",
|
|
20
|
+
"locale",
|
|
19
21
|
"cordis.patch.yml",
|
|
20
22
|
"LICENSE",
|
|
21
23
|
"README.md",
|