@ykurilov/agent-chat-skin-tandem 0.69.0 → 0.70.0
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/CHANGELOG.md +23 -0
- package/dist/index.js +50 -5
- package/dist/index.js.map +1 -1
- package/dist/types/work-steps.d.ts +8 -1
- package/package.json +14 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @ykurilov/agent-chat-skin-tandem
|
|
2
2
|
|
|
3
|
+
## 0.70.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @ykurilov/agent-chat-flows@0.70.0
|
|
8
|
+
- @ykurilov/agent-chat-mcp@0.70.0
|
|
9
|
+
- @ykurilov/agent-chat-messengers@0.70.0
|
|
10
|
+
- @ykurilov/agent-chat-sandbox@0.70.0
|
|
11
|
+
- @ykurilov/agent-chat-skills@0.70.0
|
|
12
|
+
- @ykurilov/agent-chat-react@0.70.0
|
|
13
|
+
|
|
14
|
+
## 0.69.1
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- 857777b: Ряд значков шагов в Тандеме — по настоящей ширине строки, «+N» всегда помещается, не вылезает за край узкой колонки; модели заголовков раздумий уходит не больше 1200 знаков раздумья (начало и конец) — длинный заголовок вдвое дешевле.
|
|
19
|
+
- @ykurilov/agent-chat-flows@0.69.1
|
|
20
|
+
- @ykurilov/agent-chat-mcp@0.69.1
|
|
21
|
+
- @ykurilov/agent-chat-messengers@0.69.1
|
|
22
|
+
- @ykurilov/agent-chat-sandbox@0.69.1
|
|
23
|
+
- @ykurilov/agent-chat-skills@0.69.1
|
|
24
|
+
- @ykurilov/agent-chat-react@0.69.1
|
|
25
|
+
|
|
3
26
|
## 0.69.0
|
|
4
27
|
|
|
5
28
|
### Minor Changes
|
package/dist/index.js
CHANGED
|
@@ -2778,7 +2778,7 @@ function StatusMark2({ status }) {
|
|
|
2778
2778
|
import { Button as Button29, cn as cn13 } from "@tandem/ui";
|
|
2779
2779
|
import { useChatLabels as useChatLabels43 } from "@ykurilov/agent-chat-react";
|
|
2780
2780
|
import { ChevronDown as ChevronDown6 } from "lucide-react";
|
|
2781
|
-
import { useId as useId13 } from "react";
|
|
2781
|
+
import { useId as useId13, useLayoutEffect as useLayoutEffect4, useRef as useRef12, useState as useState8 } from "react";
|
|
2782
2782
|
|
|
2783
2783
|
// src/step-icon.tsx
|
|
2784
2784
|
import { cn as cn12 } from "@tandem/ui";
|
|
@@ -2810,9 +2810,50 @@ function TandemStepIcon({ icon, className }) {
|
|
|
2810
2810
|
|
|
2811
2811
|
// src/work-steps.tsx
|
|
2812
2812
|
import { jsx as jsx52, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
2813
|
+
var GAP_PX = 4;
|
|
2814
|
+
function visibleStepIcons(available, total, plusWidthOf, iconPx = 14) {
|
|
2815
|
+
const iconsWidth = (count) => count * iconPx + Math.max(0, count - 1) * GAP_PX;
|
|
2816
|
+
if (iconsWidth(total) <= available) return total;
|
|
2817
|
+
for (let count = total - 1; count > 0; count--) if (iconsWidth(count) + GAP_PX + plusWidthOf(total - count) <= available) return count;
|
|
2818
|
+
return plusWidthOf(total) <= available ? 0 : null;
|
|
2819
|
+
}
|
|
2820
|
+
function useIconRowSpace() {
|
|
2821
|
+
const lineRef = useRef12(null);
|
|
2822
|
+
const rowRef = useRef12(null);
|
|
2823
|
+
const [measured, setMeasured] = useState8(null);
|
|
2824
|
+
useLayoutEffect4(() => {
|
|
2825
|
+
const line = lineRef.current;
|
|
2826
|
+
if (!line || typeof ResizeObserver === "undefined") return;
|
|
2827
|
+
const measure = () => {
|
|
2828
|
+
const button = line.firstElementChild;
|
|
2829
|
+
const row = rowRef.current;
|
|
2830
|
+
if (!button || !row || line.clientWidth === 0) return;
|
|
2831
|
+
const rest = button.getBoundingClientRect().width - row.getBoundingClientRect().width;
|
|
2832
|
+
const icon = row.querySelector("svg")?.getBoundingClientRect().width;
|
|
2833
|
+
const more = row.querySelector("[data-step-icons-more]");
|
|
2834
|
+
const moreText = more?.textContent ?? "";
|
|
2835
|
+
setMeasured((previous) => {
|
|
2836
|
+
const next = {
|
|
2837
|
+
space: Math.max(0, line.clientWidth - rest - 4),
|
|
2838
|
+
iconPx: icon || previous?.iconPx || 16,
|
|
2839
|
+
// Знак «+N» с запасом в 1 px: «+N» всегда влезает.
|
|
2840
|
+
charPx: more && moreText ? more.getBoundingClientRect().width / moreText.length + 1 : previous?.charPx ?? 8
|
|
2841
|
+
};
|
|
2842
|
+
return previous && previous.space === next.space && previous.iconPx === next.iconPx && previous.charPx === next.charPx ? previous : next;
|
|
2843
|
+
});
|
|
2844
|
+
};
|
|
2845
|
+
measure();
|
|
2846
|
+
const observer = new ResizeObserver(measure);
|
|
2847
|
+
observer.observe(line);
|
|
2848
|
+
if (rowRef.current) observer.observe(rowRef.current);
|
|
2849
|
+
return () => observer.disconnect();
|
|
2850
|
+
}, []);
|
|
2851
|
+
return { lineRef, rowRef, measured };
|
|
2852
|
+
}
|
|
2813
2853
|
function TandemWorkSteps(view) {
|
|
2814
2854
|
const labels = useChatLabels43();
|
|
2815
2855
|
const listId = useId13();
|
|
2856
|
+
const { lineRef, rowRef, measured } = useIconRowSpace();
|
|
2816
2857
|
if (view.state === "live") {
|
|
2817
2858
|
return /* @__PURE__ */ jsxs42("div", { "data-work-live": true, className: "mb-2 flex h-7 min-w-0 items-center gap-2 last:mb-0 text-xs font-medium text-[var(--foreground-muted)] not-first:mt-3", children: [
|
|
2818
2859
|
view.icon ? /* @__PURE__ */ jsx52(TandemStepIcon, { icon: view.icon, className: "text-[var(--action)] motion-safe:animate-pulse" }) : /* @__PURE__ */ jsx52("span", { "aria-hidden": "true", className: "size-1.5 shrink-0 rounded-full bg-[var(--action)] motion-safe:animate-pulse" }),
|
|
@@ -2822,7 +2863,11 @@ function TandemWorkSteps(view) {
|
|
|
2822
2863
|
}
|
|
2823
2864
|
const { steps, count, open, onOpenChange, items, icons = [], moreIcons = 0 } = view;
|
|
2824
2865
|
const list = items ?? steps.map((step) => ({ ...step, icon: void 0 }));
|
|
2825
|
-
|
|
2866
|
+
const total = icons.length + moreIcons;
|
|
2867
|
+
const fitting = measured && visibleStepIcons(measured.space, total, (count2) => labels.workView.moreSteps(count2).length * measured.charPx, measured.iconPx);
|
|
2868
|
+
const shown = measured === null ? icons.length : fitting === null ? 0 : Math.min(icons.length, fitting);
|
|
2869
|
+
const hidden = fitting === null && measured !== null ? 0 : total - shown;
|
|
2870
|
+
return /* @__PURE__ */ jsxs42("div", { ref: lineRef, className: "mb-2 min-w-0 not-first:mt-3", children: [
|
|
2826
2871
|
/* @__PURE__ */ jsxs42(
|
|
2827
2872
|
Button29,
|
|
2828
2873
|
{
|
|
@@ -2834,9 +2879,9 @@ function TandemWorkSteps(view) {
|
|
|
2834
2879
|
className: "-ml-2 h-7 max-w-full min-w-0 gap-1 px-2 text-xs font-medium text-[var(--foreground-muted)]",
|
|
2835
2880
|
children: [
|
|
2836
2881
|
/* @__PURE__ */ jsx52("span", { className: "shrink-0", children: labels.workView.stepsDone(count) }),
|
|
2837
|
-
icons.length > 0 && /* @__PURE__ */ jsxs42("span", { "data-step-icons": true, "aria-hidden": "true", className: "ml-1 flex min-w-0 items-center gap-1 overflow-hidden text-[var(--foreground-subtle)]", children: [
|
|
2838
|
-
icons.map((icon, index) => /* @__PURE__ */ jsx52(TandemStepIcon, { icon }, index)),
|
|
2839
|
-
|
|
2882
|
+
icons.length > 0 && /* @__PURE__ */ jsxs42("span", { ref: rowRef, "data-step-icons": true, "aria-hidden": "true", className: "ml-1 flex min-w-0 items-center gap-1 overflow-hidden text-[var(--foreground-subtle)]", children: [
|
|
2883
|
+
icons.slice(0, shown).map((icon, index) => /* @__PURE__ */ jsx52(TandemStepIcon, { icon }, index)),
|
|
2884
|
+
hidden > 0 && /* @__PURE__ */ jsx52("span", { "data-step-icons-more": true, className: "shrink-0 tabular-nums", children: labels.workView.moreSteps(hidden) })
|
|
2840
2885
|
] }),
|
|
2841
2886
|
/* @__PURE__ */ jsx52(ChevronDown6, { "aria-hidden": "true", className: cn13("size-3.5 shrink-0 transition-transform duration-[var(--motion-fast)]", open && "rotate-180") })
|
|
2842
2887
|
]
|