@huai_xin/dsh-model-picker 0.3.0 → 0.3.1

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
@@ -4,6 +4,16 @@
4
4
 
5
5
  DSH 自带的模型选择器是按两级菜单设计的。模型一多,找一个模型要翻两层;思考档位藏在二级菜单里,改一次要点三次。这个插件把它换成一次点开的列表:直接搜、直接选。
6
6
 
7
+ ## 预览
8
+
9
+ 深色主题:
10
+
11
+ ![思考档位面板(深色主题)](docs/effort-dark.png)
12
+
13
+ 浅色主题:
14
+
15
+ ![思考档位面板(浅色主题)](docs/effort-light.png)
16
+
7
17
  ## 它做了什么
8
18
 
9
19
  **可搜索的模型列表** — 点开即输入,按名字或 id 过滤,按 provider 分组显示。
package/client.js CHANGED
@@ -327,6 +327,29 @@ function createCaptionMark(React) {
327
327
  * @returns the slider element tree.
328
328
  */
329
329
 
330
+ /**
331
+ * Which accent a reasoning level uses, as a string the stylesheet matches on.
332
+ *
333
+ * The two highest stops are the only ones that differ: `top` (the last) takes the
334
+ * violet, `high` (the one before) the amber. Every other level — and the single-level
335
+ * case — returns undefined, which is what leaves the default blue in place and makes
336
+ * the two marked stops read as "above normal" rather than as two arbitrary colours in
337
+ * a five-colour ramp.
338
+ *
339
+ * It lives at module scope because it is shared: the slider marks itself with it, and
340
+ * so does the composer trigger, which renders outside this component's subtree.
341
+ *
342
+ * @param index - the level's position, 0-based.
343
+ * @param count - how many levels the model declares.
344
+ * @returns 'top' | 'high' | undefined
345
+ */
346
+ function tierFor(index, count) {
347
+ if (count <= 1) return undefined
348
+ if (index === count - 1) return 'top'
349
+ if (index === count - 2) return 'high'
350
+ return undefined
351
+ }
352
+
330
353
  function createEffortSlider(React) {
331
354
  const h = React.createElement
332
355
  const CaptionMark = createCaptionMark(React)
@@ -510,6 +533,14 @@ function createEffortSlider(React) {
510
533
  * level feel like more of the same instead of the end of the range.
511
534
  */
512
535
  const withTrail = count > 1 && index === count - 1
536
+ /**
537
+ * Which accent the current level uses.
538
+ *
539
+ * The two highest stops are the only ones that differ. Everything below keeps the
540
+ * normal blue, which is what makes the two marked stops read as "above normal"
541
+ * rather than as two arbitrary colours in a five-colour ramp.
542
+ */
543
+ const tier = tierFor(index, count)
513
544
 
514
545
  return h('div', {
515
546
  // `dmp-slider-dragging` drops the left transition on the knob, the fill and
@@ -518,6 +549,9 @@ function createEffortSlider(React) {
518
549
  // from a position the knob had not reached yet.
519
550
  className: `dmp-slider${dragging === null ? '' : ' dmp-slider-dragging'}`,
520
551
  'aria-disabled': disabled === true,
552
+ // The stylesheet picks the accent from this: 'top' and 'high' are the two
553
+ // levels with their own colour, everything else leaves it unset.
554
+ 'data-tier': tier,
521
555
  style: { '--dmp-effort-at': position(index) }
522
556
  },
523
557
  h('div', { className: 'dmp-slider-head' },
@@ -753,9 +787,16 @@ const CSS = `
753
787
  margin-top: -7px; }
754
788
  /* The tag names the level; it is not a brightness meter. Taking the ramp colour here
755
789
  made "Low" render dim grey and "High" near white, so the control appeared to change
756
- weight as the level moved. The ramp stays on the track, where it means intensity. */
790
+ weight as the level moved. The ramp stays on the track, where it means intensity.
791
+
792
+ The two tier levels are the exception, and they are the point of the tiers: the name
793
+ itself takes the tier accent, so the button in the composer row carries the same
794
+ colour as the bar inside the panel it opens. */
757
795
  .dmp-trigger-effort-text { flex: 1 1 auto; min-width: 0; text-align: center;
758
796
  color: var(--dsw-alias-label-primary); font-weight: 600; }
797
+ .dmp-trigger-effort[data-tier="top"] .dmp-trigger-effort-text,
798
+ .dmp-trigger-effort[data-tier="high"] .dmp-trigger-effort-text {
799
+ color: var(--dmp-accent); }
759
800
  /* Hover and open share ONE background, and it is the translucent interactive
760
801
  token, not the opaque layer-2 surface.
761
802
  The layer-2 token resolves to the composer's own surface colour in both themes
@@ -859,12 +900,14 @@ const CSS = `
859
900
  height: 22px; box-sizing: border-box; padding: 0 8px; border-radius: 8px;
860
901
  font-size: 12px; line-height: 1; font-weight: 600; white-space: nowrap;
861
902
  letter-spacing: .01em;
862
- /* The pill is a label, not a rank meter: it must read the SAME at every level.
863
- It used to take the level's ramp colour, so Low rendered dim grey and Max near
864
- white — the same component looking like two different things depending on the
865
- setting. The ramp colour stays on the track, where it encodes intensity. */
903
+ /* The pill is a label, not a rank meter, so it reads the same at every level — EXCEPT
904
+ the two that carry a tier accent: those take the accent colour in the panel's top
905
+ right corner too, which is what ties the label to the bar below it. Without a tier
906
+ the colour is the plain primary label. */
866
907
  color: var(--dsw-alias-label-primary);
867
908
  background: var(--dsw-alias-interactive-bg-hover); }
909
+ .dmp-slider[data-tier="top"] .dmp-slider-value,
910
+ .dmp-slider[data-tier="high"] .dmp-slider-value { color: var(--dmp-accent); }
868
911
  /* Reasoning effort: the slider.
869
912
  ---------------------------------------------------------------------------
870
913
  A thick pill-shaped track with a solid accent fill and a disc riding on it. The
@@ -898,6 +941,23 @@ const CSS = `
898
941
  while the app looks pale — the demo used to hard-code a blue of its own. */
899
942
  .dmp-slider { --dmp-accent: var(--dsw-static-deepseek-450,
900
943
  var(--dsw-alias-state-business-primary, var(--dsw-alias-brand-primary))); }
944
+ /* The two top levels get their own accent.
945
+ Borrowed from Codex's TUI, which reserves colour for its highest tiers rather than
946
+ painting a ramp across every stop: its Ultra is a violet family and its Max is an
947
+ amber one. Here the LAST stop takes Ultra's violet and the second-to-last takes
948
+ Max's amber, so the two highest levels are the ones that look different — a level
949
+ below that keeps the normal blue, which is what makes the distinction mean
950
+ something.
951
+ The values are the dark-background hues from Codex's tier table. Each tier carries
952
+ a three-hue set there for its gradient animation; only the first is used here, since
953
+ this control does not run that animation.
954
+ data-tier is set by the component on the slider AND on the trigger, because the
955
+ same accent has to reach the level button in the composer row, which is outside the
956
+ panel's subtree. */
957
+ .dmp-slider[data-tier="top"],
958
+ .dmp-trigger-effort[data-tier="top"] { --dmp-accent: #ba82ff; }
959
+ .dmp-slider[data-tier="high"],
960
+ .dmp-trigger-effort[data-tier="high"] { --dmp-accent: #f7c473; }
901
961
  /* Radius is a LITERAL 15px on a 28px-tall rail — deliberately ONE more than half the
902
962
  height, so the ends curve a touch harder than a true semicircle and read as round
903
963
  rather than as pillowed caps. Anything below half looks square; this is the
@@ -1697,6 +1757,11 @@ function createModelPicker(React) {
1697
1757
  type: 'button',
1698
1758
  ref: effortAnchor.ref,
1699
1759
  className: 'dmp-trigger dmp-trigger-effort',
1760
+ // The two highest levels name themselves in their accent colour here, so the
1761
+ // tag in the composer row carries the same colour as the bar in the panel it
1762
+ // opens. The slider computes the value for its own subtree; this component has
1763
+ // to compute it again because the tag is NOT a descendant of the slider.
1764
+ 'data-tier': tierFor(efforts.findIndex((effort) => effort.id === activeEffortId), efforts.length),
1700
1765
  // Only a locked composer disables the level tag. Its own commits flip the
1701
1766
  // directory to `selecting`, and disabling here killed the drag after the
1702
1767
  // first stop — the same reason the slider's range input stays enabled.
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@huai_xin/dsh-model-picker",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "A searchable, provider-grouped replacement for the DSH composer's model picker.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -35,7 +35,8 @@
35
35
  "locale/*.json",
36
36
  "icon.svg",
37
37
  "README.md",
38
- "LICENSE"
38
+ "LICENSE",
39
+ "docs/*.png"
39
40
  ],
40
41
  "scripts": {
41
42
  "build": "node scripts/build.mjs",