@djangocfg/ui-tools 2.1.407 → 2.1.409

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 (297) hide show
  1. package/README.md +9 -10
  2. package/dist/file-icon/index.cjs +449 -61
  3. package/dist/file-icon/index.cjs.map +1 -1
  4. package/dist/file-icon/index.d.cts +56 -18
  5. package/dist/file-icon/index.d.ts +56 -18
  6. package/dist/file-icon/index.mjs +448 -62
  7. package/dist/file-icon/index.mjs.map +1 -1
  8. package/dist/tree/index.cjs +49 -22
  9. package/dist/tree/index.cjs.map +1 -1
  10. package/dist/tree/index.d.cts +9 -3
  11. package/dist/tree/index.d.ts +9 -3
  12. package/dist/tree/index.mjs +49 -22
  13. package/dist/tree/index.mjs.map +1 -1
  14. package/dist/{types-B_zhyAqR.d.cts → types-eEu8SeiQ.d.cts} +4 -0
  15. package/dist/{types-B_zhyAqR.d.ts → types-eEu8SeiQ.d.ts} +4 -0
  16. package/package.json +8 -13
  17. package/src/components/FloatingToolbar/index.tsx +37 -3
  18. package/src/lib/page-snapshot/__tests__/capture-integration.test.ts +85 -0
  19. package/src/lib/page-snapshot/__tests__/engine.test.ts +36 -0
  20. package/src/lib/page-snapshot/__tests__/redaction-integration.test.ts +99 -0
  21. package/src/lib/page-snapshot/__tests__/tokens.test.ts +17 -0
  22. package/src/lib/page-snapshot/capture/__tests__/budget.test.ts +49 -0
  23. package/src/lib/page-snapshot/capture/__tests__/chrome-filter.test.ts +47 -0
  24. package/src/lib/page-snapshot/capture/__tests__/fold.test.ts +66 -0
  25. package/src/lib/page-snapshot/capture/__tests__/scope.test.ts +74 -0
  26. package/src/lib/page-snapshot/capture/__tests__/walk.test.ts +129 -0
  27. package/src/lib/page-snapshot/capture/accessible-name.ts +73 -0
  28. package/src/lib/page-snapshot/capture/budget.ts +95 -0
  29. package/src/lib/page-snapshot/capture/chrome-filter.ts +81 -0
  30. package/src/lib/page-snapshot/capture/classify.ts +111 -0
  31. package/src/lib/page-snapshot/capture/dom-utils.ts +111 -0
  32. package/src/lib/page-snapshot/capture/fold.ts +96 -0
  33. package/src/lib/page-snapshot/capture/scope.ts +169 -0
  34. package/src/lib/page-snapshot/capture/walk.ts +250 -0
  35. package/src/lib/page-snapshot/cst/__tests__/serialize.test.ts +50 -0
  36. package/src/lib/page-snapshot/cst/directives.ts +47 -0
  37. package/src/lib/page-snapshot/cst/payload.ts +50 -0
  38. package/src/lib/page-snapshot/cst/serialize.ts +84 -0
  39. package/src/lib/page-snapshot/cst/types.ts +115 -0
  40. package/src/lib/page-snapshot/engine.ts +176 -0
  41. package/src/lib/page-snapshot/index.ts +93 -0
  42. package/src/lib/page-snapshot/react/PageSnapshotChip.tsx +72 -0
  43. package/src/lib/page-snapshot/react/PageSnapshotPreview.tsx +78 -0
  44. package/src/lib/page-snapshot/react/__tests__/PageSnapshotChip.test.tsx +54 -0
  45. package/src/lib/page-snapshot/react/__tests__/provider.test.tsx +103 -0
  46. package/src/lib/page-snapshot/react/__tests__/use-page-snapshot-toggle.test.tsx +62 -0
  47. package/src/lib/page-snapshot/react/provider.tsx +162 -0
  48. package/src/lib/page-snapshot/react/use-page-snapshot-toggle.ts +47 -0
  49. package/src/lib/page-snapshot/react/use-page-snapshot.ts +67 -0
  50. package/src/lib/page-snapshot/redaction/__tests__/audit.test.ts +25 -0
  51. package/src/lib/page-snapshot/redaction/__tests__/heuristics.test.ts +73 -0
  52. package/src/lib/page-snapshot/redaction/__tests__/luhn.test.ts +26 -0
  53. package/src/lib/page-snapshot/redaction/__tests__/patterns.test.ts +60 -0
  54. package/src/lib/page-snapshot/redaction/audit.ts +58 -0
  55. package/src/lib/page-snapshot/redaction/heuristics.ts +75 -0
  56. package/src/lib/page-snapshot/redaction/index.ts +75 -0
  57. package/src/lib/page-snapshot/redaction/luhn.ts +25 -0
  58. package/src/lib/page-snapshot/redaction/patterns.ts +111 -0
  59. package/src/lib/page-snapshot/refs/__tests__/registry.test.ts +24 -0
  60. package/src/lib/page-snapshot/refs/registry.ts +46 -0
  61. package/src/lib/page-snapshot/staleness/__tests__/hash.test.ts +34 -0
  62. package/src/lib/page-snapshot/staleness/hash.ts +20 -0
  63. package/src/lib/page-snapshot/tokens.ts +15 -0
  64. package/src/tools/AudioPlayer/context/PlayerProvider.tsx +13 -14
  65. package/src/tools/AudioPlayer/hooks/useAudioElementEvents.ts +55 -6
  66. package/src/tools/AudioPlayer/parts/Meta/TimeDisplay.tsx +2 -5
  67. package/src/tools/Chat/README.md +277 -39
  68. package/src/tools/Chat/composer/Composer.tsx +471 -0
  69. package/src/tools/Chat/composer/ComposerActionBar.tsx +65 -0
  70. package/src/tools/Chat/composer/ComposerBanner.tsx +128 -0
  71. package/src/tools/Chat/composer/ComposerButton.tsx +64 -0
  72. package/src/tools/Chat/composer/ComposerFooter.tsx +90 -0
  73. package/src/tools/Chat/composer/ComposerMenuButton.tsx +62 -0
  74. package/src/tools/Chat/composer/ComposerModelPicker.tsx +104 -0
  75. package/src/tools/Chat/composer/ComposerRichTextarea.tsx +88 -0
  76. package/src/tools/Chat/composer/ComposerToolPill.tsx +95 -0
  77. package/src/tools/Chat/composer/index.ts +45 -0
  78. package/src/tools/Chat/composer/size-context.tsx +26 -0
  79. package/src/tools/Chat/composer/types.ts +143 -0
  80. package/src/tools/Chat/composer/useComposerActions.tsx +164 -0
  81. package/src/tools/Chat/context/ChatProvider.tsx +54 -3
  82. package/src/tools/Chat/core/__tests__/metadata.test.ts +69 -0
  83. package/src/tools/Chat/core/index.ts +23 -1
  84. package/src/tools/Chat/core/markdown.ts +1 -1
  85. package/src/tools/Chat/core/metadata.ts +47 -0
  86. package/src/tools/Chat/core/payload-dispatch.ts +1 -1
  87. package/src/tools/Chat/core/transport/http.ts +71 -32
  88. package/src/tools/Chat/core/transport/sse.ts +18 -10
  89. package/src/tools/Chat/highlight/HighlightOverlay.tsx +101 -0
  90. package/src/tools/Chat/highlight/README.md +103 -0
  91. package/src/tools/Chat/highlight/SpotlightCanvas.tsx +153 -0
  92. package/src/tools/Chat/highlight/__tests__/HighlightOverlay.test.tsx +112 -0
  93. package/src/tools/Chat/highlight/__tests__/resolveRef.test.ts +55 -0
  94. package/src/tools/Chat/highlight/index.ts +21 -0
  95. package/src/tools/Chat/highlight/resolveRef.ts +42 -0
  96. package/src/tools/Chat/highlight/types.ts +49 -0
  97. package/src/tools/Chat/highlight/useHighlightTargets.ts +128 -0
  98. package/src/tools/Chat/hooks/index.ts +0 -5
  99. package/src/tools/Chat/hooks/useAutoFocusOnStreamEnd.ts +28 -47
  100. package/src/tools/Chat/hooks/useChat.ts +47 -14
  101. package/src/tools/Chat/hooks/useChatComposer.ts +2 -2
  102. package/src/tools/Chat/hooks/useChatLayout.ts +1 -1
  103. package/src/tools/Chat/hooks/useStreamEndFocus.ts +54 -0
  104. package/src/tools/Chat/index.ts +25 -219
  105. package/src/tools/Chat/launcher/ChatDock.tsx +1 -1
  106. package/src/tools/Chat/launcher/ChatLauncher.tsx +1 -1
  107. package/src/tools/Chat/launcher/{ChatHeader.tsx → header/ChatHeader.tsx} +24 -11
  108. package/src/tools/Chat/launcher/{ChatHeaderActionButton.tsx → header/ChatHeaderActionButton.tsx} +34 -3
  109. package/src/tools/Chat/launcher/{ChatHeaderLanguageButton.tsx → header/ChatHeaderLanguageButton.tsx} +2 -2
  110. package/src/tools/Chat/launcher/{ChatHeaderModeToggle.tsx → header/ChatHeaderModeToggle.tsx} +1 -1
  111. package/src/tools/Chat/launcher/{ChatHeaderResetButton.tsx → header/ChatHeaderResetButton.tsx} +2 -1
  112. package/src/tools/Chat/launcher/{HeaderSlots.tsx → header/HeaderSlots.tsx} +3 -3
  113. package/src/tools/Chat/launcher/header/index.ts +26 -0
  114. package/src/tools/Chat/launcher/index.ts +3 -10
  115. package/src/tools/Chat/lazy.tsx +38 -284
  116. package/src/tools/Chat/{components → messages}/MessageBubble.tsx +58 -5
  117. package/src/tools/Chat/{components → messages}/MessageList.tsx +8 -25
  118. package/src/tools/Chat/messages/blocks/MessageBlocks.tsx +131 -0
  119. package/src/tools/Chat/messages/blocks/builtin.tsx +91 -0
  120. package/src/tools/Chat/messages/blocks/index.ts +12 -0
  121. package/src/tools/Chat/messages/blocks/registry.tsx +42 -0
  122. package/src/tools/Chat/messages/blocks/renderers/AudioBlock.tsx +20 -0
  123. package/src/tools/Chat/messages/blocks/renderers/CodeBlock.tsx +19 -0
  124. package/src/tools/Chat/messages/blocks/renderers/GalleryBlock.tsx +26 -0
  125. package/src/tools/Chat/messages/blocks/renderers/ImageBlock.tsx +27 -0
  126. package/src/tools/Chat/messages/blocks/renderers/JsonBlock.tsx +12 -0
  127. package/src/tools/Chat/messages/blocks/renderers/LottieBlock.tsx +11 -0
  128. package/src/tools/Chat/messages/blocks/renderers/MapBlock.tsx +36 -0
  129. package/src/tools/Chat/messages/blocks/renderers/MermaidBlock.tsx +11 -0
  130. package/src/tools/Chat/messages/blocks/renderers/VideoBlock.tsx +24 -0
  131. package/src/tools/Chat/messages/blocks/renderers/types.ts +8 -0
  132. package/src/tools/Chat/{components → messages}/index.ts +11 -5
  133. package/src/tools/Chat/public.ts +212 -0
  134. package/src/tools/Chat/shell/ChatRoot.tsx +345 -0
  135. package/src/tools/Chat/{components → shell}/EmptyState.tsx +4 -2
  136. package/src/tools/Chat/shell/index.ts +15 -0
  137. package/src/tools/Chat/types/block.ts +120 -0
  138. package/src/tools/Chat/types/config.ts +0 -5
  139. package/src/tools/Chat/types/index.ts +17 -0
  140. package/src/tools/Chat/types/message.ts +3 -0
  141. package/src/tools/Chat/utils/index.ts +4 -0
  142. package/src/tools/CodeEditor/README.md +4 -6
  143. package/src/tools/CodeEditor/components/DiffEditor.tsx +48 -13
  144. package/src/tools/CodeEditor/components/Editor.tsx +96 -44
  145. package/src/tools/CodeEditor/context/EditorProvider.tsx +34 -17
  146. package/src/tools/CodeEditor/hooks/useEditorTheme.ts +92 -99
  147. package/src/tools/CodeEditor/hooks/useMonaco.ts +37 -22
  148. package/src/tools/CodeEditor/lazy.tsx +6 -0
  149. package/src/tools/CodeEditor/lib/index.ts +1 -1
  150. package/src/tools/CodeEditor/lib/themes.ts +3 -39
  151. package/src/tools/CronScheduler/CronScheduler.client.tsx +230 -61
  152. package/src/tools/CronScheduler/components/CustomInput.tsx +21 -4
  153. package/src/tools/CronScheduler/components/DayChips.tsx +13 -11
  154. package/src/tools/CronScheduler/components/MonthDayGrid.tsx +4 -4
  155. package/src/tools/CronScheduler/components/SchedulePreview.tsx +7 -3
  156. package/src/tools/CronScheduler/components/TimeSelector.tsx +1 -1
  157. package/src/tools/CronScheduler/index.tsx +1 -1
  158. package/src/tools/CronScheduler/types/index.ts +8 -3
  159. package/src/tools/CronScheduler/utils/cron-humanize.ts +61 -16
  160. package/src/tools/CronScheduler/utils/cron-parser.ts +13 -4
  161. package/src/tools/FileIcon/FileIcon.tsx +24 -39
  162. package/src/tools/FileIcon/get-file-icon.ts +73 -0
  163. package/src/tools/FileIcon/icons/icon-data.ts +399 -0
  164. package/src/tools/FileIcon/index.ts +4 -0
  165. package/src/tools/FileIcon/loader.ts +17 -35
  166. package/src/tools/FileIcon/specialFolders.ts +18 -0
  167. package/src/tools/Gallery/components/lightbox/GalleryLightbox.tsx +112 -35
  168. package/src/tools/Gallery/components/media/GalleryVideo.tsx +21 -2
  169. package/src/tools/Gallery/components/preview/GalleryCarousel.tsx +11 -1
  170. package/src/tools/Gallery/hooks/usePreloadImages.ts +54 -7
  171. package/src/tools/ImageViewer/components/ImageInfo.tsx +12 -1
  172. package/src/tools/ImageViewer/components/ImageToolbar.tsx +51 -43
  173. package/src/tools/ImageViewer/components/ImageViewer.tsx +96 -24
  174. package/src/tools/ImageViewer/hooks/useImageLoading.ts +13 -0
  175. package/src/tools/ImageViewer/utils/constants.ts +3 -0
  176. package/src/tools/ImageViewer/utils/index.ts +1 -0
  177. package/src/tools/JsonForm/JsonSchemaForm.tsx +4 -1
  178. package/src/tools/JsonForm/templates/ArrayFieldTemplate.tsx +5 -3
  179. package/src/tools/JsonForm/templates/BaseInputTemplate.tsx +7 -4
  180. package/src/tools/JsonForm/templates/ErrorListTemplate.tsx +3 -1
  181. package/src/tools/JsonForm/templates/ObjectFieldTemplate.tsx +23 -3
  182. package/src/tools/JsonForm/widgets/ColorWidget.tsx +20 -12
  183. package/src/tools/JsonForm/widgets/NumberWidget.tsx +14 -9
  184. package/src/tools/JsonForm/widgets/RadioWidget.tsx +78 -0
  185. package/src/tools/JsonForm/widgets/SelectWidget.tsx +1 -0
  186. package/src/tools/JsonForm/widgets/SliderWidget.tsx +7 -4
  187. package/src/tools/JsonForm/widgets/TextWidget.tsx +41 -17
  188. package/src/tools/JsonForm/widgets/index.ts +1 -0
  189. package/src/tools/JsonTree/components/JsonContent.tsx +115 -40
  190. package/src/tools/LottiePlayer/LottiePlayer.client.tsx +177 -72
  191. package/src/tools/LottiePlayer/index.tsx +14 -4
  192. package/src/tools/LottiePlayer/lazy.tsx +11 -3
  193. package/src/tools/LottiePlayer/types.ts +31 -1
  194. package/src/tools/LottiePlayer/useLottie.ts +32 -9
  195. package/src/tools/LottiePlayer/usePrefersReducedMotion.ts +46 -0
  196. package/src/tools/Map/components/LayerSwitcher.tsx +54 -21
  197. package/src/tools/Map/components/MapCluster.tsx +28 -21
  198. package/src/tools/Map/components/MapContainer.tsx +11 -4
  199. package/src/tools/Map/components/MapLegend.tsx +46 -15
  200. package/src/tools/Map/components/MapMarker.tsx +31 -2
  201. package/src/tools/Map/hooks/useMapEvents.ts +64 -105
  202. package/src/tools/MarkdownEditor/MarkdownEditor.tsx +61 -6
  203. package/src/tools/MarkdownEditor/MentionList.tsx +37 -4
  204. package/src/tools/MarkdownEditor/createMentionSuggestion.ts +11 -0
  205. package/src/tools/MarkdownEditor/lazy.tsx +32 -7
  206. package/src/tools/MarkdownEditor/styles.css +13 -0
  207. package/src/tools/MarkdownMessage/CodeBlock.tsx +40 -17
  208. package/src/tools/MarkdownMessage/MarkdownMessage.tsx +26 -6
  209. package/src/tools/MarkdownMessage/components.tsx +22 -9
  210. package/src/tools/MarkdownMessage/types.ts +24 -1
  211. package/src/tools/Mermaid/Mermaid.client.tsx +27 -5
  212. package/src/tools/Mermaid/components/MermaidErrorPanel.tsx +31 -0
  213. package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +14 -17
  214. package/src/tools/Mermaid/hooks/useMermaidRenderer.ts +264 -168
  215. package/src/tools/Mermaid/hooks/useMermaidValidation.ts +76 -10
  216. package/src/tools/Mermaid/index.tsx +6 -0
  217. package/src/tools/Mermaid/utils/mermaid-helpers.ts +141 -18
  218. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/FieldRow.tsx +11 -1
  219. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/buildTree.ts +49 -20
  220. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/index.tsx +7 -0
  221. package/src/tools/OpenapiViewer/components/DocsLayout/grouping.ts +7 -4
  222. package/src/tools/OpenapiViewer/constants.ts +3 -0
  223. package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +73 -11
  224. package/src/tools/OpenapiViewer/utils/schemaExport.ts +26 -6
  225. package/src/tools/PrettyCode/PrettyCode.client.tsx +23 -16
  226. package/src/tools/PrettyCode/lazy.tsx +1 -1
  227. package/src/tools/SpeechRecognition/README.md +1 -1
  228. package/src/tools/SpeechRecognition/__tests__/language.test.ts +9 -3
  229. package/src/tools/SpeechRecognition/components/RecordingPulse.tsx +59 -0
  230. package/src/tools/SpeechRecognition/components/index.ts +2 -0
  231. package/src/tools/SpeechRecognition/core/engine/external.ts +24 -7
  232. package/src/tools/SpeechRecognition/core/language.ts +23 -6
  233. package/src/tools/SpeechRecognition/hooks/usePushToTalk.ts +36 -5
  234. package/src/tools/SpeechRecognition/hooks/useSpeechRecognition.ts +18 -11
  235. package/src/tools/SpeechRecognition/widgets/VoiceComposerSlot.tsx +94 -26
  236. package/src/tools/SpeechRecognition/widgets/index.ts +1 -1
  237. package/src/tools/Tree/README.md +4 -8
  238. package/src/tools/Tree/TreeRoot.tsx +22 -10
  239. package/src/tools/Tree/components/TreeContent.tsx +24 -4
  240. package/src/tools/Tree/components/TreeLabel.tsx +8 -2
  241. package/src/tools/Tree/components/TreeRow.tsx +16 -6
  242. package/src/tools/Tree/data/flatten.ts +10 -4
  243. package/src/tools/Tree/types.ts +4 -0
  244. package/src/tools/Uploader/components/UploadAddButton.tsx +29 -6
  245. package/src/tools/Uploader/components/UploadDropzone.tsx +63 -7
  246. package/src/tools/Uploader/components/UploadPageDropOverlay.tsx +19 -5
  247. package/src/tools/Uploader/components/UploadPreviewItem.tsx +47 -17
  248. package/src/tools/Uploader/components/UploadPreviewList.tsx +24 -12
  249. package/src/tools/Uploader/utils/formatters.ts +8 -3
  250. package/src/tools/VideoPlayer/canvas/hls-canvas.tsx +1 -0
  251. package/src/tools/VideoPlayer/canvas/{jsx.d.ts → jsx-augmentation.ts} +12 -19
  252. package/src/tools/VideoPlayer/canvas/vimeo-canvas.tsx +1 -0
  253. package/src/tools/VideoPlayer/canvas/youtube-canvas.tsx +1 -0
  254. package/src/tools/VideoPlayer/parts/fullscreen.tsx +1 -1
  255. package/src/tools/VideoPlayer/parts/pip.tsx +1 -1
  256. package/src/tools/VideoPlayer/parts/playback-rate.tsx +1 -1
  257. package/src/tools/VideoPlayer/parts/seek-bar.tsx +2 -2
  258. package/src/tools/VideoPlayer/parts/volume.tsx +2 -2
  259. package/src/tools/index.ts +2 -1
  260. package/src/tools/Chat/components/AudioToggle.tsx +0 -78
  261. package/src/tools/Chat/components/ChatRoot.tsx +0 -305
  262. package/src/tools/Chat/components/Composer.tsx +0 -216
  263. package/src/tools/Chat/hooks/useChatScroll.ts +0 -145
  264. package/src/tools/Chat/types.ts +0 -9
  265. package/src/tools/JsonTree/components/JsonToolbar.tsx +0 -95
  266. package/src/tools/JsonTree/hooks/useElementCorner.ts +0 -84
  267. package/src/tools/JsonTree/hooks/useNavbarHeight.ts +0 -83
  268. package/src/tools/OpenapiViewer/components/DocsLayout/schemaFields.ts +0 -121
  269. package/src/tools/Tour/README.md +0 -373
  270. package/src/tools/Tour/components/Tour.tsx +0 -12
  271. package/src/tools/Tour/components/TourContent.tsx +0 -171
  272. package/src/tools/Tour/components/TourNavigation.tsx +0 -77
  273. package/src/tools/Tour/components/TourProgress.tsx +0 -88
  274. package/src/tools/Tour/components/TourSpotlight.tsx +0 -199
  275. package/src/tools/Tour/components/index.ts +0 -5
  276. package/src/tools/Tour/context/TourContext.ts +0 -19
  277. package/src/tools/Tour/context/TourProvider.tsx +0 -292
  278. package/src/tools/Tour/context/index.ts +0 -2
  279. package/src/tools/Tour/hooks/index.ts +0 -3
  280. package/src/tools/Tour/hooks/useKeyboardNavigation.ts +0 -59
  281. package/src/tools/Tour/hooks/useStepTarget.ts +0 -121
  282. package/src/tools/Tour/hooks/useTour.ts +0 -42
  283. package/src/tools/Tour/index.ts +0 -38
  284. package/src/tools/Tour/types/index.ts +0 -224
  285. package/src/tools/Tour/utils/dom.ts +0 -98
  286. package/src/tools/Tour/utils/index.ts +0 -3
  287. package/src/tools/Tour/utils/logger.ts +0 -3
  288. package/src/tools/Tour/utils/scrollIntoView.ts +0 -24
  289. /package/src/tools/Chat/{config.ts → constants.ts} +0 -0
  290. /package/src/tools/Chat/launcher/{ChatHeaderAudioToggle.tsx → header/ChatHeaderAudioToggle.tsx} +0 -0
  291. /package/src/tools/Chat/{components → messages}/Attachments.tsx +0 -0
  292. /package/src/tools/Chat/{components → messages}/JumpToLatest.tsx +0 -0
  293. /package/src/tools/Chat/{components → messages}/MessageActions.tsx +0 -0
  294. /package/src/tools/Chat/{components → messages}/Sources.tsx +0 -0
  295. /package/src/tools/Chat/{components → messages}/StreamingIndicator.tsx +0 -0
  296. /package/src/tools/Chat/{components → messages}/ToolCalls.tsx +0 -0
  297. /package/src/tools/Chat/{components → shell}/ErrorBanner.tsx +0 -0
@@ -1,59 +0,0 @@
1
- 'use client';
2
-
3
- import { useEffect } from 'react';
4
-
5
- interface UseKeyboardNavigationOptions {
6
- enabled: boolean;
7
- onNext?: () => void;
8
- onPrevious?: () => void;
9
- onClose?: () => void;
10
- }
11
-
12
- /**
13
- * Hook for keyboard navigation in tours.
14
- * - ArrowRight/ArrowDown: Next step
15
- * - ArrowLeft/ArrowUp: Previous step
16
- * - Escape: Close tour
17
- */
18
- export function useKeyboardNavigation({
19
- enabled,
20
- onNext,
21
- onPrevious,
22
- onClose,
23
- }: UseKeyboardNavigationOptions): void {
24
- useEffect(() => {
25
- if (!enabled) return;
26
-
27
- const handleKeyDown = (event: KeyboardEvent) => {
28
- // Ignore if user is typing in an input
29
- const target = event.target as HTMLElement;
30
- if (
31
- target.tagName === 'INPUT' ||
32
- target.tagName === 'TEXTAREA' ||
33
- target.isContentEditable
34
- ) {
35
- return;
36
- }
37
-
38
- switch (event.key) {
39
- case 'ArrowRight':
40
- case 'ArrowDown':
41
- event.preventDefault();
42
- onNext?.();
43
- break;
44
- case 'ArrowLeft':
45
- case 'ArrowUp':
46
- event.preventDefault();
47
- onPrevious?.();
48
- break;
49
- case 'Escape':
50
- event.preventDefault();
51
- onClose?.();
52
- break;
53
- }
54
- };
55
-
56
- document.addEventListener('keydown', handleKeyDown);
57
- return () => document.removeEventListener('keydown', handleKeyDown);
58
- }, [enabled, onNext, onPrevious, onClose]);
59
- }
@@ -1,121 +0,0 @@
1
- 'use client';
2
-
3
- import { useState, useEffect, useCallback, useRef } from 'react';
4
- import { findTargetElements, getElementBorderRadius } from '../utils/dom';
5
- import { scrollToElement } from '../utils/scrollIntoView';
6
- import type { SpotlightTarget } from '../types';
7
-
8
- interface UseStepTargetOptions {
9
- scrollToTarget?: boolean;
10
- scrollBehavior?: ScrollBehavior;
11
- spotlightPadding?: number;
12
- }
13
-
14
- interface UseStepTargetReturn {
15
- targets: SpotlightTarget[];
16
- isReady: boolean;
17
- }
18
-
19
- /**
20
- * Hook to track target elements for current tour step.
21
- * Handles scroll, resize, and DOM mutations.
22
- */
23
- export function useStepTarget(
24
- target: string | undefined,
25
- stepId: string | undefined,
26
- options: UseStepTargetOptions = {}
27
- ): UseStepTargetReturn {
28
- const {
29
- scrollToTarget = true,
30
- scrollBehavior = 'smooth',
31
- spotlightPadding = 8,
32
- } = options;
33
-
34
- const [targets, setTargets] = useState<SpotlightTarget[]>([]);
35
- const [isReady, setIsReady] = useState(false);
36
- const hasScrolledRef = useRef(false);
37
- const updateTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
38
-
39
- const updateTargets = useCallback(() => {
40
- if (!stepId) {
41
- setTargets([]);
42
- setIsReady(false);
43
- return;
44
- }
45
-
46
- const elements = findTargetElements(target, stepId);
47
- if (elements.length === 0) {
48
- setTargets([]);
49
- setIsReady(false);
50
- return;
51
- }
52
-
53
- const newTargets: SpotlightTarget[] = elements.map((element) => ({
54
- element,
55
- rect: element.getBoundingClientRect(),
56
- padding: spotlightPadding,
57
- radius: getElementBorderRadius(element),
58
- }));
59
-
60
- setTargets(newTargets);
61
- setIsReady(true);
62
-
63
- // Scroll to first target on initial render
64
- if (scrollToTarget && !hasScrolledRef.current && elements[0]) {
65
- scrollToElement(elements[0], scrollBehavior);
66
- hasScrolledRef.current = true;
67
- }
68
- }, [target, stepId, scrollToTarget, scrollBehavior, spotlightPadding]);
69
-
70
- // Debounced update for performance
71
- const debouncedUpdate = useCallback(() => {
72
- if (updateTimeoutRef.current) {
73
- clearTimeout(updateTimeoutRef.current);
74
- }
75
- updateTimeoutRef.current = setTimeout(updateTargets, 16);
76
- }, [updateTargets]);
77
-
78
- // Reset scroll flag when step changes
79
- useEffect(() => {
80
- hasScrolledRef.current = false;
81
- }, [stepId]);
82
-
83
- // Initial update and event listeners
84
- useEffect(() => {
85
- if (!stepId) return;
86
-
87
- // Initial update
88
- updateTargets();
89
-
90
- // Resize listener
91
- window.addEventListener('resize', debouncedUpdate);
92
-
93
- // Scroll listener (capture phase to catch all scrolls)
94
- window.addEventListener('scroll', debouncedUpdate, true);
95
-
96
- // Mutation observer for DOM changes
97
- const observer = new MutationObserver(debouncedUpdate);
98
- observer.observe(document.body, {
99
- childList: true,
100
- subtree: true,
101
- attributes: true,
102
- attributeFilter: ['style', 'class'],
103
- });
104
-
105
- // ResizeObserver for element size changes
106
- const resizeObserver = new ResizeObserver(debouncedUpdate);
107
- resizeObserver.observe(document.body);
108
-
109
- return () => {
110
- window.removeEventListener('resize', debouncedUpdate);
111
- window.removeEventListener('scroll', debouncedUpdate, true);
112
- observer.disconnect();
113
- resizeObserver.disconnect();
114
- if (updateTimeoutRef.current) {
115
- clearTimeout(updateTimeoutRef.current);
116
- }
117
- };
118
- }, [stepId, updateTargets, debouncedUpdate]);
119
-
120
- return { targets, isReady };
121
- }
@@ -1,42 +0,0 @@
1
- 'use client';
2
-
3
- import { useTourContext } from '../context/TourContext';
4
- import type { UseTourReturn } from '../types';
5
-
6
- /**
7
- * Hook to control the tour.
8
- * Must be used within a TourProvider.
9
- */
10
- export function useTour(): UseTourReturn {
11
- const {
12
- start,
13
- next,
14
- previous,
15
- goTo,
16
- close,
17
- isActive,
18
- activeTourId,
19
- currentStep,
20
- currentStepIndex,
21
- totalSteps,
22
- isFirstStep,
23
- isLastStep,
24
- progress,
25
- } = useTourContext();
26
-
27
- return {
28
- start,
29
- next,
30
- previous,
31
- goTo,
32
- close,
33
- isActive,
34
- activeTourId,
35
- currentStep,
36
- currentStepIndex,
37
- totalSteps,
38
- isFirstStep,
39
- isLastStep,
40
- progress,
41
- };
42
- }
@@ -1,38 +0,0 @@
1
- // Components
2
- export { Tour } from './components/Tour';
3
- export { TourSpotlight } from './components/TourSpotlight';
4
- export { TourProgress } from './components/TourProgress';
5
- export { TourNavigation } from './components/TourNavigation';
6
- export { TourContent } from './components/TourContent';
7
-
8
- // Context
9
- export { TourProvider } from './context';
10
-
11
- // Hooks
12
- export { useTour } from './hooks/useTour';
13
- export { useStepTarget } from './hooks/useStepTarget';
14
- export { useKeyboardNavigation } from './hooks/useKeyboardNavigation';
15
-
16
- // Utils
17
- export { findTargetElements, isElementInViewport } from './utils/dom';
18
- export { scrollToElement } from './utils/scrollIntoView';
19
-
20
- // Types
21
- export type {
22
- Tour as TourConfig,
23
- TourStep,
24
- TourAction,
25
- TourState,
26
- TourPosition,
27
- TourAlign,
28
- ProgressVariant,
29
- TourCallbacks,
30
- TourProviderProps,
31
- TourProps,
32
- TourContentProps,
33
- TourSpotlightProps,
34
- TourProgressProps,
35
- TourNavigationProps,
36
- SpotlightTarget,
37
- UseTourReturn,
38
- } from './types';
@@ -1,224 +0,0 @@
1
- import type { ReactNode } from 'react';
2
-
3
- // Position & Alignment
4
- export type TourPosition = 'top' | 'bottom' | 'left' | 'right' | 'auto';
5
- export type TourAlign = 'start' | 'center' | 'end';
6
- export type ProgressVariant = 'dots' | 'bar' | 'fraction' | 'none';
7
-
8
- // Step Action
9
- export interface TourAction {
10
- label: ReactNode;
11
- onClick: () => void;
12
- variant?: 'default' | 'outline' | 'ghost' | 'destructive';
13
- }
14
-
15
- // Step Definition
16
- export interface TourStep {
17
- /** Unique step identifier */
18
- id: string;
19
- /** CSS selector or data-tour-step-id value to find target element */
20
- target?: string;
21
- /** Step title */
22
- title: ReactNode;
23
- /** Step description/content */
24
- content: ReactNode;
25
- /** Popover position relative to target */
26
- position?: TourPosition;
27
- /** Offset from target in pixels */
28
- offset?: number;
29
- /** Alignment along the position axis */
30
- align?: TourAlign;
31
- /** Alignment offset in pixels */
32
- alignOffset?: number;
33
- /** Custom class for this step's popover */
34
- className?: string;
35
- /** Route to navigate on Next (for multi-page tours) */
36
- nextRoute?: string;
37
- /** Route to navigate on Previous */
38
- previousRoute?: string;
39
- /** Custom Next button label */
40
- nextLabel?: ReactNode;
41
- /** Custom Previous button label */
42
- previousLabel?: ReactNode;
43
- /** Disable spotlight for this step */
44
- disableSpotlight?: boolean;
45
- /** Spotlight padding around target */
46
- spotlightPadding?: number;
47
- /** Custom spotlight border radius */
48
- spotlightRadius?: number;
49
- /** Allow interaction with target while step is active */
50
- allowTargetInteraction?: boolean;
51
- /** Auto-advance after delay (ms) */
52
- autoAdvance?: number;
53
- /** Custom action buttons */
54
- actions?: TourAction[];
55
- /** Called before step shows, return false to skip */
56
- onBeforeShow?: () => boolean | Promise<boolean>;
57
- /** Called after step renders */
58
- onShow?: () => void;
59
- /** Called before step hides */
60
- onHide?: () => void;
61
- }
62
-
63
- // Tour Definition
64
- export interface Tour {
65
- id: string;
66
- steps: TourStep[];
67
- /** Tour-level defaults for steps */
68
- defaults?: Partial<TourStep>;
69
- }
70
-
71
- // State
72
- export interface TourState {
73
- isActive: boolean;
74
- activeTourId: string | null;
75
- currentStepIndex: number;
76
- isTransitioning: boolean;
77
- direction: 'forward' | 'backward';
78
- }
79
-
80
- // Callbacks
81
- export interface TourCallbacks {
82
- /** Called when tour starts */
83
- onStart?: (tourId: string) => void;
84
- /** Called when tour completes (last step finished) */
85
- onComplete?: (tourId: string) => void;
86
- /** Called when tour is skipped/closed early */
87
- onSkip?: (tourId: string, stepIndex: number) => void;
88
- /** Called on step change */
89
- onStepChange?: (stepIndex: number, step: TourStep, direction: 'forward' | 'backward') => void;
90
- /** Called before step transition, return false to cancel */
91
- onBeforeStepChange?: (currentIndex: number, nextIndex: number) => boolean | Promise<boolean>;
92
- }
93
-
94
- // Provider Props
95
- export interface TourProviderProps extends TourCallbacks {
96
- tours: Tour[];
97
- children: ReactNode;
98
- /** Enable spotlight (default: true) */
99
- spotlight?: boolean;
100
- /** Spotlight opacity 0-1 (default: 0.5) */
101
- spotlightOpacity?: number;
102
- /** Spotlight blur amount in pixels (default: 0) */
103
- spotlightBlur?: number;
104
- /** Enable spotlight animations (default: true) */
105
- animated?: boolean;
106
- /** Show pulsing ring around target (default: false) */
107
- pulseRing?: boolean;
108
- /** Show arrow pointing to target (default: false) */
109
- showArrow?: boolean;
110
- /** Enable keyboard navigation (default: true) */
111
- keyboardNavigation?: boolean;
112
- /** Close on overlay click (default: false) */
113
- closeOnOverlayClick?: boolean;
114
- /** Close on Escape key (default: true) */
115
- closeOnEscape?: boolean;
116
- /** Scroll target into view (default: true) */
117
- scrollToTarget?: boolean;
118
- /** Scroll behavior (default: 'smooth') */
119
- scrollBehavior?: ScrollBehavior;
120
- /** Progress indicator variant (default: 'dots') */
121
- progressVariant?: ProgressVariant;
122
- /** Show skip button (default: true) */
123
- showSkipButton?: boolean;
124
- /** Custom skip button label */
125
- skipLabel?: ReactNode;
126
- /** Custom finish button label */
127
- finishLabel?: ReactNode;
128
- /** Portal container (default: document.body) */
129
- portalContainer?: HTMLElement;
130
- /** Z-index for overlay (default: 50) */
131
- zIndex?: number;
132
- }
133
-
134
- // Hook Return
135
- export interface UseTourReturn {
136
- /** Start a tour by ID */
137
- start: (tourId: string, startIndex?: number) => void;
138
- /** Go to next step */
139
- next: () => void;
140
- /** Go to previous step */
141
- previous: () => void;
142
- /** Go to specific step */
143
- goTo: (index: number) => void;
144
- /** Close/skip tour */
145
- close: () => void;
146
- /** Is tour currently active */
147
- isActive: boolean;
148
- /** Currently active tour ID */
149
- activeTourId: string | null;
150
- /** Current step object */
151
- currentStep: TourStep | null;
152
- /** Current step index */
153
- currentStepIndex: number;
154
- /** Total number of steps */
155
- totalSteps: number;
156
- /** Is first step */
157
- isFirstStep: boolean;
158
- /** Is last step */
159
- isLastStep: boolean;
160
- /** Progress 0-1 */
161
- progress: number;
162
- }
163
-
164
- // Spotlight Target
165
- export interface SpotlightTarget {
166
- element: HTMLElement;
167
- rect: DOMRect;
168
- padding: number;
169
- radius: number;
170
- }
171
-
172
- // Component Props
173
- export interface TourSpotlightProps {
174
- targets: SpotlightTarget[];
175
- opacity?: number;
176
- blur?: number;
177
- animated?: boolean;
178
- pulseRing?: boolean;
179
- className?: string;
180
- onClick?: () => void;
181
- allowInteraction?: boolean;
182
- }
183
-
184
- export interface TourProgressProps {
185
- current: number;
186
- total: number;
187
- variant?: ProgressVariant;
188
- onDotClick?: (index: number) => void;
189
- className?: string;
190
- }
191
-
192
- export interface TourNavigationProps {
193
- onNext: () => void;
194
- onPrevious: () => void;
195
- isFirstStep: boolean;
196
- isLastStep: boolean;
197
- nextLabel?: ReactNode;
198
- previousLabel?: ReactNode;
199
- finishLabel?: ReactNode;
200
- nextRoute?: string;
201
- previousRoute?: string;
202
- className?: string;
203
- }
204
-
205
- export interface TourContentProps {
206
- step: TourStep;
207
- targetRect: DOMRect;
208
- currentIndex: number;
209
- totalSteps: number;
210
- onNext: () => void;
211
- onPrevious: () => void;
212
- onClose: () => void;
213
- progressVariant?: ProgressVariant;
214
- showSkipButton?: boolean;
215
- showArrow?: boolean;
216
- skipLabel?: ReactNode;
217
- finishLabel?: ReactNode;
218
- onGoTo?: (index: number) => void;
219
- className?: string;
220
- }
221
-
222
- export interface TourProps extends Omit<TourProviderProps, 'children'> {
223
- children?: ReactNode;
224
- }
@@ -1,98 +0,0 @@
1
- import { emitRuntimeError } from '@djangocfg/ui-core/utils';
2
-
3
- import { logger } from './logger';
4
-
5
- /**
6
- * Safely escape string for use in CSS attribute selector
7
- */
8
- function escapeCSS(str: string): string {
9
- return str.replace(/["\\]/g, '\\$&');
10
- }
11
-
12
- /**
13
- * Find target elements for a tour step.
14
- * Supports CSS selectors and data-tour-step-id attribute.
15
- */
16
- export function findTargetElements(
17
- target: string | undefined,
18
- stepId: string
19
- ): HTMLElement[] {
20
- if (!target) {
21
- // Fallback to data-tour-step-id attribute
22
- try {
23
- const escapedStepId = escapeCSS(stepId);
24
- const elements = document.querySelectorAll<HTMLElement>(
25
- `[data-tour-step-id="${escapedStepId}"], [data-tour-step-id*="${escapedStepId}"]`
26
- );
27
- return filterValidElements(Array.from(elements));
28
- } catch (error) {
29
- const err = error instanceof Error ? error : new Error(String(error));
30
- logger.error(`Tour: Invalid stepId selector "${stepId}"`, { error: err.message, stepId });
31
- emitRuntimeError('Tour', `Invalid stepId: ${stepId}`, err);
32
- return [];
33
- }
34
- }
35
-
36
- // Try as CSS selector first
37
- try {
38
- const elements = document.querySelectorAll<HTMLElement>(target);
39
- const valid = filterValidElements(Array.from(elements));
40
- if (valid.length > 0) return valid;
41
- } catch (error) {
42
- const err = error instanceof Error ? error : new Error(String(error));
43
- logger.warn(`Tour: Invalid target selector "${target}"`, { error: err.message, target, stepId });
44
- emitRuntimeError('Tour', `Invalid selector: ${target}`, err);
45
- return [];
46
- }
47
-
48
- // Fallback to data attribute
49
- try {
50
- const escapedTarget = escapeCSS(target);
51
- const elements = document.querySelectorAll<HTMLElement>(
52
- `[data-tour-step-id="${escapedTarget}"], [data-tour-step-id*="${escapedTarget}"]`
53
- );
54
- return filterValidElements(Array.from(elements));
55
- } catch (error) {
56
- const err = error instanceof Error ? error : new Error(String(error));
57
- logger.error(`Tour: Invalid fallback selector for "${target}"`, { error: err.message, target, stepId });
58
- emitRuntimeError('Tour', `Invalid fallback selector: ${target}`, err);
59
- return [];
60
- }
61
- }
62
-
63
- /**
64
- * Filter out elements that are not visible or have zero dimensions.
65
- */
66
- function filterValidElements(elements: HTMLElement[]): HTMLElement[] {
67
- return elements.filter((el) => {
68
- const rect = el.getBoundingClientRect();
69
- // Skip elements with zero dimensions
70
- if (rect.width === 0 && rect.height === 0) return false;
71
- // Skip hidden elements
72
- const style = window.getComputedStyle(el);
73
- if (style.display === 'none' || style.visibility === 'hidden') return false;
74
- return true;
75
- });
76
- }
77
-
78
- /**
79
- * Get computed border radius from element.
80
- */
81
- export function getElementBorderRadius(element: HTMLElement): number {
82
- const style = window.getComputedStyle(element);
83
- const radius = parseFloat(style.borderRadius) || 0;
84
- return Math.min(radius, 20); // Cap at 20px for reasonable spotlight
85
- }
86
-
87
- /**
88
- * Check if element is in viewport.
89
- */
90
- export function isElementInViewport(element: HTMLElement): boolean {
91
- const rect = element.getBoundingClientRect();
92
- return (
93
- rect.top >= 0 &&
94
- rect.left >= 0 &&
95
- rect.bottom <= window.innerHeight &&
96
- rect.right <= window.innerWidth
97
- );
98
- }
@@ -1,3 +0,0 @@
1
- export { logger } from './logger';
2
- export { findTargetElements, getElementBorderRadius, isElementInViewport } from './dom';
3
- export { scrollToElement, waitForScroll } from './scrollIntoView';
@@ -1,3 +0,0 @@
1
- import { createLogger } from '@djangocfg/ui-core/lib';
2
-
3
- export const logger = createLogger('Tour');
@@ -1,24 +0,0 @@
1
- import { isElementInViewport } from './dom';
2
-
3
- /**
4
- * Scroll element into view if not already visible.
5
- */
6
- export function scrollToElement(
7
- element: HTMLElement,
8
- behavior: ScrollBehavior = 'smooth'
9
- ): void {
10
- if (isElementInViewport(element)) return;
11
-
12
- element.scrollIntoView({
13
- behavior,
14
- block: 'center',
15
- inline: 'center',
16
- });
17
- }
18
-
19
- /**
20
- * Wait for scroll to complete (approximate).
21
- */
22
- export function waitForScroll(duration = 300): Promise<void> {
23
- return new Promise((resolve) => setTimeout(resolve, duration));
24
- }
File without changes