dsh-width-tiers 2.0.0 → 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 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).
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.1-rc.2: 640px floor, 176px handle budget,
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)。
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.1-rc.2 对照:640px 下限、176px 手柄预留、
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": return `${NOMINAL_WIDTH_PX[tierId]}px`;
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 GUIDE_FALLBACK;
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 top = `${rect.top + rect.height / 2}px`;
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);
@@ -880,33 +917,116 @@ window.__ModuleLoader__.load({
880
917
  // src/client/locales.ts
881
918
  /** Dictionary namespace owned by this plugin. */
882
919
  const NS = "width-tiers";
883
- /** Simplified Chinese dictionary (the key-set source of truth). */
884
- const zh = {
885
- "tier.standard": "标准",
886
- "tier.medium": "中等",
887
- "tier.wide": "宽",
888
- "tier.ultra": "超宽",
889
- "tier.full": "全宽",
890
- "tier.custom": "自定义",
891
- "value.custom.unset": "未设置",
892
- "guide.hint": "拖拽右侧边缘调整对话宽度",
893
- "button.aria": "对话区宽度档位:{label}({value}),点击选择档位",
894
- "button.title.summary": "对话区宽度档位:{label}({value})",
895
- "button.title.hint": "点击选择:{list}"
896
- };
897
- /** English dictionary, checked complete against the zh key set. */
898
- const en = {
899
- "tier.standard": "Standard",
900
- "tier.medium": "Medium",
901
- "tier.wide": "Wide",
902
- "tier.ultra": "Ultra",
903
- "tier.full": "Full",
904
- "tier.custom": "Custom",
905
- "value.custom.unset": "Not set",
906
- "guide.hint": "Drag the right edge to resize",
907
- "button.aria": "Chat width tier: {label} ({value}). Click to choose a tier.",
908
- "button.title.summary": "Chat width tier: {label} ({value})",
909
- "button.title.hint": "Click to choose: {list}"
920
+ /**
921
+ * Every shipped dictionary, keyed by the locale id the DSH locale service
922
+ * accepts. The set matches the languages DSH 0.2.2 ships (zh, en, ja, es,
923
+ * fr, de, ru, pt); other languages fall back through English.
924
+ */
925
+ const dictionaries = {
926
+ zh: {
927
+ "tier.standard": "标准",
928
+ "tier.medium": "中等",
929
+ "tier.wide": "宽",
930
+ "tier.ultra": "超宽",
931
+ "tier.full": "全宽",
932
+ "tier.custom": "自定义",
933
+ "value.custom.unset": "未设置",
934
+ "guide.hint": "拖拽右侧边缘调整对话宽度",
935
+ "button.aria": "对话区宽度档位:{label}({value}),点击选择档位",
936
+ "button.title.summary": "对话区宽度档位:{label}({value})",
937
+ "button.title.hint": "点击选择:{list}"
938
+ },
939
+ en: {
940
+ "tier.standard": "Standard",
941
+ "tier.medium": "Medium",
942
+ "tier.wide": "Wide",
943
+ "tier.ultra": "Ultra",
944
+ "tier.full": "Full",
945
+ "tier.custom": "Custom",
946
+ "value.custom.unset": "Not set",
947
+ "guide.hint": "Drag the right edge to resize",
948
+ "button.aria": "Chat width tier: {label} ({value}). Click to choose a tier.",
949
+ "button.title.summary": "Chat width tier: {label} ({value})",
950
+ "button.title.hint": "Click to choose: {list}"
951
+ },
952
+ ja: {
953
+ "tier.standard": "標準",
954
+ "tier.medium": "中",
955
+ "tier.wide": "ワイド",
956
+ "tier.ultra": "ウルトラワイド",
957
+ "tier.full": "全幅",
958
+ "tier.custom": "カスタム",
959
+ "value.custom.unset": "未設定",
960
+ "guide.hint": "右端をドラッグして会話幅を調整",
961
+ "button.aria": "会話エリアの幅設定:{label}({value})。クリックして選択",
962
+ "button.title.summary": "会話エリアの幅設定:{label}({value})",
963
+ "button.title.hint": "クリックして選択:{list}"
964
+ },
965
+ es: {
966
+ "tier.standard": "Estándar",
967
+ "tier.medium": "Medio",
968
+ "tier.wide": "Ancho",
969
+ "tier.ultra": "Muy ancho",
970
+ "tier.full": "Completo",
971
+ "tier.custom": "Personalizado",
972
+ "value.custom.unset": "Sin definir",
973
+ "guide.hint": "Arrastra el borde derecho para ajustar el ancho",
974
+ "button.aria": "Ancho del área de chat: {label} ({value}). Haz clic para elegir un nivel.",
975
+ "button.title.summary": "Ancho del área de chat: {label} ({value})",
976
+ "button.title.hint": "Haz clic para elegir: {list}"
977
+ },
978
+ fr: {
979
+ "tier.standard": "Standard",
980
+ "tier.medium": "Moyen",
981
+ "tier.wide": "Large",
982
+ "tier.ultra": "Très large",
983
+ "tier.full": "Pleine largeur",
984
+ "tier.custom": "Personnalisé",
985
+ "value.custom.unset": "Non défini",
986
+ "guide.hint": "Faites glisser le bord droit pour ajuster la largeur",
987
+ "button.aria": "Largeur de la zone de chat : {label} ({value}). Cliquez pour choisir un palier.",
988
+ "button.title.summary": "Largeur de la zone de chat : {label} ({value})",
989
+ "button.title.hint": "Cliquez pour choisir : {list}"
990
+ },
991
+ de: {
992
+ "tier.standard": "Standard",
993
+ "tier.medium": "Mittel",
994
+ "tier.wide": "Breit",
995
+ "tier.ultra": "Sehr breit",
996
+ "tier.full": "Volle Breite",
997
+ "tier.custom": "Benutzerdefiniert",
998
+ "value.custom.unset": "Nicht festgelegt",
999
+ "guide.hint": "Rechten Rand ziehen, um die Breite anzupassen",
1000
+ "button.aria": "Chatbreite: {label} ({value}). Klicken, um eine Stufe zu wählen.",
1001
+ "button.title.summary": "Chatbreite: {label} ({value})",
1002
+ "button.title.hint": "Klicken zum Auswählen: {list}"
1003
+ },
1004
+ ru: {
1005
+ "tier.standard": "Стандартная",
1006
+ "tier.medium": "Средняя",
1007
+ "tier.wide": "Широкая",
1008
+ "tier.ultra": "Очень широкая",
1009
+ "tier.full": "На всю ширину",
1010
+ "tier.custom": "Своя",
1011
+ "value.custom.unset": "Не задано",
1012
+ "guide.hint": "Перетащите правый край, чтобы изменить ширину",
1013
+ "button.aria": "Ширина области чата: {label} ({value}). Нажмите, чтобы выбрать уровень.",
1014
+ "button.title.summary": "Ширина области чата: {label} ({value})",
1015
+ "button.title.hint": "Нажмите, чтобы выбрать: {list}"
1016
+ },
1017
+ pt: {
1018
+ "tier.standard": "Padrão",
1019
+ "tier.medium": "Médio",
1020
+ "tier.wide": "Largo",
1021
+ "tier.ultra": "Muito largo",
1022
+ "tier.full": "Largura total",
1023
+ "tier.custom": "Personalizado",
1024
+ "value.custom.unset": "Não definido",
1025
+ "guide.hint": "Arraste a borda direita para ajustar a largura",
1026
+ "button.aria": "Largura da área de chat: {label} ({value}). Clique para escolher um nível.",
1027
+ "button.title.summary": "Largura da área de chat: {label} ({value})",
1028
+ "button.title.hint": "Clique para escolher: {list}"
1029
+ }
910
1030
  };
911
1031
  // src/client/WidthTierPicker.tsx
912
1032
  /** How long the selection ring stays on the button. */
@@ -1114,10 +1234,12 @@ window.__ModuleLoader__.load({
1114
1234
  * @param ctx - client root context (slots + layout + locale injected).
1115
1235
  */
1116
1236
  function apply(ctx) {
1117
- ctx.effect(() => ctx.locale.register(NS, {
1118
- zh,
1119
- en
1120
- }), "dsh-width-tiers: dictionaries");
1237
+ ctx.effect(() => {
1238
+ const disposers = Object.entries(dictionaries).map(([locale, dictionary]) => ctx.locale.register(NS, locale, dictionary));
1239
+ return () => {
1240
+ for (const dispose of disposers) dispose();
1241
+ };
1242
+ }, "dsh-width-tiers: dictionaries");
1121
1243
  const t = ctx.locale.bind(NS);
1122
1244
  const controller = createWidthTiers({
1123
1245
  layout: ctx.layout,
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
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Width tiers (dsh-width-tiers)",
4
+ "description": "Chat content width tiers (standard / medium / wide / ultra / full / custom) with a floating picker; drives the app's native width axis so the built-in drag handles keep working."
5
+ }
6
+ }
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
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "会話幅のプリセット (dsh-width-tiers)",
4
+ "description": "会話内容の幅プリセット(標準 / 中 / ワイド / ウルトラワイド / 全幅 / カスタム)。フローティングの選択ボタンから切り替え、アプリ本来の幅軸を操作するため内蔵のドラッグハンドルもそのまま使えます。"
5
+ }
6
+ }
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
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "宽度档位 (dsh-width-tiers)",
4
+ "description": "聊天内容宽度档位(标准 / 中等 / 宽 / 超宽 / 全宽 / 自定义),带浮动选择按钮;直接驱动应用原生宽度轴,内置拖拽手柄保持可用。"
5
+ }
6
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-width-tiers",
3
- "version": "2.0.0",
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).",
3
+ "version": "2.0.2",
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",
7
7
  "publishConfig": {
@@ -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",