@gram-ai/elements 1.34.0 → 1.36.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/dist/compat-shims-CO9JXXV4.cjs.map +1 -1
- package/dist/compat-shims-DxtUrORi.js.map +1 -1
- package/dist/compat-shims.d.ts +9 -8
- package/dist/components/Chat/index.d.ts +2 -1
- package/dist/components/ChatHistory.d.ts +1 -1
- package/dist/components/FrontendTools/index.d.ts +1 -1
- package/dist/components/Replay.d.ts +1 -1
- package/dist/components/Replay.stories.d.ts +2 -2
- package/dist/components/ShadowRoot.d.ts +1 -1
- package/dist/components/ShareButton/index.d.ts +1 -1
- package/dist/components/assistant-ui/thinking-indicator.d.ts +8 -0
- package/dist/components/ui/avatar.d.ts +3 -3
- package/dist/components/ui/button.d.ts +2 -2
- package/dist/components/ui/buttonVariants.d.ts +2 -2
- package/dist/components/ui/calendar.d.ts +2 -1
- package/dist/components/ui/collapsible.d.ts +3 -3
- package/dist/components/ui/dialog.d.ts +10 -10
- package/dist/components/ui/popover.d.ts +4 -4
- package/dist/components/ui/skeleton.d.ts +1 -1
- package/dist/components/ui/time-range-picker.d.ts +2 -1
- package/dist/components/ui/tool-ui.d.ts +9 -7
- package/dist/components/ui/tooltip.d.ts +4 -4
- package/dist/contexts/ConnectionStatusContext.d.ts +1 -1
- package/dist/contexts/ElementsProvider.d.ts +1 -1
- package/dist/contexts/ToolApprovalContext.d.ts +2 -2
- package/dist/contexts/ToolExecutionContext.d.ts +1 -1
- package/dist/contexts/portal-container.d.ts +1 -1
- package/dist/elements.cjs +1 -1
- package/dist/elements.css +1 -1
- package/dist/elements.js +2 -2
- package/dist/hooks/useDensity.d.ts +1 -1
- package/dist/hooks/useElements.d.ts +2 -1
- package/dist/hooks/useGramThreadListAdapter.d.ts +13 -0
- package/dist/hooks/useRadius.d.ts +1 -1
- package/dist/hooks/useThemeProps.d.ts +1 -1
- package/dist/hooks/useToolApproval.d.ts +2 -1
- package/dist/index-7fTI_vaV.cjs +194 -0
- package/dist/index-7fTI_vaV.cjs.map +1 -0
- package/dist/{index-B5lZrrO2.js → index-Bv-yE4G1.js} +2919 -2806
- package/dist/index-Bv-yE4G1.js.map +1 -0
- package/dist/{index-BFU6NvbL.js → index-BziIHO9O.js} +9621 -9308
- package/dist/index-BziIHO9O.js.map +1 -0
- package/dist/{index-C08dvTEo.cjs → index-CGBkMd0d.cjs} +48 -48
- package/dist/index-CGBkMd0d.cjs.map +1 -0
- package/dist/lib/errorTracking.d.ts +1 -1
- package/dist/lib/tools.d.ts +11 -10
- package/dist/plugins/generative-ui/catalog.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/accordion-wrapper.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/accordion.d.ts +4 -4
- package/dist/plugins/generative-ui/ui/action-button.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/alert-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/alert.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/avatar-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/avatar.d.ts +6 -6
- package/dist/plugins/generative-ui/ui/badge.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/button-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/button.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/card-wrapper.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/card.d.ts +7 -7
- package/dist/plugins/generative-ui/ui/checkbox-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/checkbox.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/data-table.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/dialog.d.ts +10 -10
- package/dist/plugins/generative-ui/ui/dropdown-menu.d.ts +15 -15
- package/dist/plugins/generative-ui/ui/grid.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/index.d.ts +57 -40
- package/dist/plugins/generative-ui/ui/input-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/input.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/label.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/list.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/metric.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/pagination.d.ts +7 -7
- package/dist/plugins/generative-ui/ui/popover.d.ts +7 -7
- package/dist/plugins/generative-ui/ui/progress.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/radio-group.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/select-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/select.d.ts +10 -10
- package/dist/plugins/generative-ui/ui/separator.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/skeleton-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/skeleton.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/stack.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/switch.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/table.d.ts +8 -8
- package/dist/plugins/generative-ui/ui/tabs-wrapper.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/tabs.d.ts +4 -4
- package/dist/plugins/generative-ui/ui/text.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/textarea.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/tooltip.d.ts +4 -4
- package/dist/plugins.cjs +1 -1
- package/dist/plugins.js +1 -1
- package/dist/{profiler-BRnyr1GA.cjs → profiler-DuJEf_S6.cjs} +2 -2
- package/dist/{profiler-BRnyr1GA.cjs.map → profiler-DuJEf_S6.cjs.map} +1 -1
- package/dist/{profiler-KLSTpp6I.js → profiler-xLXOPfmj.js} +2 -2
- package/dist/{profiler-KLSTpp6I.js.map → profiler-xLXOPfmj.js.map} +1 -1
- package/dist/react-shim.cjs.map +1 -1
- package/dist/react-shim.d.ts +1 -1
- package/dist/react-shim.js +1 -4
- package/dist/react-shim.js.map +1 -1
- package/dist/server/bun.cjs.map +1 -1
- package/dist/server/bun.js.map +1 -1
- package/dist/server/express.cjs.map +1 -1
- package/dist/server/express.js.map +1 -1
- package/dist/server/fastify.cjs.map +1 -1
- package/dist/server/fastify.js.map +1 -1
- package/dist/server/hono.cjs.map +1 -1
- package/dist/server/hono.js.map +1 -1
- package/dist/server/nextjs.cjs.map +1 -1
- package/dist/server/nextjs.js.map +1 -1
- package/dist/server/tanstack-start.cjs.map +1 -1
- package/dist/server/tanstack-start.js.map +1 -1
- package/dist/{startRecording-CKx-YWbq.cjs → startRecording-C2XF9-Ol.cjs} +2 -2
- package/dist/{startRecording-CKx-YWbq.cjs.map → startRecording-C2XF9-Ol.cjs.map} +1 -1
- package/dist/{startRecording-BfxB1xxR.js → startRecording-qKnXr4lw.js} +2 -2
- package/dist/{startRecording-BfxB1xxR.js.map → startRecording-qKnXr4lw.js.map} +1 -1
- package/dist/types/index.d.ts +29 -3
- package/package.json +8 -11
- package/src/compat-shims.ts +16 -2
- package/src/components/Chat/index.tsx +4 -1
- package/src/components/Chat/stories/FrontendTools.stories.tsx +1 -1
- package/src/components/Chat/stories/ToolApproval.stories.tsx +2 -2
- package/src/components/Chat/stories/Tools.stories.tsx +13 -5
- package/src/components/ChatHistory.tsx +3 -1
- package/src/components/FrontendTools/index.tsx +1 -1
- package/src/components/MessageContent.tsx +1 -0
- package/src/components/Replay.stories.tsx +2 -3
- package/src/components/Replay.tsx +17 -10
- package/src/components/ShadowRoot.tsx +2 -2
- package/src/components/ShareButton/index.tsx +4 -2
- package/src/components/assistant-ui/assistant-modal.tsx +5 -3
- package/src/components/assistant-ui/attachment.tsx +1 -1
- package/src/components/assistant-ui/error-boundary.tsx +1 -1
- package/src/components/assistant-ui/markdown-text.tsx +1 -1
- package/src/components/assistant-ui/thinking-indicator.tsx +175 -0
- package/src/components/assistant-ui/thread.tsx +251 -27
- package/src/components/assistant-ui/tool-fallback.tsx +8 -8
- package/src/components/assistant-ui/tool-group.tsx +4 -13
- package/src/components/assistant-ui/tool-mention-autocomplete.tsx +1 -1
- package/src/components/ui/avatar.tsx +3 -3
- package/src/components/ui/calendar.tsx +1 -1
- package/src/components/ui/collapsible.tsx +7 -3
- package/src/components/ui/dialog.tsx +18 -10
- package/src/components/ui/generative-ui.tsx +9 -4
- package/src/components/ui/popover.tsx +4 -4
- package/src/components/ui/skeleton.tsx +4 -1
- package/src/components/ui/time-range-picker.stories.tsx +164 -154
- package/src/components/ui/time-range-picker.tsx +11 -5
- package/src/components/ui/tool-ui.tsx +68 -40
- package/src/components/ui/tooltip.tsx +4 -4
- package/src/contexts/ChatIdContext.tsx +1 -1
- package/src/contexts/ConnectionStatusContext.tsx +6 -5
- package/src/contexts/ElementsProvider.tsx +64 -41
- package/src/contexts/ReplayContext.ts +1 -1
- package/src/contexts/ToolApprovalContext.tsx +5 -1
- package/src/contexts/ToolExecutionContext.tsx +1 -1
- package/src/contexts/portal-container.tsx +1 -1
- package/src/global.css +55 -16
- package/src/hooks/useAuth.ts +2 -1
- package/src/hooks/useDensity.ts +1 -1
- package/src/hooks/useElements.ts +2 -1
- package/src/hooks/useFollowOnSuggestions.ts +3 -6
- package/src/hooks/useGramThreadListAdapter.tsx +50 -3
- package/src/hooks/useMCPTools.ts +2 -2
- package/src/hooks/useModel.ts +1 -3
- package/src/hooks/usePluginComponents.ts +3 -1
- package/src/hooks/useRadius.ts +1 -1
- package/src/hooks/useSession.ts +3 -1
- package/src/hooks/useThemeProps.ts +5 -5
- package/src/hooks/useToolApproval.ts +2 -1
- package/src/lib/cassette.ts +20 -8
- package/src/lib/errorTracking.ts +1 -4
- package/src/lib/messageConverter.test.ts +11 -13
- package/src/lib/messageConverter.ts +13 -4
- package/src/lib/token.ts +2 -5
- package/src/lib/tool-mentions.ts +5 -2
- package/src/lib/tools.byte-cap.test.ts +1 -1
- package/src/lib/tools.test.ts +1 -1
- package/src/lib/tools.ts +15 -5
- package/src/lib/utils.ts +2 -2
- package/src/lib.d.ts +8 -1
- package/src/plugins/chart/chart.test.ts +3 -4
- package/src/plugins/chart/component.tsx +7 -6
- package/src/plugins/chart/ui/area-chart.tsx +1 -1
- package/src/plugins/chart/ui/line-chart.tsx +1 -1
- package/src/plugins/generative-ui/ui/accordion-wrapper.tsx +2 -2
- package/src/plugins/generative-ui/ui/accordion.tsx +4 -4
- package/src/plugins/generative-ui/ui/action-button.tsx +4 -2
- package/src/plugins/generative-ui/ui/alert-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/alert.tsx +7 -3
- package/src/plugins/generative-ui/ui/avatar-wrapper.tsx +5 -1
- package/src/plugins/generative-ui/ui/avatar.tsx +12 -6
- package/src/plugins/generative-ui/ui/badge.tsx +1 -1
- package/src/plugins/generative-ui/ui/button-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/button.tsx +1 -1
- package/src/plugins/generative-ui/ui/card-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/card.tsx +28 -7
- package/src/plugins/generative-ui/ui/checkbox-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/checkbox.tsx +1 -1
- package/src/plugins/generative-ui/ui/data-table.tsx +1 -1
- package/src/plugins/generative-ui/ui/dialog.tsx +15 -10
- package/src/plugins/generative-ui/ui/dropdown-menu.tsx +33 -15
- package/src/plugins/generative-ui/ui/grid.tsx +1 -1
- package/src/plugins/generative-ui/ui/index.ts +154 -40
- package/src/plugins/generative-ui/ui/input-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/input.tsx +5 -1
- package/src/plugins/generative-ui/ui/label.tsx +1 -1
- package/src/plugins/generative-ui/ui/list.tsx +5 -1
- package/src/plugins/generative-ui/ui/metric.tsx +2 -1
- package/src/plugins/generative-ui/ui/pagination.tsx +12 -7
- package/src/plugins/generative-ui/ui/popover.tsx +13 -7
- package/src/plugins/generative-ui/ui/progress.tsx +1 -1
- package/src/plugins/generative-ui/ui/radio-group.tsx +2 -2
- package/src/plugins/generative-ui/ui/select-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/select.tsx +14 -10
- package/src/plugins/generative-ui/ui/separator.tsx +1 -1
- package/src/plugins/generative-ui/ui/skeleton-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/skeleton.tsx +4 -1
- package/src/plugins/generative-ui/ui/stack.tsx +1 -1
- package/src/plugins/generative-ui/ui/switch.tsx +1 -1
- package/src/plugins/generative-ui/ui/table.tsx +29 -8
- package/src/plugins/generative-ui/ui/tabs-wrapper.tsx +5 -2
- package/src/plugins/generative-ui/ui/tabs.tsx +4 -4
- package/src/plugins/generative-ui/ui/text.tsx +1 -1
- package/src/plugins/generative-ui/ui/textarea.tsx +4 -1
- package/src/plugins/generative-ui/ui/tooltip.tsx +4 -4
- package/src/react-shim.ts +9 -4
- package/src/server/bun.ts +1 -1
- package/src/server/express.ts +1 -1
- package/src/server/fastify.ts +1 -1
- package/src/server/hono.ts +1 -1
- package/src/server/nextjs.ts +1 -1
- package/src/server/tanstack-start.ts +1 -1
- package/src/storybook.d.ts +5 -0
- package/src/types/index.ts +39 -3
- package/dist/index-B5lZrrO2.js.map +0 -1
- package/dist/index-BFU6NvbL.js.map +0 -1
- package/dist/index-C08dvTEo.cjs.map +0 -1
- package/dist/index-DzZ1-jQY.cjs +0 -194
- package/dist/index-DzZ1-jQY.cjs.map +0 -1
|
@@ -36,171 +36,214 @@ const meta: Meta<typeof TimeRangePicker> = {
|
|
|
36
36
|
export default meta;
|
|
37
37
|
type Story = StoryObj<typeof TimeRangePicker>;
|
|
38
38
|
|
|
39
|
+
function DefaultStory() {
|
|
40
|
+
const [preset, setPreset] = useState<DateRangePreset | null>("7d");
|
|
41
|
+
const [customRange, setCustomRange] = useState<TimeRange | null>(null);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<TimeRangePicker
|
|
45
|
+
preset={customRange ? null : preset}
|
|
46
|
+
customRange={customRange}
|
|
47
|
+
onPresetChange={(p) => {
|
|
48
|
+
setPreset(p);
|
|
49
|
+
setCustomRange(null);
|
|
50
|
+
}}
|
|
51
|
+
onCustomRangeChange={(from, to, label) => {
|
|
52
|
+
setCustomRange({ from, to });
|
|
53
|
+
setPreset(null);
|
|
54
|
+
console.log("Custom range:", { from, to, label });
|
|
55
|
+
}}
|
|
56
|
+
onClearCustomRange={() => {
|
|
57
|
+
setCustomRange(null);
|
|
58
|
+
setPreset("7d");
|
|
59
|
+
}}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
39
64
|
/**
|
|
40
65
|
* Default time range picker with preset badges and calendar.
|
|
41
66
|
* Supports natural language input with AI parsing.
|
|
42
67
|
*/
|
|
43
68
|
export const Default: Story = {
|
|
44
|
-
render: () =>
|
|
45
|
-
const [preset, setPreset] = useState<DateRangePreset | null>("7d");
|
|
46
|
-
const [customRange, setCustomRange] = useState<TimeRange | null>(null);
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<TimeRangePicker
|
|
50
|
-
preset={customRange ? null : preset}
|
|
51
|
-
customRange={customRange}
|
|
52
|
-
onPresetChange={(p) => {
|
|
53
|
-
setPreset(p);
|
|
54
|
-
setCustomRange(null);
|
|
55
|
-
}}
|
|
56
|
-
onCustomRangeChange={(from, to, label) => {
|
|
57
|
-
setCustomRange({ from, to });
|
|
58
|
-
setPreset(null);
|
|
59
|
-
console.log("Custom range:", { from, to, label });
|
|
60
|
-
}}
|
|
61
|
-
onClearCustomRange={() => {
|
|
62
|
-
setCustomRange(null);
|
|
63
|
-
setPreset("7d");
|
|
64
|
-
}}
|
|
65
|
-
/>
|
|
66
|
-
);
|
|
67
|
-
},
|
|
69
|
+
render: () => <DefaultStory />,
|
|
68
70
|
};
|
|
69
71
|
|
|
72
|
+
function WithTimezoneStory() {
|
|
73
|
+
const [preset, setPreset] = useState<DateRangePreset | null>("30d");
|
|
74
|
+
const [customRange, setCustomRange] = useState<TimeRange | null>(null);
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<TimeRangePicker
|
|
78
|
+
preset={customRange ? null : preset}
|
|
79
|
+
customRange={customRange}
|
|
80
|
+
onPresetChange={(p) => {
|
|
81
|
+
setPreset(p);
|
|
82
|
+
setCustomRange(null);
|
|
83
|
+
}}
|
|
84
|
+
onCustomRangeChange={(from, to) => {
|
|
85
|
+
setCustomRange({ from, to });
|
|
86
|
+
setPreset(null);
|
|
87
|
+
}}
|
|
88
|
+
onClearCustomRange={() => {
|
|
89
|
+
setCustomRange(null);
|
|
90
|
+
setPreset("30d");
|
|
91
|
+
}}
|
|
92
|
+
timezone="UTC-08:00"
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
70
97
|
/**
|
|
71
98
|
* Time range picker with timezone indicator.
|
|
72
99
|
*/
|
|
73
100
|
export const WithTimezone: Story = {
|
|
74
|
-
render: () =>
|
|
75
|
-
|
|
76
|
-
|
|
101
|
+
render: () => <WithTimezoneStory />,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
function WithLiveModeStory() {
|
|
105
|
+
const [preset, setPreset] = useState<DateRangePreset | null>("15m");
|
|
106
|
+
const [customRange, setCustomRange] = useState<TimeRange | null>(null);
|
|
107
|
+
const [isLive, setIsLive] = useState(true);
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<TimeRangePicker
|
|
111
|
+
preset={customRange ? null : preset}
|
|
112
|
+
customRange={customRange}
|
|
113
|
+
onPresetChange={(p) => {
|
|
114
|
+
setPreset(p);
|
|
115
|
+
setCustomRange(null);
|
|
116
|
+
}}
|
|
117
|
+
onCustomRangeChange={(from, to) => {
|
|
118
|
+
setCustomRange({ from, to });
|
|
119
|
+
setPreset(null);
|
|
120
|
+
}}
|
|
121
|
+
onClearCustomRange={() => {
|
|
122
|
+
setCustomRange(null);
|
|
123
|
+
setPreset("15m");
|
|
124
|
+
}}
|
|
125
|
+
showLive
|
|
126
|
+
isLive={isLive}
|
|
127
|
+
onLiveChange={setIsLive}
|
|
128
|
+
/>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
77
131
|
|
|
78
|
-
|
|
132
|
+
/**
|
|
133
|
+
* With LIVE mode toggle enabled.
|
|
134
|
+
*/
|
|
135
|
+
export const WithLiveMode: Story = {
|
|
136
|
+
render: () => <WithLiveModeStory />,
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Disabled state.
|
|
141
|
+
*/
|
|
142
|
+
export const Disabled: Story = {
|
|
143
|
+
args: {
|
|
144
|
+
preset: "7d",
|
|
145
|
+
disabled: true,
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
function DatadogStyleStory() {
|
|
150
|
+
const [preset, setPreset] = useState<DateRangePreset | null>("7d");
|
|
151
|
+
const [customRange, setCustomRange] = useState<TimeRange | null>(null);
|
|
152
|
+
const [customLabel, setCustomLabel] = useState<string | null>(null);
|
|
153
|
+
const [isLive, setIsLive] = useState(false);
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<div className="space-y-4">
|
|
79
157
|
<TimeRangePicker
|
|
80
158
|
preset={customRange ? null : preset}
|
|
81
159
|
customRange={customRange}
|
|
160
|
+
customRangeLabel={customLabel}
|
|
82
161
|
onPresetChange={(p) => {
|
|
83
162
|
setPreset(p);
|
|
84
163
|
setCustomRange(null);
|
|
164
|
+
setCustomLabel(null);
|
|
85
165
|
}}
|
|
86
|
-
onCustomRangeChange={(from, to) => {
|
|
166
|
+
onCustomRangeChange={(from, to, label) => {
|
|
87
167
|
setCustomRange({ from, to });
|
|
88
168
|
setPreset(null);
|
|
169
|
+
setCustomLabel(label || null);
|
|
89
170
|
}}
|
|
90
171
|
onClearCustomRange={() => {
|
|
91
172
|
setCustomRange(null);
|
|
92
|
-
setPreset("
|
|
173
|
+
setPreset("7d");
|
|
174
|
+
setCustomLabel(null);
|
|
93
175
|
}}
|
|
176
|
+
showLive
|
|
177
|
+
isLive={isLive}
|
|
178
|
+
onLiveChange={setIsLive}
|
|
94
179
|
timezone="UTC-08:00"
|
|
95
180
|
/>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
181
|
+
<div className="rounded-md bg-muted p-3 text-xs text-muted-foreground">
|
|
182
|
+
<strong>Current state:</strong>
|
|
183
|
+
<pre className="mt-1 overflow-auto">
|
|
184
|
+
{JSON.stringify(
|
|
185
|
+
{
|
|
186
|
+
preset,
|
|
187
|
+
customRange: customRange
|
|
188
|
+
? {
|
|
189
|
+
from: customRange.from.toISOString(),
|
|
190
|
+
to: customRange.to.toISOString(),
|
|
191
|
+
}
|
|
192
|
+
: null,
|
|
193
|
+
customLabel,
|
|
194
|
+
isLive,
|
|
195
|
+
},
|
|
196
|
+
null,
|
|
197
|
+
2,
|
|
198
|
+
)}
|
|
199
|
+
</pre>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
99
204
|
|
|
100
205
|
/**
|
|
101
|
-
*
|
|
206
|
+
* Full Datadog-style configuration with all features.
|
|
207
|
+
* Type natural language like "3 days ago", "last Wednesday", "past 2 weeks".
|
|
102
208
|
*/
|
|
103
|
-
export const
|
|
104
|
-
render: () =>
|
|
105
|
-
|
|
106
|
-
const [customRange, setCustomRange] = useState<TimeRange | null>(null);
|
|
107
|
-
const [isLive, setIsLive] = useState(true);
|
|
209
|
+
export const DatadogStyle: Story = {
|
|
210
|
+
render: () => <DatadogStyleStory />,
|
|
211
|
+
};
|
|
108
212
|
|
|
109
|
-
|
|
213
|
+
function NaturalLanguageParsingStory() {
|
|
214
|
+
const [preset, setPreset] = useState<DateRangePreset | null>("30d");
|
|
215
|
+
const [customRange, setCustomRange] = useState<TimeRange | null>(null);
|
|
216
|
+
const [customLabel, setCustomLabel] = useState<string | null>(null);
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<div className="space-y-4">
|
|
220
|
+
<p className="text-sm text-muted-foreground">
|
|
221
|
+
Try typing: "yesterday", "3 days ago", "last Wednesday", "January"
|
|
222
|
+
</p>
|
|
110
223
|
<TimeRangePicker
|
|
111
224
|
preset={customRange ? null : preset}
|
|
112
225
|
customRange={customRange}
|
|
226
|
+
customRangeLabel={customLabel}
|
|
113
227
|
onPresetChange={(p) => {
|
|
114
228
|
setPreset(p);
|
|
115
229
|
setCustomRange(null);
|
|
230
|
+
setCustomLabel(null);
|
|
116
231
|
}}
|
|
117
|
-
onCustomRangeChange={(from, to) => {
|
|
232
|
+
onCustomRangeChange={(from, to, label) => {
|
|
118
233
|
setCustomRange({ from, to });
|
|
119
234
|
setPreset(null);
|
|
235
|
+
setCustomLabel(label || null);
|
|
236
|
+
console.log("AI parsed:", { from, to, label });
|
|
120
237
|
}}
|
|
121
238
|
onClearCustomRange={() => {
|
|
122
239
|
setCustomRange(null);
|
|
123
|
-
setPreset("
|
|
240
|
+
setPreset("30d");
|
|
241
|
+
setCustomLabel(null);
|
|
124
242
|
}}
|
|
125
|
-
showLive
|
|
126
|
-
isLive={isLive}
|
|
127
|
-
onLiveChange={setIsLive}
|
|
128
243
|
/>
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Disabled state.
|
|
135
|
-
*/
|
|
136
|
-
export const Disabled: Story = {
|
|
137
|
-
args: {
|
|
138
|
-
preset: "7d",
|
|
139
|
-
disabled: true,
|
|
140
|
-
},
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Full Datadog-style configuration with all features.
|
|
145
|
-
* Type natural language like "3 days ago", "last Wednesday", "past 2 weeks".
|
|
146
|
-
*/
|
|
147
|
-
export const DatadogStyle: Story = {
|
|
148
|
-
render: () => {
|
|
149
|
-
const [preset, setPreset] = useState<DateRangePreset | null>("7d");
|
|
150
|
-
const [customRange, setCustomRange] = useState<TimeRange | null>(null);
|
|
151
|
-
const [customLabel, setCustomLabel] = useState<string | null>(null);
|
|
152
|
-
const [isLive, setIsLive] = useState(false);
|
|
153
|
-
|
|
154
|
-
return (
|
|
155
|
-
<div className="space-y-4">
|
|
156
|
-
<TimeRangePicker
|
|
157
|
-
preset={customRange ? null : preset}
|
|
158
|
-
customRange={customRange}
|
|
159
|
-
customRangeLabel={customLabel}
|
|
160
|
-
onPresetChange={(p) => {
|
|
161
|
-
setPreset(p);
|
|
162
|
-
setCustomRange(null);
|
|
163
|
-
setCustomLabel(null);
|
|
164
|
-
}}
|
|
165
|
-
onCustomRangeChange={(from, to, label) => {
|
|
166
|
-
setCustomRange({ from, to });
|
|
167
|
-
setPreset(null);
|
|
168
|
-
setCustomLabel(label || null);
|
|
169
|
-
}}
|
|
170
|
-
onClearCustomRange={() => {
|
|
171
|
-
setCustomRange(null);
|
|
172
|
-
setPreset("7d");
|
|
173
|
-
setCustomLabel(null);
|
|
174
|
-
}}
|
|
175
|
-
showLive
|
|
176
|
-
isLive={isLive}
|
|
177
|
-
onLiveChange={setIsLive}
|
|
178
|
-
timezone="UTC-08:00"
|
|
179
|
-
/>
|
|
180
|
-
<div className="rounded-md bg-muted p-3 text-xs text-muted-foreground">
|
|
181
|
-
<strong>Current state:</strong>
|
|
182
|
-
<pre className="mt-1 overflow-auto">
|
|
183
|
-
{JSON.stringify(
|
|
184
|
-
{
|
|
185
|
-
preset,
|
|
186
|
-
customRange: customRange
|
|
187
|
-
? {
|
|
188
|
-
from: customRange.from.toISOString(),
|
|
189
|
-
to: customRange.to.toISOString(),
|
|
190
|
-
}
|
|
191
|
-
: null,
|
|
192
|
-
customLabel,
|
|
193
|
-
isLive,
|
|
194
|
-
},
|
|
195
|
-
null,
|
|
196
|
-
2,
|
|
197
|
-
)}
|
|
198
|
-
</pre>
|
|
199
|
-
</div>
|
|
200
|
-
</div>
|
|
201
|
-
);
|
|
202
|
-
},
|
|
203
|
-
};
|
|
244
|
+
</div>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
204
247
|
|
|
205
248
|
/**
|
|
206
249
|
* Natural language parsing demo.
|
|
@@ -212,38 +255,5 @@ export const DatadogStyle: Story = {
|
|
|
212
255
|
* - "January 2024"
|
|
213
256
|
*/
|
|
214
257
|
export const NaturalLanguageParsing: Story = {
|
|
215
|
-
render: () =>
|
|
216
|
-
const [preset, setPreset] = useState<DateRangePreset | null>("30d");
|
|
217
|
-
const [customRange, setCustomRange] = useState<TimeRange | null>(null);
|
|
218
|
-
const [customLabel, setCustomLabel] = useState<string | null>(null);
|
|
219
|
-
|
|
220
|
-
return (
|
|
221
|
-
<div className="space-y-4">
|
|
222
|
-
<p className="text-sm text-muted-foreground">
|
|
223
|
-
Try typing: "yesterday", "3 days ago", "last Wednesday", "January"
|
|
224
|
-
</p>
|
|
225
|
-
<TimeRangePicker
|
|
226
|
-
preset={customRange ? null : preset}
|
|
227
|
-
customRange={customRange}
|
|
228
|
-
customRangeLabel={customLabel}
|
|
229
|
-
onPresetChange={(p) => {
|
|
230
|
-
setPreset(p);
|
|
231
|
-
setCustomRange(null);
|
|
232
|
-
setCustomLabel(null);
|
|
233
|
-
}}
|
|
234
|
-
onCustomRangeChange={(from, to, label) => {
|
|
235
|
-
setCustomRange({ from, to });
|
|
236
|
-
setPreset(null);
|
|
237
|
-
setCustomLabel(label || null);
|
|
238
|
-
console.log("AI parsed:", { from, to, label });
|
|
239
|
-
}}
|
|
240
|
-
onClearCustomRange={() => {
|
|
241
|
-
setCustomRange(null);
|
|
242
|
-
setPreset("30d");
|
|
243
|
-
setCustomLabel(null);
|
|
244
|
-
}}
|
|
245
|
-
/>
|
|
246
|
-
</div>
|
|
247
|
-
);
|
|
248
|
-
},
|
|
258
|
+
render: () => <NaturalLanguageParsingStory />,
|
|
249
259
|
};
|
|
@@ -155,7 +155,7 @@ const BADGE_WIDTH = "min-w-10";
|
|
|
155
155
|
|
|
156
156
|
export function getPresetRange(preset: DateRangePreset): TimeRange {
|
|
157
157
|
const p = PRESETS.find((p) => p.value === preset);
|
|
158
|
-
return p ? p.getRange() : PRESETS[5]
|
|
158
|
+
return p ? p.getRange() : PRESETS[5]!.getRange(); // Default to 3d
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
function getPresetByValue(value: DateRangePreset): TimeRangePreset | undefined {
|
|
@@ -188,11 +188,15 @@ function parseAsLocalDate(isoString: string): Date {
|
|
|
188
188
|
// Try to extract just the date part and create a local date
|
|
189
189
|
const dateMatch = isoString.match(/^(\d{4})-(\d{2})-(\d{2})/);
|
|
190
190
|
if (dateMatch) {
|
|
191
|
-
const
|
|
191
|
+
const year = dateMatch[1]!;
|
|
192
|
+
const month = dateMatch[2]!;
|
|
193
|
+
const day = dateMatch[3]!;
|
|
192
194
|
// Check if there's a time component
|
|
193
195
|
const timeMatch = isoString.match(/T(\d{2}):(\d{2}):?(\d{2})?/);
|
|
194
196
|
if (timeMatch) {
|
|
195
|
-
const
|
|
197
|
+
const hours = timeMatch[1]!;
|
|
198
|
+
const minutes = timeMatch[2]!;
|
|
199
|
+
const seconds = timeMatch[3] ?? "0";
|
|
196
200
|
return new Date(
|
|
197
201
|
parseInt(year),
|
|
198
202
|
parseInt(month) - 1,
|
|
@@ -372,7 +376,7 @@ function TimeRangePicker({
|
|
|
372
376
|
projectSlug,
|
|
373
377
|
authHeaders,
|
|
374
378
|
className,
|
|
375
|
-
}: TimeRangePickerProps) {
|
|
379
|
+
}: TimeRangePickerProps): React.JSX.Element {
|
|
376
380
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
377
381
|
const [showCalendar, setShowCalendar] = React.useState(false);
|
|
378
382
|
const [inputValue, setInputValue] = React.useState("");
|
|
@@ -585,7 +589,9 @@ function TimeRangePicker({
|
|
|
585
589
|
onClick={handleInputClick}
|
|
586
590
|
onFocus={handleInputFocus}
|
|
587
591
|
onBlur={handleInputBlur}
|
|
588
|
-
onKeyDown={
|
|
592
|
+
onKeyDown={(e) => {
|
|
593
|
+
void handleInputKeyDown(e);
|
|
594
|
+
}}
|
|
589
595
|
placeholder="e.g., 3 days ago, last week..."
|
|
590
596
|
disabled={disabled}
|
|
591
597
|
className={cn(
|
|
@@ -159,7 +159,11 @@ function isStructuredContent(
|
|
|
159
159
|
* Helper Components
|
|
160
160
|
* -------------------------------------------------------------------------- */
|
|
161
161
|
|
|
162
|
-
function StatusIndicator({
|
|
162
|
+
function StatusIndicator({
|
|
163
|
+
status,
|
|
164
|
+
}: {
|
|
165
|
+
status: ToolStatus;
|
|
166
|
+
}): React.JSX.Element {
|
|
163
167
|
return (
|
|
164
168
|
<div className={cn(statusVariants({ status }))}>
|
|
165
169
|
{status === "pending" && null}
|
|
@@ -173,7 +177,7 @@ function StatusIndicator({ status }: { status: ToolStatus }) {
|
|
|
173
177
|
);
|
|
174
178
|
}
|
|
175
179
|
|
|
176
|
-
function CopyButton({ content }: { content: string }) {
|
|
180
|
+
function CopyButton({ content }: { content: string }): React.JSX.Element {
|
|
177
181
|
const [copied, setCopied] = useState(false);
|
|
178
182
|
|
|
179
183
|
const handleCopy = async (e: React.MouseEvent) => {
|
|
@@ -185,7 +189,9 @@ function CopyButton({ content }: { content: string }) {
|
|
|
185
189
|
|
|
186
190
|
return (
|
|
187
191
|
<button
|
|
188
|
-
onClick={
|
|
192
|
+
onClick={(e) => {
|
|
193
|
+
void handleCopy(e);
|
|
194
|
+
}}
|
|
189
195
|
className="rounded p-1 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
|
|
190
196
|
aria-label="Copy to clipboard"
|
|
191
197
|
>
|
|
@@ -226,7 +232,7 @@ function SyntaxHighlightedCode({
|
|
|
226
232
|
text: string;
|
|
227
233
|
language?: BundledLanguage;
|
|
228
234
|
className?: string;
|
|
229
|
-
}) {
|
|
235
|
+
}): React.JSX.Element {
|
|
230
236
|
const [highlightedCode, setHighlightedCode] = useState<string | null>(null);
|
|
231
237
|
const [expanded, setExpanded] = useState(false);
|
|
232
238
|
|
|
@@ -241,7 +247,7 @@ function SyntaxHighlightedCode({
|
|
|
241
247
|
setHighlightedCode(null);
|
|
242
248
|
if (!language || !canHighlight) return;
|
|
243
249
|
let cancelled = false;
|
|
244
|
-
codeToHtml(displayText, {
|
|
250
|
+
void codeToHtml(displayText, {
|
|
245
251
|
lang: language,
|
|
246
252
|
theme: "github-dark-default",
|
|
247
253
|
rootStyle: "background-color: transparent;",
|
|
@@ -370,7 +376,7 @@ function ToolUISection({
|
|
|
370
376
|
defaultExpanded = false,
|
|
371
377
|
highlightSyntax = true,
|
|
372
378
|
language = "json",
|
|
373
|
-
}: ToolUISectionProps) {
|
|
379
|
+
}: ToolUISectionProps): React.JSX.Element {
|
|
374
380
|
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
|
375
381
|
|
|
376
382
|
// For structured content, we don't stringify it
|
|
@@ -434,7 +440,7 @@ function ToolUI({
|
|
|
434
440
|
onApproveOnce,
|
|
435
441
|
onApproveForSession,
|
|
436
442
|
onDeny,
|
|
437
|
-
}: ToolUIProps) {
|
|
443
|
+
}: ToolUIProps): React.JSX.Element {
|
|
438
444
|
// Use annotation title if available, otherwise fall back to name
|
|
439
445
|
const displayName = annotations?.title || name;
|
|
440
446
|
const isApprovalPending =
|
|
@@ -455,6 +461,7 @@ function ToolUI({
|
|
|
455
461
|
if (!isApprovalPending && isExpanded && !defaultExpanded) {
|
|
456
462
|
setIsExpanded(false);
|
|
457
463
|
}
|
|
464
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps -- only react to approval transition; defaultExpanded/isExpanded are intentionally not deps
|
|
458
465
|
}, [isApprovalPending]);
|
|
459
466
|
|
|
460
467
|
// Handle approve based on selected mode
|
|
@@ -497,7 +504,9 @@ function ToolUI({
|
|
|
497
504
|
|
|
498
505
|
{/* Tool row */}
|
|
499
506
|
<button
|
|
500
|
-
onClick={() =>
|
|
507
|
+
onClick={() => {
|
|
508
|
+
if (hasContent) setIsExpanded(!isExpanded);
|
|
509
|
+
}}
|
|
501
510
|
disabled={!hasContent}
|
|
502
511
|
className={cn(
|
|
503
512
|
"flex w-full items-center gap-2 px-4 py-3 text-left",
|
|
@@ -702,6 +711,8 @@ interface ToolUIGroupProps {
|
|
|
702
711
|
status?: "running" | "complete";
|
|
703
712
|
/** Whether the group starts expanded */
|
|
704
713
|
defaultExpanded?: boolean;
|
|
714
|
+
/** Render without the group header, showing children directly. */
|
|
715
|
+
headerless?: boolean;
|
|
705
716
|
/** Child tool UI components */
|
|
706
717
|
children: React.ReactNode;
|
|
707
718
|
/** Additional class names */
|
|
@@ -713,11 +724,23 @@ function ToolUIGroup({
|
|
|
713
724
|
icon,
|
|
714
725
|
status = "complete",
|
|
715
726
|
defaultExpanded = false,
|
|
727
|
+
headerless = false,
|
|
716
728
|
children,
|
|
717
729
|
className,
|
|
718
|
-
}: ToolUIGroupProps) {
|
|
730
|
+
}: ToolUIGroupProps): React.JSX.Element {
|
|
719
731
|
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
|
720
732
|
|
|
733
|
+
// A headerless group shows its children unconditionally; when it gains a
|
|
734
|
+
// header mid-stream, start expanded — collapsing would hide content the
|
|
735
|
+
// user was already looking at.
|
|
736
|
+
const [prevHeaderless, setPrevHeaderless] = useState(headerless);
|
|
737
|
+
if (prevHeaderless !== headerless) {
|
|
738
|
+
setPrevHeaderless(headerless);
|
|
739
|
+
if (prevHeaderless) setIsExpanded(true);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
const showChildren = headerless || isExpanded;
|
|
743
|
+
|
|
721
744
|
return (
|
|
722
745
|
<div
|
|
723
746
|
data-slot="tool-ui-group"
|
|
@@ -727,40 +750,45 @@ function ToolUIGroup({
|
|
|
727
750
|
)}
|
|
728
751
|
>
|
|
729
752
|
{/* Group header */}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
<StatusIndicator
|
|
736
|
-
status={status === "running" ? "running" : "complete"}
|
|
737
|
-
/>
|
|
738
|
-
)}
|
|
739
|
-
<span
|
|
740
|
-
className={cn(
|
|
741
|
-
"flex-1 text-sm font-medium",
|
|
742
|
-
status === "running" && "shimmer",
|
|
743
|
-
)}
|
|
753
|
+
{!headerless && (
|
|
754
|
+
<button
|
|
755
|
+
onClick={() => setIsExpanded(!isExpanded)}
|
|
756
|
+
aria-expanded={isExpanded}
|
|
757
|
+
className="flex w-full items-center gap-2 px-4 py-3 text-left transition-colors hover:bg-accent/50"
|
|
744
758
|
>
|
|
745
|
-
{
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
"size-4 text-muted-foreground transition-transform duration-200",
|
|
750
|
-
isExpanded && "rotate-180",
|
|
759
|
+
{icon || (
|
|
760
|
+
<StatusIndicator
|
|
761
|
+
status={status === "running" ? "running" : "complete"}
|
|
762
|
+
/>
|
|
751
763
|
)}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
764
|
+
<span
|
|
765
|
+
className={cn(
|
|
766
|
+
"flex-1 text-sm font-medium",
|
|
767
|
+
status === "running" && "shimmer",
|
|
768
|
+
)}
|
|
769
|
+
>
|
|
770
|
+
{title}
|
|
771
|
+
</span>
|
|
772
|
+
<ChevronDownIcon
|
|
773
|
+
className={cn(
|
|
774
|
+
"size-4 text-muted-foreground transition-transform duration-200",
|
|
775
|
+
isExpanded && "rotate-180",
|
|
776
|
+
)}
|
|
777
|
+
/>
|
|
778
|
+
</button>
|
|
763
779
|
)}
|
|
780
|
+
|
|
781
|
+
{/* Collapsed children are hidden, not unmounted — unmounting would
|
|
782
|
+
reset their state (expansion, async syntax highlighting). */}
|
|
783
|
+
<div
|
|
784
|
+
data-slot="tool-ui-group-content"
|
|
785
|
+
className={cn(
|
|
786
|
+
!headerless && "border-t border-border",
|
|
787
|
+
!showChildren && "hidden",
|
|
788
|
+
)}
|
|
789
|
+
>
|
|
790
|
+
{children}
|
|
791
|
+
</div>
|
|
764
792
|
</div>
|
|
765
793
|
);
|
|
766
794
|
}
|
|
@@ -9,7 +9,7 @@ import { usePortalContainer } from "@/hooks/usePortalContainer";
|
|
|
9
9
|
function TooltipProvider({
|
|
10
10
|
delayDuration = 0,
|
|
11
11
|
...props
|
|
12
|
-
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
|
|
12
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Provider>): React.JSX.Element {
|
|
13
13
|
return (
|
|
14
14
|
<TooltipPrimitive.Provider
|
|
15
15
|
data-slot="tooltip-provider"
|
|
@@ -21,7 +21,7 @@ function TooltipProvider({
|
|
|
21
21
|
|
|
22
22
|
function Tooltip({
|
|
23
23
|
...props
|
|
24
|
-
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
|
24
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Root>): React.JSX.Element {
|
|
25
25
|
return (
|
|
26
26
|
<TooltipProvider>
|
|
27
27
|
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
|
@@ -31,7 +31,7 @@ function Tooltip({
|
|
|
31
31
|
|
|
32
32
|
function TooltipTrigger({
|
|
33
33
|
...props
|
|
34
|
-
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
|
34
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>): React.JSX.Element {
|
|
35
35
|
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -43,7 +43,7 @@ function TooltipContent({
|
|
|
43
43
|
...props
|
|
44
44
|
}: React.ComponentProps<typeof TooltipPrimitive.Content> & {
|
|
45
45
|
container?: HTMLElement | null;
|
|
46
|
-
}) {
|
|
46
|
+
}): React.JSX.Element {
|
|
47
47
|
const portalContainer = usePortalContainer();
|
|
48
48
|
return (
|
|
49
49
|
<TooltipPrimitive.Portal container={container ?? portalContainer}>
|
|
@@ -12,7 +12,7 @@ export const ChatIdContext = createContext<ChatIdContextValue | null>(null);
|
|
|
12
12
|
*
|
|
13
13
|
* @returns The current chat ID, or null if not yet initialized
|
|
14
14
|
*/
|
|
15
|
-
export const useChatId = () => {
|
|
15
|
+
export const useChatId = (): string | null => {
|
|
16
16
|
const context = useContext(ChatIdContext);
|
|
17
17
|
if (!context) {
|
|
18
18
|
throw new Error("useChatId must be used within ElementsProvider");
|
|
@@ -36,7 +36,7 @@ interface ConnectionStatusProviderProps {
|
|
|
36
36
|
|
|
37
37
|
export const ConnectionStatusProvider = ({
|
|
38
38
|
children,
|
|
39
|
-
}: ConnectionStatusProviderProps) => {
|
|
39
|
+
}: ConnectionStatusProviderProps): React.JSX.Element => {
|
|
40
40
|
const [state, setState] = useState<ConnectionState>("connected");
|
|
41
41
|
const [retryCount, setRetryCount] = useState(0);
|
|
42
42
|
const [isOnline, setIsOnline] = useState(
|
|
@@ -138,7 +138,7 @@ export const ConnectionStatusProvider = ({
|
|
|
138
138
|
);
|
|
139
139
|
};
|
|
140
140
|
|
|
141
|
-
export const useConnectionStatus = () => {
|
|
141
|
+
export const useConnectionStatus = (): ConnectionStatusContextValue => {
|
|
142
142
|
const context = useContext(ConnectionStatusContext);
|
|
143
143
|
if (!context) {
|
|
144
144
|
throw new Error(
|
|
@@ -153,6 +153,7 @@ export const useConnectionStatus = () => {
|
|
|
153
153
|
* Returns null if not within a ConnectionStatusProvider (for backwards compatibility).
|
|
154
154
|
*/
|
|
155
155
|
|
|
156
|
-
export const useConnectionStatusOptional =
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
export const useConnectionStatusOptional =
|
|
157
|
+
(): ConnectionStatusContextValue | null => {
|
|
158
|
+
return useContext(ConnectionStatusContext);
|
|
159
|
+
};
|