@djangocfg/ui-tools 2.1.390 → 2.1.394

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.
Files changed (184) hide show
  1. package/README.md +7 -10
  2. package/dist/chunk-PAWJFY3S.mjs +6 -0
  3. package/dist/{chunk-N2XQF2OL.mjs.map → chunk-PAWJFY3S.mjs.map} +1 -1
  4. package/dist/chunk-PK6SKIKE.cjs +8 -0
  5. package/dist/{chunk-OLISEQHS.cjs.map → chunk-PK6SKIKE.cjs.map} +1 -1
  6. package/dist/file-icon/index.cjs +6 -6
  7. package/dist/file-icon/index.d.cts +1 -1
  8. package/dist/file-icon/index.d.ts +1 -1
  9. package/dist/file-icon/index.mjs +1 -1
  10. package/dist/tree/index.cjs +1372 -143
  11. package/dist/tree/index.cjs.map +1 -1
  12. package/dist/tree/index.d.cts +2 -2
  13. package/dist/tree/index.d.ts +2 -2
  14. package/dist/tree/index.mjs +1322 -3
  15. package/dist/tree/index.mjs.map +1 -1
  16. package/dist/{types-CevSbyfD.d.cts → types-B_zhyAqR.d.cts} +1 -1
  17. package/dist/{types-CevSbyfD.d.ts → types-B_zhyAqR.d.ts} +1 -1
  18. package/package.json +6 -14
  19. package/src/tools/AudioPlayer/README.md +4 -4
  20. package/src/tools/Chat/README.md +6 -6
  21. package/src/tools/CronScheduler/index.tsx +1 -1
  22. package/src/tools/CronScheduler/lazy.tsx +1 -1
  23. package/src/tools/ImageViewer/README.md +1 -1
  24. package/src/tools/JsonForm/README.md +2 -2
  25. package/src/tools/MarkdownEditor/README.md +3 -3
  26. package/src/tools/MarkdownMessage/README.md +2 -2
  27. package/src/tools/OpenapiViewer/components/DocsLayout/grouping.ts +5 -1
  28. package/src/tools/PrettyCode/lazy.tsx +6 -0
  29. package/src/tools/SpeechRecognition/README.md +1 -1
  30. package/dist/ChatRoot-EFNXQXXN.cjs +0 -15
  31. package/dist/ChatRoot-EFNXQXXN.cjs.map +0 -1
  32. package/dist/ChatRoot-FITF5RVP.mjs +0 -6
  33. package/dist/ChatRoot-FITF5RVP.mjs.map +0 -1
  34. package/dist/ChatRoot-PNNGQCYF.css +0 -7
  35. package/dist/ChatRoot-PNNGQCYF.css.map +0 -1
  36. package/dist/CronScheduler.client-DLMXCPAJ.mjs +0 -67
  37. package/dist/CronScheduler.client-DLMXCPAJ.mjs.map +0 -1
  38. package/dist/CronScheduler.client-WEJF4PWQ.cjs +0 -72
  39. package/dist/CronScheduler.client-WEJF4PWQ.cjs.map +0 -1
  40. package/dist/DictationField-AS2F33WI.cjs +0 -13
  41. package/dist/DictationField-AS2F33WI.cjs.map +0 -1
  42. package/dist/DictationField-WPONUCYE.mjs +0 -4
  43. package/dist/DictationField-WPONUCYE.mjs.map +0 -1
  44. package/dist/DocsLayout-EKASBSP7.mjs +0 -3448
  45. package/dist/DocsLayout-EKASBSP7.mjs.map +0 -1
  46. package/dist/DocsLayout-MBFIB4NO.css +0 -7
  47. package/dist/DocsLayout-MBFIB4NO.css.map +0 -1
  48. package/dist/DocsLayout-OURFYWQE.cjs +0 -3455
  49. package/dist/DocsLayout-OURFYWQE.cjs.map +0 -1
  50. package/dist/JsonSchemaForm-DD7CLRIG.cjs +0 -13
  51. package/dist/JsonSchemaForm-DD7CLRIG.cjs.map +0 -1
  52. package/dist/JsonSchemaForm-XKUIVELK.mjs +0 -4
  53. package/dist/JsonSchemaForm-XKUIVELK.mjs.map +0 -1
  54. package/dist/JsonTree-43PQAJKY.mjs +0 -5
  55. package/dist/JsonTree-43PQAJKY.mjs.map +0 -1
  56. package/dist/JsonTree-MLET23ZA.css +0 -7
  57. package/dist/JsonTree-MLET23ZA.css.map +0 -1
  58. package/dist/JsonTree-X6W5YEVY.cjs +0 -11
  59. package/dist/JsonTree-X6W5YEVY.cjs.map +0 -1
  60. package/dist/LottiePlayer.client-2S7ISJ2S.cjs +0 -168
  61. package/dist/LottiePlayer.client-2S7ISJ2S.cjs.map +0 -1
  62. package/dist/LottiePlayer.client-5LDSSJWS.mjs +0 -161
  63. package/dist/LottiePlayer.client-5LDSSJWS.mjs.map +0 -1
  64. package/dist/MapContainer-AKIPABJK.mjs +0 -4
  65. package/dist/MapContainer-AKIPABJK.mjs.map +0 -1
  66. package/dist/MapContainer-STVDMC36.cjs +0 -17
  67. package/dist/MapContainer-STVDMC36.cjs.map +0 -1
  68. package/dist/Mermaid.client-DDXWXZXY.css +0 -7
  69. package/dist/Mermaid.client-DDXWXZXY.css.map +0 -1
  70. package/dist/Mermaid.client-NL4SVR7F.mjs +0 -481
  71. package/dist/Mermaid.client-NL4SVR7F.mjs.map +0 -1
  72. package/dist/Mermaid.client-NNTI6DFX.cjs +0 -487
  73. package/dist/Mermaid.client-NNTI6DFX.cjs.map +0 -1
  74. package/dist/Player-BRV7XTWR.mjs +0 -4
  75. package/dist/Player-BRV7XTWR.mjs.map +0 -1
  76. package/dist/Player-PM7F7DD7.cjs +0 -13
  77. package/dist/Player-PM7F7DD7.cjs.map +0 -1
  78. package/dist/Player-ZGQKKOWI.css +0 -66
  79. package/dist/Player-ZGQKKOWI.css.map +0 -1
  80. package/dist/PrettyCode.client-GWFAIVFN.css +0 -7
  81. package/dist/PrettyCode.client-GWFAIVFN.css.map +0 -1
  82. package/dist/PrettyCode.client-KOHDVPPN.cjs +0 -285
  83. package/dist/PrettyCode.client-KOHDVPPN.cjs.map +0 -1
  84. package/dist/PrettyCode.client-ZGYGKE7G.mjs +0 -283
  85. package/dist/PrettyCode.client-ZGYGKE7G.mjs.map +0 -1
  86. package/dist/TreeRoot-5COOOSWG.mjs +0 -4
  87. package/dist/TreeRoot-5COOOSWG.mjs.map +0 -1
  88. package/dist/TreeRoot-AABP2J6Y.cjs +0 -19
  89. package/dist/TreeRoot-AABP2J6Y.cjs.map +0 -1
  90. package/dist/chunk-2NG4SXEP.mjs +0 -743
  91. package/dist/chunk-2NG4SXEP.mjs.map +0 -1
  92. package/dist/chunk-4LFB7I5K.cjs +0 -1387
  93. package/dist/chunk-4LFB7I5K.cjs.map +0 -1
  94. package/dist/chunk-5D2OCOPQ.cjs +0 -222
  95. package/dist/chunk-5D2OCOPQ.cjs.map +0 -1
  96. package/dist/chunk-5I5QNGUG.cjs +0 -611
  97. package/dist/chunk-5I5QNGUG.cjs.map +0 -1
  98. package/dist/chunk-6ZX2G25W.mjs +0 -1361
  99. package/dist/chunk-6ZX2G25W.mjs.map +0 -1
  100. package/dist/chunk-76NNDZH6.cjs +0 -1061
  101. package/dist/chunk-76NNDZH6.cjs.map +0 -1
  102. package/dist/chunk-7CWGZPO3.mjs +0 -214
  103. package/dist/chunk-7CWGZPO3.mjs.map +0 -1
  104. package/dist/chunk-7EYHNP3E.cjs +0 -965
  105. package/dist/chunk-7EYHNP3E.cjs.map +0 -1
  106. package/dist/chunk-7IYXZUJO.cjs +0 -769
  107. package/dist/chunk-7IYXZUJO.cjs.map +0 -1
  108. package/dist/chunk-ADEN3UA4.cjs +0 -892
  109. package/dist/chunk-ADEN3UA4.cjs.map +0 -1
  110. package/dist/chunk-B6IR5KSC.mjs +0 -59
  111. package/dist/chunk-B6IR5KSC.mjs.map +0 -1
  112. package/dist/chunk-C6GXVH5J.mjs +0 -338
  113. package/dist/chunk-C6GXVH5J.mjs.map +0 -1
  114. package/dist/chunk-DMX7W4XZ.mjs +0 -1113
  115. package/dist/chunk-DMX7W4XZ.mjs.map +0 -1
  116. package/dist/chunk-ECONRHIG.mjs +0 -212
  117. package/dist/chunk-ECONRHIG.mjs.map +0 -1
  118. package/dist/chunk-FEN5S772.cjs +0 -1227
  119. package/dist/chunk-FEN5S772.cjs.map +0 -1
  120. package/dist/chunk-FP2RLYQZ.cjs +0 -187
  121. package/dist/chunk-FP2RLYQZ.cjs.map +0 -1
  122. package/dist/chunk-FVVF7VCD.cjs +0 -1325
  123. package/dist/chunk-FVVF7VCD.cjs.map +0 -1
  124. package/dist/chunk-GYIO7W7M.mjs +0 -1197
  125. package/dist/chunk-GYIO7W7M.mjs.map +0 -1
  126. package/dist/chunk-KNDLV4PI.cjs +0 -1356
  127. package/dist/chunk-KNDLV4PI.cjs.map +0 -1
  128. package/dist/chunk-KNEQRUBA.mjs +0 -181
  129. package/dist/chunk-KNEQRUBA.mjs.map +0 -1
  130. package/dist/chunk-N2XQF2OL.mjs +0 -14
  131. package/dist/chunk-N4MZYNR4.mjs +0 -1342
  132. package/dist/chunk-N4MZYNR4.mjs.map +0 -1
  133. package/dist/chunk-NTVBIIUD.mjs +0 -1439
  134. package/dist/chunk-NTVBIIUD.mjs.map +0 -1
  135. package/dist/chunk-OBRSGM64.mjs +0 -607
  136. package/dist/chunk-OBRSGM64.mjs.map +0 -1
  137. package/dist/chunk-ODO4GMW7.mjs +0 -79
  138. package/dist/chunk-ODO4GMW7.mjs.map +0 -1
  139. package/dist/chunk-OLISEQHS.cjs +0 -18
  140. package/dist/chunk-PVAX67JG.mjs +0 -1041
  141. package/dist/chunk-PVAX67JG.mjs.map +0 -1
  142. package/dist/chunk-QJ6GTUCO.cjs +0 -81
  143. package/dist/chunk-QJ6GTUCO.cjs.map +0 -1
  144. package/dist/chunk-T3MWM23F.cjs +0 -214
  145. package/dist/chunk-T3MWM23F.cjs.map +0 -1
  146. package/dist/chunk-TBSHZO5R.cjs +0 -1134
  147. package/dist/chunk-TBSHZO5R.cjs.map +0 -1
  148. package/dist/chunk-UNCS5V5F.mjs +0 -887
  149. package/dist/chunk-UNCS5V5F.mjs.map +0 -1
  150. package/dist/chunk-VWQ5WOIL.mjs +0 -2059
  151. package/dist/chunk-VWQ5WOIL.mjs.map +0 -1
  152. package/dist/chunk-W75B7Y6C.cjs +0 -1478
  153. package/dist/chunk-W75B7Y6C.cjs.map +0 -1
  154. package/dist/chunk-Y6UTOBF6.mjs +0 -938
  155. package/dist/chunk-Y6UTOBF6.mjs.map +0 -1
  156. package/dist/chunk-YDPDTOSP.cjs +0 -2061
  157. package/dist/chunk-YDPDTOSP.cjs.map +0 -1
  158. package/dist/chunk-YW5IVWHQ.cjs +0 -346
  159. package/dist/chunk-YW5IVWHQ.cjs.map +0 -1
  160. package/dist/chunk-YXZ6GU7H.cjs +0 -63
  161. package/dist/chunk-YXZ6GU7H.cjs.map +0 -1
  162. package/dist/chunk-ZL7FH4NW.mjs +0 -1274
  163. package/dist/chunk-ZL7FH4NW.mjs.map +0 -1
  164. package/dist/components-EHOGXATG.cjs +0 -22
  165. package/dist/components-EHOGXATG.cjs.map +0 -1
  166. package/dist/components-MQ6DR7TX.cjs +0 -26
  167. package/dist/components-MQ6DR7TX.cjs.map +0 -1
  168. package/dist/components-XRX7QGLB.mjs +0 -5
  169. package/dist/components-XRX7QGLB.mjs.map +0 -1
  170. package/dist/components-YATKRWLH.mjs +0 -5
  171. package/dist/components-YATKRWLH.mjs.map +0 -1
  172. package/dist/index.cjs +0 -3674
  173. package/dist/index.cjs.map +0 -1
  174. package/dist/index.css +0 -234
  175. package/dist/index.css.map +0 -1
  176. package/dist/index.d.cts +0 -4929
  177. package/dist/index.d.ts +0 -4929
  178. package/dist/index.mjs +0 -2912
  179. package/dist/index.mjs.map +0 -1
  180. package/dist/launcher-5Y42OBSN.mjs +0 -6
  181. package/dist/launcher-5Y42OBSN.mjs.map +0 -1
  182. package/dist/launcher-PMW2YB24.cjs +0 -59
  183. package/dist/launcher-PMW2YB24.cjs.map +0 -1
  184. package/src/index.ts +0 -157
package/dist/index.mjs DELETED
@@ -1,2912 +0,0 @@
1
- import { createLazyComponent, MapLoadingFallback, CardLoadingFallback, LoadingFallback } from './chunk-NTVBIIUD.mjs';
2
- export { CardLoadingFallback, ChatDock, ChatFAB, ChatGreeting, ChatHeader, ChatHeaderActionButton, ChatHeaderAudioToggle, ChatHeaderLanguageButton, ChatHeaderModeToggle, ChatHeaderResetButton, ChatLauncher, ChatUnreadPreview, LazyWrapper, LoadingFallback, MapLoadingFallback, Spinner, createLazyComponent, useChatPresence, useChatReset } from './chunk-NTVBIIUD.mjs';
3
- export { Attachments, AttachmentsGrid, AttachmentsList, ChatRoot, Composer, EmptyState, ErrorBanner, JumpToLatest, MessageActions, MessageBubble, MessageList, Sources, StreamingIndicator, ToolCalls, deriveInitials, isSubmittableDraft, resolvePersona, sanitizeDraft, useAutoFocusOnStreamEnd, useChatBubbleStyles, useChatComposer, useChatDestructiveStyles, useChatRoleStyles, useFocusOnEmptyClick, useRegisterComposer } from './chunk-6ZX2G25W.mjs';
4
- import { LIMITS, createId, useChatContext, useChatContextOptional } from './chunk-DMX7W4XZ.mjs';
5
- export { CHAT_EVENT_NAME, CSS_VARS, ChatProvider, DEFAULT_CHAT_SOUNDS, DEFAULT_LABELS, DEFAULT_SIDEBAR, DEFAULT_Z_INDEX, HOTKEYS, LIMITS, STORAGE_KEYS, createId, createTokenBuffer, getChatLogger, initialState, reducer, useChat, useChatAudio, useChatContext, useChatContextOptional, useChatLayout } from './chunk-DMX7W4XZ.mjs';
6
- export { ArrayFieldItemTemplate, ArrayFieldTemplate, BaseInputTemplate, CheckboxWidget, ColorWidget, ErrorListTemplate, FieldTemplate, JsonSchemaForm, NumberWidget, ObjectFieldTemplate, SelectWidget, SliderWidget, SwitchWidget, TextWidget, evaluateDisabledWhen, getRequiredFields, hasRequiredFields, mergeDefaults, normalizeFormData, safeJsonParse, safeJsonStringify, validateRequiredFields, validateSchema } from './chunk-GYIO7W7M.mjs';
7
- export { useLottie } from './chunk-ODO4GMW7.mjs';
8
- export { Player as AudioPlayer } from './chunk-VWQ5WOIL.mjs';
9
- export { NativeProvider, StreamProvider, VideoControls, VideoErrorFallback, VideoPlayer, VideoPlayerProvider, VidstackProvider, createVideoErrorFallback, isSimpleStreamSource, resolveFileSource, resolvePlayerMode, resolveStreamSource, useVideoPlayerContext } from './chunk-N4MZYNR4.mjs';
10
- export { ImageViewer } from './chunk-OBRSGM64.mjs';
11
- export { generateContentKey, useAudioCache, useBlobUrlCleanup, useImageCache, useMediaCacheStore, useVideoCache, useVideoPlayerSettings } from './chunk-C6GXVH5J.mjs';
12
- export { CronSchedulerProvider, CustomInput, DayChips, MonthDayGrid, SchedulePreview, ScheduleTypeSelector, TimeSelector, buildCron, humanizeCron, isValidCron, parseCron, useCronCustom, useCronMonthDays, useCronPreview, useCronScheduler, useCronSchedulerContext, useCronTime, useCronType, useCronWeekDays } from './chunk-PVAX67JG.mjs';
13
- import './chunk-UNCS5V5F.mjs';
14
- export { TreeError, TreeSkeleton, createDemoTree } from './chunk-B6IR5KSC.mjs';
15
- export { DEFAULT_TREE_APPEARANCE, DEFAULT_TREE_LABELS, TreeRoot as Tree, TreeChevron, TreeContent, TreeEmpty, TreeIcon, TreeIndentGuides, TreeLabel, TreeProvider, TreeRoot, TreeRow, TreeSearchInput, appearanceToStyle, clearTreeState, createChildCache, flattenTree, loadTreeState, resolveAppearance, resolveChildren, saveTreeState, useTreeActions, useTreeContext, useTreeExpansion, useTreeFocus, useTreeKeyboard, useTreeLabels, useTreeRows, useTreeSearch, useTreeSelection, useTreeTypeAhead } from './chunk-ZL7FH4NW.mjs';
16
- import { useMapContext } from './chunk-7CWGZPO3.mjs';
17
- import { PlaygroundProvider } from './chunk-Y6UTOBF6.mjs';
18
- export { ANCHOR, ActionRow, BUBBLE_SURFACE, ChatMessageRow, DESTRUCTIVE_SURFACE, MarkdownMessage, MarkdownMessage_default as MarkdownMessageDefault, Mermaid_default as Mermaid, PrettyCode_default as PrettyCode, TOGGLE, TOOL_CALL, extractTextFromChildren, useCollapsibleContent } from './chunk-2NG4SXEP.mjs';
19
- export { JsonTree_default as JsonTree } from './chunk-ECONRHIG.mjs';
20
- import './chunk-KNEQRUBA.mjs';
21
- import { __name, __publicField } from './chunk-N2XQF2OL.mjs';
22
- import { Marker, Popup, useMap, Source, Layer, useControl } from 'react-map-gl/maplibre';
23
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
24
- import { memo, useCallback, useState, useEffect, lazy, forwardRef, useRef, useImperativeHandle, createContext, useMemo, Suspense, useContext } from 'react';
25
- import { createPortal } from 'react-dom';
26
- import { createAudioPrefsStore, useLocalStorage, useResolvedTheme } from '@djangocfg/ui-core/hooks';
27
- import { Bold, Italic, Strikethrough, Code, Heading1, Heading2, Heading3, List, ListOrdered, Quote, Minus, VolumeX, Volume2 } from 'lucide-react';
28
- import { Button } from '@djangocfg/ui-core/components';
29
- import { cn } from '@djangocfg/ui-core/lib';
30
- import { useEditor as useEditor$1, EditorContent, ReactRenderer } from '@tiptap/react';
31
- import StarterKit from '@tiptap/starter-kit';
32
- import Placeholder from '@tiptap/extension-placeholder';
33
- import Mention from '@tiptap/extension-mention';
34
- import { Markdown } from '@tiptap/markdown';
35
- import { autoUpdate, computePosition, offset, flip, shift } from '@floating-ui/dom';
36
- import { Extension } from '@tiptap/core';
37
-
38
- var DefaultPin = memo(/* @__PURE__ */ __name(function DefaultPin2({
39
- size = 24,
40
- color = "#ef4444"
41
- }) {
42
- return /* @__PURE__ */ jsxs(
43
- "svg",
44
- {
45
- width: size,
46
- height: size,
47
- viewBox: "0 0 24 24",
48
- fill: "none",
49
- style: { cursor: "pointer" },
50
- children: [
51
- /* @__PURE__ */ jsx(
52
- "path",
53
- {
54
- d: "M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7z",
55
- fill: color,
56
- stroke: "#fff",
57
- strokeWidth: "1.5"
58
- }
59
- ),
60
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "9", r: "2.5", fill: "#fff" })
61
- ]
62
- }
63
- );
64
- }, "DefaultPin"));
65
- memo(/* @__PURE__ */ __name(function MapMarker2({
66
- marker,
67
- onClick,
68
- children,
69
- anchor = "bottom",
70
- draggable = false,
71
- onDragStart,
72
- onDrag,
73
- onDragEnd,
74
- color,
75
- size
76
- }) {
77
- const handleClick = useCallback(
78
- (e) => {
79
- e.originalEvent.stopPropagation();
80
- onClick?.(marker);
81
- },
82
- [onClick, marker]
83
- );
84
- const handleDragStart = useCallback(
85
- (e) => {
86
- onDragStart?.(marker);
87
- },
88
- [onDragStart, marker]
89
- );
90
- const handleDrag = useCallback(
91
- (e) => {
92
- onDrag?.(marker, e.lngLat);
93
- },
94
- [onDrag, marker]
95
- );
96
- const handleDragEnd = useCallback(
97
- (e) => {
98
- onDragEnd?.(marker, e.lngLat);
99
- },
100
- [onDragEnd, marker]
101
- );
102
- return /* @__PURE__ */ jsx(
103
- Marker,
104
- {
105
- longitude: marker.longitude,
106
- latitude: marker.latitude,
107
- anchor,
108
- draggable,
109
- onClick: handleClick,
110
- onDragStart: handleDragStart,
111
- onDrag: handleDrag,
112
- onDragEnd: handleDragEnd,
113
- children: children ?? /* @__PURE__ */ jsx(DefaultPin, { color, size })
114
- }
115
- );
116
- }, "MapMarker"));
117
- memo(/* @__PURE__ */ __name(function MapPopup2({
118
- longitude,
119
- latitude,
120
- onClose,
121
- children,
122
- anchor = "bottom",
123
- closeOnClick = true,
124
- closeButton = true,
125
- className,
126
- maxWidth = "300px",
127
- offset: offset2 = 15
128
- }) {
129
- return /* @__PURE__ */ jsx(
130
- Popup,
131
- {
132
- longitude,
133
- latitude,
134
- anchor,
135
- onClose,
136
- closeOnClick,
137
- closeButton,
138
- className,
139
- maxWidth,
140
- offset: offset2,
141
- children
142
- }
143
- );
144
- }, "MapPopup"));
145
-
146
- // src/tools/Map/layers/cluster.ts
147
- var DEFAULT_COLORS = ["#51bbd6", "#f1f075", "#f28cb1"];
148
- var DEFAULT_RADII = [20, 30, 40];
149
- var DEFAULT_THRESHOLDS = [100, 750];
150
- var DEFAULT_HOVER_COLOR = "#3b82f6";
151
- function createClusterLayers(options) {
152
- const {
153
- sourceId,
154
- colors = DEFAULT_COLORS,
155
- radii = DEFAULT_RADII,
156
- thresholds = DEFAULT_THRESHOLDS,
157
- hoverColor = DEFAULT_HOVER_COLOR
158
- } = options;
159
- const cluster = {
160
- id: `${sourceId}-clusters`,
161
- type: "circle",
162
- source: sourceId,
163
- filter: ["has", "point_count"],
164
- paint: {
165
- "circle-color": [
166
- "case",
167
- ["boolean", ["feature-state", "hover"], false],
168
- hoverColor,
169
- [
170
- "step",
171
- ["get", "point_count"],
172
- colors[0],
173
- thresholds[0],
174
- colors[1],
175
- thresholds[1],
176
- colors[2]
177
- ]
178
- ],
179
- "circle-radius": [
180
- "step",
181
- ["get", "point_count"],
182
- radii[0],
183
- thresholds[0],
184
- radii[1],
185
- thresholds[1],
186
- radii[2]
187
- ],
188
- "circle-stroke-width": 2,
189
- "circle-stroke-color": "#fff"
190
- }
191
- };
192
- const clusterCount = {
193
- id: `${sourceId}-cluster-count`,
194
- type: "symbol",
195
- source: sourceId,
196
- filter: ["has", "point_count"],
197
- layout: {
198
- "text-field": ["get", "point_count_abbreviated"],
199
- "text-size": 12
200
- },
201
- paint: {
202
- "text-color": "#000"
203
- }
204
- };
205
- const unclusteredPoint = {
206
- id: `${sourceId}-unclustered-point`,
207
- type: "circle",
208
- source: sourceId,
209
- filter: ["!", ["has", "point_count"]],
210
- paint: {
211
- "circle-color": [
212
- "case",
213
- ["boolean", ["feature-state", "hover"], false],
214
- hoverColor,
215
- colors[0]
216
- ],
217
- "circle-radius": [
218
- "case",
219
- ["boolean", ["feature-state", "hover"], false],
220
- 10,
221
- 8
222
- ],
223
- "circle-stroke-width": 2,
224
- "circle-stroke-color": "#fff"
225
- }
226
- };
227
- return { cluster, clusterCount, unclusteredPoint };
228
- }
229
- __name(createClusterLayers, "createClusterLayers");
230
- var POPUP_STYLE_ID = "map-cluster-popup-styles";
231
- function injectPopupStyles() {
232
- if (typeof document === "undefined") return;
233
- if (document.getElementById(POPUP_STYLE_ID)) return;
234
- const style = document.createElement("style");
235
- style.id = POPUP_STYLE_ID;
236
- style.textContent = `
237
- .maplibregl-popup.map-popup-clean .maplibregl-popup-content {
238
- padding: 0 !important;
239
- background: transparent !important;
240
- box-shadow: none !important;
241
- border-radius: 0 !important;
242
- }
243
- .maplibregl-popup.map-popup-clean .maplibregl-popup-tip {
244
- display: none !important;
245
- }
246
- `;
247
- document.head.appendChild(style);
248
- }
249
- __name(injectPopupStyles, "injectPopupStyles");
250
- memo(/* @__PURE__ */ __name(function MapCluster2({
251
- sourceId,
252
- data,
253
- clusterRadius = 50,
254
- clusterMaxZoom = 14,
255
- onClusterClick,
256
- onPointClick,
257
- renderPopup,
258
- popupAnchor = "bottom",
259
- popupOffset = 15,
260
- panOffsetX = 0,
261
- panOffsetY = 150,
262
- colors,
263
- radii,
264
- thresholds,
265
- hoverColor
266
- }) {
267
- const { current: map } = useMap();
268
- const [selectedFeature, setSelectedFeature] = useState(null);
269
- const [popupCoords, setPopupCoords] = useState(null);
270
- useEffect(() => {
271
- injectPopupStyles();
272
- }, []);
273
- const layerOptions = {
274
- sourceId,
275
- colors,
276
- radii,
277
- thresholds,
278
- hoverColor
279
- };
280
- const { cluster, clusterCount, unclusteredPoint } = createClusterLayers(layerOptions);
281
- const handleClosePopup = useCallback(() => {
282
- setSelectedFeature(null);
283
- setPopupCoords(null);
284
- }, []);
285
- const handleClick = useCallback(
286
- async (event) => {
287
- if (!map) return;
288
- const features = map.queryRenderedFeatures(event.point, {
289
- layers: [cluster.id, unclusteredPoint.id]
290
- });
291
- if (!features || features.length === 0) return;
292
- const feature = features[0];
293
- const geometry = feature.geometry;
294
- if (geometry.type !== "Point") return;
295
- const coordinates = geometry.coordinates;
296
- const clusterId = feature.properties?.cluster_id;
297
- if (clusterId) {
298
- const source = map.getSource(sourceId);
299
- if (!source) return;
300
- try {
301
- const zoom = await source.getClusterExpansionZoom(clusterId);
302
- map.easeTo({
303
- center: coordinates,
304
- zoom,
305
- duration: 500
306
- });
307
- onClusterClick?.(clusterId, coordinates);
308
- } catch (error) {
309
- console.error("Error expanding cluster:", error);
310
- }
311
- } else {
312
- onPointClick?.(feature);
313
- if (renderPopup) {
314
- map.easeTo({
315
- center: coordinates,
316
- duration: 300,
317
- offset: [panOffsetX, panOffsetY]
318
- });
319
- setSelectedFeature(feature);
320
- setPopupCoords(coordinates);
321
- }
322
- }
323
- },
324
- [map, sourceId, cluster.id, unclusteredPoint.id, onClusterClick, onPointClick, renderPopup, panOffsetX, panOffsetY]
325
- );
326
- const handleMapClick = useCallback(
327
- (event) => {
328
- if (!map) return;
329
- const features = map.queryRenderedFeatures(event.point, {
330
- layers: [cluster.id, unclusteredPoint.id]
331
- });
332
- if (!features || features.length === 0) {
333
- handleClosePopup();
334
- }
335
- },
336
- [map, cluster.id, unclusteredPoint.id, handleClosePopup]
337
- );
338
- useEffect(() => {
339
- if (!map) return;
340
- const clusterLayerId = cluster.id;
341
- const pointLayerId = unclusteredPoint.id;
342
- let currentHoveredId = null;
343
- const clearHoverState = /* @__PURE__ */ __name(() => {
344
- if (currentHoveredId !== null) {
345
- map.setFeatureState(
346
- { source: sourceId, id: currentHoveredId },
347
- { hover: false }
348
- );
349
- currentHoveredId = null;
350
- }
351
- }, "clearHoverState");
352
- const handleMouseMove = /* @__PURE__ */ __name((e) => {
353
- const features = map.queryRenderedFeatures(e.point, {
354
- layers: [clusterLayerId, pointLayerId]
355
- });
356
- if (features.length > 0) {
357
- map.getCanvas().style.cursor = "pointer";
358
- const feature = features[0];
359
- const featureId = feature.id;
360
- if (featureId !== void 0 && featureId !== currentHoveredId) {
361
- clearHoverState();
362
- currentHoveredId = featureId;
363
- map.setFeatureState(
364
- { source: sourceId, id: featureId },
365
- { hover: true }
366
- );
367
- }
368
- } else {
369
- map.getCanvas().style.cursor = "";
370
- clearHoverState();
371
- }
372
- }, "handleMouseMove");
373
- const handleMouseLeave = /* @__PURE__ */ __name(() => {
374
- map.getCanvas().style.cursor = "";
375
- clearHoverState();
376
- }, "handleMouseLeave");
377
- map.on("click", clusterLayerId, handleClick);
378
- map.on("click", pointLayerId, handleClick);
379
- map.on("click", handleMapClick);
380
- map.on("mousemove", clusterLayerId, handleMouseMove);
381
- map.on("mousemove", pointLayerId, handleMouseMove);
382
- map.on("mouseleave", clusterLayerId, handleMouseLeave);
383
- map.on("mouseleave", pointLayerId, handleMouseLeave);
384
- return () => {
385
- clearHoverState();
386
- map.off("click", clusterLayerId, handleClick);
387
- map.off("click", pointLayerId, handleClick);
388
- map.off("click", handleMapClick);
389
- map.off("mousemove", clusterLayerId, handleMouseMove);
390
- map.off("mousemove", pointLayerId, handleMouseMove);
391
- map.off("mouseleave", clusterLayerId, handleMouseLeave);
392
- map.off("mouseleave", pointLayerId, handleMouseLeave);
393
- };
394
- }, [map, sourceId, cluster.id, unclusteredPoint.id, handleClick, handleMapClick]);
395
- return /* @__PURE__ */ jsxs(Fragment, { children: [
396
- /* @__PURE__ */ jsxs(
397
- Source,
398
- {
399
- id: sourceId,
400
- type: "geojson",
401
- data,
402
- cluster: true,
403
- clusterMaxZoom,
404
- clusterRadius,
405
- generateId: true,
406
- children: [
407
- /* @__PURE__ */ jsx(Layer, { ...cluster }),
408
- /* @__PURE__ */ jsx(Layer, { ...clusterCount }),
409
- /* @__PURE__ */ jsx(Layer, { ...unclusteredPoint })
410
- ]
411
- }
412
- ),
413
- renderPopup && selectedFeature && popupCoords && /* @__PURE__ */ jsx(
414
- Popup,
415
- {
416
- longitude: popupCoords[0],
417
- latitude: popupCoords[1],
418
- anchor: popupAnchor,
419
- onClose: handleClosePopup,
420
- closeOnClick: false,
421
- closeButton: false,
422
- offset: popupOffset,
423
- maxWidth: "none",
424
- className: "map-popup-clean",
425
- children: renderPopup(selectedFeature, handleClosePopup)
426
- }
427
- )
428
- ] });
429
- }, "MapCluster"));
430
- memo(/* @__PURE__ */ __name(function MapSource2({
431
- id,
432
- data,
433
- type = "geojson",
434
- children
435
- }) {
436
- return /* @__PURE__ */ jsx(Source, { id, type, data, children });
437
- }, "MapSource"));
438
- memo(/* @__PURE__ */ __name(function MapLayer2(props) {
439
- return /* @__PURE__ */ jsx(Layer, { ...props });
440
- }, "MapLayer"));
441
- var _OverlayControl = class _OverlayControl {
442
- constructor(redraw) {
443
- __publicField(this, "_map", null);
444
- __publicField(this, "_container", null);
445
- __publicField(this, "_redraw");
446
- this._redraw = redraw;
447
- }
448
- onAdd(map) {
449
- this._map = map;
450
- map.on("move", this._redraw);
451
- this._container = document.createElement("div");
452
- this._redraw();
453
- return this._container;
454
- }
455
- onRemove() {
456
- this._container?.remove();
457
- this._map?.off("move", this._redraw);
458
- this._map = null;
459
- }
460
- getElement() {
461
- return this._container;
462
- }
463
- };
464
- __name(_OverlayControl, "OverlayControl");
465
- var OverlayControl = _OverlayControl;
466
- function CustomOverlayComponent({ children }) {
467
- const [, setVersion] = useState(0);
468
- const ctrl = useControl(() => {
469
- const forceUpdate = /* @__PURE__ */ __name(() => setVersion((v) => v + 1), "forceUpdate");
470
- return new OverlayControl(forceUpdate);
471
- });
472
- const element = ctrl.getElement();
473
- if (!element) return null;
474
- return createPortal(children, element);
475
- }
476
- __name(CustomOverlayComponent, "CustomOverlayComponent");
477
- memo(CustomOverlayComponent);
478
- var positionStyles = {
479
- "top-left": { top: 10, left: 10 },
480
- "top-right": { top: 10, right: 10 },
481
- "bottom-left": { bottom: 10, left: 10 },
482
- "bottom-right": { bottom: 10, right: 10 }
483
- };
484
- function LegendIcon({
485
- type,
486
- color
487
- }) {
488
- const fill = color || "#888";
489
- switch (type) {
490
- case "circle":
491
- return /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6", fill }) });
492
- case "line":
493
- return /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx(
494
- "line",
495
- {
496
- x1: "0",
497
- y1: "8",
498
- x2: "16",
499
- y2: "8",
500
- stroke: fill,
501
- strokeWidth: "3",
502
- strokeLinecap: "round"
503
- }
504
- ) });
505
- case "fill":
506
- return /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx("rect", { x: "1", y: "1", width: "14", height: "14", fill, rx: "2" }) });
507
- case "symbol":
508
- default:
509
- return /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx(
510
- "path",
511
- {
512
- d: "M8 1l2.5 5 5.5.8-4 3.9.9 5.3L8 13.5l-4.9 2.5.9-5.3-4-3.9 5.5-.8z",
513
- fill
514
- }
515
- ) });
516
- }
517
- }
518
- __name(LegendIcon, "LegendIcon");
519
- function MapLegendComponent({
520
- items,
521
- position = "bottom-right",
522
- title,
523
- collapsible = false,
524
- defaultCollapsed = false,
525
- className = "",
526
- style,
527
- onItemClick
528
- }) {
529
- const [collapsed, setCollapsed] = useState(defaultCollapsed);
530
- const containerStyle = useMemo(
531
- () => ({
532
- position: "absolute",
533
- ...positionStyles[position],
534
- backgroundColor: "white",
535
- borderRadius: 8,
536
- boxShadow: "0 2px 8px rgba(0,0,0,0.15)",
537
- padding: collapsed ? 8 : 12,
538
- minWidth: collapsed ? "auto" : 120,
539
- zIndex: 1,
540
- ...style
541
- }),
542
- [position, collapsed, style]
543
- );
544
- const headerStyle = useMemo(
545
- () => ({
546
- display: "flex",
547
- alignItems: "center",
548
- justifyContent: "space-between",
549
- gap: 8,
550
- cursor: collapsible ? "pointer" : "default",
551
- fontWeight: 600,
552
- fontSize: 12,
553
- color: "#333",
554
- marginBottom: collapsed ? 0 : 8
555
- }),
556
- [collapsible, collapsed]
557
- );
558
- const itemStyle = useMemo(
559
- () => ({
560
- display: "flex",
561
- alignItems: "center",
562
- gap: 8,
563
- padding: "4px 0",
564
- fontSize: 12,
565
- color: "#666",
566
- cursor: onItemClick ? "pointer" : "default"
567
- }),
568
- [onItemClick]
569
- );
570
- const handleHeaderClick = collapsible ? () => setCollapsed(!collapsed) : void 0;
571
- return /* @__PURE__ */ jsxs("div", { className, style: containerStyle, children: [
572
- (title || collapsible) && /* @__PURE__ */ jsxs("div", { style: headerStyle, onClick: handleHeaderClick, children: [
573
- title && /* @__PURE__ */ jsx("span", { children: title }),
574
- collapsible && /* @__PURE__ */ jsx(
575
- "svg",
576
- {
577
- width: "12",
578
- height: "12",
579
- viewBox: "0 0 12 12",
580
- style: {
581
- transform: collapsed ? "rotate(-90deg)" : "rotate(0deg)",
582
- transition: "transform 0.2s"
583
- },
584
- children: /* @__PURE__ */ jsx("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "#666", fill: "none" })
585
- }
586
- )
587
- ] }),
588
- !collapsed && /* @__PURE__ */ jsx("div", { children: items.map((item) => /* @__PURE__ */ jsxs(
589
- "div",
590
- {
591
- style: {
592
- ...itemStyle,
593
- opacity: item.visible === false ? 0.5 : 1
594
- },
595
- onClick: onItemClick ? () => onItemClick(item) : void 0,
596
- children: [
597
- item.icon || /* @__PURE__ */ jsx(LegendIcon, { type: item.type, color: item.color }),
598
- /* @__PURE__ */ jsx("span", { children: item.label })
599
- ]
600
- },
601
- item.id
602
- )) })
603
- ] });
604
- }
605
- __name(MapLegendComponent, "MapLegendComponent");
606
- memo(MapLegendComponent);
607
- function useMapLayers() {
608
- const { mapRef, isLoaded } = useMapContext();
609
- const addLayer = useCallback(
610
- (layer, beforeId) => {
611
- const map = mapRef.current?.getMap();
612
- if (!map || !isLoaded) return;
613
- if (layer.id && map.getLayer(layer.id)) {
614
- map.removeLayer(layer.id);
615
- }
616
- map.addLayer(layer, beforeId);
617
- },
618
- [mapRef, isLoaded]
619
- );
620
- const removeLayer = useCallback(
621
- (id) => {
622
- const map = mapRef.current?.getMap();
623
- if (!map || !isLoaded) return;
624
- if (map.getLayer(id)) {
625
- map.removeLayer(id);
626
- }
627
- },
628
- [mapRef, isLoaded]
629
- );
630
- const setLayerVisibility = useCallback(
631
- (id, visible) => {
632
- const map = mapRef.current?.getMap();
633
- if (!map || !isLoaded) return;
634
- if (map.getLayer(id)) {
635
- map.setLayoutProperty(id, "visibility", visible ? "visible" : "none");
636
- }
637
- },
638
- [mapRef, isLoaded]
639
- );
640
- const setLayerFilter = useCallback(
641
- (id, filter) => {
642
- const map = mapRef.current?.getMap();
643
- if (!map || !isLoaded) return;
644
- if (map.getLayer(id)) {
645
- map.setFilter(id, filter);
646
- }
647
- },
648
- [mapRef, isLoaded]
649
- );
650
- const setLayerPaint = useCallback(
651
- (id, property, value) => {
652
- const map = mapRef.current?.getMap();
653
- if (!map || !isLoaded) return;
654
- if (map.getLayer(id)) {
655
- map.setPaintProperty(id, property, value);
656
- }
657
- },
658
- [mapRef, isLoaded]
659
- );
660
- return {
661
- addLayer,
662
- removeLayer,
663
- setLayerVisibility,
664
- setLayerFilter,
665
- setLayerPaint
666
- };
667
- }
668
- __name(useMapLayers, "useMapLayers");
669
- var positionStyles2 = {
670
- "top-left": { top: 10, left: 10 },
671
- "top-right": { top: 10, right: 10 },
672
- "bottom-left": { bottom: 10, left: 10 },
673
- "bottom-right": { bottom: 10, right: 10 }
674
- };
675
- function LayerSwitcherComponent({
676
- layers,
677
- position = "top-right",
678
- title = "Layers",
679
- collapsible = true,
680
- defaultCollapsed = false,
681
- showToggleAll = false,
682
- className = "",
683
- style,
684
- onChange
685
- }) {
686
- const { setLayerVisibility } = useMapLayers();
687
- const [collapsed, setCollapsed] = useState(defaultCollapsed);
688
- const initialVisibility = useMemo(() => {
689
- const initial = {};
690
- layers.forEach((layer) => {
691
- initial[layer.id] = layer.defaultVisible !== false;
692
- });
693
- return initial;
694
- }, [layers]);
695
- const [visibility, setVisibility] = useState(initialVisibility);
696
- const handleToggle = useCallback(
697
- (layerId) => {
698
- const newVisible = !visibility[layerId];
699
- setVisibility((prev) => ({ ...prev, [layerId]: newVisible }));
700
- setLayerVisibility(layerId, newVisible);
701
- onChange?.(layerId, newVisible);
702
- },
703
- [visibility, setLayerVisibility, onChange]
704
- );
705
- const handleToggleAll = useCallback(
706
- (visible) => {
707
- const newVisibility = {};
708
- layers.forEach((layer) => {
709
- newVisibility[layer.id] = visible;
710
- setLayerVisibility(layer.id, visible);
711
- onChange?.(layer.id, visible);
712
- });
713
- setVisibility(newVisibility);
714
- },
715
- [layers, setLayerVisibility, onChange]
716
- );
717
- const allVisible = useMemo(() => Object.values(visibility).every(Boolean), [visibility]);
718
- const noneVisible = useMemo(() => Object.values(visibility).every((v) => !v), [visibility]);
719
- const containerStyle = useMemo(
720
- () => ({
721
- position: "absolute",
722
- ...positionStyles2[position],
723
- backgroundColor: "white",
724
- borderRadius: 8,
725
- boxShadow: "0 2px 8px rgba(0,0,0,0.15)",
726
- padding: collapsed ? 8 : 12,
727
- minWidth: collapsed ? "auto" : 150,
728
- zIndex: 1,
729
- ...style
730
- }),
731
- [position, collapsed, style]
732
- );
733
- const headerStyle = useMemo(
734
- () => ({
735
- display: "flex",
736
- alignItems: "center",
737
- justifyContent: "space-between",
738
- gap: 8,
739
- cursor: collapsible ? "pointer" : "default",
740
- fontWeight: 600,
741
- fontSize: 12,
742
- color: "#333",
743
- marginBottom: collapsed ? 0 : 8
744
- }),
745
- [collapsible, collapsed]
746
- );
747
- const itemStyle = useMemo(
748
- () => ({
749
- display: "flex",
750
- alignItems: "center",
751
- gap: 8,
752
- padding: "4px 0",
753
- fontSize: 12,
754
- color: "#666",
755
- cursor: "pointer"
756
- }),
757
- []
758
- );
759
- const checkboxStyle = useMemo(
760
- () => ({
761
- width: 14,
762
- height: 14,
763
- cursor: "pointer"
764
- }),
765
- []
766
- );
767
- const groups = useMemo(() => {
768
- return layers.reduce(
769
- (acc, layer) => {
770
- const group = layer.group || "";
771
- if (!acc[group]) acc[group] = [];
772
- acc[group].push(layer);
773
- return acc;
774
- },
775
- {}
776
- );
777
- }, [layers]);
778
- const handleHeaderClick = collapsible ? () => setCollapsed(!collapsed) : void 0;
779
- return /* @__PURE__ */ jsxs("div", { className, style: containerStyle, children: [
780
- /* @__PURE__ */ jsxs("div", { style: headerStyle, onClick: handleHeaderClick, children: [
781
- /* @__PURE__ */ jsx("span", { children: title }),
782
- collapsible && /* @__PURE__ */ jsx(
783
- "svg",
784
- {
785
- width: "12",
786
- height: "12",
787
- viewBox: "0 0 12 12",
788
- style: {
789
- transform: collapsed ? "rotate(-90deg)" : "rotate(0deg)",
790
- transition: "transform 0.2s"
791
- },
792
- children: /* @__PURE__ */ jsx("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "#666", fill: "none" })
793
- }
794
- )
795
- ] }),
796
- !collapsed && /* @__PURE__ */ jsxs("div", { children: [
797
- showToggleAll && /* @__PURE__ */ jsxs(
798
- "div",
799
- {
800
- style: {
801
- ...itemStyle,
802
- borderBottom: "1px solid #eee",
803
- marginBottom: 4,
804
- paddingBottom: 8
805
- },
806
- children: [
807
- /* @__PURE__ */ jsx(
808
- "button",
809
- {
810
- onClick: () => handleToggleAll(true),
811
- disabled: allVisible,
812
- style: {
813
- fontSize: 10,
814
- padding: "2px 6px",
815
- cursor: allVisible ? "default" : "pointer",
816
- opacity: allVisible ? 0.5 : 1
817
- },
818
- children: "All"
819
- }
820
- ),
821
- /* @__PURE__ */ jsx(
822
- "button",
823
- {
824
- onClick: () => handleToggleAll(false),
825
- disabled: noneVisible,
826
- style: {
827
- fontSize: 10,
828
- padding: "2px 6px",
829
- cursor: noneVisible ? "default" : "pointer",
830
- opacity: noneVisible ? 0.5 : 1
831
- },
832
- children: "None"
833
- }
834
- )
835
- ]
836
- }
837
- ),
838
- Object.entries(groups).map(([group, groupLayers]) => /* @__PURE__ */ jsxs("div", { children: [
839
- group && /* @__PURE__ */ jsx(
840
- "div",
841
- {
842
- style: {
843
- fontSize: 10,
844
- fontWeight: 600,
845
- color: "#999",
846
- marginTop: 8,
847
- marginBottom: 4,
848
- textTransform: "uppercase"
849
- },
850
- children: group
851
- }
852
- ),
853
- groupLayers.map((layer) => /* @__PURE__ */ jsxs(
854
- "div",
855
- {
856
- style: itemStyle,
857
- onClick: () => handleToggle(layer.id),
858
- children: [
859
- /* @__PURE__ */ jsx(
860
- "input",
861
- {
862
- type: "checkbox",
863
- checked: visibility[layer.id],
864
- onChange: () => handleToggle(layer.id),
865
- style: checkboxStyle
866
- }
867
- ),
868
- /* @__PURE__ */ jsx("span", { children: layer.label })
869
- ]
870
- },
871
- layer.id
872
- ))
873
- ] }, group || "default"))
874
- ] })
875
- ] });
876
- }
877
- __name(LayerSwitcherComponent, "LayerSwitcherComponent");
878
- memo(LayerSwitcherComponent);
879
- var LazyMapContainer = createLazyComponent(
880
- () => import('./MapContainer-AKIPABJK.mjs').then((mod) => ({ default: mod.MapContainer })),
881
- {
882
- displayName: "LazyMapContainer",
883
- fallback: /* @__PURE__ */ jsx(MapLoadingFallback, { minHeight: 400 })
884
- }
885
- );
886
- var LazyMapView = createLazyComponent(
887
- () => import('./MapContainer-AKIPABJK.mjs').then((mod) => ({ default: mod.MapView })),
888
- {
889
- displayName: "LazyMapView",
890
- fallback: /* @__PURE__ */ jsx(MapLoadingFallback, { minHeight: 400 })
891
- }
892
- );
893
- var LazyMermaid = createLazyComponent(
894
- () => import('./Mermaid.client-NL4SVR7F.mjs'),
895
- {
896
- displayName: "LazyMermaid",
897
- fallback: /* @__PURE__ */ jsx(
898
- CardLoadingFallback,
899
- {
900
- title: "Diagram",
901
- description: "Loading...",
902
- minHeight: 200
903
- }
904
- )
905
- }
906
- );
907
- function CodeLoadingFallback() {
908
- return /* @__PURE__ */ jsx("div", { className: "relative rounded-sm border border-border overflow-hidden bg-muted dark:bg-zinc-900", children: /* @__PURE__ */ jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
909
- /* @__PURE__ */ jsx("div", { className: "animate-pulse h-4 w-4 rounded-full bg-muted-foreground/20" }),
910
- /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Loading code..." })
911
- ] }) }) });
912
- }
913
- __name(CodeLoadingFallback, "CodeLoadingFallback");
914
- var LazyPrettyCode = createLazyComponent(
915
- () => import('./PrettyCode.client-ZGYGKE7G.mjs'),
916
- {
917
- displayName: "LazyPrettyCode",
918
- fallback: /* @__PURE__ */ jsx(CodeLoadingFallback, {})
919
- }
920
- );
921
- function OpenapiLoadingFallback() {
922
- return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[400px] bg-muted/30 rounded-lg", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
923
- /* @__PURE__ */ jsx("div", { className: "inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-primary border-r-transparent" }),
924
- /* @__PURE__ */ jsx("p", { className: "mt-3 text-sm text-muted-foreground", children: "Loading API Playground..." })
925
- ] }) });
926
- }
927
- __name(OpenapiLoadingFallback, "OpenapiLoadingFallback");
928
- var LazyDocsLayout = createLazyComponent(
929
- () => import('./DocsLayout-EKASBSP7.mjs').then((mod) => ({ default: mod.DocsLayout })),
930
- {
931
- displayName: "LazyDocsLayout",
932
- fallback: /* @__PURE__ */ jsx(OpenapiLoadingFallback, {})
933
- }
934
- );
935
- var LazyOpenapiViewer = /* @__PURE__ */ __name(({ config }) => {
936
- return /* @__PURE__ */ jsx(PlaygroundProvider, { config, children: /* @__PURE__ */ jsx(LazyDocsLayout, {}) });
937
- }, "LazyOpenapiViewer");
938
- LazyOpenapiViewer.displayName = "LazyOpenapiViewer";
939
- var LazyJsonSchemaForm = createLazyComponent(
940
- () => import('./JsonSchemaForm-XKUIVELK.mjs').then((mod) => ({ default: mod.JsonSchemaForm })),
941
- {
942
- displayName: "LazyJsonSchemaForm",
943
- fallback: /* @__PURE__ */ jsx(
944
- CardLoadingFallback,
945
- {
946
- title: "Form",
947
- description: "Loading form schema...",
948
- minHeight: 200
949
- }
950
- )
951
- }
952
- );
953
- function LottieLoadingFallback() {
954
- return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center p-8", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2", children: [
955
- /* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-muted border-t-primary" }),
956
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Loading animation..." })
957
- ] }) });
958
- }
959
- __name(LottieLoadingFallback, "LottieLoadingFallback");
960
- var LazyLottiePlayer = createLazyComponent(
961
- () => import('./LottiePlayer.client-5LDSSJWS.mjs').then((mod) => ({ default: mod.LottiePlayer })),
962
- {
963
- displayName: "LazyLottiePlayer",
964
- fallback: /* @__PURE__ */ jsx(LottieLoadingFallback, {})
965
- }
966
- );
967
- var LazyPlayer = createLazyComponent(
968
- () => import('./Player-BRV7XTWR.mjs').then((mod) => ({ default: mod.Player })),
969
- {
970
- displayName: "LazyAudioPlayer",
971
- fallback: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border/60 bg-card px-4 py-6 text-sm text-muted-foreground", children: "Loading audio player\u2026" })
972
- }
973
- );
974
- function VideoLoadingFallback() {
975
- return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center bg-black/90 rounded-lg aspect-video", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2", children: [
976
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
977
- /* @__PURE__ */ jsx("div", { className: "h-10 w-10 animate-spin rounded-full border-4 border-white/20 border-t-white" }),
978
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx(
979
- "svg",
980
- {
981
- className: "h-5 w-5 text-white/60",
982
- fill: "currentColor",
983
- viewBox: "0 0 24 24",
984
- children: /* @__PURE__ */ jsx("path", { d: "M8 5v14l11-7z" })
985
- }
986
- ) })
987
- ] }),
988
- /* @__PURE__ */ jsx("span", { className: "text-sm text-white/60", children: "Loading video player..." })
989
- ] }) });
990
- }
991
- __name(VideoLoadingFallback, "VideoLoadingFallback");
992
- var LazyVideoPlayer = createLazyComponent(
993
- () => import('./components-XRX7QGLB.mjs').then((mod) => ({ default: mod.VideoPlayer })),
994
- {
995
- displayName: "LazyVideoPlayer",
996
- fallback: /* @__PURE__ */ jsx(VideoLoadingFallback, {})
997
- }
998
- );
999
- var LazyJsonTree = createLazyComponent(
1000
- () => import('./JsonTree-43PQAJKY.mjs'),
1001
- {
1002
- displayName: "LazyJsonTree",
1003
- fallback: /* @__PURE__ */ jsx(LoadingFallback, { minHeight: 100, text: "Loading JSON viewer..." })
1004
- }
1005
- );
1006
- var LazyImageViewer = createLazyComponent(
1007
- () => import('./components-YATKRWLH.mjs').then((mod) => ({ default: mod.ImageViewer })),
1008
- {
1009
- displayName: "LazyImageViewer",
1010
- fallback: /* @__PURE__ */ jsx(LoadingFallback, { minHeight: 200, text: "Loading image viewer..." })
1011
- }
1012
- );
1013
- var LazyCronScheduler = createLazyComponent(
1014
- () => import('./CronScheduler.client-DLMXCPAJ.mjs'),
1015
- {
1016
- displayName: "LazyCronScheduler",
1017
- fallback: /* @__PURE__ */ jsx(
1018
- LoadingFallback,
1019
- {
1020
- minHeight: 120,
1021
- showText: false,
1022
- className: "rounded-lg"
1023
- }
1024
- )
1025
- }
1026
- );
1027
- var LazyTree = createLazyComponent(
1028
- () => import('./TreeRoot-5COOOSWG.mjs'),
1029
- {
1030
- displayName: "LazyTree",
1031
- fallback: /* @__PURE__ */ jsx(LoadingFallback, { minHeight: 200, text: "Loading tree\u2026" })
1032
- }
1033
- );
1034
-
1035
- // src/tools/Chat/core/transport/types.ts
1036
- var _TransportError = class _TransportError extends Error {
1037
- constructor(message, code = "transport_error") {
1038
- super(message);
1039
- __publicField(this, "code");
1040
- this.name = "TransportError";
1041
- this.code = code;
1042
- }
1043
- };
1044
- __name(_TransportError, "TransportError");
1045
- var TransportError = _TransportError;
1046
-
1047
- // src/tools/Chat/core/transport/sse.ts
1048
- var DEFAULT_MAP = /* @__PURE__ */ __name((raw) => {
1049
- if (!raw.data) return null;
1050
- try {
1051
- const parsed = JSON.parse(raw.data);
1052
- if (raw.event && !("type" in parsed)) {
1053
- return { ...parsed, type: raw.event };
1054
- }
1055
- return parsed;
1056
- } catch {
1057
- return null;
1058
- }
1059
- }, "DEFAULT_MAP");
1060
- async function* parseSSE(response, options = {}) {
1061
- if (!response.body) {
1062
- throw new Error("SSE response has no body");
1063
- }
1064
- const map = options.map ?? DEFAULT_MAP;
1065
- const idleMs = options.idleTimeoutMs ?? LIMITS.sseIdleMs;
1066
- const reader = response.body.getReader();
1067
- const decoder = new TextDecoder();
1068
- let buffer = "";
1069
- let lastChunkAt = Date.now();
1070
- const idleCheck = /* @__PURE__ */ __name(() => {
1071
- if (Date.now() - lastChunkAt > idleMs) {
1072
- throw new Error(`SSE idle timeout (${idleMs}ms)`);
1073
- }
1074
- }, "idleCheck");
1075
- try {
1076
- while (true) {
1077
- if (options.signal?.aborted) {
1078
- return;
1079
- }
1080
- const { value, done } = await reader.read();
1081
- if (done) break;
1082
- lastChunkAt = Date.now();
1083
- buffer += decoder.decode(value, { stream: true });
1084
- let separator = buffer.indexOf("\n\n");
1085
- while (separator !== -1) {
1086
- const rawBlock = buffer.slice(0, separator);
1087
- buffer = buffer.slice(separator + 2);
1088
- const raw = parseEventBlock(rawBlock);
1089
- const evt = map(raw);
1090
- if (evt) {
1091
- if (Array.isArray(evt)) {
1092
- for (const e of evt) yield e;
1093
- } else {
1094
- yield evt;
1095
- }
1096
- }
1097
- separator = buffer.indexOf("\n\n");
1098
- }
1099
- idleCheck();
1100
- }
1101
- if (buffer.trim()) {
1102
- const raw = parseEventBlock(buffer);
1103
- const evt = map(raw);
1104
- if (evt) {
1105
- if (Array.isArray(evt)) {
1106
- for (const e of evt) yield e;
1107
- } else {
1108
- yield evt;
1109
- }
1110
- }
1111
- }
1112
- } finally {
1113
- try {
1114
- reader.releaseLock();
1115
- } catch {
1116
- }
1117
- }
1118
- }
1119
- __name(parseSSE, "parseSSE");
1120
- function parseEventBlock(block) {
1121
- const out = {};
1122
- const lines = block.split(/\r?\n/);
1123
- const dataLines = [];
1124
- for (const line of lines) {
1125
- if (!line || line.startsWith(":")) continue;
1126
- const colon = line.indexOf(":");
1127
- if (colon === -1) continue;
1128
- const field = line.slice(0, colon).trim();
1129
- const value = line.slice(colon + 1).replace(/^ /, "");
1130
- if (field === "event") out.event = value;
1131
- else if (field === "data") dataLines.push(value);
1132
- }
1133
- if (dataLines.length) out.data = dataLines.join("\n");
1134
- return out;
1135
- }
1136
- __name(parseEventBlock, "parseEventBlock");
1137
-
1138
- // src/tools/Chat/core/transport/http.ts
1139
- var DEFAULT_TIMEOUT = 2e4;
1140
- async function jsonOrThrow(res, label) {
1141
- if (!res.ok) {
1142
- const text = await res.text().catch(() => "");
1143
- throw new TransportError(
1144
- `${label} failed (${res.status}): ${text || res.statusText}`,
1145
- mapStatusToCode(res.status)
1146
- );
1147
- }
1148
- try {
1149
- return await res.json();
1150
- } catch {
1151
- throw new TransportError(`${label} returned invalid JSON`, "invalid_response");
1152
- }
1153
- }
1154
- __name(jsonOrThrow, "jsonOrThrow");
1155
- function mapStatusToCode(status) {
1156
- if (status === 401) return "unauthorized";
1157
- if (status === 403) return "forbidden";
1158
- if (status === 404) return "not_found";
1159
- if (status === 429) return "rate_limited";
1160
- if (status >= 500) return "server_error";
1161
- return "http_error";
1162
- }
1163
- __name(mapStatusToCode, "mapStatusToCode");
1164
- function withTimeout(signal, timeoutMs) {
1165
- const ctrl = new AbortController();
1166
- const onAbort = /* @__PURE__ */ __name(() => ctrl.abort(), "onAbort");
1167
- signal?.addEventListener("abort", onAbort, { once: true });
1168
- setTimeout(() => ctrl.abort(), timeoutMs);
1169
- return ctrl.signal;
1170
- }
1171
- __name(withTimeout, "withTimeout");
1172
- function createHttpTransport(config) {
1173
- const fetchImpl = config.fetchImpl ?? fetch;
1174
- const timeout = config.timeoutMs ?? DEFAULT_TIMEOUT;
1175
- const base = config.baseUrl.replace(/\/$/, "");
1176
- async function buildHeaders(extra) {
1177
- const auth = await config.getAuthHeader?.() ?? {};
1178
- return {
1179
- "Content-Type": "application/json",
1180
- ...auth,
1181
- ...extra ?? {}
1182
- };
1183
- }
1184
- __name(buildHeaders, "buildHeaders");
1185
- return {
1186
- async createSession(opts) {
1187
- const res = await fetchImpl(`${base}/sessions`, {
1188
- method: "POST",
1189
- headers: await buildHeaders(),
1190
- body: JSON.stringify({ slug: config.slug, metadata: opts?.metadata ?? {} }),
1191
- signal: withTimeout(void 0, timeout)
1192
- });
1193
- return jsonOrThrow(res, "createSession");
1194
- },
1195
- async loadHistory(sessionId, cursor, limit) {
1196
- const params = new URLSearchParams();
1197
- if (cursor) params.set("cursor", cursor);
1198
- if (limit) params.set("limit", String(limit));
1199
- const url = `${base}/sessions/${encodeURIComponent(sessionId)}/history${params.toString() ? `?${params.toString()}` : ""}`;
1200
- const res = await fetchImpl(url, {
1201
- method: "GET",
1202
- headers: await buildHeaders(),
1203
- signal: withTimeout(void 0, timeout)
1204
- });
1205
- return jsonOrThrow(res, "loadHistory");
1206
- },
1207
- async *stream(sessionId, content, options) {
1208
- const url = `${base}/sessions/${encodeURIComponent(sessionId)}/messages`;
1209
- const res = await fetchImpl(url, {
1210
- method: "POST",
1211
- headers: await buildHeaders({ Accept: "text/event-stream" }),
1212
- body: JSON.stringify({
1213
- content,
1214
- attachments: options.attachments ?? [],
1215
- metadata: options.metadata ?? {}
1216
- }),
1217
- signal: options.signal
1218
- });
1219
- if (!res.ok) {
1220
- const text = await res.text().catch(() => "");
1221
- throw new TransportError(
1222
- `stream failed (${res.status}): ${text || res.statusText}`,
1223
- mapStatusToCode(res.status)
1224
- );
1225
- }
1226
- yield* parseSSE(res, { signal: options.signal });
1227
- },
1228
- async send(sessionId, content, options) {
1229
- const url = `${base}/sessions/${encodeURIComponent(sessionId)}/messages/buffered`;
1230
- const res = await fetchImpl(url, {
1231
- method: "POST",
1232
- headers: await buildHeaders(),
1233
- body: JSON.stringify({
1234
- content,
1235
- attachments: options?.attachments ?? [],
1236
- metadata: options?.metadata ?? {}
1237
- }),
1238
- signal: options?.signal ?? withTimeout(void 0, timeout)
1239
- });
1240
- return jsonOrThrow(res, "send");
1241
- },
1242
- async closeSession(sessionId) {
1243
- const url = `${base}/sessions/${encodeURIComponent(sessionId)}`;
1244
- const res = await fetchImpl(url, {
1245
- method: "DELETE",
1246
- headers: await buildHeaders(),
1247
- signal: withTimeout(void 0, timeout)
1248
- });
1249
- if (!res.ok && res.status !== 404) {
1250
- throw new TransportError(`closeSession failed (${res.status})`, mapStatusToCode(res.status));
1251
- }
1252
- }
1253
- };
1254
- }
1255
- __name(createHttpTransport, "createHttpTransport");
1256
-
1257
- // src/tools/Chat/core/transport/mock.ts
1258
- var DEFAULT_REPLY = "Hi there!";
1259
- function splitForStream(text, parts = 4) {
1260
- if (!text) return [];
1261
- const chunkSize = Math.max(1, Math.ceil(text.length / parts));
1262
- const out = [];
1263
- for (let i = 0; i < text.length; i += chunkSize) {
1264
- out.push(text.slice(i, i + chunkSize));
1265
- }
1266
- return out;
1267
- }
1268
- __name(splitForStream, "splitForStream");
1269
- var sleep = /* @__PURE__ */ __name((ms) => new Promise((r) => setTimeout(r, ms)), "sleep");
1270
- function createMockTransport(opts = {}) {
1271
- const replies = opts.replies?.length ? opts.replies : [DEFAULT_REPLY];
1272
- const latency = opts.latencyMs ?? 30;
1273
- const history = [...opts.initialMessages ?? []];
1274
- let turn = 0;
1275
- let attempt = 0;
1276
- return {
1277
- async createSession(_opts) {
1278
- await sleep(latency);
1279
- return {
1280
- sessionId: createId("s"),
1281
- messages: history.length ? [...history] : void 0,
1282
- hasMore: false,
1283
- cursor: null,
1284
- resumed: history.length > 0
1285
- };
1286
- },
1287
- async loadHistory(_sid, _cursor, _limit) {
1288
- await sleep(latency);
1289
- return { messages: [], hasMore: false, nextCursor: null };
1290
- },
1291
- async *stream(_sid, content, options) {
1292
- attempt += 1;
1293
- if (opts.shouldFail?.(attempt)) {
1294
- throw new Error("mock transport scripted failure");
1295
- }
1296
- history.push({
1297
- id: createId("u"),
1298
- role: "user",
1299
- content,
1300
- createdAt: Date.now()
1301
- });
1302
- const messageId = createId("a");
1303
- yield { type: "message_start", messageId, sessionId: _sid };
1304
- const reply = replies[turn % replies.length];
1305
- turn += 1;
1306
- if (typeof reply === "string") {
1307
- for (const piece of splitForStream(reply)) {
1308
- if (options.signal.aborted) return;
1309
- await sleep(latency);
1310
- yield { type: "chunk", delta: piece };
1311
- }
1312
- yield { type: "message_end", tokensIn: content.length, tokensOut: reply.length };
1313
- } else {
1314
- for (const ev of reply) {
1315
- if (options.signal.aborted) return;
1316
- await sleep(latency);
1317
- yield ev;
1318
- }
1319
- const lastType = reply[reply.length - 1]?.type;
1320
- if (lastType !== "message_end" && lastType !== "error") {
1321
- yield { type: "message_end" };
1322
- }
1323
- }
1324
- },
1325
- async send(_sid, content, _options) {
1326
- await sleep(latency);
1327
- const reply = replies[turn % replies.length];
1328
- turn += 1;
1329
- const text = typeof reply === "string" ? reply : reply.filter((e) => e.type === "chunk").map((e) => e.delta).join("");
1330
- return {
1331
- id: createId("a"),
1332
- role: "assistant",
1333
- content: text || DEFAULT_REPLY,
1334
- createdAt: Date.now()
1335
- };
1336
- },
1337
- async closeSession(_sid) {
1338
- }
1339
- };
1340
- }
1341
- __name(createMockTransport, "createMockTransport");
1342
-
1343
- // src/tools/Chat/core/transport/mappers/pydantic-ai.ts
1344
- function createToolIdQueue() {
1345
- const queues = /* @__PURE__ */ new Map();
1346
- let counter = 0;
1347
- return {
1348
- push(name) {
1349
- const id = `${name}-${counter++}-${Date.now()}`;
1350
- const q = queues.get(name) ?? [];
1351
- q.push(id);
1352
- queues.set(name, q);
1353
- return id;
1354
- },
1355
- shift(name) {
1356
- return queues.get(name)?.shift() ?? `${name}-orphan-${counter++}`;
1357
- },
1358
- clear() {
1359
- queues.clear();
1360
- }
1361
- };
1362
- }
1363
- __name(createToolIdQueue, "createToolIdQueue");
1364
- function* mapPydanticAIEvent(ev, toolIds) {
1365
- switch (ev.type) {
1366
- case "text_delta":
1367
- if (ev.delta) yield { type: "chunk", delta: ev.delta };
1368
- return;
1369
- case "tool_call": {
1370
- const name = ev.tool ?? "tool";
1371
- const toolId = toolIds.push(name);
1372
- yield { type: "tool_call_start", toolId, name, input: ev.args };
1373
- return;
1374
- }
1375
- case "tool_result": {
1376
- const name = ev.tool ?? "tool";
1377
- const toolId = toolIds.shift(name);
1378
- const output = ev.data !== void 0 ? ev.data : ev.result;
1379
- yield { type: "tool_call_end", toolId, output, status: "success" };
1380
- return;
1381
- }
1382
- case "done":
1383
- yield { type: "message_end", tokensOut: ev.total_tokens };
1384
- return;
1385
- case "error":
1386
- yield { type: "error", code: "backend_error", message: ev.error ?? "Unknown error" };
1387
- return;
1388
- case "approval_required":
1389
- return;
1390
- }
1391
- }
1392
- __name(mapPydanticAIEvent, "mapPydanticAIEvent");
1393
- function createPydanticAISSEMap() {
1394
- const toolIds = createToolIdQueue();
1395
- return (raw) => {
1396
- if (!raw.data) return null;
1397
- let parsed;
1398
- try {
1399
- parsed = JSON.parse(raw.data);
1400
- } catch {
1401
- return null;
1402
- }
1403
- const out = [];
1404
- for (const evt of mapPydanticAIEvent(parsed, toolIds)) {
1405
- out.push(evt);
1406
- }
1407
- if (out.length === 0) return null;
1408
- if (out.length === 1) return out[0];
1409
- return out;
1410
- };
1411
- }
1412
- __name(createPydanticAISSEMap, "createPydanticAISSEMap");
1413
-
1414
- // src/tools/Chat/core/transport/pydantic-ai-transport.ts
1415
- var DEFAULT_SESSION_ID = "default";
1416
- function mapStatusToCode2(status) {
1417
- if (status === 401 || status === 403) return "unauthorized";
1418
- if (status === 404) return "not_found";
1419
- if (status === 408) return "timeout";
1420
- if (status === 429) return "rate_limited";
1421
- if (status >= 500) return "server_error";
1422
- return "error";
1423
- }
1424
- __name(mapStatusToCode2, "mapStatusToCode");
1425
- function createPydanticAIChatTransport(opts) {
1426
- const fetchImpl = opts.fetchImpl ?? fetch.bind(globalThis);
1427
- const streamMethod = opts.streamMethod ?? "POST";
1428
- async function resolvedHeaders(extra) {
1429
- const base = opts.buildHeaders ? await opts.buildHeaders() : {};
1430
- const headers = new Headers(base);
1431
- if (extra) {
1432
- for (const [k, v] of Object.entries(extra)) headers.set(k, v);
1433
- }
1434
- return headers;
1435
- }
1436
- __name(resolvedHeaders, "resolvedHeaders");
1437
- return {
1438
- async createSession(createOpts) {
1439
- if (opts.bootstrapSession) return opts.bootstrapSession(createOpts);
1440
- return { sessionId: DEFAULT_SESSION_ID };
1441
- },
1442
- async loadHistory(sessionId, cursor) {
1443
- if (opts.loadHistory) return opts.loadHistory(sessionId, cursor);
1444
- return { messages: [], hasMore: false, nextCursor: null };
1445
- },
1446
- async *stream(sessionId, content, options) {
1447
- const url = opts.buildStreamUrl(sessionId, content);
1448
- const headers = await resolvedHeaders({ Accept: "text/event-stream" });
1449
- const init = {
1450
- method: streamMethod,
1451
- headers,
1452
- signal: options.signal
1453
- };
1454
- if (streamMethod === "POST") {
1455
- headers.set("Content-Type", "application/json");
1456
- init.body = JSON.stringify({
1457
- content,
1458
- attachments: options.attachments ?? [],
1459
- metadata: options.metadata ?? {}
1460
- });
1461
- }
1462
- const res = await fetchImpl(typeof url === "string" ? url : url.toString(), init);
1463
- if (!res.ok) {
1464
- const text = await res.text().catch(() => "");
1465
- throw new TransportError(
1466
- `stream failed (${res.status}): ${text || res.statusText}`,
1467
- mapStatusToCode2(res.status)
1468
- );
1469
- }
1470
- const sideChannel = opts.onPydanticEvent;
1471
- if (!sideChannel) {
1472
- yield* parseSSE(res, {
1473
- signal: options.signal,
1474
- idleTimeoutMs: opts.idleTimeoutMs,
1475
- map: createPydanticAISSEMap()
1476
- });
1477
- return;
1478
- }
1479
- const toolIds = createToolIdQueue();
1480
- yield* parseSSE(res, {
1481
- signal: options.signal,
1482
- idleTimeoutMs: opts.idleTimeoutMs,
1483
- map: /* @__PURE__ */ __name((raw) => {
1484
- if (!raw.data) return null;
1485
- let parsed;
1486
- try {
1487
- parsed = JSON.parse(raw.data);
1488
- } catch {
1489
- return null;
1490
- }
1491
- try {
1492
- sideChannel(parsed);
1493
- } catch {
1494
- }
1495
- const out = [];
1496
- for (const evt of mapPydanticAIEvent(parsed, toolIds)) out.push(evt);
1497
- if (out.length === 0) return null;
1498
- if (out.length === 1) return out[0];
1499
- return out;
1500
- }, "map")
1501
- });
1502
- },
1503
- async send(sessionId, content, sendOpts) {
1504
- if (opts.send) return opts.send(sessionId, content, sendOpts);
1505
- throw new TransportError(
1506
- "Buffered send is not supported by this transport",
1507
- "unsupported"
1508
- );
1509
- },
1510
- async closeSession(sessionId) {
1511
- if (opts.closeSession) await opts.closeSession(sessionId);
1512
- }
1513
- };
1514
- }
1515
- __name(createPydanticAIChatTransport, "createPydanticAIChatTransport");
1516
- function useChatScroll(options) {
1517
- const {
1518
- containerRef,
1519
- bottomRef,
1520
- isStreaming = false,
1521
- bottomThresholdPx = 80,
1522
- messagesCount = 0
1523
- } = options;
1524
- const [isAtBottom, setIsAtBottom] = useState(true);
1525
- const [unreadCount, setUnreadCount] = useState(0);
1526
- const lastCountRef = useRef(messagesCount);
1527
- const stickyRef = useRef(true);
1528
- const wasStreamingRef = useRef(isStreaming);
1529
- const scrollToBottom = useCallback(
1530
- (smooth = false) => {
1531
- const el = containerRef.current;
1532
- if (!el) return;
1533
- el.scrollTo({
1534
- top: el.scrollHeight,
1535
- behavior: smooth ? "smooth" : "auto"
1536
- });
1537
- stickyRef.current = true;
1538
- setIsAtBottom(true);
1539
- setUnreadCount(0);
1540
- },
1541
- [containerRef]
1542
- );
1543
- const resetUnread = useCallback(() => setUnreadCount(0), []);
1544
- useEffect(() => {
1545
- const el = containerRef.current;
1546
- if (!el) return;
1547
- const onScroll = /* @__PURE__ */ __name(() => {
1548
- const distance = el.scrollHeight - el.scrollTop - el.clientHeight;
1549
- const atBottom = distance <= bottomThresholdPx;
1550
- stickyRef.current = atBottom;
1551
- setIsAtBottom(atBottom);
1552
- if (atBottom) setUnreadCount(0);
1553
- }, "onScroll");
1554
- onScroll();
1555
- el.addEventListener("scroll", onScroll, { passive: true });
1556
- return () => {
1557
- el.removeEventListener("scroll", onScroll);
1558
- };
1559
- }, [containerRef, bottomThresholdPx]);
1560
- useEffect(() => {
1561
- const el = containerRef.current;
1562
- if (!el) return;
1563
- if (isStreaming) {
1564
- wasStreamingRef.current = true;
1565
- if (!stickyRef.current) return;
1566
- let raf = 0;
1567
- const tick = /* @__PURE__ */ __name(() => {
1568
- if (!stickyRef.current) return;
1569
- el.scrollTop = el.scrollHeight;
1570
- raf = requestAnimationFrame(tick);
1571
- }, "tick");
1572
- raf = requestAnimationFrame(tick);
1573
- return () => cancelAnimationFrame(raf);
1574
- }
1575
- if (wasStreamingRef.current && stickyRef.current) {
1576
- wasStreamingRef.current = false;
1577
- let raf1 = 0;
1578
- let raf2 = 0;
1579
- raf1 = requestAnimationFrame(() => {
1580
- el.scrollTop = el.scrollHeight;
1581
- raf2 = requestAnimationFrame(() => {
1582
- el.scrollTop = el.scrollHeight;
1583
- });
1584
- });
1585
- return () => {
1586
- cancelAnimationFrame(raf1);
1587
- cancelAnimationFrame(raf2);
1588
- };
1589
- }
1590
- wasStreamingRef.current = false;
1591
- return;
1592
- }, [containerRef, isStreaming]);
1593
- useEffect(() => {
1594
- if (messagesCount > lastCountRef.current) {
1595
- if (stickyRef.current) {
1596
- const el = containerRef.current;
1597
- if (el) el.scrollTop = el.scrollHeight;
1598
- } else {
1599
- setUnreadCount((n) => n + (messagesCount - lastCountRef.current));
1600
- }
1601
- }
1602
- lastCountRef.current = messagesCount;
1603
- }, [containerRef, messagesCount]);
1604
- useEffect(() => {
1605
- }, [bottomRef]);
1606
- return { isAtBottom, unreadCount, scrollToBottom, resetUnread };
1607
- }
1608
- __name(useChatScroll, "useChatScroll");
1609
- function useChatHistory(options) {
1610
- const { enabled = true, containerRef, topSentinelRef, hasMore, isLoadingMore, loadMore } = options;
1611
- const heightBeforeRef = useRef(null);
1612
- useEffect(() => {
1613
- if (heightBeforeRef.current == null) return;
1614
- const el = containerRef.current;
1615
- if (!el) {
1616
- heightBeforeRef.current = null;
1617
- return;
1618
- }
1619
- if (!isLoadingMore) {
1620
- const delta = el.scrollHeight - heightBeforeRef.current;
1621
- if (delta > 0) {
1622
- el.scrollTop += delta;
1623
- }
1624
- heightBeforeRef.current = null;
1625
- }
1626
- }, [containerRef, isLoadingMore]);
1627
- useEffect(() => {
1628
- if (!enabled || !hasMore) return;
1629
- const sentinel = topSentinelRef.current;
1630
- const root = containerRef.current;
1631
- if (!sentinel || !root) return;
1632
- const observer = new IntersectionObserver(
1633
- (entries) => {
1634
- const entry = entries[0];
1635
- if (!entry?.isIntersecting) return;
1636
- if (isLoadingMore) return;
1637
- const el = containerRef.current;
1638
- if (el) heightBeforeRef.current = el.scrollHeight;
1639
- void loadMore();
1640
- },
1641
- { root, threshold: 0, rootMargin: "200px 0px 0px 0px" }
1642
- );
1643
- observer.observe(sentinel);
1644
- return () => observer.disconnect();
1645
- }, [enabled, hasMore, isLoadingMore, containerRef, topSentinelRef, loadMore]);
1646
- }
1647
- __name(useChatHistory, "useChatHistory");
1648
- function useChatLightbox() {
1649
- const [state, setState] = useState(null);
1650
- const open = useCallback((att, gallery) => {
1651
- const list = gallery && gallery.length ? gallery : [att];
1652
- const idx = list.findIndex((a) => a.id === att.id);
1653
- setState({ gallery: list, index: idx === -1 ? 0 : idx });
1654
- }, []);
1655
- const close = useCallback(() => setState(null), []);
1656
- return { state, open, close };
1657
- }
1658
- __name(useChatLightbox, "useChatLightbox");
1659
- var DEFAULT_STORAGE_KEY = "chat.visitor.fingerprint";
1660
- function generate() {
1661
- if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
1662
- return crypto.randomUUID();
1663
- }
1664
- return `v-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
1665
- }
1666
- __name(generate, "generate");
1667
- function useVisitorFingerprint(opts = {}) {
1668
- const storageKey = opts.storageKey ?? DEFAULT_STORAGE_KEY;
1669
- const [fp, setFp] = useState(null);
1670
- useEffect(() => {
1671
- let value = null;
1672
- try {
1673
- value = window.localStorage.getItem(storageKey);
1674
- if (!value) {
1675
- value = generate();
1676
- window.localStorage.setItem(storageKey, value);
1677
- }
1678
- } catch {
1679
- value = generate();
1680
- }
1681
- setFp(value);
1682
- }, [storageKey]);
1683
- return fp;
1684
- }
1685
- __name(useVisitorFingerprint, "useVisitorFingerprint");
1686
- var DEFAULT_DOCK_PREFS = {
1687
- mode: "popover",
1688
- side: "right",
1689
- sideWidth: 420
1690
- };
1691
- var DEFAULT_KEY = "chat.dock.prefs";
1692
- function useChatDockPrefs(opts = {}) {
1693
- const key = opts.storageKey ?? DEFAULT_KEY;
1694
- const initial = { ...DEFAULT_DOCK_PREFS, ...opts.defaults };
1695
- const [prefs, setStored] = useLocalStorage(key, initial);
1696
- const setPrefs = useCallback(
1697
- (patch) => {
1698
- setStored((prev) => ({ ...prev, ...patch }));
1699
- },
1700
- [setStored]
1701
- );
1702
- const toggleMode = useCallback(() => {
1703
- setStored((prev) => ({ ...prev, mode: prev.mode === "side" ? "popover" : "side" }));
1704
- }, [setStored]);
1705
- const toggleSide = useCallback(() => {
1706
- setStored((prev) => ({ ...prev, side: prev.side === "right" ? "left" : "right" }));
1707
- }, [setStored]);
1708
- const reset = useCallback(() => setStored(initial), [setStored, initial]);
1709
- return { ...prefs, setPrefs, toggleMode, toggleSide, reset };
1710
- }
1711
- __name(useChatDockPrefs, "useChatDockPrefs");
1712
- function useChatUnread(opts = {}) {
1713
- const { open = false, countRoles = ["assistant"] } = opts;
1714
- const ctx = useChatContext();
1715
- const [lastSeenId, setLastSeenId] = useState(null);
1716
- const initialized = useRef(false);
1717
- useEffect(() => {
1718
- if (initialized.current) return;
1719
- initialized.current = true;
1720
- const tail = ctx.messages[ctx.messages.length - 1];
1721
- setLastSeenId(tail?.id ?? null);
1722
- }, [ctx.messages]);
1723
- useEffect(() => {
1724
- if (!open) return;
1725
- const tail = ctx.messages[ctx.messages.length - 1];
1726
- setLastSeenId(tail?.id ?? null);
1727
- }, [open, ctx.messages]);
1728
- const seenIdx = lastSeenId ? ctx.messages.findIndex((m) => m.id === lastSeenId) : -1;
1729
- const after = seenIdx === -1 ? ctx.messages : ctx.messages.slice(seenIdx + 1);
1730
- const inbound = after.filter((m) => countRoles.includes(m.role));
1731
- const unread = inbound.length > 0 ? inbound[inbound.length - 1] : null;
1732
- const markRead = useCallback(() => {
1733
- const tail = ctx.messages[ctx.messages.length - 1];
1734
- setLastSeenId(tail?.id ?? null);
1735
- }, [ctx.messages]);
1736
- return { unread, count: inbound.length, markRead };
1737
- }
1738
- __name(useChatUnread, "useChatUnread");
1739
- var STORAGE_KEY = "djangocfg-chat-audio:prefs";
1740
- var useChatAudioPrefs = createAudioPrefsStore(STORAGE_KEY);
1741
-
1742
- // src/tools/Chat/core/payload-dispatch.ts
1743
- function dispatchToolPayload(matchers, fallback) {
1744
- return (value, kind, call) => {
1745
- for (const m of matchers) {
1746
- if (m.match(value, kind, call)) return m.render(value, kind, call);
1747
- }
1748
- return fallback(value, kind, call);
1749
- };
1750
- }
1751
- __name(dispatchToolPayload, "dispatchToolPayload");
1752
- function isPlainObject(v) {
1753
- return v !== null && typeof v === "object" && !Array.isArray(v);
1754
- }
1755
- __name(isPlainObject, "isPlainObject");
1756
- function isLatLng(v) {
1757
- return isPlainObject(v) && typeof v.lat === "number" && typeof v.lng === "number";
1758
- }
1759
- __name(isLatLng, "isLatLng");
1760
- function isGeoJSONFeatureCollection(v) {
1761
- return isPlainObject(v) && v.type === "FeatureCollection" && Array.isArray(v.features);
1762
- }
1763
- __name(isGeoJSONFeatureCollection, "isGeoJSONFeatureCollection");
1764
- function isStringValue(v) {
1765
- return typeof v === "string";
1766
- }
1767
- __name(isStringValue, "isStringValue");
1768
-
1769
- // src/tools/Chat/utils/collectImageAttachments.ts
1770
- function collectImageAttachments(messages) {
1771
- const out = [];
1772
- for (const m of messages) {
1773
- if (!m.attachments) continue;
1774
- for (const a of m.attachments) {
1775
- if (a.type === "image") out.push(a);
1776
- }
1777
- }
1778
- return out;
1779
- }
1780
- __name(collectImageAttachments, "collectImageAttachments");
1781
- function AudioToggle({
1782
- size = "icon",
1783
- variant = "ghost",
1784
- alwaysShow = false,
1785
- className
1786
- }) {
1787
- const muted = useChatAudioPrefs((s) => s.muted);
1788
- const setMuted = useChatAudioPrefs((s) => s.setMuted);
1789
- const ctx = useChatContextOptional();
1790
- if (ctx && !ctx.hasAudio && !alwaysShow) return null;
1791
- const Icon = muted ? VolumeX : Volume2;
1792
- const label = muted ? "Unmute chat sounds" : "Mute chat sounds";
1793
- return /* @__PURE__ */ jsx(
1794
- Button,
1795
- {
1796
- type: "button",
1797
- variant,
1798
- size,
1799
- onClick: () => setMuted(!muted),
1800
- "aria-label": label,
1801
- "aria-pressed": muted,
1802
- title: label,
1803
- className: cn(size === "icon" ? "h-9 w-9" : "", className),
1804
- children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": true, className: "size-4" })
1805
- }
1806
- );
1807
- }
1808
- __name(AudioToggle, "AudioToggle");
1809
- var LazyChat = createLazyComponent(
1810
- () => import('./ChatRoot-FITF5RVP.mjs').then((m) => ({ default: m.ChatRoot })),
1811
- {
1812
- displayName: "LazyChat",
1813
- fallback: /* @__PURE__ */ jsx(LoadingFallback, { minHeight: 320, text: "Loading chat\u2026" })
1814
- }
1815
- );
1816
- createLazyComponent(
1817
- () => import('./launcher-5Y42OBSN.mjs').then((m) => ({ default: m.ChatLauncher })),
1818
- {
1819
- displayName: "LazyChatLauncher",
1820
- // Launcher renders a floating FAB by default — no inline placeholder.
1821
- fallback: null
1822
- }
1823
- );
1824
- var LottiePlayerClient = lazy(
1825
- () => import('./LottiePlayer.client-5LDSSJWS.mjs').then((mod) => ({ default: mod.LottiePlayer }))
1826
- );
1827
- var LoadingFallback5 = /* @__PURE__ */ __name(() => /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center p-8", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2", children: [
1828
- /* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-gray-300 border-t-gray-900" }),
1829
- /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500", children: "Loading player..." })
1830
- ] }) }), "LoadingFallback");
1831
- function LottiePlayer(props) {
1832
- return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingFallback5, {}), children: /* @__PURE__ */ jsx(LottiePlayerClient, { ...props }) });
1833
- }
1834
- __name(LottiePlayer, "LottiePlayer");
1835
- var DocsLayout = lazy(
1836
- () => import('./DocsLayout-EKASBSP7.mjs').then((mod) => ({ default: mod.DocsLayout }))
1837
- );
1838
- var LoadingFallback6 = /* @__PURE__ */ __name(() => /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[400px]", children: /* @__PURE__ */ jsx("div", { className: "text-muted-foreground", children: "Loading API Playground..." }) }), "LoadingFallback");
1839
- var Playground = /* @__PURE__ */ __name(({ config }) => {
1840
- return /* @__PURE__ */ jsx(PlaygroundProvider, { config, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingFallback6, {}), children: /* @__PURE__ */ jsx(DocsLayout, {}) }) });
1841
- }, "Playground");
1842
- var OpenapiViewer_default = Playground;
1843
- var CronSchedulerClient = lazy(() => import('./CronScheduler.client-DLMXCPAJ.mjs'));
1844
- function CronScheduler(props) {
1845
- return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(CronSchedulerFallback, {}), children: /* @__PURE__ */ jsx(CronSchedulerClient, { ...props }) });
1846
- }
1847
- __name(CronScheduler, "CronScheduler");
1848
- function CronSchedulerFallback() {
1849
- return /* @__PURE__ */ jsx(
1850
- LoadingFallback,
1851
- {
1852
- minHeight: 120,
1853
- showText: false,
1854
- className: "rounded-lg"
1855
- }
1856
- );
1857
- }
1858
- __name(CronSchedulerFallback, "CronSchedulerFallback");
1859
-
1860
- // src/tools/CodeEditor/workers/setup.ts
1861
- var isSetup = false;
1862
- function setupMonacoWorkers(getWorker) {
1863
- if (isSetup || typeof window === "undefined") return;
1864
- if (getWorker) {
1865
- self.MonacoEnvironment = {
1866
- getWorker: /* @__PURE__ */ __name((_workerId, label) => getWorker(label), "getWorker")
1867
- };
1868
- }
1869
- isSetup = true;
1870
- }
1871
- __name(setupMonacoWorkers, "setupMonacoWorkers");
1872
-
1873
- // src/tools/CodeEditor/hooks/useMonaco.ts
1874
- function useMonaco() {
1875
- const [monaco, setMonaco] = useState(null);
1876
- const [isLoading, setIsLoading] = useState(true);
1877
- const [error, setError] = useState(null);
1878
- useEffect(() => {
1879
- let mounted = true;
1880
- async function loadMonaco() {
1881
- try {
1882
- setupMonacoWorkers();
1883
- const monacoModule = await import('monaco-editor');
1884
- if (mounted) {
1885
- setMonaco(monacoModule);
1886
- setIsLoading(false);
1887
- }
1888
- } catch (err) {
1889
- if (mounted) {
1890
- setError(err instanceof Error ? err : new Error("Failed to load Monaco Editor"));
1891
- setIsLoading(false);
1892
- }
1893
- }
1894
- }
1895
- __name(loadMonaco, "loadMonaco");
1896
- loadMonaco();
1897
- return () => {
1898
- mounted = false;
1899
- };
1900
- }, []);
1901
- return { monaco, isLoading, error };
1902
- }
1903
- __name(useMonaco, "useMonaco");
1904
- function useEditorTheme(monaco, themeOverride) {
1905
- const appTheme = useResolvedTheme();
1906
- const registered = useRef(false);
1907
- useEffect(() => {
1908
- if (!monaco || registered.current) return;
1909
- try {
1910
- const colors = _readCSSColors();
1911
- monaco.editor.defineTheme("app-dark", {
1912
- base: "vs-dark",
1913
- inherit: true,
1914
- rules: [
1915
- { token: "comment", foreground: "6A9955", fontStyle: "italic" },
1916
- { token: "keyword", foreground: "C586C0" },
1917
- { token: "string", foreground: "CE9178" },
1918
- { token: "number", foreground: "B5CEA8" },
1919
- { token: "type", foreground: "4EC9B0" },
1920
- { token: "function", foreground: "DCDCAA" },
1921
- { token: "variable", foreground: "9CDCFE" }
1922
- ],
1923
- colors: {
1924
- "editor.background": colors.background,
1925
- "editor.foreground": colors.foreground,
1926
- "editor.lineHighlightBackground": colors.lineHighlight,
1927
- "editor.selectionBackground": colors.selection,
1928
- "editorCursor.foreground": colors.foreground,
1929
- "editorLineNumber.foreground": colors.mutedForeground,
1930
- "editorWidget.background": colors.card,
1931
- "editorWidget.border": colors.border,
1932
- "input.background": colors.card,
1933
- "dropdown.background": colors.card
1934
- }
1935
- });
1936
- monaco.editor.defineTheme("app-light", {
1937
- base: "vs",
1938
- inherit: true,
1939
- rules: [
1940
- { token: "comment", foreground: "008000", fontStyle: "italic" },
1941
- { token: "keyword", foreground: "AF00DB" },
1942
- { token: "string", foreground: "A31515" },
1943
- { token: "number", foreground: "098658" },
1944
- { token: "type", foreground: "267F99" },
1945
- { token: "function", foreground: "795E26" },
1946
- { token: "variable", foreground: "001080" }
1947
- ],
1948
- colors: {
1949
- "editor.background": colors.backgroundLight,
1950
- "editor.foreground": colors.foregroundLight,
1951
- "editor.lineHighlightBackground": colors.lineHighlightLight,
1952
- "editor.selectionBackground": colors.selectionLight,
1953
- "editorLineNumber.foreground": colors.mutedForegroundLight,
1954
- "editorWidget.background": colors.cardLight,
1955
- "editorWidget.border": colors.borderLight
1956
- }
1957
- });
1958
- registered.current = true;
1959
- } catch {
1960
- }
1961
- }, [monaco]);
1962
- if (themeOverride) return themeOverride;
1963
- if (registered.current) {
1964
- return appTheme === "dark" ? "app-dark" : "app-light";
1965
- }
1966
- return appTheme === "dark" ? "vs-dark" : "vs";
1967
- }
1968
- __name(useEditorTheme, "useEditorTheme");
1969
- function _readCSSColors() {
1970
- const get = /* @__PURE__ */ __name((varName) => {
1971
- if (typeof document === "undefined") return "";
1972
- return getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
1973
- }, "get");
1974
- const hslToHex = /* @__PURE__ */ __name((hsl) => {
1975
- if (!hsl) return "";
1976
- const parts = hsl.split(/\s+/).map((s2) => parseFloat(s2.replace("%", "")));
1977
- if (parts.length < 3 || parts.some(isNaN)) return "";
1978
- const [h, s, l] = [parts[0], parts[1] / 100, parts[2] / 100];
1979
- const a = s * Math.min(l, 1 - l);
1980
- const f = /* @__PURE__ */ __name((n) => {
1981
- const k = (n + h / 30) % 12;
1982
- const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
1983
- return Math.round(255 * color).toString(16).padStart(2, "0");
1984
- }, "f");
1985
- return `#${f(0)}${f(8)}${f(4)}`;
1986
- }, "hslToHex");
1987
- const background = hslToHex(get("--background")) || "#0a0a0a";
1988
- const foreground = hslToHex(get("--foreground")) || "#f5f5f5";
1989
- const card = hslToHex(get("--card")) || "#141414";
1990
- const border = hslToHex(get("--border")) || "#262626";
1991
- const mutedForeground = hslToHex(get("--muted-foreground")) || "#858585";
1992
- const lineHighlight = _adjustBrightness(background, 10);
1993
- const primary = hslToHex(get("--primary"));
1994
- const selection = primary ? _adjustBrightness(primary, -40) : "#264F78";
1995
- return {
1996
- background,
1997
- foreground,
1998
- card,
1999
- border,
2000
- mutedForeground,
2001
- lineHighlight,
2002
- selection,
2003
- // Light variants
2004
- backgroundLight: "#ffffff",
2005
- foregroundLight: "#1a1a1a",
2006
- cardLight: "#ffffff",
2007
- borderLight: "#e5e5e5",
2008
- mutedForegroundLight: "#737373",
2009
- lineHighlightLight: "#f5f5f5",
2010
- selectionLight: "#ADD6FF"
2011
- };
2012
- }
2013
- __name(_readCSSColors, "_readCSSColors");
2014
- function _adjustBrightness(hex, amount) {
2015
- const num = parseInt(hex.replace("#", ""), 16);
2016
- const r = Math.min(255, Math.max(0, (num >> 16 & 255) + amount));
2017
- const g = Math.min(255, Math.max(0, (num >> 8 & 255) + amount));
2018
- const b = Math.min(255, Math.max(0, (num & 255) + amount));
2019
- return `#${(r << 16 | g << 8 | b).toString(16).padStart(6, "0")}`;
2020
- }
2021
- __name(_adjustBrightness, "_adjustBrightness");
2022
- var Editor = forwardRef(/* @__PURE__ */ __name(function Editor2({
2023
- value = "",
2024
- language = "plaintext",
2025
- onChange,
2026
- onMount,
2027
- options = {},
2028
- className = "",
2029
- height = "100%",
2030
- width = "100%",
2031
- autoHeight = false,
2032
- minHeight = 100,
2033
- maxHeight = 600
2034
- }, ref) {
2035
- const containerRef = useRef(null);
2036
- const editorRef = useRef(null);
2037
- const { monaco, isLoading } = useMonaco();
2038
- const resolvedTheme = useEditorTheme(monaco, options.theme);
2039
- const [contentHeight, setContentHeight] = useState(null);
2040
- const updateContentHeight = useCallback((editor) => {
2041
- if (!autoHeight) return;
2042
- const h = editor.getContentHeight();
2043
- setContentHeight(Math.min(Math.max(h, minHeight), maxHeight));
2044
- }, [autoHeight, minHeight, maxHeight]);
2045
- const isInternalChangeRef = useRef(false);
2046
- useImperativeHandle(ref, () => ({
2047
- getEditor: /* @__PURE__ */ __name(() => editorRef.current, "getEditor"),
2048
- getValue: /* @__PURE__ */ __name(() => editorRef.current?.getValue() || "", "getValue"),
2049
- setValue: /* @__PURE__ */ __name((val) => editorRef.current?.setValue(val), "setValue"),
2050
- focus: /* @__PURE__ */ __name(() => editorRef.current?.focus(), "focus")
2051
- }));
2052
- useEffect(() => {
2053
- if (!monaco || !containerRef.current || editorRef.current) return;
2054
- const editor = monaco.editor.create(containerRef.current, {
2055
- value,
2056
- language,
2057
- theme: resolvedTheme,
2058
- fontSize: options.fontSize || 14,
2059
- fontFamily: options.fontFamily || "'Fira Code', 'Consolas', monospace",
2060
- tabSize: options.tabSize || 2,
2061
- insertSpaces: options.insertSpaces !== false,
2062
- wordWrap: options.wordWrap || "on",
2063
- minimap: { enabled: options.minimap !== false },
2064
- lineNumbers: options.lineNumbers || "on",
2065
- readOnly: options.readOnly || false,
2066
- automaticLayout: true,
2067
- scrollBeyondLastLine: autoHeight ? false : false,
2068
- scrollbar: autoHeight ? { vertical: "hidden", horizontal: "auto" } : void 0,
2069
- overviewRulerLanes: autoHeight ? 0 : void 0,
2070
- padding: { top: 16, bottom: 16 },
2071
- renderLineHighlight: "all",
2072
- cursorBlinking: "smooth",
2073
- cursorSmoothCaretAnimation: "on",
2074
- smoothScrolling: true,
2075
- bracketPairColorization: { enabled: true },
2076
- guides: {
2077
- bracketPairs: true,
2078
- indentation: true
2079
- }
2080
- });
2081
- editorRef.current = editor;
2082
- if (onChange) {
2083
- editor.onDidChangeModelContent(() => {
2084
- isInternalChangeRef.current = true;
2085
- onChange(editor.getValue());
2086
- });
2087
- }
2088
- if (autoHeight) {
2089
- editor.onDidContentSizeChange(() => updateContentHeight(editor));
2090
- updateContentHeight(editor);
2091
- }
2092
- onMount?.(editor);
2093
- return () => {
2094
- editor.dispose();
2095
- editorRef.current = null;
2096
- };
2097
- }, [monaco]);
2098
- useEffect(() => {
2099
- const editor = editorRef.current;
2100
- if (!editor) return;
2101
- if (isInternalChangeRef.current) {
2102
- isInternalChangeRef.current = false;
2103
- return;
2104
- }
2105
- const currentValue = editor.getValue();
2106
- if (value !== currentValue) {
2107
- const position = editor.getPosition();
2108
- const selections = editor.getSelections();
2109
- editor.setValue(value);
2110
- if (position) {
2111
- editor.setPosition(position);
2112
- }
2113
- if (selections && selections.length > 0) {
2114
- editor.setSelections(selections);
2115
- }
2116
- }
2117
- }, [value]);
2118
- useEffect(() => {
2119
- const editor = editorRef.current;
2120
- if (!editor || !monaco) return;
2121
- const model = editor.getModel();
2122
- if (model) {
2123
- monaco.editor.setModelLanguage(model, language);
2124
- }
2125
- }, [language, monaco]);
2126
- useEffect(() => {
2127
- const editor = editorRef.current;
2128
- if (!editor) return;
2129
- editor.updateOptions({
2130
- theme: resolvedTheme,
2131
- fontSize: options.fontSize,
2132
- readOnly: options.readOnly,
2133
- minimap: { enabled: options.minimap !== false },
2134
- wordWrap: options.wordWrap,
2135
- lineNumbers: options.lineNumbers
2136
- });
2137
- }, [options, resolvedTheme]);
2138
- if (isLoading) {
2139
- return /* @__PURE__ */ jsx(
2140
- "div",
2141
- {
2142
- className,
2143
- style: {
2144
- width,
2145
- height,
2146
- display: "flex",
2147
- alignItems: "center",
2148
- justifyContent: "center",
2149
- backgroundColor: "#1e1e1e",
2150
- color: "#666"
2151
- },
2152
- children: "Loading editor..."
2153
- }
2154
- );
2155
- }
2156
- const resolvedHeight = autoHeight && contentHeight != null ? contentHeight : height;
2157
- return /* @__PURE__ */ jsx(
2158
- "div",
2159
- {
2160
- ref: containerRef,
2161
- className,
2162
- style: {
2163
- width,
2164
- height: resolvedHeight,
2165
- ...autoHeight && { minHeight, maxHeight, overflow: "hidden" }
2166
- }
2167
- }
2168
- );
2169
- }, "Editor"));
2170
- function DiffEditor({
2171
- original,
2172
- modified,
2173
- language = "plaintext",
2174
- options = {},
2175
- className = "",
2176
- height = "100%"
2177
- }) {
2178
- const containerRef = useRef(null);
2179
- const editorRef = useRef(null);
2180
- const { monaco, isLoading } = useMonaco();
2181
- const resolvedTheme = useEditorTheme(monaco, options.theme);
2182
- useEffect(() => {
2183
- if (!monaco || !containerRef.current || editorRef.current) return;
2184
- const editor = monaco.editor.createDiffEditor(containerRef.current, {
2185
- theme: resolvedTheme,
2186
- fontSize: options.fontSize || 14,
2187
- fontFamily: options.fontFamily || "'Fira Code', 'Consolas', monospace",
2188
- readOnly: true,
2189
- automaticLayout: true,
2190
- renderSideBySide: true,
2191
- scrollBeyondLastLine: false,
2192
- minimap: { enabled: false }
2193
- });
2194
- const originalModel = monaco.editor.createModel(original, language);
2195
- const modifiedModel = monaco.editor.createModel(modified, language);
2196
- editor.setModel({
2197
- original: originalModel,
2198
- modified: modifiedModel
2199
- });
2200
- editorRef.current = editor;
2201
- return () => {
2202
- originalModel.dispose();
2203
- modifiedModel.dispose();
2204
- editor.dispose();
2205
- editorRef.current = null;
2206
- };
2207
- }, [monaco]);
2208
- useEffect(() => {
2209
- const editor = editorRef.current;
2210
- if (!editor || !monaco) return;
2211
- const model = editor.getModel();
2212
- if (model) {
2213
- model.original.setValue(original);
2214
- model.modified.setValue(modified);
2215
- }
2216
- }, [original, modified, monaco]);
2217
- useEffect(() => {
2218
- const editor = editorRef.current;
2219
- if (!editor || !monaco) return;
2220
- const model = editor.getModel();
2221
- if (model) {
2222
- monaco.editor.setModelLanguage(model.original, language);
2223
- monaco.editor.setModelLanguage(model.modified, language);
2224
- }
2225
- }, [language, monaco]);
2226
- if (isLoading) {
2227
- return /* @__PURE__ */ jsx(
2228
- "div",
2229
- {
2230
- className,
2231
- style: {
2232
- width: "100%",
2233
- height,
2234
- display: "flex",
2235
- alignItems: "center",
2236
- justifyContent: "center",
2237
- backgroundColor: "#1e1e1e",
2238
- color: "#666"
2239
- },
2240
- children: "Loading diff editor..."
2241
- }
2242
- );
2243
- }
2244
- return /* @__PURE__ */ jsx(
2245
- "div",
2246
- {
2247
- ref: containerRef,
2248
- className,
2249
- style: {
2250
- width: "100%",
2251
- height
2252
- }
2253
- }
2254
- );
2255
- }
2256
- __name(DiffEditor, "DiffEditor");
2257
-
2258
- // src/tools/CodeEditor/lib/languages.ts
2259
- var LANGUAGE_MAP = {
2260
- // Web
2261
- ".html": "html",
2262
- ".htm": "html",
2263
- ".xhtml": "html",
2264
- ".vue": "html",
2265
- ".svelte": "html",
2266
- // CSS
2267
- ".css": "css",
2268
- ".scss": "scss",
2269
- ".sass": "scss",
2270
- ".less": "less",
2271
- // JavaScript/TypeScript
2272
- ".js": "javascript",
2273
- ".mjs": "javascript",
2274
- ".cjs": "javascript",
2275
- ".jsx": "javascript",
2276
- ".ts": "typescript",
2277
- ".tsx": "typescript",
2278
- ".mts": "typescript",
2279
- ".cts": "typescript",
2280
- // Data formats
2281
- ".json": "json",
2282
- ".jsonc": "json",
2283
- ".json5": "json",
2284
- ".yaml": "yaml",
2285
- ".yml": "yaml",
2286
- ".toml": "ini",
2287
- ".xml": "xml",
2288
- ".svg": "xml",
2289
- ".xsl": "xml",
2290
- ".xsd": "xml",
2291
- // Markdown & Documentation
2292
- ".md": "markdown",
2293
- ".mdx": "markdown",
2294
- ".markdown": "markdown",
2295
- ".rst": "restructuredtext",
2296
- ".txt": "plaintext",
2297
- ".text": "plaintext",
2298
- // Programming languages
2299
- ".py": "python",
2300
- ".pyw": "python",
2301
- ".pyi": "python",
2302
- ".rb": "ruby",
2303
- ".rake": "ruby",
2304
- ".gemspec": "ruby",
2305
- ".php": "php",
2306
- ".phtml": "php",
2307
- ".java": "java",
2308
- ".kt": "kotlin",
2309
- ".kts": "kotlin",
2310
- ".scala": "scala",
2311
- ".go": "go",
2312
- ".rs": "rust",
2313
- ".swift": "swift",
2314
- ".c": "c",
2315
- ".h": "c",
2316
- ".cpp": "cpp",
2317
- ".cc": "cpp",
2318
- ".cxx": "cpp",
2319
- ".hpp": "cpp",
2320
- ".hxx": "cpp",
2321
- ".cs": "csharp",
2322
- ".fs": "fsharp",
2323
- ".fsx": "fsharp",
2324
- ".vb": "vb",
2325
- ".lua": "lua",
2326
- ".r": "r",
2327
- ".R": "r",
2328
- ".m": "objective-c",
2329
- ".mm": "objective-c",
2330
- ".pl": "perl",
2331
- ".pm": "perl",
2332
- ".ex": "elixir",
2333
- ".exs": "elixir",
2334
- ".erl": "erlang",
2335
- ".hrl": "erlang",
2336
- ".clj": "clojure",
2337
- ".cljs": "clojure",
2338
- ".cljc": "clojure",
2339
- ".hs": "haskell",
2340
- ".lhs": "haskell",
2341
- ".ml": "fsharp",
2342
- ".mli": "fsharp",
2343
- ".dart": "dart",
2344
- ".groovy": "groovy",
2345
- ".gradle": "groovy",
2346
- ".jl": "julia",
2347
- // Shell & Scripts
2348
- ".sh": "shell",
2349
- ".bash": "shell",
2350
- ".zsh": "shell",
2351
- ".fish": "shell",
2352
- ".ps1": "powershell",
2353
- ".psm1": "powershell",
2354
- ".psd1": "powershell",
2355
- ".bat": "bat",
2356
- ".cmd": "bat",
2357
- // Config files
2358
- ".ini": "ini",
2359
- ".cfg": "ini",
2360
- ".conf": "ini",
2361
- ".properties": "ini",
2362
- ".env": "ini",
2363
- ".gitignore": "ini",
2364
- ".gitattributes": "ini",
2365
- ".editorconfig": "ini",
2366
- ".npmrc": "ini",
2367
- // Database
2368
- ".sql": "sql",
2369
- ".mysql": "mysql",
2370
- ".pgsql": "pgsql",
2371
- ".plsql": "plsql",
2372
- ".redis": "redis",
2373
- // Templates
2374
- ".hbs": "handlebars",
2375
- ".handlebars": "handlebars",
2376
- ".mustache": "handlebars",
2377
- ".ejs": "html",
2378
- ".pug": "pug",
2379
- ".jade": "pug",
2380
- ".twig": "twig",
2381
- ".liquid": "liquid",
2382
- // GraphQL
2383
- ".graphql": "graphql",
2384
- ".gql": "graphql",
2385
- // Docker
2386
- ".dockerfile": "dockerfile",
2387
- // Other
2388
- ".diff": "diff",
2389
- ".patch": "diff",
2390
- ".log": "log",
2391
- ".tex": "latex",
2392
- ".cls": "latex",
2393
- ".sty": "latex",
2394
- ".proto": "protobuf",
2395
- ".sol": "sol",
2396
- ".asm": "mips",
2397
- ".s": "mips",
2398
- ".wasm": "wasm"
2399
- };
2400
- var FILENAME_MAP = {
2401
- Dockerfile: "dockerfile",
2402
- "docker-compose.yml": "yaml",
2403
- "docker-compose.yaml": "yaml",
2404
- Makefile: "makefile",
2405
- makefile: "makefile",
2406
- Gemfile: "ruby",
2407
- Rakefile: "ruby",
2408
- Jenkinsfile: "groovy",
2409
- Vagrantfile: "ruby",
2410
- ".bashrc": "shell",
2411
- ".bash_profile": "shell",
2412
- ".zshrc": "shell",
2413
- ".profile": "shell",
2414
- ".vimrc": "plaintext",
2415
- ".gitconfig": "ini",
2416
- ".htaccess": "ini",
2417
- "nginx.conf": "ini",
2418
- "package.json": "json",
2419
- "tsconfig.json": "json",
2420
- "jsconfig.json": "json",
2421
- ".prettierrc": "json",
2422
- ".eslintrc": "json",
2423
- "composer.json": "json",
2424
- "Cargo.toml": "ini",
2425
- "go.mod": "go",
2426
- "go.sum": "plaintext",
2427
- "requirements.txt": "plaintext",
2428
- "pyproject.toml": "ini",
2429
- "setup.py": "python",
2430
- "setup.cfg": "ini"
2431
- };
2432
- function getLanguageByFilename(filename) {
2433
- if (FILENAME_MAP[filename]) {
2434
- return FILENAME_MAP[filename];
2435
- }
2436
- const lastDot = filename.lastIndexOf(".");
2437
- if (lastDot === -1) {
2438
- return "plaintext";
2439
- }
2440
- const extension = filename.slice(lastDot).toLowerCase();
2441
- return LANGUAGE_MAP[extension] || "plaintext";
2442
- }
2443
- __name(getLanguageByFilename, "getLanguageByFilename");
2444
- var EditorContext = createContext(null);
2445
- function useEditorContext() {
2446
- const context = useContext(EditorContext);
2447
- if (!context) {
2448
- throw new Error("useEditorContext must be used within EditorProvider");
2449
- }
2450
- return context;
2451
- }
2452
- __name(useEditorContext, "useEditorContext");
2453
- function EditorProvider({ children, onSave }) {
2454
- const { monaco } = useMonaco();
2455
- const [editor, setEditor] = useState(null);
2456
- const [openFiles, setOpenFiles] = useState([]);
2457
- const [activeFilePath, setActiveFilePath] = useState(null);
2458
- const activeFile = useMemo(
2459
- () => openFiles.find((f) => f.path === activeFilePath) || null,
2460
- [openFiles, activeFilePath]
2461
- );
2462
- const openFile = useCallback(
2463
- (path, content, language) => {
2464
- setOpenFiles((files) => {
2465
- const existing = files.find((f) => f.path === path);
2466
- if (existing) {
2467
- return files;
2468
- }
2469
- const basename = path.split("/").pop() || path;
2470
- const detectedLanguage = language || getLanguageByFilename(basename);
2471
- const newFile = {
2472
- path,
2473
- content,
2474
- language: detectedLanguage,
2475
- isDirty: false
2476
- };
2477
- return [...files, newFile];
2478
- });
2479
- setActiveFilePath(path);
2480
- },
2481
- []
2482
- );
2483
- const closeFile = useCallback(
2484
- (path) => {
2485
- setOpenFiles((files) => {
2486
- const index = files.findIndex((f) => f.path === path);
2487
- if (index === -1) return files;
2488
- const newFiles = files.filter((f) => f.path !== path);
2489
- if (activeFilePath === path && newFiles.length > 0) {
2490
- const newIndex = Math.min(index, newFiles.length - 1);
2491
- setActiveFilePath(newFiles[newIndex].path);
2492
- } else if (newFiles.length === 0) {
2493
- setActiveFilePath(null);
2494
- }
2495
- return newFiles;
2496
- });
2497
- },
2498
- [activeFilePath]
2499
- );
2500
- const setActiveFile = useCallback((path) => {
2501
- setActiveFilePath(path);
2502
- }, []);
2503
- const updateContent = useCallback((path, content) => {
2504
- setOpenFiles(
2505
- (files) => files.map(
2506
- (f) => f.path === path ? { ...f, content, isDirty: true } : f
2507
- )
2508
- );
2509
- }, []);
2510
- const saveFile = useCallback(
2511
- async (path) => {
2512
- const file = openFiles.find((f) => f.path === path);
2513
- if (!file) return;
2514
- if (onSave) {
2515
- await onSave(path, file.content);
2516
- }
2517
- setOpenFiles(
2518
- (files) => files.map(
2519
- (f) => f.path === path ? { ...f, isDirty: false } : f
2520
- )
2521
- );
2522
- },
2523
- [openFiles, onSave]
2524
- );
2525
- const isDirty = useCallback(
2526
- (path) => {
2527
- const file = openFiles.find((f) => f.path === path);
2528
- return file?.isDirty || false;
2529
- },
2530
- [openFiles]
2531
- );
2532
- const getContent = useCallback(
2533
- (path) => {
2534
- const file = openFiles.find((f) => f.path === path);
2535
- return file?.content || null;
2536
- },
2537
- [openFiles]
2538
- );
2539
- const getFile = useCallback(
2540
- (path) => {
2541
- return openFiles.find((f) => f.path === path) || null;
2542
- },
2543
- [openFiles]
2544
- );
2545
- const value = {
2546
- openFiles,
2547
- activeFile,
2548
- monaco,
2549
- editor,
2550
- isReady: monaco !== null && editor !== null,
2551
- openFile,
2552
- closeFile,
2553
- setActiveFile,
2554
- updateContent,
2555
- saveFile,
2556
- isDirty,
2557
- getContent,
2558
- getFile
2559
- };
2560
- return /* @__PURE__ */ jsx(EditorContext.Provider, { value, children });
2561
- }
2562
- __name(EditorProvider, "EditorProvider");
2563
- function useEditor() {
2564
- const [editor, setEditorState] = useState(null);
2565
- const setEditor = useCallback((editorInstance) => {
2566
- setEditorState(editorInstance);
2567
- }, []);
2568
- return {
2569
- editor,
2570
- isReady: editor !== null,
2571
- setEditor
2572
- };
2573
- }
2574
- __name(useEditor, "useEditor");
2575
- function useLanguage(filename) {
2576
- return useMemo(() => {
2577
- if (!filename) return "plaintext";
2578
- const basename = filename.split("/").pop() || filename;
2579
- return getLanguageByFilename(basename);
2580
- }, [filename]);
2581
- }
2582
- __name(useLanguage, "useLanguage");
2583
- var MentionList = forwardRef(
2584
- ({ items, command }, ref) => {
2585
- const [selectedIndex, setSelectedIndex] = useState(0);
2586
- useEffect(() => setSelectedIndex(0), [items]);
2587
- const select = useCallback(
2588
- (index) => {
2589
- const item = items[index];
2590
- if (item) command(item);
2591
- },
2592
- [items, command]
2593
- );
2594
- useImperativeHandle(ref, () => ({
2595
- onKeyDown: /* @__PURE__ */ __name((event) => {
2596
- if (event.key === "ArrowUp") {
2597
- setSelectedIndex((i) => (i + items.length - 1) % items.length);
2598
- return true;
2599
- }
2600
- if (event.key === "ArrowDown") {
2601
- setSelectedIndex((i) => (i + 1) % items.length);
2602
- return true;
2603
- }
2604
- if (event.key === "Enter") {
2605
- select(selectedIndex);
2606
- return true;
2607
- }
2608
- return false;
2609
- }, "onKeyDown")
2610
- }));
2611
- if (items.length === 0) return null;
2612
- return /* @__PURE__ */ jsx("div", { className: "markdown-mention-list", children: items.map((item, i) => {
2613
- const isSelected = i === selectedIndex;
2614
- const cls = `markdown-mention-item ${isSelected ? "selected" : ""}`;
2615
- return /* @__PURE__ */ jsxs("button", { type: "button", className: cls, onClick: () => select(i), children: [
2616
- item.thumbnail && /* @__PURE__ */ jsx("img", { src: item.thumbnail, alt: "", className: "markdown-mention-avatar" }),
2617
- /* @__PURE__ */ jsxs("div", { className: "markdown-mention-info", children: [
2618
- /* @__PURE__ */ jsx("span", { className: "markdown-mention-name", children: item.label }),
2619
- item.description && /* @__PURE__ */ jsx("span", { className: "markdown-mention-desc", children: item.description })
2620
- ] })
2621
- ] }, item.id);
2622
- }) });
2623
- }
2624
- );
2625
- MentionList.displayName = "MentionList";
2626
-
2627
- // src/tools/MarkdownEditor/createMentionSuggestion.ts
2628
- function createMentionSuggestion(config) {
2629
- const { maxItems = 5, trigger = "@" } = config;
2630
- return {
2631
- char: trigger,
2632
- items: /* @__PURE__ */ __name(({ query }) => {
2633
- const q = query.toLowerCase();
2634
- return config.items.filter((item) => item.label.toLowerCase().includes(q)).slice(0, maxItems);
2635
- }, "items"),
2636
- render: /* @__PURE__ */ __name(() => {
2637
- let component = null;
2638
- let popup = null;
2639
- let cleanupAutoUpdate = null;
2640
- let getReferenceRect = null;
2641
- const buildVirtualElement = /* @__PURE__ */ __name(() => ({
2642
- getBoundingClientRect: /* @__PURE__ */ __name(() => {
2643
- const rect = getReferenceRect?.();
2644
- return rect ?? new DOMRect(0, 0, 0, 0);
2645
- }, "getBoundingClientRect")
2646
- }), "buildVirtualElement");
2647
- const updatePosition = /* @__PURE__ */ __name(() => {
2648
- if (!popup) return;
2649
- const virtualEl = buildVirtualElement();
2650
- void computePosition(virtualEl, popup, {
2651
- placement: "bottom-start",
2652
- middleware: [
2653
- offset(4),
2654
- flip({ fallbackPlacements: ["top-start"] }),
2655
- shift({ padding: 8 })
2656
- ]
2657
- }).then(({ x, y }) => {
2658
- if (!popup) return;
2659
- popup.style.transform = `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`;
2660
- });
2661
- }, "updatePosition");
2662
- const teardown = /* @__PURE__ */ __name(() => {
2663
- cleanupAutoUpdate?.();
2664
- cleanupAutoUpdate = null;
2665
- popup?.remove();
2666
- popup = null;
2667
- component?.destroy();
2668
- component = null;
2669
- getReferenceRect = null;
2670
- }, "teardown");
2671
- return {
2672
- onStart: /* @__PURE__ */ __name((props) => {
2673
- component = new ReactRenderer(MentionList, {
2674
- props: {
2675
- items: props.items,
2676
- command: /* @__PURE__ */ __name((item) => {
2677
- props.command({ id: item.id, label: item.label });
2678
- }, "command")
2679
- },
2680
- editor: props.editor
2681
- });
2682
- popup = document.createElement("div");
2683
- popup.style.cssText = "position: absolute; top: 0; left: 0; z-index: 99999;";
2684
- popup.appendChild(component.element);
2685
- document.body.appendChild(popup);
2686
- getReferenceRect = /* @__PURE__ */ __name(() => props.clientRect?.() ?? null, "getReferenceRect");
2687
- const virtualEl = buildVirtualElement();
2688
- cleanupAutoUpdate = autoUpdate(virtualEl, popup, updatePosition);
2689
- }, "onStart"),
2690
- onUpdate: /* @__PURE__ */ __name((props) => {
2691
- component?.updateProps({
2692
- items: props.items,
2693
- command: /* @__PURE__ */ __name((item) => {
2694
- props.command({ id: item.id, label: item.label });
2695
- }, "command")
2696
- });
2697
- getReferenceRect = /* @__PURE__ */ __name(() => props.clientRect?.() ?? null, "getReferenceRect");
2698
- updatePosition();
2699
- }, "onUpdate"),
2700
- onKeyDown: /* @__PURE__ */ __name((props) => {
2701
- if (props.event.key === "Escape") {
2702
- teardown();
2703
- return true;
2704
- }
2705
- return component?.ref?.onKeyDown(props.event) ?? false;
2706
- }, "onKeyDown"),
2707
- onExit: /* @__PURE__ */ __name(() => {
2708
- teardown();
2709
- }, "onExit")
2710
- };
2711
- }, "render")
2712
- };
2713
- }
2714
- __name(createMentionSuggestion, "createMentionSuggestion");
2715
-
2716
- // src/tools/MarkdownEditor/mentionPresets.ts
2717
- var escapeMd = /* @__PURE__ */ __name((s) => s.replace(/([\\\[\]()_*~`])/g, "\\$1"), "escapeMd");
2718
- var mentionPresets = {
2719
- /** "@Label" — default, ideal for chat where LLMs read the text. */
2720
- plainAt: /* @__PURE__ */ __name((({ label, id }) => `@${label || id}`), "plainAt"),
2721
- /** "Label" — bare label, no @ prefix. */
2722
- plainLabel: /* @__PURE__ */ __name((({ label, id }) => label || id), "plainLabel"),
2723
- /** "[@Label](baseUrl/id)" — clickable markdown link. */
2724
- markdownLink: /* @__PURE__ */ __name((baseUrl) => ({ label, id }) => `[@${escapeMd(label || id)}](${baseUrl}${encodeURIComponent(id)})`, "markdownLink"),
2725
- /** "@[Label](scheme://kind/id)" — Notion / Linear-style custom URI. */
2726
- customUri: /* @__PURE__ */ __name((scheme, kind) => ({ label, id }) => `@[${escapeMd(label || id)}](${scheme}://${kind}/${encodeURIComponent(id)})`, "customUri"),
2727
- /** "<@id>" — Slack-style id-only reference (label dropped — receivers resolve it). */
2728
- slackStyle: /* @__PURE__ */ __name((({ id }) => `<@${id}>`), "slackStyle"),
2729
- /** Inline HTML span — for products that consume markdown with raw HTML allowed. */
2730
- htmlSpan: /* @__PURE__ */ __name((className = "mention") => ({ label, id }) => `<span class="${className}" data-mention-id="${encodeURIComponent(id)}">@${escapeMd(label || id)}</span>`, "htmlSpan")
2731
- };
2732
- var SubmitOnEnter = Extension.create({
2733
- name: "submitOnEnter",
2734
- addOptions() {
2735
- return {
2736
- // Default no-op — explicit consumer must override. We never
2737
- // intercept Enter unless an onSubmit is wired, so leaving the
2738
- // extension installed with no handler is safe.
2739
- onSubmit: /* @__PURE__ */ __name(() => false, "onSubmit")
2740
- };
2741
- },
2742
- addKeyboardShortcuts() {
2743
- return {
2744
- Enter: /* @__PURE__ */ __name(() => {
2745
- if (typeof document !== "undefined" && document.querySelector(".markdown-mention-list")) {
2746
- return false;
2747
- }
2748
- const result = this.options.onSubmit();
2749
- return result !== false;
2750
- }, "Enter"),
2751
- // Shift+Enter — always insert a newline. Tiptap's StarterKit
2752
- // already binds this to HardBreak; we re-bind to `false` (not
2753
- // handled) so the chain falls through cleanly even if other
2754
- // extensions try to grab Shift+Enter.
2755
- "Shift-Enter": /* @__PURE__ */ __name(() => false, "Shift-Enter")
2756
- };
2757
- }
2758
- });
2759
- function getMarkdown(editor) {
2760
- const storage = editor.storage.markdown;
2761
- if (!storage?.manager) return editor.getText();
2762
- return storage.manager.serialize(editor.getJSON());
2763
- }
2764
- __name(getMarkdown, "getMarkdown");
2765
- function extractMentionIds(editor) {
2766
- const ids = [];
2767
- editor.state.doc.descendants((node) => {
2768
- if (node.type.name === "mention" && node.attrs.id) {
2769
- ids.push(node.attrs.id);
2770
- }
2771
- });
2772
- return [...new Set(ids)];
2773
- }
2774
- __name(extractMentionIds, "extractMentionIds");
2775
- var MarkdownEditor = forwardRef(/* @__PURE__ */ __name(function MarkdownEditor2({
2776
- value,
2777
- onChange,
2778
- placeholder = "Write markdown...",
2779
- minHeight = 120,
2780
- className = "",
2781
- disabled = false,
2782
- showToolbar = true,
2783
- mentions,
2784
- onMentionIdsChange,
2785
- onSubmit
2786
- }, ref) {
2787
- const onSubmitRef = useRef(onSubmit);
2788
- onSubmitRef.current = onSubmit;
2789
- const isExternalUpdate = useRef(false);
2790
- const initialMentionsDefinedRef = useRef(mentions !== void 0);
2791
- const warnedRef = useRef(false);
2792
- if (process.env.NODE_ENV !== "production" && !initialMentionsDefinedRef.current && mentions !== void 0 && !warnedRef.current) {
2793
- warnedRef.current = true;
2794
- console.warn(
2795
- "[MarkdownEditor] `mentions` flipped from undefined to a config after mount. Tiptap only installs the Mention extension on first render \u2014 the @-popover will NOT work for this editor instance. Pass `{ items: [] }` from the very first render and mutate `.items` in place instead."
2796
- );
2797
- }
2798
- const extensions = useMemo(() => {
2799
- const exts = [
2800
- StarterKit.configure({ heading: { levels: [1, 2, 3] } }),
2801
- Placeholder.configure({ placeholder }),
2802
- Markdown,
2803
- // SubmitOnEnter — when the consumer wired an onSubmit, intercept
2804
- // Enter at the keymap level (before StarterKit's HardBreak).
2805
- // The extension calls through `onSubmitRef.current` so handler
2806
- // identity changes don't require an editor rebuild. See
2807
- // submitOnEnter.ts for the keymap-vs-wrapper-handler rationale.
2808
- SubmitOnEnter.configure({
2809
- onSubmit: /* @__PURE__ */ __name(() => {
2810
- const h = onSubmitRef.current;
2811
- if (!h) return false;
2812
- return h();
2813
- }, "onSubmit")
2814
- })
2815
- ];
2816
- if (mentions) {
2817
- const renderMarkdown = mentions.renderMarkdown ?? mentionPresets.plainAt;
2818
- exts.push(
2819
- Mention.extend({
2820
- renderMarkdown(node) {
2821
- const raw = node.attrs;
2822
- const attrs = {
2823
- id: raw?.id ?? "",
2824
- label: raw?.label ?? ""
2825
- };
2826
- if (!attrs.id && !attrs.label) return "";
2827
- return renderMarkdown(attrs);
2828
- }
2829
- }).configure({
2830
- HTMLAttributes: { class: "markdown-mention" },
2831
- suggestion: createMentionSuggestion(mentions),
2832
- renderText: /* @__PURE__ */ __name(({ node }) => `@${node.attrs.label}`, "renderText")
2833
- })
2834
- );
2835
- }
2836
- return exts;
2837
- }, [placeholder, mentions]);
2838
- const editor = useEditor$1({
2839
- immediatelyRender: false,
2840
- editable: !disabled,
2841
- extensions,
2842
- content: value,
2843
- onUpdate: /* @__PURE__ */ __name(({ editor: editor2 }) => {
2844
- if (isExternalUpdate.current) return;
2845
- onChange(getMarkdown(editor2));
2846
- if (onMentionIdsChange) {
2847
- onMentionIdsChange(extractMentionIds(editor2));
2848
- }
2849
- }, "onUpdate"),
2850
- editorProps: {
2851
- attributes: {
2852
- class: "markdown-editor-content focus:outline-none text-sm",
2853
- style: `min-height: ${minHeight}px`
2854
- }
2855
- }
2856
- });
2857
- useEffect(() => {
2858
- if (!editor) return;
2859
- const current = getMarkdown(editor);
2860
- if (current !== value) {
2861
- isExternalUpdate.current = true;
2862
- editor.commands.setContent(value);
2863
- isExternalUpdate.current = false;
2864
- }
2865
- }, [value, editor]);
2866
- useImperativeHandle(
2867
- ref,
2868
- () => ({
2869
- focus: /* @__PURE__ */ __name(() => {
2870
- editor?.commands.focus();
2871
- }, "focus"),
2872
- moveCursorToEnd: /* @__PURE__ */ __name(() => {
2873
- editor?.commands.focus("end");
2874
- }, "moveCursorToEnd"),
2875
- getEditor: /* @__PURE__ */ __name(() => editor ?? null, "getEditor")
2876
- }),
2877
- [editor]
2878
- );
2879
- const wrapperClass = `markdown-editor rounded-md border border-input bg-background ${disabled ? "opacity-60" : ""} ${className}`.trim();
2880
- return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
2881
- showToolbar && editor && /* @__PURE__ */ jsx(MarkdownToolbar, { editor }),
2882
- /* @__PURE__ */ jsx("div", { className: "px-3 py-2", children: /* @__PURE__ */ jsx(EditorContent, { editor }) })
2883
- ] });
2884
- }, "MarkdownEditor"));
2885
- function MarkdownToolbar({ editor }) {
2886
- const items = useMemo(() => [
2887
- { icon: Bold, title: "Bold", action: /* @__PURE__ */ __name(() => editor.chain().focus().toggleBold().run(), "action"), active: editor.isActive("bold") },
2888
- { icon: Italic, title: "Italic", action: /* @__PURE__ */ __name(() => editor.chain().focus().toggleItalic().run(), "action"), active: editor.isActive("italic") },
2889
- { icon: Strikethrough, title: "Strike", action: /* @__PURE__ */ __name(() => editor.chain().focus().toggleStrike().run(), "action"), active: editor.isActive("strike") },
2890
- { icon: Code, title: "Code", action: /* @__PURE__ */ __name(() => editor.chain().focus().toggleCode().run(), "action"), active: editor.isActive("code") },
2891
- null,
2892
- { icon: Heading1, title: "H1", action: /* @__PURE__ */ __name(() => editor.chain().focus().toggleHeading({ level: 1 }).run(), "action"), active: editor.isActive("heading", { level: 1 }) },
2893
- { icon: Heading2, title: "H2", action: /* @__PURE__ */ __name(() => editor.chain().focus().toggleHeading({ level: 2 }).run(), "action"), active: editor.isActive("heading", { level: 2 }) },
2894
- { icon: Heading3, title: "H3", action: /* @__PURE__ */ __name(() => editor.chain().focus().toggleHeading({ level: 3 }).run(), "action"), active: editor.isActive("heading", { level: 3 }) },
2895
- null,
2896
- { icon: List, title: "Bullet list", action: /* @__PURE__ */ __name(() => editor.chain().focus().toggleBulletList().run(), "action"), active: editor.isActive("bulletList") },
2897
- { icon: ListOrdered, title: "Ordered list", action: /* @__PURE__ */ __name(() => editor.chain().focus().toggleOrderedList().run(), "action"), active: editor.isActive("orderedList") },
2898
- { icon: Quote, title: "Quote", action: /* @__PURE__ */ __name(() => editor.chain().focus().toggleBlockquote().run(), "action"), active: editor.isActive("blockquote") },
2899
- { icon: Minus, title: "Divider", action: /* @__PURE__ */ __name(() => editor.chain().focus().setHorizontalRule().run(), "action"), active: false }
2900
- ], [editor]);
2901
- return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0.5 px-2 py-1.5 border-b border-border", children: items.map((item, i) => {
2902
- if (!item) return /* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-border mx-1" }, i);
2903
- const Icon = item.icon;
2904
- const btnClass = `markdown-toolbar-btn ${item.active ? "active" : ""}`;
2905
- return /* @__PURE__ */ jsx("button", { type: "button", onClick: item.action, title: item.title, className: btnClass, children: /* @__PURE__ */ jsx(Icon, { style: { width: 14, height: 14 } }) }, i);
2906
- }) });
2907
- }
2908
- __name(MarkdownToolbar, "MarkdownToolbar");
2909
-
2910
- export { AudioToggle, CronScheduler, DEFAULT_DOCK_PREFS, DiffEditor, Editor, EditorProvider, LazyPlayer as LazyAudioPlayer, LazyChat, LazyCronScheduler, LazyImageViewer, LazyJsonSchemaForm, LazyJsonTree, LazyLottiePlayer, LazyMapContainer, LazyMapView, LazyMermaid, LazyOpenapiViewer, LazyPrettyCode, LazyTree, LazyVideoPlayer, LottiePlayer, MarkdownEditor, OpenapiViewer_default as OpenapiViewer, TransportError, collectImageAttachments, createHttpTransport, createMockTransport, createPydanticAIChatTransport, createPydanticAISSEMap, createToolIdQueue, dispatchToolPayload, isGeoJSONFeatureCollection, isLatLng, isPlainObject, isStringValue, mapPydanticAIEvent, mentionPresets, parseSSE, useChatAudioPrefs, useChatDockPrefs, useChatHistory, useChatLightbox, useChatScroll, useChatUnread, useEditor, useEditorContext, useLanguage, useMonaco, useVisitorFingerprint };
2911
- //# sourceMappingURL=index.mjs.map
2912
- //# sourceMappingURL=index.mjs.map