xertica-ui 2.1.2 → 2.1.4

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 (181) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +1 -1
  3. package/bin/cli.ts +1 -1
  4. package/bin/generate-tokens.ts +13 -7
  5. package/components/assistant/xertica-assistant/index.ts +2 -0
  6. package/components/assistant/xertica-assistant/parts/AssistantCollapsedView.tsx +97 -0
  7. package/components/assistant/xertica-assistant/parts/AssistantConversationList.tsx +104 -0
  8. package/components/assistant/xertica-assistant/parts/AssistantDocumentEditor.tsx +81 -0
  9. package/components/assistant/xertica-assistant/parts/AssistantFeedbackDialog.tsx +86 -0
  10. package/components/assistant/xertica-assistant/parts/AssistantHeader.tsx +77 -0
  11. package/components/assistant/xertica-assistant/parts/AssistantMessageBubble.tsx +573 -0
  12. package/components/assistant/xertica-assistant/parts/AssistantTabBar.tsx +65 -0
  13. package/components/assistant/xertica-assistant/parts/AssistantTypingIndicator.tsx +41 -0
  14. package/components/assistant/xertica-assistant/parts/AssistantWelcomeScreen.tsx +98 -0
  15. package/components/assistant/xertica-assistant/parts/index.ts +16 -0
  16. package/components/assistant/xertica-assistant/types.ts +139 -0
  17. package/components/assistant/xertica-assistant/use-assistant.ts +559 -0
  18. package/components/assistant/xertica-assistant/xertica-assistant.stories.tsx +200 -0
  19. package/components/assistant/xertica-assistant/xertica-assistant.tsx +198 -1460
  20. package/components/brand/theme-toggle/ThemeToggle.tsx +8 -27
  21. package/components/hooks/index.ts +3 -0
  22. package/components/hooks/use-layout-shortcuts.ts +46 -0
  23. package/components/layout/sidebar/index.ts +2 -0
  24. package/components/layout/sidebar/sidebar.stories.tsx +160 -8
  25. package/components/layout/sidebar/sidebar.tsx +606 -497
  26. package/components/layout/sidebar/use-sidebar.ts +104 -0
  27. package/components/media/audio-player/AudioPlayer.tsx +131 -206
  28. package/components/media/audio-player/use-audio-player.ts +298 -0
  29. package/components/pages/home-page/HomePage.tsx +1 -1
  30. package/components/pages/template-content/TemplateContent.tsx +5 -5
  31. package/components/pages/template-page/TemplatePage.tsx +5 -5
  32. package/components/shared/CustomTooltipContent.tsx +52 -0
  33. package/components/shared/layout-constants.ts +1 -1
  34. package/components/ui/chart/chart.stories.tsx +966 -7
  35. package/components/ui/chart/chart.tsx +918 -45
  36. package/components/ui/file-upload/file-upload.stories.tsx +100 -0
  37. package/components/ui/file-upload/file-upload.tsx +14 -74
  38. package/components/ui/file-upload/index.ts +1 -0
  39. package/components/ui/file-upload/use-file-upload.ts +181 -0
  40. package/components/ui/pagination/index.ts +2 -0
  41. package/components/ui/pagination/pagination.stories.tsx +94 -0
  42. package/components/ui/pagination/use-pagination.ts +194 -0
  43. package/components/ui/rich-text-editor/index.ts +2 -0
  44. package/components/ui/rich-text-editor/rich-text-editor.stories.tsx +129 -1
  45. package/components/ui/rich-text-editor/rich-text-editor.tsx +86 -305
  46. package/components/ui/rich-text-editor/use-rich-text-editor.ts +439 -0
  47. package/components/ui/stepper/index.ts +3 -1
  48. package/components/ui/stepper/stepper.stories.tsx +116 -0
  49. package/components/ui/stepper/stepper.tsx +4 -4
  50. package/components/ui/stepper/use-stepper.ts +137 -0
  51. package/components/ui/tree-view/index.ts +4 -1
  52. package/components/ui/tree-view/tree-view.stories.tsx +110 -4
  53. package/components/ui/tree-view/tree-view.tsx +17 -125
  54. package/components/ui/tree-view/use-tree-view.ts +229 -0
  55. package/contexts/AssistenteContext.tsx +17 -54
  56. package/contexts/BrandColorsContext.tsx +6 -17
  57. package/contexts/LayoutContext.tsx +5 -31
  58. package/dist/AssistantChart-BAudAfne.cjs +3591 -0
  59. package/dist/AssistantChart-BP8upjMk.js +3565 -0
  60. package/dist/AudioPlayer-1ypwE2Wh.cjs +936 -0
  61. package/dist/AudioPlayer-DuKXrCfy.js +937 -0
  62. package/dist/CustomTooltipContent-DHjkY0ww.js +40 -0
  63. package/dist/CustomTooltipContent-c_K-DWRr.cjs +56 -0
  64. package/dist/LanguageContext-BwhwC3G2.js +657 -0
  65. package/dist/LanguageContext-DvUt5jBg.cjs +656 -0
  66. package/dist/LayoutContext-BDmcZfMH.cjs +84 -0
  67. package/dist/LayoutContext-dbQvdC4O.js +85 -0
  68. package/dist/ThemeContext-RTy1m2Uq.js +82 -0
  69. package/dist/ThemeContext-bSzuOit2.cjs +81 -0
  70. package/dist/VerifyEmailPage-C_ihbcth.js +2828 -0
  71. package/dist/VerifyEmailPage-Dt7zgA4w.cjs +2827 -0
  72. package/dist/XerticaProvider-CW9hpCdF.cjs +39 -0
  73. package/dist/XerticaProvider-siSt9uG2.js +40 -0
  74. package/dist/XerticaXLogo-D8jf0SNv.cjs +214 -0
  75. package/dist/XerticaXLogo-fAJMy3H4.js +215 -0
  76. package/dist/assistant.cjs.js +2 -1
  77. package/dist/assistant.es.js +3 -2
  78. package/dist/brand.cjs.js +2 -2
  79. package/dist/brand.es.js +2 -2
  80. package/dist/cli.js +14 -8
  81. package/dist/components/assistant/xertica-assistant/index.d.ts +2 -0
  82. package/dist/components/assistant/xertica-assistant/parts/AssistantCollapsedView.d.ts +13 -0
  83. package/dist/components/assistant/xertica-assistant/parts/AssistantConversationList.d.ts +16 -0
  84. package/dist/components/assistant/xertica-assistant/parts/AssistantDocumentEditor.d.ts +17 -0
  85. package/dist/components/assistant/xertica-assistant/parts/AssistantFeedbackDialog.d.ts +19 -0
  86. package/dist/components/assistant/xertica-assistant/parts/AssistantHeader.d.ts +11 -0
  87. package/dist/components/assistant/xertica-assistant/parts/AssistantMessageBubble.d.ts +29 -0
  88. package/dist/components/assistant/xertica-assistant/parts/AssistantTabBar.d.ts +13 -0
  89. package/dist/components/assistant/xertica-assistant/parts/AssistantTypingIndicator.d.ts +4 -0
  90. package/dist/components/assistant/xertica-assistant/parts/AssistantWelcomeScreen.d.ts +17 -0
  91. package/dist/components/assistant/xertica-assistant/parts/index.d.ts +16 -0
  92. package/dist/components/assistant/xertica-assistant/types.d.ts +106 -0
  93. package/dist/components/assistant/xertica-assistant/use-assistant.d.ts +125 -0
  94. package/dist/components/assistant/xertica-assistant/xertica-assistant.d.ts +8 -97
  95. package/dist/components/hooks/index.d.ts +3 -0
  96. package/dist/components/hooks/use-layout-shortcuts.d.ts +22 -0
  97. package/dist/components/layout/sidebar/index.d.ts +2 -0
  98. package/dist/components/layout/sidebar/sidebar.d.ts +80 -0
  99. package/dist/components/layout/sidebar/use-sidebar.d.ts +22 -0
  100. package/dist/components/media/audio-player/AudioPlayer.d.ts +4 -1
  101. package/dist/components/media/audio-player/use-audio-player.d.ts +72 -0
  102. package/dist/components/shared/CustomTooltipContent.d.ts +20 -0
  103. package/dist/components/shared/layout-constants.d.ts +1 -1
  104. package/dist/components/ui/alert/alert.d.ts +1 -1
  105. package/dist/components/ui/badge/badge.d.ts +1 -1
  106. package/dist/components/ui/button/button.d.ts +2 -2
  107. package/dist/components/ui/chart/chart.d.ts +162 -5
  108. package/dist/components/ui/file-upload/file-upload.d.ts +2 -0
  109. package/dist/components/ui/file-upload/index.d.ts +1 -0
  110. package/dist/components/ui/file-upload/use-file-upload.d.ts +49 -0
  111. package/dist/components/ui/pagination/index.d.ts +2 -0
  112. package/dist/components/ui/pagination/use-pagination.d.ts +78 -0
  113. package/dist/components/ui/rich-text-editor/index.d.ts +2 -0
  114. package/dist/components/ui/rich-text-editor/use-rich-text-editor.d.ts +107 -0
  115. package/dist/components/ui/stepper/index.d.ts +3 -1
  116. package/dist/components/ui/stepper/stepper.d.ts +2 -2
  117. package/dist/components/ui/stepper/use-stepper.d.ts +60 -0
  118. package/dist/components/ui/tree-view/index.d.ts +4 -1
  119. package/dist/components/ui/tree-view/tree-view.d.ts +4 -6
  120. package/dist/components/ui/tree-view/use-tree-view.d.ts +60 -0
  121. package/dist/contexts/AssistenteContext.d.ts +10 -49
  122. package/dist/hooks.cjs.js +30 -10
  123. package/dist/hooks.es.js +25 -4
  124. package/dist/index.cjs.js +20 -9
  125. package/dist/index.es.js +38 -27
  126. package/dist/layout.cjs.js +82 -1
  127. package/dist/layout.es.js +83 -2
  128. package/dist/media.cjs.js +1 -1
  129. package/dist/media.es.js +1 -1
  130. package/dist/pages.cjs.js +1 -1
  131. package/dist/pages.es.js +1 -1
  132. package/dist/rich-text-editor-BmsjY03B.js +2949 -0
  133. package/dist/rich-text-editor-GS2kpTAK.cjs +2966 -0
  134. package/dist/sidebar-CVUGHOS_.cjs +756 -0
  135. package/dist/sidebar-CmvwjnVb.js +757 -0
  136. package/dist/ui.cjs.js +12 -2
  137. package/dist/ui.es.js +24 -14
  138. package/dist/use-audio-player-Bkh23vQ3.js +177 -0
  139. package/dist/use-audio-player-Dn1NR9xN.cjs +176 -0
  140. package/dist/utils/color-utils.d.ts +51 -0
  141. package/dist/xertica-assistant-BMqdyRVi.js +2082 -0
  142. package/dist/xertica-assistant-Bj3vBCq_.cjs +2081 -0
  143. package/dist/xertica-ui.css +1 -1
  144. package/docs/ai-usage.md +28 -10
  145. package/docs/architecture-improvements.md +463 -0
  146. package/docs/architecture.md +77 -1
  147. package/docs/components/assistant-chart.md +1 -1
  148. package/docs/components/assistant.md +159 -0
  149. package/docs/components/audio-player.md +46 -0
  150. package/docs/components/branding.md +251 -0
  151. package/docs/components/chart.md +354 -39
  152. package/docs/components/code-block.md +108 -0
  153. package/docs/components/file-upload.md +119 -2
  154. package/docs/components/formatted-document.md +113 -0
  155. package/docs/components/hooks.md +430 -0
  156. package/docs/components/image-with-fallback.md +106 -0
  157. package/docs/components/map-layers.md +140 -0
  158. package/docs/components/modern-chat-input.md +163 -0
  159. package/docs/components/pages.md +351 -0
  160. package/docs/components/pagination.md +187 -0
  161. package/docs/components/rich-text-editor.md +164 -0
  162. package/docs/components/sidebar.md +153 -4
  163. package/docs/components/stepper.md +157 -12
  164. package/docs/components/tree-view.md +164 -6
  165. package/docs/doc-audit.md +223 -0
  166. package/docs/getting-started.md +155 -1
  167. package/docs/guidelines.md +14 -8
  168. package/docs/layout.md +2 -2
  169. package/docs/llms.md +29 -9
  170. package/docs/patterns/detail-page.md +276 -0
  171. package/docs/patterns/settings.md +346 -0
  172. package/docs/patterns/wizard.md +217 -0
  173. package/guidelines/Guidelines.md +5 -3
  174. package/llms.txt +1 -1
  175. package/package.json +10 -10
  176. package/styles/xertica/tokens.css +41 -12
  177. package/templates/CLAUDE.md +16 -6
  178. package/templates/guidelines/Guidelines.md +16 -4
  179. package/templates/package.json +3 -3
  180. package/templates/src/styles/xertica/tokens.css +39 -10
  181. package/utils/color-utils.ts +72 -0
@@ -0,0 +1,106 @@
1
+ # ImageWithFallback
2
+
3
+ A drop-in replacement for the native `<img>` element that gracefully handles broken or missing image URLs by displaying a placeholder SVG instead of a broken image icon.
4
+
5
+ ---
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { ImageWithFallback } from 'xertica-ui';
11
+ // or from the figma subpath (internal)
12
+ import { ImageWithFallback } from 'xertica-ui/ui';
13
+ ```
14
+
15
+ ---
16
+
17
+ ## Basic Usage
18
+
19
+ ```tsx
20
+ <ImageWithFallback
21
+ src="https://example.com/photo.jpg"
22
+ alt="User profile photo"
23
+ className="w-32 h-32 rounded-lg object-cover"
24
+ />
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Props
30
+
31
+ `ImageWithFallback` accepts all standard HTML `<img>` attributes:
32
+
33
+ | Prop | Type | Description |
34
+ |---|---|---|
35
+ | `src` | `string` | Image URL. If this fails to load, the fallback placeholder is shown. |
36
+ | `alt` | `string` | Accessible alternative text (required for accessibility) |
37
+ | `className` | `string` | CSS classes applied to both the `<img>` and the fallback container |
38
+ | `style` | `CSSProperties` | Inline styles applied to both states |
39
+ | `...rest` | `ImgHTMLAttributes` | All other standard `<img>` attributes (`width`, `height`, `loading`, etc.) |
40
+
41
+ ---
42
+
43
+ ## Behavior
44
+
45
+ 1. **Normal state**: Renders a standard `<img>` element with the provided `src`.
46
+ 2. **Error state**: When the image fails to load (`onError` fires), the component switches to a fallback `<div>` containing a centered placeholder SVG (a simple broken-image icon).
47
+ 3. **Fallback container**: The fallback `<div>` uses `bg-gray-100` and inherits the same `className` and `style` as the original image, so it maintains the same dimensions and shape.
48
+ 4. **Original URL preserved**: The fallback `<img>` stores the original URL in `data-original-url` for debugging purposes.
49
+
50
+ ---
51
+
52
+ ## Usage Examples
53
+
54
+ ### Hero Image with Fallback
55
+
56
+ ```tsx
57
+ <ImageWithFallback
58
+ src={article.heroImageUrl}
59
+ alt={article.title}
60
+ className="w-full h-48 object-cover rounded-t-lg"
61
+ />
62
+ ```
63
+
64
+ ### User Avatar with Fallback
65
+
66
+ ```tsx
67
+ <ImageWithFallback
68
+ src={user.avatarUrl}
69
+ alt={`${user.name} avatar`}
70
+ className="w-10 h-10 rounded-full object-cover"
71
+ />
72
+ ```
73
+
74
+ > **Note**: For user avatars, prefer the `<Avatar>` component which has built-in fallback support via `<AvatarFallback>` (shows initials). Use `ImageWithFallback` for non-avatar images.
75
+
76
+ ### Lazy Loading
77
+
78
+ ```tsx
79
+ <ImageWithFallback
80
+ src={product.imageUrl}
81
+ alt={product.name}
82
+ loading="lazy"
83
+ className="w-full aspect-square object-contain"
84
+ />
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Comparison: `ImageWithFallback` vs `Avatar`
90
+
91
+ | Feature | `ImageWithFallback` | `Avatar` |
92
+ |---|---|---|
93
+ | Fallback type | SVG placeholder icon | Text initials |
94
+ | Use case | General images, hero images, thumbnails | User profile pictures |
95
+ | Shape | Any (controlled by `className`) | Circle (default) |
96
+ | Import | `xertica-ui/ui` | `xertica-ui/ui` |
97
+
98
+ ---
99
+
100
+ ## AI Rules
101
+
102
+ > [!IMPORTANT]
103
+ > - **Always provide `alt`**: The `alt` attribute is required for accessibility. Never omit it. Use an empty string (`alt=""`) only for purely decorative images.
104
+ > - **Use for external images**: Use `ImageWithFallback` whenever the image URL comes from an external source (API, user upload, CMS) that may be unavailable. For static local assets, a regular `<img>` is acceptable.
105
+ > - **Do not use for avatars**: For user profile pictures, use the `<Avatar>` + `<AvatarFallback>` pattern instead — it shows initials which is more informative than a broken-image icon.
106
+ > - **Maintain dimensions in fallback**: The fallback container inherits `className` and `style`, so always set explicit dimensions (via Tailwind classes like `w-32 h-32` or inline styles) to prevent layout shift when the fallback renders.
@@ -0,0 +1,140 @@
1
+ # MapLayers / useMapLayers
2
+
3
+ A hook for managing Google Maps native overlay layers (traffic, transit, bicycling) on a map instance. Used internally by the `Map` component via its `layers` prop.
4
+
5
+ ---
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { useMapLayers } from 'xertica-ui/ui';
11
+ // or
12
+ import { useMapLayers, MapLayersConfig } from 'xertica-ui';
13
+ ```
14
+
15
+ ---
16
+
17
+ ## `useMapLayers`
18
+
19
+ A React hook that attaches and detaches Google Maps overlay layers reactively based on a configuration object.
20
+
21
+ ### Signature
22
+
23
+ ```tsx
24
+ function useMapLayers(
25
+ map: google.maps.Map | null,
26
+ layers: MapLayersConfig
27
+ ): void
28
+ ```
29
+
30
+ ### Parameters
31
+
32
+ | Parameter | Type | Description |
33
+ |---|---|---|
34
+ | `map` | `google.maps.Map \| null` | The Google Maps instance to attach layers to. Pass `null` to skip (layers are not rendered). |
35
+ | `layers` | `MapLayersConfig` | Configuration object specifying which layers to display |
36
+
37
+ ### `MapLayersConfig`
38
+
39
+ ```tsx
40
+ interface MapLayersConfig {
41
+ traffic?: boolean; // Real-time traffic overlay
42
+ transit?: boolean; // Public transit routes overlay
43
+ bicycling?: boolean; // Bicycle route overlay
44
+ }
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Available Layers
50
+
51
+ | Layer | Key | Description |
52
+ |---|---|---|
53
+ | Traffic | `traffic` | Real-time traffic conditions with color-coded road segments |
54
+ | Transit | `transit` | Public transit routes (bus, metro, train) |
55
+ | Bicycling | `bicycling` | Dedicated bicycle lanes and paths |
56
+
57
+ ---
58
+
59
+ ## Usage
60
+
61
+ ### Standalone Hook
62
+
63
+ ```tsx
64
+ import { useMapLayers } from 'xertica-ui/ui';
65
+
66
+ function MapWithLayers() {
67
+ const [mapInstance, setMapInstance] = useState<google.maps.Map | null>(null);
68
+ const [showTraffic, setShowTraffic] = useState(false);
69
+ const [showTransit, setShowTransit] = useState(false);
70
+
71
+ useMapLayers(mapInstance, {
72
+ traffic: showTraffic,
73
+ transit: showTransit,
74
+ });
75
+
76
+ return (
77
+ <div>
78
+ <label>
79
+ <input
80
+ type="checkbox"
81
+ checked={showTraffic}
82
+ onChange={e => setShowTraffic(e.target.checked)}
83
+ />
84
+ Traffic
85
+ </label>
86
+ {/* map container */}
87
+ </div>
88
+ );
89
+ }
90
+ ```
91
+
92
+ ### Via `Map` Component (Recommended)
93
+
94
+ The `Map` component accepts a `layers` prop that internally uses `useMapLayers`:
95
+
96
+ ```tsx
97
+ import { Map } from 'xertica-ui/ui';
98
+
99
+ <Map
100
+ center={{ lat: -23.5505, lng: -46.6333 }}
101
+ zoom={12}
102
+ layers={{
103
+ traffic: true,
104
+ transit: false,
105
+ bicycling: false,
106
+ }}
107
+ />
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Behavior
113
+
114
+ - **Reactive**: Layers are added or removed automatically when the `layers` config changes.
115
+ - **Cleanup**: Each layer is removed from the map on component unmount (via `useEffect` cleanup).
116
+ - **Null-safe**: If `map` is `null`, the hook does nothing. This is safe to use before the map instance is ready.
117
+ - **Singleton layers**: Each layer type is created once and reused (stored in refs). Toggling a layer on/off does not create new instances.
118
+
119
+ ---
120
+
121
+ ## Prerequisites
122
+
123
+ The Google Maps JavaScript API must be loaded before using this hook. Use `GoogleMapsLoader` or `XerticaProvider` with a `googleMapsApiKey`:
124
+
125
+ ```tsx
126
+ import { XerticaProvider } from 'xertica-ui/brand';
127
+
128
+ <XerticaProvider googleMapsApiKey="YOUR_API_KEY">
129
+ <App />
130
+ </XerticaProvider>
131
+ ```
132
+
133
+ ---
134
+
135
+ ## AI Rules
136
+
137
+ > [!IMPORTANT]
138
+ > - **Use via `Map` component when possible**: The `Map` component's `layers` prop is the recommended way to enable overlays. Use `useMapLayers` directly only when building a custom map integration.
139
+ > - **Requires Google Maps API**: This hook uses `google.maps.TrafficLayer`, `google.maps.TransitLayer`, and `google.maps.BicyclingLayer`. These are only available after the Maps JavaScript API is loaded.
140
+ > - **Pass `null` safely**: If the map instance is not yet available, pass `null` as the first argument. The hook will skip all operations until a valid map is provided.
@@ -0,0 +1,163 @@
1
+ # ModernChatInput
2
+
3
+ An advanced floating chat input with rich action chips, voice recording simulation, and file attachment support. Used as the primary input interface inside `XerticaAssistant`.
4
+
5
+ ---
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { ModernChatInput } from 'xertica-ui/assistant';
11
+ ```
12
+
13
+ ---
14
+
15
+ ## Basic Usage
16
+
17
+ ```tsx
18
+ const [message, setMessage] = useState('');
19
+
20
+ <ModernChatInput
21
+ value={message}
22
+ onChange={setMessage}
23
+ onSubmit={() => {
24
+ console.log('Sending:', message);
25
+ setMessage('');
26
+ }}
27
+ />
28
+ ```
29
+
30
+ ---
31
+
32
+ ## Props
33
+
34
+ | Prop | Type | Default | Description |
35
+ |---|---|---|---|
36
+ | `value` | `string` | _(required)_ | Current input text value |
37
+ | `onChange` | `(value: string) => void` | _(required)_ | Callback fired on every keystroke |
38
+ | `onSubmit` | `(action?: ActionType) => void` | _(required)_ | Callback fired when user submits (Enter key or send button) |
39
+ | `placeholder` | `string` | `'Mande uma mensagem para o Xertica'` | Input placeholder text |
40
+ | `disabled` | `boolean` | `false` | Disables the input and all action buttons |
41
+ | `onFileUpload` | `() => void` | — | Callback for the file attachment button |
42
+ | `onAudioUpload` | `() => void` | — | Callback for the audio upload button |
43
+ | `onVoiceRecording` | `(transcript: string) => void` | — | Callback fired when voice recording finishes |
44
+ | `isFullPage` | `boolean` | `false` | Adjusts layout for full-page assistant view |
45
+ | `enableAudioInput` | `boolean` | `true` | Shows/hides the voice recording button |
46
+ | `enableFileAttachment` | `boolean` | `true` | Shows/hides the file attachment button |
47
+ | `enableDocumentCreation` | `boolean` | `true` | Shows/hides the "Create document" action chip |
48
+ | `enablePodcastGeneration` | `boolean` | `true` | Shows/hides the "Generate podcast" action chip |
49
+ | `enableSearch` | `boolean` | `true` | Shows/hides the "Search" action chip |
50
+
51
+ ---
52
+
53
+ ## `ActionType`
54
+
55
+ The `onSubmit` callback receives an optional `ActionType` parameter indicating which special action was triggered:
56
+
57
+ ```tsx
58
+ type ActionType = 'document' | 'podcast' | 'search' | null;
59
+ ```
60
+
61
+ | Value | Trigger | Description |
62
+ |---|---|---|
63
+ | `null` | Enter key or send button | Standard text message |
64
+ | `'document'` | "Create document" chip | Triggers document generation workflow |
65
+ | `'podcast'` | "Generate podcast" chip | Triggers audio podcast generation |
66
+ | `'search'` | "Search" chip | Triggers knowledge base search |
67
+
68
+ ### Handling Actions
69
+
70
+ ```tsx
71
+ <ModernChatInput
72
+ value={message}
73
+ onChange={setMessage}
74
+ onSubmit={(action) => {
75
+ if (action === 'document') {
76
+ // trigger document generation
77
+ } else if (action === 'podcast') {
78
+ // trigger podcast generation
79
+ } else if (action === 'search') {
80
+ // trigger search
81
+ } else {
82
+ // send regular message
83
+ }
84
+ setMessage('');
85
+ }}
86
+ />
87
+ ```
88
+
89
+ ---
90
+
91
+ ## Features
92
+
93
+ ### Auto-Resizing Textarea
94
+
95
+ The input grows vertically as the user types, up to a maximum height of 100px. Beyond that, it becomes scrollable.
96
+
97
+ ### Action Chips
98
+
99
+ A `+` button opens a popover with quick-action chips:
100
+ - **Document** (`FileText` icon) — triggers `onSubmit('document')`
101
+ - **Podcast** (`Radio` icon) — triggers `onSubmit('podcast')`
102
+ - **Search** (`Search` icon) — triggers `onSubmit('search')`
103
+
104
+ Each chip can be individually disabled via props.
105
+
106
+ ### Voice Recording (Simulated)
107
+
108
+ When `enableAudioInput={true}`, a microphone button is shown. Clicking it:
109
+ 1. Shows a recording indicator with a pulsing animation
110
+ 2. After 3 seconds, calls `onVoiceRecording` with a simulated transcript string
111
+ 3. Returns to idle state
112
+
113
+ > **Note**: Voice recording is simulated — it does not use the browser's MediaRecorder API. The transcript returned is a placeholder string for UI demonstration purposes.
114
+
115
+ ### Keyboard Shortcuts
116
+
117
+ - **Enter** — submits the message
118
+ - **Shift+Enter** — inserts a newline (multi-line input)
119
+
120
+ ---
121
+
122
+ ## Usage with XerticaAssistant
123
+
124
+ `ModernChatInput` is used internally by `XerticaAssistant`. You typically do not need to use it directly unless building a custom chat interface:
125
+
126
+ ```tsx
127
+ import { ModernChatInput } from 'xertica-ui/assistant';
128
+ import { useAssistant } from 'xertica-ui/assistant'; // internal hook
129
+
130
+ function CustomChatInterface() {
131
+ const [message, setMessage] = useState('');
132
+
133
+ const handleSubmit = (action?: ActionType) => {
134
+ // handle message or action
135
+ setMessage('');
136
+ };
137
+
138
+ return (
139
+ <div className="flex flex-col h-screen">
140
+ <div className="flex-1 overflow-y-auto">
141
+ {/* messages */}
142
+ </div>
143
+ <ModernChatInput
144
+ value={message}
145
+ onChange={setMessage}
146
+ onSubmit={handleSubmit}
147
+ isFullPage={true}
148
+ />
149
+ </div>
150
+ );
151
+ }
152
+ ```
153
+
154
+ ---
155
+
156
+ ## AI Rules
157
+
158
+ > [!IMPORTANT]
159
+ > - **Controlled component**: Always provide both `value` and `onChange`. This is a controlled input — do not use it uncontrolled.
160
+ > - **Clear after submit**: Call `setMessage('')` (or equivalent) inside `onSubmit` to reset the input after sending.
161
+ > - **`isFullPage` for page layouts**: Set `isFullPage={true}` when using the input in a full-page assistant view (not the sidebar panel). This adjusts padding and max-width.
162
+ > - **Voice recording is simulated**: Do not rely on `onVoiceRecording` for real speech-to-text. Integrate a real STT service and pass the transcript via `onChange` instead.
163
+ > - **Disable unused actions**: If your application does not support document generation or podcasts, set `enableDocumentCreation={false}` and `enablePodcastGeneration={false}` to avoid confusing users.