@djangocfg/ui-tools 2.1.385 → 2.1.389
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -11
- package/dist/ChatRoot-EFNXQXXN.cjs +15 -0
- package/dist/{ChatRoot-JVR3M3H2.mjs.map → ChatRoot-EFNXQXXN.cjs.map} +1 -1
- package/dist/ChatRoot-FITF5RVP.mjs +6 -0
- package/dist/{ChatRoot-LXIUBOXF.cjs.map → ChatRoot-FITF5RVP.mjs.map} +1 -1
- package/dist/{DocsLayout-2P3ONDWJ.mjs → DocsLayout-EKASBSP7.mjs} +3 -3
- package/dist/{DocsLayout-2P3ONDWJ.mjs.map → DocsLayout-EKASBSP7.mjs.map} +1 -1
- package/dist/{DocsLayout-2YZNS5VK.cjs → DocsLayout-OURFYWQE.cjs} +8 -8
- package/dist/{DocsLayout-2YZNS5VK.cjs.map → DocsLayout-OURFYWQE.cjs.map} +1 -1
- package/dist/MapContainer-AKIPABJK.mjs +4 -0
- package/dist/MapContainer-AKIPABJK.mjs.map +1 -0
- package/dist/MapContainer-STVDMC36.cjs +17 -0
- package/dist/MapContainer-STVDMC36.cjs.map +1 -0
- package/dist/{chunk-HIK6BPL7.mjs → chunk-2NG4SXEP.mjs} +6 -5
- package/dist/chunk-2NG4SXEP.mjs.map +1 -0
- package/dist/chunk-4LFB7I5K.cjs +1387 -0
- package/dist/chunk-4LFB7I5K.cjs.map +1 -0
- package/dist/{MapContainer-76YL2JXL.cjs → chunk-5D2OCOPQ.cjs} +3 -2
- package/dist/chunk-5D2OCOPQ.cjs.map +1 -0
- package/dist/chunk-6ZX2G25W.mjs +1361 -0
- package/dist/chunk-6ZX2G25W.mjs.map +1 -0
- package/dist/{MapContainer-7HXBI3OH.mjs → chunk-7CWGZPO3.mjs} +3 -3
- package/dist/chunk-7CWGZPO3.mjs.map +1 -0
- package/dist/{chunk-FIRK5CEH.cjs → chunk-7IYXZUJO.cjs} +8 -4
- package/dist/chunk-7IYXZUJO.cjs.map +1 -0
- package/dist/{chunk-PEKBT75W.mjs → chunk-DMX7W4XZ.mjs} +53 -1387
- package/dist/chunk-DMX7W4XZ.mjs.map +1 -0
- package/dist/chunk-NTVBIIUD.mjs +1439 -0
- package/dist/chunk-NTVBIIUD.mjs.map +1 -0
- package/dist/{chunk-HPK3EWBF.cjs → chunk-TBSHZO5R.cjs} +50 -1409
- package/dist/chunk-TBSHZO5R.cjs.map +1 -0
- package/dist/chunk-W75B7Y6C.cjs +1478 -0
- package/dist/chunk-W75B7Y6C.cjs.map +1 -0
- package/dist/index.cjs +1269 -1790
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +660 -623
- package/dist/index.d.ts +660 -623
- package/dist/index.mjs +856 -1427
- package/dist/index.mjs.map +1 -1
- package/dist/launcher-5Y42OBSN.mjs +6 -0
- package/dist/launcher-5Y42OBSN.mjs.map +1 -0
- package/dist/launcher-PMW2YB24.cjs +59 -0
- package/dist/launcher-PMW2YB24.cjs.map +1 -0
- package/package.json +23 -18
- package/src/components/index.ts +2 -2
- package/src/index.ts +20 -2
- package/src/tools/AudioPlayer/lazy.tsx +100 -0
- package/src/tools/Chat/README.md +85 -1
- package/src/tools/Chat/components/MessageBubble.tsx +1 -1
- package/src/tools/Chat/context/ChatProvider.tsx +42 -0
- package/src/tools/Chat/index.ts +1 -1
- package/src/tools/Chat/lazy.tsx +300 -1
- package/src/tools/CodeEditor/lazy.tsx +70 -0
- package/src/tools/Map/lazy.tsx +38 -1
- package/src/tools/MarkdownEditor/lazy.tsx +42 -0
- package/src/{components/markdown → tools}/MarkdownMessage/CodeBlock.tsx +1 -1
- package/src/{components/markdown → tools}/MarkdownMessage/CollapseToggle.tsx +1 -1
- package/src/{components/markdown → tools}/MarkdownMessage/MarkdownMessage.tsx +1 -1
- package/src/{components/markdown → tools}/MarkdownMessage/components.tsx +2 -2
- package/src/tools/OpenapiViewer/components/DocsLayout/ApiIntroSection.tsx +1 -1
- package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Header/index.tsx +1 -1
- package/src/tools/SpeechRecognition/README.md +48 -0
- package/dist/ChatRoot-JVR3M3H2.mjs +0 -5
- package/dist/ChatRoot-LXIUBOXF.cjs +0 -14
- package/dist/MapContainer-76YL2JXL.cjs.map +0 -1
- package/dist/MapContainer-7HXBI3OH.mjs.map +0 -1
- package/dist/chunk-FIRK5CEH.cjs.map +0 -1
- package/dist/chunk-HIK6BPL7.mjs.map +0 -1
- package/dist/chunk-HPK3EWBF.cjs.map +0 -1
- package/dist/chunk-PEKBT75W.mjs.map +0 -1
- package/src/components/markdown/index.ts +0 -19
- /package/src/{components/markdown → hooks}/useCollapsibleContent.ts +0 -0
- /package/src/{components/markdown → tools}/MarkdownMessage/ActionRow.tsx +0 -0
- /package/src/{components/markdown → tools}/MarkdownMessage/ChatMessageRow.tsx +0 -0
- /package/src/{components/markdown → tools}/MarkdownMessage/README.md +0 -0
- /package/src/{components/markdown → tools}/MarkdownMessage/index.ts +0 -0
- /package/src/{components/markdown → tools}/MarkdownMessage/linkRules.ts +0 -0
- /package/src/{components/markdown → tools}/MarkdownMessage/plainText.ts +0 -0
- /package/src/{components/markdown → tools}/MarkdownMessage/sanitize.ts +0 -0
- /package/src/{components/markdown → tools}/MarkdownMessage/types.ts +0 -0
package/src/tools/Chat/lazy.tsx
CHANGED
|
@@ -1,7 +1,36 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* `@djangocfg/ui-tools/chat` subpath entrypoint.
|
|
5
|
+
*
|
|
6
|
+
* This file is the public surface consumers see when they
|
|
7
|
+
* `import … from '@djangocfg/ui-tools/chat'`. It is designed so that the
|
|
8
|
+
* heavy chat UI (~hundreds of KB across MessageList, Composer, ToolCalls,
|
|
9
|
+
* Attachments, MarkdownMessage transitively) loads only when one of the
|
|
10
|
+
* `Lazy*` wrappers actually mounts.
|
|
11
|
+
*
|
|
12
|
+
* Rules of thumb:
|
|
13
|
+
* - **Heavy** (ChatRoot, ChatLauncher, ChatFAB, ChatDock, MessageList,
|
|
14
|
+
* MessageBubble, Composer, ToolCalls, Attachments*, ChatHeader*, …) —
|
|
15
|
+
* loaded only via `Lazy*` wrappers below. Do NOT add synchronous
|
|
16
|
+
* re-exports for these from this file.
|
|
17
|
+
* - **Light** (types, config constants, pure core reducer/utils,
|
|
18
|
+
* transports, hooks without UI, audio prefs, draft sanitizer) —
|
|
19
|
+
* re-exported synchronously here. Types are erased at compile time;
|
|
20
|
+
* helpers and hooks pull in no UI components.
|
|
21
|
+
*
|
|
22
|
+
* Consumers that need synchronous access to the heavy components
|
|
23
|
+
* (custom chat layouts, Storybook stories) can import from the root
|
|
24
|
+
* barrel `@djangocfg/ui-tools` instead.
|
|
25
|
+
*/
|
|
26
|
+
|
|
3
27
|
import { createLazyComponent, LoadingFallback } from '../../components/lazy-wrapper';
|
|
4
28
|
import type { ChatRootProps } from './components/ChatRoot';
|
|
29
|
+
import type { ChatLauncherProps } from './launcher';
|
|
30
|
+
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Lazy UI components
|
|
33
|
+
// ============================================================================
|
|
5
34
|
|
|
6
35
|
export const LazyChat = createLazyComponent<ChatRootProps>(
|
|
7
36
|
() => import('./components/ChatRoot').then((m) => ({ default: m.ChatRoot })),
|
|
@@ -11,4 +40,274 @@ export const LazyChat = createLazyComponent<ChatRootProps>(
|
|
|
11
40
|
},
|
|
12
41
|
);
|
|
13
42
|
|
|
14
|
-
export
|
|
43
|
+
export const LazyChatLauncher = createLazyComponent<ChatLauncherProps>(
|
|
44
|
+
() => import('./launcher').then((m) => ({ default: m.ChatLauncher })),
|
|
45
|
+
{
|
|
46
|
+
displayName: 'LazyChatLauncher',
|
|
47
|
+
// Launcher renders a floating FAB by default — no inline placeholder.
|
|
48
|
+
fallback: null,
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// Light surface re-exports — types + pure helpers + hooks without UI
|
|
54
|
+
// ============================================================================
|
|
55
|
+
|
|
56
|
+
// Types (erased at compile time, free to re-export)
|
|
57
|
+
export type {
|
|
58
|
+
ChatRole,
|
|
59
|
+
ChatMessage,
|
|
60
|
+
ChatPersona,
|
|
61
|
+
ChatToolCall,
|
|
62
|
+
ChatAttachment,
|
|
63
|
+
ChatSource,
|
|
64
|
+
ChatDisplayMode,
|
|
65
|
+
ChatUserContext,
|
|
66
|
+
ChatAssistantContext,
|
|
67
|
+
ChatPrefs,
|
|
68
|
+
ChatConfig,
|
|
69
|
+
ChatLabels,
|
|
70
|
+
ChatTransport,
|
|
71
|
+
ChatStreamEvent,
|
|
72
|
+
CreateSessionOptions,
|
|
73
|
+
SessionInfo,
|
|
74
|
+
HistoryPage,
|
|
75
|
+
StreamOptions,
|
|
76
|
+
SendOptions,
|
|
77
|
+
} from './types';
|
|
78
|
+
export { DEFAULT_LABELS } from './types';
|
|
79
|
+
|
|
80
|
+
// Config — plain constants, no UI imports
|
|
81
|
+
export {
|
|
82
|
+
STORAGE_KEYS,
|
|
83
|
+
CSS_VARS,
|
|
84
|
+
DEFAULT_Z_INDEX,
|
|
85
|
+
LIMITS,
|
|
86
|
+
DEFAULT_SIDEBAR,
|
|
87
|
+
HOTKEYS,
|
|
88
|
+
CHAT_EVENT_NAME,
|
|
89
|
+
type ChatEventDetail,
|
|
90
|
+
} from './config';
|
|
91
|
+
|
|
92
|
+
// Core — pure reducer / id / token buffer / persona / initials
|
|
93
|
+
export {
|
|
94
|
+
reducer,
|
|
95
|
+
initialState,
|
|
96
|
+
createId,
|
|
97
|
+
createTokenBuffer,
|
|
98
|
+
resolvePersona,
|
|
99
|
+
deriveInitials,
|
|
100
|
+
type ChatState,
|
|
101
|
+
type ChatAction,
|
|
102
|
+
type TokenBuffer,
|
|
103
|
+
} from './core';
|
|
104
|
+
|
|
105
|
+
// Transports — pure functions, no UI
|
|
106
|
+
export {
|
|
107
|
+
createHttpTransport,
|
|
108
|
+
createMockTransport,
|
|
109
|
+
parseSSE,
|
|
110
|
+
TransportError,
|
|
111
|
+
createPydanticAIChatTransport,
|
|
112
|
+
createToolIdQueue,
|
|
113
|
+
mapPydanticAIEvent,
|
|
114
|
+
createPydanticAISSEMap,
|
|
115
|
+
type HttpTransportConfig,
|
|
116
|
+
type MockTransportOptions,
|
|
117
|
+
type ParseSSEOptions,
|
|
118
|
+
type PydanticAIChatTransportOpts,
|
|
119
|
+
type PydanticAIEvent,
|
|
120
|
+
type ToolIdQueue,
|
|
121
|
+
} from './core/transport';
|
|
122
|
+
|
|
123
|
+
// Hooks — no JSX, no UI
|
|
124
|
+
export {
|
|
125
|
+
useChat,
|
|
126
|
+
useChatComposer,
|
|
127
|
+
useChatScroll,
|
|
128
|
+
useChatHistory,
|
|
129
|
+
useChatLayout,
|
|
130
|
+
useChatAudio,
|
|
131
|
+
useAutoFocusOnStreamEnd,
|
|
132
|
+
useRegisterComposer,
|
|
133
|
+
useChatReset,
|
|
134
|
+
useVisitorFingerprint,
|
|
135
|
+
useChatDockPrefs,
|
|
136
|
+
DEFAULT_DOCK_PREFS,
|
|
137
|
+
useFocusOnEmptyClick,
|
|
138
|
+
useChatUnread,
|
|
139
|
+
useChatLightbox,
|
|
140
|
+
type UseChatUnreadOptions,
|
|
141
|
+
type UseChatUnreadReturn,
|
|
142
|
+
type UseChatConfig,
|
|
143
|
+
type UseChatReturn,
|
|
144
|
+
type UseChatComposerOptions,
|
|
145
|
+
type UseChatComposerReturn,
|
|
146
|
+
type UseChatScrollOptions,
|
|
147
|
+
type UseChatScrollReturn,
|
|
148
|
+
type UseChatHistoryOptions,
|
|
149
|
+
type UseChatLayoutConfig,
|
|
150
|
+
type UseChatLayoutReturn,
|
|
151
|
+
type UseAutoFocusOnStreamEndOptions,
|
|
152
|
+
type Focusable,
|
|
153
|
+
type UseChatResetOptions,
|
|
154
|
+
type UseChatResetReturn,
|
|
155
|
+
type UseVisitorFingerprintOptions,
|
|
156
|
+
type ChatDockPrefs,
|
|
157
|
+
type UseChatDockPrefsOptions,
|
|
158
|
+
type UseChatDockPrefsReturn,
|
|
159
|
+
type UseFocusOnEmptyClickOptions,
|
|
160
|
+
type UseChatLightboxReturn,
|
|
161
|
+
type ChatLightboxState,
|
|
162
|
+
} from './hooks';
|
|
163
|
+
|
|
164
|
+
// Audio
|
|
165
|
+
export {
|
|
166
|
+
useChatAudioPrefs,
|
|
167
|
+
DEFAULT_CHAT_SOUNDS,
|
|
168
|
+
type ChatAudioEvent,
|
|
169
|
+
type ChatAudioSounds,
|
|
170
|
+
type ChatAudioConfig,
|
|
171
|
+
type UseChatAudioReturn,
|
|
172
|
+
} from './core/audio';
|
|
173
|
+
|
|
174
|
+
// Tool-call payload dispatcher — pure
|
|
175
|
+
export {
|
|
176
|
+
dispatchToolPayload,
|
|
177
|
+
isPlainObject,
|
|
178
|
+
isLatLng,
|
|
179
|
+
isGeoJSONFeatureCollection,
|
|
180
|
+
isStringValue,
|
|
181
|
+
type ToolPayloadMatcher,
|
|
182
|
+
type ToolPayloadFallback,
|
|
183
|
+
} from './core/payload-dispatch';
|
|
184
|
+
|
|
185
|
+
// Logger — pure
|
|
186
|
+
export {
|
|
187
|
+
getChatLogger,
|
|
188
|
+
type ChatLogger,
|
|
189
|
+
type ChatLogScope,
|
|
190
|
+
} from './core/logger';
|
|
191
|
+
|
|
192
|
+
// Utils — pure
|
|
193
|
+
export { sanitizeDraft, isSubmittableDraft } from './utils/sanitizeDraft';
|
|
194
|
+
export { collectImageAttachments } from './utils/collectImageAttachments';
|
|
195
|
+
|
|
196
|
+
// Style tokens — strings + hooks, no UI components
|
|
197
|
+
export {
|
|
198
|
+
BUBBLE_SURFACE,
|
|
199
|
+
ANCHOR,
|
|
200
|
+
TOGGLE,
|
|
201
|
+
DESTRUCTIVE_SURFACE,
|
|
202
|
+
TOOL_CALL,
|
|
203
|
+
useChatBubbleStyles,
|
|
204
|
+
useChatRoleStyles,
|
|
205
|
+
useChatDestructiveStyles,
|
|
206
|
+
type ChatBubbleSurface,
|
|
207
|
+
type ChatBubbleStyles,
|
|
208
|
+
type ChatRoleStyles,
|
|
209
|
+
type ChatDestructiveStyles,
|
|
210
|
+
} from './styles';
|
|
211
|
+
|
|
212
|
+
// Provider / context — needed by callers wiring custom chat shells
|
|
213
|
+
export {
|
|
214
|
+
ChatProvider,
|
|
215
|
+
useChatContext,
|
|
216
|
+
useChatContextOptional,
|
|
217
|
+
type ChatContextValue,
|
|
218
|
+
type ChatProviderProps,
|
|
219
|
+
} from './context';
|
|
220
|
+
|
|
221
|
+
// ============================================================================
|
|
222
|
+
// Composable surface — synchronously re-exported components and their prop
|
|
223
|
+
// types. These are needed by consumers that build custom chat shells
|
|
224
|
+
// (e.g. `@djangocfg/crm`'s AdminChat / PublicChat) rather than rendering
|
|
225
|
+
// `LazyChat` directly.
|
|
226
|
+
//
|
|
227
|
+
// They DO transitively pull in MarkdownMessage / Sources / StreamingIndicator
|
|
228
|
+
// when actually rendered. Importing the types alone is free. Importing the
|
|
229
|
+
// component costs the dependency graph — that's the price of a custom shell.
|
|
230
|
+
//
|
|
231
|
+
// Apps that want maximum laziness should use `LazyChat` / `LazyChatLauncher`
|
|
232
|
+
// above and skip these.
|
|
233
|
+
// ============================================================================
|
|
234
|
+
|
|
235
|
+
export {
|
|
236
|
+
ChatLauncher,
|
|
237
|
+
ChatFAB,
|
|
238
|
+
ChatDock,
|
|
239
|
+
ChatHeader,
|
|
240
|
+
ChatHeaderActionButton,
|
|
241
|
+
ChatHeaderAudioToggle,
|
|
242
|
+
ChatHeaderLanguageButton,
|
|
243
|
+
ChatHeaderModeToggle,
|
|
244
|
+
ChatHeaderResetButton,
|
|
245
|
+
ChatGreeting,
|
|
246
|
+
ChatUnreadPreview,
|
|
247
|
+
} from './launcher';
|
|
248
|
+
|
|
249
|
+
export {
|
|
250
|
+
ChatRoot,
|
|
251
|
+
MessageList,
|
|
252
|
+
MessageBubble,
|
|
253
|
+
MessageActions,
|
|
254
|
+
Composer,
|
|
255
|
+
Sources,
|
|
256
|
+
ToolCalls,
|
|
257
|
+
Attachments,
|
|
258
|
+
AttachmentsGrid,
|
|
259
|
+
AttachmentsList,
|
|
260
|
+
EmptyState,
|
|
261
|
+
ErrorBanner,
|
|
262
|
+
JumpToLatest,
|
|
263
|
+
StreamingIndicator,
|
|
264
|
+
AudioToggle,
|
|
265
|
+
} from './components';
|
|
266
|
+
|
|
267
|
+
// Heavy-component prop types
|
|
268
|
+
export type {
|
|
269
|
+
ChatLauncherProps,
|
|
270
|
+
ChatLauncherHotkey,
|
|
271
|
+
ChatLauncherGreeting,
|
|
272
|
+
ChatFABProps,
|
|
273
|
+
ChatFABPosition,
|
|
274
|
+
ChatFABVariant,
|
|
275
|
+
ChatFABSize,
|
|
276
|
+
ChatDockProps,
|
|
277
|
+
ChatDockMode,
|
|
278
|
+
ChatDockSide,
|
|
279
|
+
ChatHeaderProps,
|
|
280
|
+
ChatHeaderActionButtonProps,
|
|
281
|
+
ChatHeaderModeToggleProps,
|
|
282
|
+
ChatHeaderAudioToggleProps,
|
|
283
|
+
ChatHeaderResetButtonProps,
|
|
284
|
+
ChatHeaderLanguageButtonProps,
|
|
285
|
+
ChatGreetingProps,
|
|
286
|
+
ChatUnreadPreviewProps,
|
|
287
|
+
ChatPresencePhase,
|
|
288
|
+
} from './launcher';
|
|
289
|
+
|
|
290
|
+
export { useChatPresence } from './launcher';
|
|
291
|
+
|
|
292
|
+
export type {
|
|
293
|
+
ChatRootProps,
|
|
294
|
+
MessageListProps,
|
|
295
|
+
MessageListHandle,
|
|
296
|
+
MessageBubbleProps,
|
|
297
|
+
MessageActionsProps,
|
|
298
|
+
ComposerProps,
|
|
299
|
+
SourcesProps,
|
|
300
|
+
ToolCallsProps,
|
|
301
|
+
ToolPayloadKind,
|
|
302
|
+
AttachmentsProps,
|
|
303
|
+
AttachmentsGridProps,
|
|
304
|
+
AttachmentsListProps,
|
|
305
|
+
AttachmentRenderer,
|
|
306
|
+
AttachmentRendererArgs,
|
|
307
|
+
AttachmentRendererMap,
|
|
308
|
+
EmptyStateProps,
|
|
309
|
+
ErrorBannerProps,
|
|
310
|
+
JumpToLatestProps,
|
|
311
|
+
StreamingIndicatorProps,
|
|
312
|
+
AudioToggleProps,
|
|
313
|
+
} from './components';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `@djangocfg/ui-tools/code-editor` subpath entrypoint.
|
|
5
|
+
*
|
|
6
|
+
* Monaco itself weighs ~550 KB minified — we must never pay that cost
|
|
7
|
+
* unless the editor actually mounts. The `Lazy*` wrappers here dynamically
|
|
8
|
+
* import the `Editor` and `DiffEditor` components, which transitively pull
|
|
9
|
+
* in `monaco-editor` and the worker setup.
|
|
10
|
+
*
|
|
11
|
+
* The rest of the surface (types, EditorProvider, useMonaco hook, helpers)
|
|
12
|
+
* is light:
|
|
13
|
+
* - `monaco-editor` is referenced only as a TS type (`type *`) — erased
|
|
14
|
+
* at compile time.
|
|
15
|
+
* - `useMonaco` performs a dynamic `import('monaco-editor')` itself, so
|
|
16
|
+
* importing the hook is free until the caller actually invokes it.
|
|
17
|
+
*
|
|
18
|
+
* That means consumers can wire up keyboard shortcuts, theme toggles, or
|
|
19
|
+
* file-state hooks at the top of their tree without paying Monaco's cost,
|
|
20
|
+
* and only render `<LazyEditor>` lower in the tree where it's needed.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { createLazyComponent, LoadingFallback } from '../../components';
|
|
24
|
+
import type { EditorProps, DiffEditorProps } from './types';
|
|
25
|
+
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Lazy components
|
|
28
|
+
// ============================================================================
|
|
29
|
+
|
|
30
|
+
export const LazyEditor = createLazyComponent<EditorProps>(
|
|
31
|
+
() => import('./components/Editor').then((m) => ({ default: m.Editor })),
|
|
32
|
+
{
|
|
33
|
+
displayName: 'LazyEditor',
|
|
34
|
+
fallback: <LoadingFallback minHeight={320} text="Loading editor…" />,
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
export const LazyDiffEditor = createLazyComponent<DiffEditorProps>(
|
|
39
|
+
() => import('./components/DiffEditor').then((m) => ({ default: m.DiffEditor })),
|
|
40
|
+
{
|
|
41
|
+
displayName: 'LazyDiffEditor',
|
|
42
|
+
fallback: <LoadingFallback minHeight={320} text="Loading diff editor…" />,
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Light surface
|
|
48
|
+
// ============================================================================
|
|
49
|
+
|
|
50
|
+
// Hooks — `useMonaco` does its own dynamic import; the others are pure.
|
|
51
|
+
export {
|
|
52
|
+
useMonaco,
|
|
53
|
+
useEditor,
|
|
54
|
+
useLanguage,
|
|
55
|
+
useEditorTheme,
|
|
56
|
+
} from './hooks';
|
|
57
|
+
|
|
58
|
+
// Provider + context hook
|
|
59
|
+
export { EditorProvider, useEditorContext } from './context';
|
|
60
|
+
|
|
61
|
+
// All types
|
|
62
|
+
export type {
|
|
63
|
+
EditorFile,
|
|
64
|
+
EditorOptions,
|
|
65
|
+
EditorProps,
|
|
66
|
+
EditorContextValue,
|
|
67
|
+
UseEditorReturn,
|
|
68
|
+
UseMonacoReturn,
|
|
69
|
+
DiffEditorProps,
|
|
70
|
+
} from './types';
|
package/src/tools/Map/lazy.tsx
CHANGED
|
@@ -42,11 +42,48 @@ export const LazyMapView = createLazyComponent(
|
|
|
42
42
|
);
|
|
43
43
|
|
|
44
44
|
// ============================================================================
|
|
45
|
-
//
|
|
45
|
+
// Light primitives — direct re-exports
|
|
46
|
+
//
|
|
47
|
+
// MapMarker / MapPopup / MapCluster / MapSource / MapLayer / MapControls
|
|
48
|
+
// etc. are thin wrappers around `react-map-gl/maplibre`. They don't import
|
|
49
|
+
// `maplibre-gl` at module scope (only types, which are erased), so exporting
|
|
50
|
+
// them synchronously here costs ~tens of KB at most — not the ~800KB of
|
|
51
|
+
// MapLibre GL itself.
|
|
52
|
+
//
|
|
53
|
+
// The heavy library only loads when `LazyMapContainer` actually mounts,
|
|
54
|
+
// because `MapContainer.tsx` (the only module that imports `maplibre-gl`
|
|
55
|
+
// at runtime) is reached exclusively via the dynamic import above.
|
|
56
|
+
//
|
|
57
|
+
// This means consumers can write:
|
|
58
|
+
//
|
|
59
|
+
// import { LazyMapContainer, MapMarker, MapPopup } from '@djangocfg/ui-tools/map'
|
|
60
|
+
//
|
|
61
|
+
// …and still get correct code-splitting.
|
|
46
62
|
// ============================================================================
|
|
47
63
|
|
|
64
|
+
export {
|
|
65
|
+
MapMarker,
|
|
66
|
+
MapPopup,
|
|
67
|
+
MapCluster,
|
|
68
|
+
MapSource,
|
|
69
|
+
MapLayer,
|
|
70
|
+
MapControls,
|
|
71
|
+
CustomOverlay,
|
|
72
|
+
MapLegend,
|
|
73
|
+
LayerSwitcher,
|
|
74
|
+
} from './components';
|
|
75
|
+
|
|
76
|
+
export { MapProvider, useMapContext, MapContext } from './context';
|
|
77
|
+
export type { MapProviderProps } from './context';
|
|
78
|
+
|
|
48
79
|
export type {
|
|
49
80
|
MapContainerProps,
|
|
81
|
+
MapMarkerProps,
|
|
82
|
+
MapPopupProps,
|
|
83
|
+
MapClusterProps,
|
|
84
|
+
MapSourceProps,
|
|
85
|
+
MapLayerProps,
|
|
86
|
+
MapControlsProps,
|
|
50
87
|
} from './components';
|
|
51
88
|
|
|
52
89
|
export type {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `@djangocfg/ui-tools/markdown-editor` subpath entrypoint.
|
|
5
|
+
*
|
|
6
|
+
* `MarkdownEditor` is a TipTap WYSIWYG with the full ProseMirror + TipTap
|
|
7
|
+
* extension stack — `@tiptap/react`, `starter-kit`, `markdown`, `mention`,
|
|
8
|
+
* `placeholder`, plus our `createMentionSuggestion` (floating-ui anchored
|
|
9
|
+
* dropdown). Together that's ~200 KB minified — wrap it in React.lazy so
|
|
10
|
+
* pages that don't render an editor don't pay.
|
|
11
|
+
*
|
|
12
|
+
* Light surface kept here:
|
|
13
|
+
* - All public types (erased at compile time).
|
|
14
|
+
* - `mentionPresets` — pure data describing how to render mentions to
|
|
15
|
+
* markdown. No TipTap imports at module scope.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { createLazyComponent, LoadingFallback } from '../../components';
|
|
19
|
+
import type { MarkdownEditorProps } from './MarkdownEditor';
|
|
20
|
+
|
|
21
|
+
export const LazyMarkdownEditor = createLazyComponent<MarkdownEditorProps>(
|
|
22
|
+
() => import('./MarkdownEditor').then((m) => ({ default: m.MarkdownEditor })),
|
|
23
|
+
{
|
|
24
|
+
displayName: 'LazyMarkdownEditor',
|
|
25
|
+
fallback: <LoadingFallback minHeight={140} text="Loading editor…" />,
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// Light surface — pure helpers + types.
|
|
30
|
+
export { mentionPresets } from './mentionPresets';
|
|
31
|
+
|
|
32
|
+
export type {
|
|
33
|
+
MarkdownEditorProps,
|
|
34
|
+
MarkdownEditorHandle,
|
|
35
|
+
} from './MarkdownEditor';
|
|
36
|
+
|
|
37
|
+
export type {
|
|
38
|
+
MentionItem,
|
|
39
|
+
MentionConfig,
|
|
40
|
+
MentionAttrs,
|
|
41
|
+
MentionMarkdownRenderer,
|
|
42
|
+
} from './types';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { memo } from 'react';
|
|
2
2
|
import { CopyButton } from '@djangocfg/ui-core/components';
|
|
3
3
|
import { useResolvedTheme } from '@djangocfg/ui-core/hooks';
|
|
4
|
-
import PrettyCode from '
|
|
4
|
+
import PrettyCode from '../PrettyCode';
|
|
5
5
|
|
|
6
6
|
interface CodeBlockProps {
|
|
7
7
|
code: string;
|
|
@@ -11,7 +11,7 @@ import remarkGfm from 'remark-gfm';
|
|
|
11
11
|
import remarkSmartypants from 'remark-smartypants';
|
|
12
12
|
import type { Components } from 'react-markdown';
|
|
13
13
|
|
|
14
|
-
import { useCollapsibleContent } from '
|
|
14
|
+
import { useCollapsibleContent } from '../../hooks/useCollapsibleContent';
|
|
15
15
|
import type { MarkdownMessageProps } from './types';
|
|
16
16
|
import { buildSchema, buildUrlTransform } from './sanitize';
|
|
17
17
|
import { looksLikePlainProse } from './plainText';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Components } from 'react-markdown';
|
|
3
|
-
import Mermaid from '
|
|
4
|
-
import { ANCHOR } from '
|
|
3
|
+
import Mermaid from '../Mermaid';
|
|
4
|
+
import { ANCHOR } from '../Chat/styles/bubbleTokens';
|
|
5
5
|
import { CodeBlock, CodeBlockFallback } from './CodeBlock';
|
|
6
6
|
import { extractTextFromChildren } from './plainText';
|
|
7
7
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
|
|
5
|
-
import { MarkdownMessage } from '
|
|
5
|
+
import { MarkdownMessage } from '../../../MarkdownMessage';
|
|
6
6
|
import type { ApiEndpoint, OpenApiInfo, OpenApiSchema } from '../../types';
|
|
7
7
|
import { SchemaCopyMenu } from './SchemaCopyMenu';
|
|
8
8
|
|
|
@@ -5,7 +5,7 @@ import React, { useCallback, useMemo, useState } from 'react';
|
|
|
5
5
|
|
|
6
6
|
import { Button } from '@djangocfg/ui-core/components';
|
|
7
7
|
|
|
8
|
-
import { MarkdownMessage } from '
|
|
8
|
+
import { MarkdownMessage } from '../../../../../MarkdownMessage';
|
|
9
9
|
import type { ApiEndpoint } from '../../../../types';
|
|
10
10
|
import { endpointToMarkdown } from '../../../../utils/schemaExport';
|
|
11
11
|
import type { SectionId } from '../types';
|
|
@@ -278,6 +278,54 @@ const unsubscribe = useSpeechPrefs.subscribe((state) => {
|
|
|
278
278
|
|
|
279
279
|
---
|
|
280
280
|
|
|
281
|
+
## Debug logger
|
|
282
|
+
|
|
283
|
+
Scoped, namespaced [consola](https://github.com/unjs/consola) wrapper that silences itself in production by default. Mirrors `getChatLogger()` in the Chat tool so both surfaces feel the same in DevTools.
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
import { getSpeechLogger } from '@djangocfg/ui-tools';
|
|
287
|
+
|
|
288
|
+
const log = getSpeechLogger();
|
|
289
|
+
log.dictation.info('final merged', { len: 42 });
|
|
290
|
+
log.engine.debug('state', 'listening');
|
|
291
|
+
log.error.error('engine threw', err);
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Sub-loggers: `engine`, `dictation`, `slot`, `composer`, `mic`, `push`, `error`. `error` always emits; everything else is gated.
|
|
295
|
+
|
|
296
|
+
**Opt-in (any one is enough):**
|
|
297
|
+
|
|
298
|
+
1. **Dev mode** — `NODE_ENV === 'development'` auto-enables everything.
|
|
299
|
+
2. **Runtime toggle** — paste this in DevTools to enable without a rebuild:
|
|
300
|
+
```js
|
|
301
|
+
localStorage.setItem('djangocfg:speech-debug', '1');
|
|
302
|
+
location.reload();
|
|
303
|
+
```
|
|
304
|
+
`'0'` (or `removeItem`) turns it back off.
|
|
305
|
+
3. **Explicit** — `getSpeechLogger(true)` from a host component (analogous to `<ChatRoot debug />`).
|
|
306
|
+
|
|
307
|
+
**What you'll see when on**, in order of a typical dictation session:
|
|
308
|
+
|
|
309
|
+
```
|
|
310
|
+
[speech][slot] mount { supported: true, hasComposerHandle: true, … }
|
|
311
|
+
[speech][engine] subscribe { engineId: 'webspeech' }
|
|
312
|
+
[speech][engine] state 'listening'
|
|
313
|
+
[speech][engine] partial { len: 6, segmentId: 's1' }
|
|
314
|
+
[speech][composer] setValue → composer handle { len: 12 }
|
|
315
|
+
[speech][engine] final { len: 42, confidence: 0.91 }
|
|
316
|
+
[speech][dictation] final merged { len: 42, totalLen: 54 }
|
|
317
|
+
[speech][engine] autoStop silence detected
|
|
318
|
+
[speech][engine] state 'closed'
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
If text never appears in your composer, look for:
|
|
322
|
+
|
|
323
|
+
- `[speech][slot] mount { hasComposerHandle: false, … }` → `<VoiceComposerSlot>` is outside a `<ChatProvider>` and no `value`/`onChange` props were given — text is going nowhere.
|
|
324
|
+
- `[speech][composer] warn setValue called but no composer handle is registered …` → the composer never called `useRegisterComposer(...)`. Built-in `<Composer>` and `MarkdownEditor` do this automatically; custom composers must opt in.
|
|
325
|
+
- `[speech][engine] final` arrives but no `[speech][dictation] final merged` follows → check `normaliseFinal` filtered the text (empty / whitespace only).
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
281
329
|
## Public surface
|
|
282
330
|
|
|
283
331
|
### Hooks
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkHPK3EWBF_cjs = require('./chunk-HPK3EWBF.cjs');
|
|
4
|
-
require('./chunk-FIRK5CEH.cjs');
|
|
5
|
-
require('./chunk-OLISEQHS.cjs');
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Object.defineProperty(exports, "ChatRoot", {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
get: function () { return chunkHPK3EWBF_cjs.ChatRoot; }
|
|
12
|
-
});
|
|
13
|
-
//# sourceMappingURL=ChatRoot-LXIUBOXF.cjs.map
|
|
14
|
-
//# sourceMappingURL=ChatRoot-LXIUBOXF.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tools/Map/context/MapContext.tsx","../src/tools/Map/styles/index.ts","../src/tools/Map/components/MapContainer.tsx"],"names":["createContext","useRef","useState","useCallback","useMemo","jsx","__name","useContext","useEffect","jsxs","Fragment","Map","cn","RotateCcw","ExternalLink"],"mappings":";;;;;;;;;;;;;;AAcA,IAAM,UAAA,GAAaA,oBAAsC,IAAI,CAAA;AAO7D,IAAM,gBAAA,GAAgC;AAAA,EACpC,SAAA,EAAW,QAAA;AAAA,EACX,QAAA,EAAU,OAAA;AAAA,EACV,IAAA,EAAM,EAAA;AAAA,EACN,OAAA,EAAS,CAAA;AAAA,EACT,KAAA,EAAO;AACT,CAAA;AAEO,SAAS,WAAA,CAAY,EAAE,QAAA,EAAU,eAAA,EAAgB,EAAqB;AAC3E,EAAA,MAAM,MAAA,GAASC,aAAsB,IAAI,CAAA;AACzC,EAAA,MAAM,qBAAqBA,YAAA,CAAoB;AAAA,IAC7C,GAAG,gBAAA;AAAA,IACH,GAAG;AAAA,GACJ,CAAA;AACD,EAAA,MAAM,CAAC,QAAA,EAAU,gBAAgB,CAAA,GAAIC,cAAA,CAAsB,mBAAmB,OAAO,CAAA;AACrF,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,cAAA,CAAuB,EAAE,CAAA;AACvD,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIA,eAA4B,IAAI,CAAA;AAC5E,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIA,eAAiC,IAAI,CAAA;AACjF,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIA,eAAS,KAAK,CAAA;AAE9C,EAAA,MAAM,WAAA,GAAcC,iBAAA,CAAY,CAAC,WAAA,KAAsC;AACrE,IAAA,gBAAA,CAAiB,CAAC,IAAA,MAAU,EAAE,GAAG,IAAA,EAAM,GAAG,aAAY,CAAE,CAAA;AAAA,EAC1D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,cAAA,GAAiBA,kBAAY,MAAM;AACvC,IAAA,MAAM,MAAM,MAAA,CAAO,OAAA;AACnB,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,GAAA,CAAI,KAAA,CAAM;AAAA,QACR,QAAQ,CAAC,kBAAA,CAAmB,QAAQ,SAAA,EAAW,kBAAA,CAAmB,QAAQ,QAAQ,CAAA;AAAA,QAClF,IAAA,EAAM,mBAAmB,OAAA,CAAQ,IAAA;AAAA,QACjC,OAAA,EAAS,kBAAA,CAAmB,OAAA,CAAQ,OAAA,IAAW,CAAA;AAAA,QAC/C,KAAA,EAAO,kBAAA,CAAmB,OAAA,CAAQ,KAAA,IAAS,CAAA;AAAA,QAC3C,QAAA,EAAU;AAAA,OACX,CAAA;AAAA,IACH;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,KAAA,GAAQC,aAAA;AAAA,IACZ,OAAO;AAAA,MACL,MAAA;AAAA,MACA,QAAA;AAAA,MACA,WAAA;AAAA,MACA,iBAAiB,kBAAA,CAAmB,OAAA;AAAA,MACpC,cAAA;AAAA,MACA,OAAA;AAAA,MACA,UAAA;AAAA,MACA,cAAA;AAAA,MACA,iBAAA;AAAA,MACA,cAAA;AAAA,MACA,iBAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,IACA,CAAC,QAAA,EAAU,WAAA,EAAa,gBAAgB,OAAA,EAAS,cAAA,EAAgB,gBAAgB,QAAQ;AAAA,GAC3F;AAEA,EAAA,uBAAOC,cAAA,CAAC,UAAA,CAAW,QAAA,EAAX,EAAoB,OAAe,QAAA,EAAS,CAAA;AACtD;AAjDgBC,wBAAA,CAAA,WAAA,EAAA,aAAA,CAAA;AAmDT,SAAS,aAAA,GAAiC;AAC/C,EAAA,MAAM,OAAA,GAAUC,iBAAW,UAAU,CAAA;AACrC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,iDAAiD,CAAA;AAAA,EACnE;AACA,EAAA,OAAO,OAAA;AACT;AANgBD,wBAAA,CAAA,aAAA,EAAA,eAAA,CAAA;;;AChFT,IAAM,UAAA,GAAa;AAAA,EACxB,KAAA,EAAO,+DAAA;AAAA,EACP,IAAA,EAAM,kEAAA;AAAA,EACN,OAAA,EAAS,8DAAA;AAAA,EACT,SAAA,EAAW;AACb,CAAA;AC6BA,SAAS,QAAA,CAAS;AAAA,EAChB,QAAA;AAAA,EACA,QAAA,GAAW,OAAA;AAAA,EACX,mBAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,kBAAA,GAAqB,IAAA;AAAA,EACrB,SAAA,GAAY,IAAA;AAAA,EACZ,aAAA;AAAA,EACA,eAAA,GAAkB,cAAA;AAAA,EAClB,cAAA,GAAiB,CAAA;AAAA,EACjB,eAAA,GAAkB;AACpB,CAAA,EAAkB;AAChB,EAAA,MAAM,EAAE,QAAQ,QAAA,EAAU,WAAA,EAAa,aAAa,cAAA,EAAgB,eAAA,KAAoB,aAAA,EAAc;AACtG,EAAA,MAAM,aAAA,GAAgBL,aAA8B,IAAI,CAAA;AACxD,EAAA,MAAM,gBAAA,GAAmBA,aAAO,KAAK,CAAA;AAGrC,EAAA,MAAM,kBAAA,GACJ,KAAK,GAAA,CAAI,QAAA,CAAS,YAAY,eAAA,CAAgB,SAAS,CAAA,GAAI,IAAA,IAC3D,IAAA,CAAK,GAAA,CAAI,SAAS,QAAA,GAAW,eAAA,CAAgB,QAAQ,CAAA,GAAI,IAAA,IACzD,IAAA,CAAK,IAAI,QAAA,CAAS,IAAA,GAAO,eAAA,CAAgB,IAAI,CAAA,GAAI,GAAA;AAEnD,EAAA,MAAM,UAAA,GAAaE,iBAAAA;AAAA,IACjB,CAAC,GAAA,KAA8B;AAC7B,MAAA,WAAA,CAAY;AAAA,QACV,SAAA,EAAW,IAAI,SAAA,CAAU,SAAA;AAAA,QACzB,QAAA,EAAU,IAAI,SAAA,CAAU,QAAA;AAAA,QACxB,IAAA,EAAM,IAAI,SAAA,CAAU,IAAA;AAAA,QACpB,OAAA,EAAS,IAAI,SAAA,CAAU,OAAA;AAAA,QACvB,KAAA,EAAO,IAAI,SAAA,CAAU;AAAA,OACtB,CAAA;AAAA,IACH,CAAA;AAAA,IACA,CAAC,WAAW;AAAA,GACd;AAEA,EAAA,MAAM,eAAA,GAAkBA,kBAAY,MAAM;AACxC,IAAA,gBAAA,CAAiB,OAAA,GAAU,IAAA;AAE3B,IAAA,IAAI,cAAc,OAAA,EAAS;AACzB,MAAA,YAAA,CAAa,cAAc,OAAO,CAAA;AAClC,MAAA,aAAA,CAAc,OAAA,GAAU,IAAA;AAAA,IAC1B;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,aAAA,GAAgBA,kBAAY,MAAM;AACtC,IAAA,gBAAA,CAAiB,OAAA,GAAU,KAAA;AAE3B,IAAA,IAAI,iBAAiB,CAAA,EAAG;AACtB,MAAA,aAAA,CAAc,OAAA,GAAU,WAAW,MAAM;AACvC,QAAA,IAAI,CAAC,iBAAiB,OAAA,EAAS;AAC7B,UAAA,cAAA,EAAe;AAAA,QACjB;AAAA,MACF,GAAG,cAAc,CAAA;AAAA,IACnB;AAAA,EACF,CAAA,EAAG,CAAC,cAAA,EAAgB,cAAc,CAAC,CAAA;AAEnC,EAAA,MAAM,UAAA,GAAaA,kBAAY,MAAM;AACnC,IAAA,WAAA,CAAY,IAAI,CAAA;AAAA,EAClB,CAAA,EAAG,CAAC,WAAW,CAAC,CAAA;AAGhB,EAAAK,eAAA,CAAU,MAAM;AACd,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,cAAc,OAAA,EAAS;AACzB,QAAA,YAAA,CAAa,cAAc,OAAO,CAAA;AAAA,MACpC;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,aAAA,GAAgB,QAAA,IAAY,UAAA,GAC9B,UAAA,CAAW,QAAuB,CAAA,GAClC,QAAA;AAEJ,EAAA,uBACEC,eAAA,CAAAC,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAAL,cAAAA;AAAA,MAACM,oBAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,MAAA;AAAA,QACJ,GAAG,QAAA;AAAA,QACJ,MAAA,EAAQ,UAAA;AAAA,QACR,WAAA,EAAa,eAAA;AAAA,QACb,SAAA,EAAW,aAAA;AAAA,QACX,MAAA,EAAQ,UAAA;AAAA,QACR,QAAA,EAAU,aAAA;AAAA,QACV,mBAAA;AAAA,QACA,kBAAA,EAAoB,kBAAA,GAAqB,EAAC,GAAI,KAAA;AAAA,QAC9C,SAAA;AAAA,QACA,KAAA,EAAO;AAAA,UACL,KAAA,EAAO,MAAA;AAAA,UACP,MAAA,EAAQ,MAAA;AAAA,UACR,GAAG;AAAA,SACL;AAAA,QACA,MAAA;AAAA,QAEC;AAAA;AAAA,KACH;AAAA,oBAGAF,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mDAAA,EAEZ,QAAA,EAAA;AAAA,MAAA,eAAA,IAAmB,kBAAA,oBAClBA,eAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,OAAA,EAAS,cAAA;AAAA,UACT,SAAA,EAAWG,MAAA;AAAA,YACT,qDAAA;AAAA,YACA,uEAAA;AAAA,YACA;AAAA,WACF;AAAA,UAEA,QAAA,EAAA;AAAA,4BAAAP,cAAAA,CAACQ,qBAAA,EAAA,EAAU,SAAA,EAAU,SAAA,EAAU,CAAA;AAAA,YAAE;AAAA;AAAA;AAAA,OAEnC;AAAA,MAID,aAAA,oBACCJ,eAAA;AAAA,QAAC,GAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAM,aAAA;AAAA,UACN,MAAA,EAAO,QAAA;AAAA,UACP,GAAA,EAAI,qBAAA;AAAA,UACJ,SAAA,EAAWG,MAAA;AAAA,YACT,qDAAA;AAAA,YACA,uEAAA;AAAA,YACA;AAAA,WACF;AAAA,UAEA,QAAA,EAAA;AAAA,4BAAAP,cAAAA,CAACS,wBAAA,EAAA,EAAa,SAAA,EAAU,SAAA,EAAU,CAAA;AAAA,YACjC;AAAA;AAAA;AAAA;AACH,KAAA,EAEJ;AAAA,GAAA,EACF,CAAA;AAEJ;AAtISR,wBAAA,CAAA,QAAA,EAAA,UAAA,CAAA;AAwIF,SAAS,YAAA,CAAa;AAAA,EAC3B,QAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAsB;AACpB,EAAA,uBACED,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,KAAA,EAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,UAAA,IAC3E,QAAA,kBAAAA,cAAAA,CAAC,WAAA,EAAA,EAAY,eAAA,EACX,QAAA,kBAAAA,cAAAA,CAAC,YAAU,GAAG,KAAA,EAAQ,QAAA,EAAS,CAAA,EACjC,CAAA,EACF,CAAA;AAEJ;AAbgBC,wBAAA,CAAA,YAAA,EAAA,cAAA,CAAA;AAkBT,SAAS,QAAQ,KAAA,EAAmD;AACzE,EAAA,uBAAOD,cAAAA,CAAC,QAAA,EAAA,EAAU,GAAG,KAAA,EAAO,CAAA;AAC9B;AAFgBC,wBAAA,CAAA,OAAA,EAAA,SAAA,CAAA","file":"MapContainer-76YL2JXL.cjs","sourcesContent":["'use client'\n\nimport {\n createContext,\n useContext,\n useState,\n useRef,\n useMemo,\n useCallback,\n type ReactNode,\n} from 'react'\nimport type { MapRef } from 'react-map-gl/maplibre'\nimport type { MapContextValue, MapViewport, MarkerData } from '../types'\n\nconst MapContext = createContext<MapContextValue | null>(null)\n\nexport interface MapProviderProps {\n children: ReactNode\n initialViewport?: Partial<MapViewport>\n}\n\nconst DEFAULT_VIEWPORT: MapViewport = {\n longitude: 115.1889,\n latitude: -8.4095,\n zoom: 10,\n bearing: 0,\n pitch: 0,\n}\n\nexport function MapProvider({ children, initialViewport }: MapProviderProps) {\n const mapRef = useRef<MapRef | null>(null)\n const initialViewportRef = useRef<MapViewport>({\n ...DEFAULT_VIEWPORT,\n ...initialViewport,\n })\n const [viewport, setViewportState] = useState<MapViewport>(initialViewportRef.current)\n const [markers, setMarkers] = useState<MarkerData[]>([])\n const [selectedMarker, setSelectedMarker] = useState<MarkerData | null>(null)\n const [hoveredFeature, setHoveredFeature] = useState<GeoJSON.Feature | null>(null)\n const [isLoaded, setIsLoaded] = useState(false)\n\n const setViewport = useCallback((newViewport: Partial<MapViewport>) => {\n setViewportState((prev) => ({ ...prev, ...newViewport }))\n }, [])\n\n const resetToInitial = useCallback(() => {\n const map = mapRef.current\n if (map) {\n map.flyTo({\n center: [initialViewportRef.current.longitude, initialViewportRef.current.latitude],\n zoom: initialViewportRef.current.zoom,\n bearing: initialViewportRef.current.bearing ?? 0,\n pitch: initialViewportRef.current.pitch ?? 0,\n duration: 1000,\n })\n }\n }, [])\n\n const value = useMemo<MapContextValue>(\n () => ({\n mapRef,\n viewport,\n setViewport,\n initialViewport: initialViewportRef.current,\n resetToInitial,\n markers,\n setMarkers,\n selectedMarker,\n setSelectedMarker,\n hoveredFeature,\n setHoveredFeature,\n isLoaded,\n setIsLoaded,\n }),\n [viewport, setViewport, resetToInitial, markers, selectedMarker, hoveredFeature, isLoaded]\n )\n\n return <MapContext.Provider value={value}>{children}</MapContext.Provider>\n}\n\nexport function useMapContext(): MapContextValue {\n const context = useContext(MapContext)\n if (!context) {\n throw new Error('useMapContext must be used within a MapProvider')\n }\n return context\n}\n\nexport { MapContext }\n","export const MAP_STYLES = {\n light: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',\n dark: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',\n streets: 'https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json',\n satellite: 'https://api.maptiler.com/maps/satellite/style.json',\n} as const\n\nexport type MapStyleKey = keyof typeof MAP_STYLES\n\nexport function getMapStyle(key: MapStyleKey | string): string {\n if (key in MAP_STYLES) {\n return MAP_STYLES[key as MapStyleKey]\n }\n return key\n}\n","'use client'\n\nimport { useCallback, useEffect, useRef, type ReactNode } from 'react'\nimport Map, { type ViewStateChangeEvent } from 'react-map-gl/maplibre'\nimport { ExternalLink, RotateCcw } from 'lucide-react'\nimport { cn } from '@djangocfg/ui-core/lib'\nimport 'maplibre-gl/dist/maplibre-gl.css'\n\nimport { MapProvider, useMapContext } from '../context'\nimport { MAP_STYLES } from '../styles'\nimport type { MapViewport, MapStyleKey } from '../types'\n\nexport interface MapContainerProps {\n children?: ReactNode\n initialViewport?: Partial<MapViewport>\n mapStyle?: MapStyleKey | string\n interactiveLayerIds?: string[]\n className?: string\n style?: React.CSSProperties\n cursor?: string\n attributionControl?: boolean\n reuseMaps?: boolean\n /** URL to open in external maps app (shows \"Open in Maps\" button if provided) */\n openInMapsUrl?: string\n /** Label for the open in maps button */\n openInMapsLabel?: string\n /** Auto-reset to initial viewport after N ms of inactivity (0 = disabled) */\n autoResetDelay?: number\n /** Show reset button */\n showResetButton?: boolean\n}\n\ninterface MapInnerProps extends Omit<MapContainerProps, 'initialViewport'> {}\n\nfunction MapInner({\n children,\n mapStyle = 'light',\n interactiveLayerIds,\n style,\n cursor,\n attributionControl = true,\n reuseMaps = true,\n openInMapsUrl,\n openInMapsLabel = 'Open in Maps',\n autoResetDelay = 0,\n showResetButton = false,\n}: MapInnerProps) {\n const { mapRef, viewport, setViewport, setIsLoaded, resetToInitial, initialViewport } = useMapContext()\n const resetTimerRef = useRef<NodeJS.Timeout | null>(null)\n const isInteractingRef = useRef(false)\n\n // Check if viewport has changed from initial\n const hasViewportChanged =\n Math.abs(viewport.longitude - initialViewport.longitude) > 0.0001 ||\n Math.abs(viewport.latitude - initialViewport.latitude) > 0.0001 ||\n Math.abs(viewport.zoom - initialViewport.zoom) > 0.1\n\n const handleMove = useCallback(\n (evt: ViewStateChangeEvent) => {\n setViewport({\n longitude: evt.viewState.longitude,\n latitude: evt.viewState.latitude,\n zoom: evt.viewState.zoom,\n bearing: evt.viewState.bearing,\n pitch: evt.viewState.pitch,\n })\n },\n [setViewport]\n )\n\n const handleMoveStart = useCallback(() => {\n isInteractingRef.current = true\n // Clear any pending reset timer\n if (resetTimerRef.current) {\n clearTimeout(resetTimerRef.current)\n resetTimerRef.current = null\n }\n }, [])\n\n const handleMoveEnd = useCallback(() => {\n isInteractingRef.current = false\n // Start auto-reset timer if enabled\n if (autoResetDelay > 0) {\n resetTimerRef.current = setTimeout(() => {\n if (!isInteractingRef.current) {\n resetToInitial()\n }\n }, autoResetDelay)\n }\n }, [autoResetDelay, resetToInitial])\n\n const handleLoad = useCallback(() => {\n setIsLoaded(true)\n }, [setIsLoaded])\n\n // Cleanup timer on unmount\n useEffect(() => {\n return () => {\n if (resetTimerRef.current) {\n clearTimeout(resetTimerRef.current)\n }\n }\n }, [])\n\n const resolvedStyle = mapStyle in MAP_STYLES\n ? MAP_STYLES[mapStyle as MapStyleKey]\n : mapStyle\n\n return (\n <>\n <Map\n ref={mapRef}\n {...viewport}\n onMove={handleMove}\n onMoveStart={handleMoveStart}\n onMoveEnd={handleMoveEnd}\n onLoad={handleLoad}\n mapStyle={resolvedStyle}\n interactiveLayerIds={interactiveLayerIds}\n attributionControl={attributionControl ? {} : false}\n reuseMaps={reuseMaps}\n style={{\n width: '100%',\n height: '100%',\n ...style,\n }}\n cursor={cursor}\n >\n {children}\n </Map>\n\n {/* Map overlay buttons */}\n <div className=\"absolute bottom-3 right-3 flex items-center gap-2\">\n {/* Reset button */}\n {showResetButton && hasViewportChanged && (\n <button\n type=\"button\"\n onClick={resetToInitial}\n className={cn(\n 'inline-flex items-center gap-2 px-3 py-2 rounded-lg',\n 'bg-background/95 backdrop-blur-sm text-foreground text-sm font-medium',\n 'hover:bg-background transition-colors shadow-sm border border-border'\n )}\n >\n <RotateCcw className=\"w-4 h-4\" />\n Reset\n </button>\n )}\n\n {/* Open in Maps button */}\n {openInMapsUrl && (\n <a\n href={openInMapsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n 'inline-flex items-center gap-2 px-4 py-2 rounded-lg',\n 'bg-background/95 backdrop-blur-sm text-foreground text-sm font-medium',\n 'hover:bg-background transition-colors shadow-sm border border-border'\n )}\n >\n <ExternalLink className=\"w-4 h-4\" />\n {openInMapsLabel}\n </a>\n )}\n </div>\n </>\n )\n}\n\nexport function MapContainer({\n children,\n initialViewport,\n className,\n ...props\n}: MapContainerProps) {\n return (\n <div className={className} style={{ width: '100%', height: '100%', position: 'relative' }}>\n <MapProvider initialViewport={initialViewport}>\n <MapInner {...props}>{children}</MapInner>\n </MapProvider>\n </div>\n )\n}\n\n/**\n * Use this when you need the map inside an existing MapProvider\n */\nexport function MapView(props: Omit<MapContainerProps, 'initialViewport'>) {\n return <MapInner {...props} />\n}\n"]}
|