@djangocfg/widget-chat 0.1.7 → 0.1.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/widget-chat",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "A transport-agnostic chat surface: a pure core, a store, primitives, a composer, and the assembled components a host mounts",
5
5
  "keywords": [
6
6
  "chat",
@@ -55,8 +55,8 @@
55
55
  "test:watch": "vitest"
56
56
  },
57
57
  "dependencies": {
58
- "@djangocfg/widget-kit": "^0.1.7",
59
- "@djangocfg/widget-media": "^0.1.7",
58
+ "@djangocfg/widget-kit": "^0.1.9",
59
+ "@djangocfg/widget-media": "^0.1.9",
60
60
  "@streamdown/code": "^1.1.1",
61
61
  "@streamdown/math": "^1.0.2",
62
62
  "mdast-util-to-string": "^4.0.0",
@@ -66,17 +66,17 @@
66
66
  "use-stick-to-bottom": "^1.1.6"
67
67
  },
68
68
  "peerDependencies": {
69
- "@djangocfg/i18n": "^2.1.548",
70
- "@djangocfg/ui-core": "^2.1.548",
69
+ "@djangocfg/i18n": "^2.1.550",
70
+ "@djangocfg/ui-core": "^2.1.550",
71
71
  "lucide-react": "^0.545.0",
72
72
  "react": "^19.0.0",
73
73
  "remark-gfm": "^4.0.0",
74
74
  "streamdown": "^2.6.0"
75
75
  },
76
76
  "devDependencies": {
77
- "@djangocfg/i18n": "^2.1.548",
78
- "@djangocfg/typescript-config": "^2.1.548",
79
- "@djangocfg/ui-core": "^2.1.548",
77
+ "@djangocfg/i18n": "^2.1.550",
78
+ "@djangocfg/typescript-config": "^2.1.550",
79
+ "@djangocfg/ui-core": "^2.1.550",
80
80
  "@storybook/react-vite": "^10.5.0",
81
81
  "@types/node": "^25.9.5",
82
82
  "@types/react": "19.2.15",
@@ -1,4 +1,4 @@
1
- import { useCallback, useState, type ReactNode } from "react";
1
+ import { useCallback, useEffect, useRef, useState, type ReactNode } from "react";
2
2
 
3
3
  import { cn } from "@djangocfg/ui-core/lib";
4
4
 
@@ -143,12 +143,27 @@ export function useCopyAction(
143
143
  const { label, copiedLabel, icon, copiedIcon, write, confirmMs = 1500 } = options;
144
144
  const [copied, setCopied] = useState(false);
145
145
  const text = messageCopyText(message);
146
+ // One timer, cleared on unmount and before rearming: copying twice in quick
147
+ // succession stacked two, and the first cleared the tick while the second
148
+ // copy was still fresh.
149
+ const confirmTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
150
+
151
+ useEffect(
152
+ () => () => {
153
+ if (confirmTimerRef.current) clearTimeout(confirmTimerRef.current);
154
+ },
155
+ [],
156
+ );
146
157
 
147
158
  const onSelect = useCallback(() => {
148
159
  void write(text).then((ok) => {
149
160
  if (!ok) return;
150
161
  setCopied(true);
151
- setTimeout(() => setCopied(false), confirmMs);
162
+ if (confirmTimerRef.current) clearTimeout(confirmTimerRef.current);
163
+ confirmTimerRef.current = setTimeout(() => {
164
+ confirmTimerRef.current = null;
165
+ setCopied(false);
166
+ }, confirmMs);
152
167
  });
153
168
  }, [write, text, confirmMs]);
154
169