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,72 @@
1
+ export interface UseAudioPlayerProps {
2
+ /** Source URL of the audio file */
3
+ src?: string;
4
+ /** Whether to play automatically on mount */
5
+ autoPlay?: boolean;
6
+ /** Initial playback time in seconds */
7
+ initialTime?: number;
8
+ /** Total duration in seconds (optional — loaded from metadata if not provided) */
9
+ initialDuration?: number;
10
+ /** Display variant: 'card' (standard floating) or 'bar' (global fixed bar) */
11
+ variant?: 'card' | 'bar';
12
+ /** Whether the player is currently visible and open (only for 'bar' variant) */
13
+ isOpen?: boolean;
14
+ /** Whether the player should automatically float when scrolled out of view */
15
+ enableAutoFloat?: boolean;
16
+ /** Callback fired when user manually closes the floating player */
17
+ onCloseFloating?: () => void;
18
+ }
19
+ export interface UseAudioPlayerReturn {
20
+ audioRef: React.RefObject<HTMLAudioElement>;
21
+ containerRef: React.RefObject<HTMLDivElement>;
22
+ isPlaying: boolean;
23
+ currentTime: number;
24
+ duration: number;
25
+ volume: number;
26
+ isMuted: boolean;
27
+ playbackSpeed: number;
28
+ isFloating: boolean;
29
+ isManualFloating: boolean;
30
+ isVisible: boolean;
31
+ isMobile: boolean;
32
+ enableAutoFloatLocal: boolean;
33
+ sidebarExpanded: boolean;
34
+ sidebarWidth: number;
35
+ assistenteExpanded: boolean;
36
+ togglePlay: () => void;
37
+ toggleMute: () => void;
38
+ handleSeek: (value: number[]) => void;
39
+ handleVolumeChange: (value: number[]) => void;
40
+ handleSetFloating: (floating: boolean) => void;
41
+ handleEnableManualFloat: () => void;
42
+ setPlaybackSpeed: (speed: number) => void;
43
+ resetAudio: () => void;
44
+ onPlay: () => void;
45
+ onPause: () => void;
46
+ onEnded: () => void;
47
+ onTimeUpdate: (e: React.SyntheticEvent<HTMLAudioElement>) => void;
48
+ onLoadedMetadata: (e: React.SyntheticEvent<HTMLAudioElement>) => void;
49
+ formatTime: (time: number) => string;
50
+ }
51
+ /**
52
+ * `useAudioPlayer` — Headless hook for the AudioPlayer component.
53
+ *
54
+ * Encapsulates all state management and side effects for audio playback,
55
+ * including auto-float on scroll, mobile detection, and layout context integration.
56
+ *
57
+ * @example
58
+ * ```tsx
59
+ * import { useAudioPlayer } from './use-audio-player';
60
+ *
61
+ * function MyCustomPlayer({ src }: { src: string }) {
62
+ * const { isPlaying, togglePlay, formatTime, currentTime, duration } = useAudioPlayer({ src });
63
+ * return (
64
+ * <div>
65
+ * <button onClick={togglePlay}>{isPlaying ? 'Pause' : 'Play'}</button>
66
+ * <span>{formatTime(currentTime)} / {formatTime(duration)}</span>
67
+ * </div>
68
+ * );
69
+ * }
70
+ * ```
71
+ */
72
+ export declare function useAudioPlayer({ src, autoPlay, initialTime, initialDuration, variant, isOpen, enableAutoFloat, onCloseFloating, }?: UseAudioPlayerProps): UseAudioPlayerReturn;
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
3
+ /**
4
+ * CustomTooltipContent — Tooltip com portal e seta estilo sidebar/assistente.
5
+ *
6
+ * Substitui os componentes `SidebarTooltipContent` e `AssistantTooltipContent`
7
+ * que eram definidos inline em `sidebar.tsx` e `xertica-assistant.tsx`.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * import { Tooltip, TooltipTrigger } from '../ui/tooltip';
12
+ * import { CustomTooltipContent } from '../shared/CustomTooltipContent';
13
+ *
14
+ * <Tooltip>
15
+ * <TooltipTrigger asChild><Button>Hover me</Button></TooltipTrigger>
16
+ * <CustomTooltipContent side="right">Minha dica</CustomTooltipContent>
17
+ * </Tooltip>
18
+ * ```
19
+ */
20
+ export declare function CustomTooltipContent({ className, sideOffset, children, ...props }: React.ComponentProps<typeof TooltipPrimitive.Content>): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  /** Width of the sidebar when expanded (Desktop) */
2
- export declare const SIDEBAR_EXPANDED_WIDTH = 256;
2
+ export declare const SIDEBAR_EXPANDED_WIDTH = 280;
3
3
  /** Width of the sidebar when collapsed (Desktop) */
4
4
  export declare const SIDEBAR_COLLAPSED_WIDTH = 80;
5
5
  /** Width of the assistant panel when expanded (Desktop) */
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const alertVariants: (props?: ({
4
- variant?: "default" | "success" | "info" | "warning" | "destructive" | null | undefined;
4
+ variant?: "default" | "destructive" | "success" | "info" | "warning" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  export interface AlertProps extends React.ComponentProps<"div">, VariantProps<typeof alertVariants> {
7
7
  /** Custom icon. If not provided, a default semantic icon for the variant is used. Set to null to hide. */
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const badgeVariants: (props?: ({
4
- variant?: "default" | "success" | "info" | "warning" | "destructive" | "outline" | "secondary" | null | undefined;
4
+ variant?: "default" | "destructive" | "outline" | "secondary" | "success" | "info" | "warning" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  /**
7
7
  * Informational status label for tables, lists, and counts.
@@ -1,8 +1,8 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const buttonVariants: (props?: ({
4
- variant?: "default" | "success" | "info" | "warning" | "destructive" | "link" | "outline" | "secondary" | "ghost" | null | undefined;
5
- size?: "default" | "icon" | "sm" | "lg" | null | undefined;
4
+ variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "success" | "info" | "warning" | null | undefined;
5
+ size?: "default" | "sm" | "lg" | "icon" | null | undefined;
6
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
7
  /**
8
8
  * Props for the Button component.
@@ -34,6 +34,8 @@ export type ChartPeriod = {
34
34
  label: string;
35
35
  };
36
36
  export type ChartBarSize = "sm" | "md" | "lg" | "xl" | number;
37
+ /** Curve interpolation type for line and area charts */
38
+ export type ChartCurveType = "monotone" | "linear" | "step" | "stepBefore" | "stepAfter" | "natural" | "basis";
37
39
  type ChartValueFormatter = (value: number | string) => string;
38
40
  export type ChartErrorState = boolean | string | Error | React.ReactNode;
39
41
  export type ChartStateProps = {
@@ -113,9 +115,11 @@ export interface DashboardLineChartProps extends Omit<React.ComponentProps<typeo
113
115
  showDots?: boolean;
114
116
  showGrid?: boolean;
115
117
  showLegend?: boolean;
118
+ curveType?: ChartCurveType;
119
+ strokeWidth?: number;
116
120
  valueFormatter?: ChartValueFormatter;
117
121
  }
118
- declare function DashboardLineChart({ data, config, indexKey, series, colors, showDots, showGrid, showLegend, valueFormatter, isLoading, error, onRetry, retryLabel, emptyTitle, emptyDescription, errorTitle, errorDescription, loadingLabel, stateClassName, className, ...props }: DashboardLineChartProps): import("react/jsx-runtime").JSX.Element;
122
+ declare function DashboardLineChart({ data, config, indexKey, series, colors, showDots, showGrid, showLegend, curveType, strokeWidth, valueFormatter, isLoading, error, onRetry, retryLabel, emptyTitle, emptyDescription, errorTitle, errorDescription, loadingLabel, stateClassName, className, ...props }: DashboardLineChartProps): import("react/jsx-runtime").JSX.Element;
119
123
  export interface HorizontalBarChartProps extends Omit<React.ComponentProps<typeof ChartContainer>, "children">, ChartStateProps {
120
124
  data: DashboardChartDatum[];
121
125
  indexKey?: string;
@@ -140,9 +144,13 @@ export interface InteractiveTimeSeriesChartProps extends Omit<React.ComponentPro
140
144
  filterData?: (data: DashboardChartDatum[], period: string) => DashboardChartDatum[];
141
145
  showGrid?: boolean;
142
146
  showLegend?: boolean;
147
+ showDots?: boolean;
148
+ gradientFill?: boolean;
149
+ curveType?: ChartCurveType;
150
+ strokeWidth?: number;
143
151
  valueFormatter?: ChartValueFormatter;
144
152
  }
145
- declare function InteractiveTimeSeriesChart({ data, config, indexKey, series, colors, periods, defaultPeriod, defaultSeries, filterData, showGrid, showLegend, valueFormatter, isLoading, error, onRetry, retryLabel, emptyTitle, emptyDescription, errorTitle, errorDescription, loadingLabel, stateClassName, className, ...props }: InteractiveTimeSeriesChartProps): import("react/jsx-runtime").JSX.Element;
153
+ declare function InteractiveTimeSeriesChart({ data, config, indexKey, series, colors, periods, defaultPeriod, defaultSeries, filterData, showGrid, showLegend, showDots, gradientFill, curveType, strokeWidth, valueFormatter, isLoading, error, onRetry, retryLabel, emptyTitle, emptyDescription, errorTitle, errorDescription, loadingLabel, stateClassName, className, ...props }: InteractiveTimeSeriesChartProps): import("react/jsx-runtime").JSX.Element;
146
154
  export interface ComboMetricChartProps extends Omit<React.ComponentProps<typeof ChartContainer>, "children">, ChartStateProps {
147
155
  data: DashboardChartDatum[];
148
156
  indexKey?: string;
@@ -151,9 +159,11 @@ export interface ComboMetricChartProps extends Omit<React.ComponentProps<typeof
151
159
  barSize?: ChartBarSize;
152
160
  showGrid?: boolean;
153
161
  showLegend?: boolean;
162
+ gradientFill?: boolean;
163
+ curveType?: ChartCurveType;
154
164
  valueFormatter?: ChartValueFormatter;
155
165
  }
156
- declare function ComboMetricChart({ data, config, indexKey, series, colors, barSize, showGrid, showLegend, valueFormatter, isLoading, error, onRetry, retryLabel, emptyTitle, emptyDescription, errorTitle, errorDescription, loadingLabel, stateClassName, className, ...props }: ComboMetricChartProps): import("react/jsx-runtime").JSX.Element;
166
+ declare function ComboMetricChart({ data, config, indexKey, series, colors, barSize, showGrid, showLegend, gradientFill, curveType, valueFormatter, isLoading, error, onRetry, retryLabel, emptyTitle, emptyDescription, errorTitle, errorDescription, loadingLabel, stateClassName, className, ...props }: ComboMetricChartProps): import("react/jsx-runtime").JSX.Element;
157
167
  export interface DonutBreakdownChartProps extends Omit<React.ComponentProps<typeof ChartContainer>, "children">, ChartStateProps {
158
168
  data: DashboardChartDatum[];
159
169
  nameKey?: string;
@@ -162,6 +172,153 @@ export interface DonutBreakdownChartProps extends Omit<React.ComponentProps<type
162
172
  centerLabel?: React.ReactNode;
163
173
  centerValue?: React.ReactNode;
164
174
  showLegend?: boolean;
175
+ /** Inner radius as percentage string (e.g. "58%") or number */
176
+ innerRadius?: string | number;
177
+ /** Outer radius as percentage string (e.g. "82%") or number */
178
+ outerRadius?: string | number;
179
+ }
180
+ declare function DonutBreakdownChart({ data, config, nameKey, valueKey, colors, centerLabel, centerValue, showLegend, innerRadius, outerRadius, isLoading, error, onRetry, retryLabel, emptyTitle, emptyDescription, errorTitle, errorDescription, loadingLabel, stateClassName, className, ...props }: DonutBreakdownChartProps): import("react/jsx-runtime").JSX.Element;
181
+ export interface SparklineChartProps {
182
+ /** Data array — each item must have the `dataKey` field */
183
+ data: DashboardChartDatum[];
184
+ /** Key to plot on the Y axis */
185
+ dataKey: string;
186
+ /** Color for the line/area — defaults to `var(--chart-1)` */
187
+ color?: string;
188
+ /** Show filled area under the line */
189
+ filled?: boolean;
190
+ /** Show the last data point as a dot */
191
+ showEndDot?: boolean;
192
+ /** Curve interpolation type */
193
+ curveType?: ChartCurveType;
194
+ /** Stroke width */
195
+ strokeWidth?: number;
196
+ className?: string;
197
+ }
198
+ /**
199
+ * Minimal inline sparkline chart — no axes, no grid, no tooltip.
200
+ * Ideal for embedding inside stat cards or table cells.
201
+ *
202
+ * @ai-rules
203
+ * - Use `filled` for area-style sparklines.
204
+ * - Keep `className` height small (e.g. `h-12` or `h-16`).
205
+ * - Do NOT wrap in `ChartCard` — it is designed to be inline.
206
+ */
207
+ declare function SparklineChart({ data, dataKey, color, filled, showEndDot, curveType, strokeWidth, className, }: SparklineChartProps): import("react/jsx-runtime").JSX.Element;
208
+ export interface RadarMetricChartProps extends ChartStateProps {
209
+ /** Data array — each item is one axis point on the radar */
210
+ data: DashboardChartDatum[];
211
+ /** Key in each datum used as the axis label */
212
+ labelKey: string;
213
+ /**
214
+ * Series to render. Each entry maps to one `<Radar>` element.
215
+ * Use a single entry for a simple radar, multiple for comparison.
216
+ */
217
+ series: DashboardChartSeries[];
218
+ /** Override colors per series key or as an ordered array */
219
+ colors?: DashboardChartColors;
220
+ /** Fill the radar polygon (default: true) */
221
+ filled?: boolean;
222
+ /** Fill opacity when `filled` is true (default: 0.25) */
223
+ fillOpacity?: number;
224
+ /** Show dots on each axis point (default: false) */
225
+ showDots?: boolean;
226
+ /** Show the polar grid lines (default: true) */
227
+ showGrid?: boolean;
228
+ /** Show the legend (default: true when multiple series) */
229
+ showLegend?: boolean;
230
+ /** Format axis tick values */
231
+ valueFormatter?: ChartValueFormatter;
232
+ className?: string;
233
+ }
234
+ declare function RadarMetricChart({ data, labelKey, series, colors, filled, fillOpacity, showDots, showGrid, showLegend, valueFormatter, isLoading, error, onRetry, retryLabel, emptyTitle, emptyDescription, errorTitle, errorDescription, loadingLabel, stateClassName, className, }: RadarMetricChartProps): import("react/jsx-runtime").JSX.Element;
235
+ export interface PieMetricChartProps extends ChartStateProps {
236
+ /** Data array — each item is one slice */
237
+ data: DashboardChartDatum[];
238
+ /** Key in each datum used as the slice name/label */
239
+ nameKey: string;
240
+ /** Key in each datum used as the slice value */
241
+ valueKey: string;
242
+ /** Override colors as an ordered array or per-name map */
243
+ colors?: DashboardChartColors;
244
+ /** Outer radius of the pie (default: "80%") */
245
+ outerRadius?: number | string;
246
+ /** Inner radius — set > 0 to make a donut (default: 0) */
247
+ innerRadius?: number | string;
248
+ /** Show percentage labels inside/outside each slice (default: false) */
249
+ showLabels?: boolean;
250
+ /** Show the legend (default: true) */
251
+ showLegend?: boolean;
252
+ /**
253
+ * Index of the slice to "explode" (offset outward).
254
+ * Pass -1 or undefined to disable.
255
+ */
256
+ explodeIndex?: number;
257
+ /** Offset distance for the exploded slice in px (default: 12) */
258
+ explodeOffset?: number;
259
+ /** Format tooltip values */
260
+ valueFormatter?: ChartValueFormatter;
261
+ className?: string;
262
+ }
263
+ declare function PieMetricChart({ data, nameKey, valueKey, colors, outerRadius, innerRadius, showLabels, showLegend, explodeIndex, explodeOffset, valueFormatter, isLoading, error, onRetry, retryLabel, emptyTitle, emptyDescription, errorTitle, errorDescription, loadingLabel, stateClassName, className, }: PieMetricChartProps): import("react/jsx-runtime").JSX.Element;
264
+ export interface RadialBarMetricChartProps extends ChartStateProps {
265
+ /**
266
+ * Data array. Each item should have a `name` field (for labels) and
267
+ * the `dataKey` field (for values, 0–100 for percentage-based display).
268
+ */
269
+ data: DashboardChartDatum[];
270
+ /** Key in each datum used as the bar value (default: "value") */
271
+ dataKey?: string;
272
+ /** Key in each datum used as the bar label (default: "name") */
273
+ nameKey?: string;
274
+ /** Override colors as an ordered array or per-name map */
275
+ colors?: DashboardChartColors;
276
+ /** Inner radius of the radial bar (default: "30%") */
277
+ innerRadius?: number | string;
278
+ /** Outer radius of the radial bar (default: "100%") */
279
+ outerRadius?: number | string;
280
+ /** Start angle in degrees (default: 90 — top) */
281
+ startAngle?: number;
282
+ /** End angle in degrees (default: -270 — full circle) */
283
+ endAngle?: number;
284
+ /** Show background track behind each bar (default: true) */
285
+ showBackground?: boolean;
286
+ /** Show the legend (default: true) */
287
+ showLegend?: boolean;
288
+ /** Format tooltip values */
289
+ valueFormatter?: ChartValueFormatter;
290
+ className?: string;
291
+ }
292
+ declare function RadialBarMetricChart({ data, dataKey, nameKey, colors, innerRadius, outerRadius, startAngle, endAngle, showBackground, showLegend, valueFormatter, isLoading, error, onRetry, retryLabel, emptyTitle, emptyDescription, errorTitle, errorDescription, loadingLabel, stateClassName, className, }: RadialBarMetricChartProps): import("react/jsx-runtime").JSX.Element;
293
+ export interface GaugeChartThreshold {
294
+ /** Upper bound of this zone (0–100) */
295
+ value: number;
296
+ /** Color for this zone */
297
+ color: string;
298
+ /** Optional label for this zone */
299
+ label?: string;
300
+ }
301
+ export interface GaugeChartProps {
302
+ /** Current value (must be within [min, max]) */
303
+ value: number;
304
+ /** Minimum value (default: 0) */
305
+ min?: number;
306
+ /** Maximum value (default: 100) */
307
+ max?: number;
308
+ /**
309
+ * Color zones. Each threshold defines the upper bound of a zone.
310
+ * Zones are evaluated in order; the first zone whose `value >= current %`
311
+ * determines the active color.
312
+ * If omitted, uses `--chart-1`.
313
+ */
314
+ thresholds?: GaugeChartThreshold[];
315
+ /** Label shown below the value (e.g. "CPU Usage") */
316
+ label?: React.ReactNode;
317
+ /** Format the center value text (default: shows percentage) */
318
+ valueFormatter?: (value: number, percent: number) => string;
319
+ /** Show the needle indicator (default: true) */
320
+ showNeedle?: boolean;
321
+ className?: string;
165
322
  }
166
- declare function DonutBreakdownChart({ data, config, nameKey, valueKey, colors, centerLabel, centerValue, showLegend, isLoading, error, onRetry, retryLabel, emptyTitle, emptyDescription, errorTitle, errorDescription, loadingLabel, stateClassName, className, ...props }: DonutBreakdownChartProps): import("react/jsx-runtime").JSX.Element;
167
- export { ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, ChartLegendContent, ChartStyle, ChartCard, DashboardBarChart, DashboardLineChart, HorizontalBarChart, InteractiveTimeSeriesChart, ComboMetricChart, DonutBreakdownChart, };
323
+ declare function GaugeChart({ value, min, max, thresholds, label, valueFormatter, showNeedle, className, }: GaugeChartProps): import("react/jsx-runtime").JSX.Element;
324
+ export { ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, ChartLegendContent, ChartStyle, ChartCard, DashboardBarChart, DashboardLineChart, HorizontalBarChart, InteractiveTimeSeriesChart, ComboMetricChart, DonutBreakdownChart, SparklineChart, RadarMetricChart, PieMetricChart, RadialBarMetricChart, GaugeChart, };
@@ -15,6 +15,8 @@ interface FileUploadProps extends Omit<React.InputHTMLAttributes<HTMLInputElemen
15
15
  * for file uploads. Supports click-to-browse and drag-and-drop. Shows a preview
16
16
  * list of selected files with per-file remove buttons.
17
17
  *
18
+ * Headless logic is available via `useFileUpload` for custom drop-zone UIs.
19
+ *
18
20
  * @ai-rules
19
21
  * 1. Use `onFilesChange` to capture the selected files array in your form state.
20
22
  * 2. `maxFiles` defaults to 1 (single file). Set to a higher number for multi-upload.
@@ -1 +1,2 @@
1
1
  export * from './file-upload';
2
+ export * from './use-file-upload';
@@ -0,0 +1,49 @@
1
+ export interface UseFileUploadProps {
2
+ /** Maximum number of files allowed. @default 1 */
3
+ maxFiles?: number;
4
+ /** Maximum file size in bytes. @default 5MB */
5
+ maxSize?: number;
6
+ /** Called with the current accepted file list whenever it changes. */
7
+ onFilesChange?: (files: File[]) => void;
8
+ /** Called when files are rejected due to size or count limits. */
9
+ onError?: (rejectedFiles: File[], reason: 'size' | 'count') => void;
10
+ /** Whether the upload area is disabled. */
11
+ disabled?: boolean;
12
+ }
13
+ export interface UseFileUploadReturn {
14
+ /** Currently accepted files. */
15
+ files: File[];
16
+ /** Whether a drag operation is currently active over the drop zone. */
17
+ dragActive: boolean;
18
+ /** Inline error message, or `null` when there is no error. */
19
+ errorMessage: string | null;
20
+ /** Attach to the hidden `<input type="file">` element. */
21
+ inputRef: React.RefObject<HTMLInputElement>;
22
+ /** Process a `FileList` from any source (input change, drop, paste, etc.). */
23
+ handleFiles: (newFiles: FileList | null) => void;
24
+ /** Drag enter / over / leave handler — attach to all three events. */
25
+ handleDrag: (e: React.DragEvent) => void;
26
+ /** Drop handler — attach to the drop zone element. */
27
+ handleDrop: (e: React.DragEvent) => void;
28
+ /** Input `onChange` handler — attach to the hidden `<input>`. */
29
+ handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
30
+ /** Remove a file by its index in the `files` array. */
31
+ removeFile: (index: number) => void;
32
+ /** Programmatically open the native file picker dialog. */
33
+ openFileDialog: () => void;
34
+ }
35
+ /**
36
+ * Headless hook for drag-and-drop file upload logic.
37
+ *
38
+ * @description
39
+ * Encapsulates all stateful behaviour for a file upload area: file validation
40
+ * (size and count limits), drag-active tracking, error messaging, and the
41
+ * hidden-input ref. Pair with any custom drop-zone UI.
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * const { files, dragActive, errorMessage, inputRef, handleDrag, handleDrop, handleChange, removeFile, openFileDialog } =
46
+ * useFileUpload({ maxFiles: 3, maxSize: 10 * 1024 * 1024 });
47
+ * ```
48
+ */
49
+ export declare function useFileUpload({ maxFiles, maxSize, onFilesChange, onError, disabled, }?: UseFileUploadProps): UseFileUploadReturn;
@@ -1 +1,3 @@
1
1
  export * from './pagination';
2
+ export { usePagination } from './use-pagination';
3
+ export type { PaginationPageItem, UsePaginationProps, UsePaginationReturn } from './use-pagination';
@@ -0,0 +1,78 @@
1
+ /** A page item rendered in the pagination bar. */
2
+ export type PaginationPageItem = {
3
+ type: 'page';
4
+ page: number;
5
+ } | {
6
+ type: 'ellipsis';
7
+ key: string;
8
+ };
9
+ export interface UsePaginationProps {
10
+ /** Total number of items in the data set. */
11
+ totalItems: number;
12
+ /** Number of items per page. @default 10 */
13
+ pageSize?: number;
14
+ /** Initial page (1-indexed). @default 1 */
15
+ initialPage?: number;
16
+ /**
17
+ * Controlled current page (1-indexed).
18
+ * When provided, page state is managed externally via `onPageChange`.
19
+ */
20
+ page?: number;
21
+ /** Called whenever the page changes. */
22
+ onPageChange?: (page: number) => void;
23
+ /**
24
+ * Number of page buttons to show on each side of the current page.
25
+ * @default 1
26
+ */
27
+ siblingCount?: number;
28
+ }
29
+ export interface UsePaginationReturn {
30
+ /** The currently active page (1-indexed). */
31
+ currentPage: number;
32
+ /** Total number of pages. */
33
+ totalPages: number;
34
+ /** Index of the first item on the current page (0-indexed, useful for slicing). */
35
+ startIndex: number;
36
+ /** Index of the last item on the current page (exclusive, useful for slicing). */
37
+ endIndex: number;
38
+ /** Whether there is a previous page available. */
39
+ canGoPrev: boolean;
40
+ /** Whether there is a next page available. */
41
+ canGoNext: boolean;
42
+ /** Whether the current page is the first page. */
43
+ isFirstPage: boolean;
44
+ /** Whether the current page is the last page. */
45
+ isLastPage: boolean;
46
+ /**
47
+ * Ordered list of items to render in the pagination bar.
48
+ * Each item is either a `{ type: 'page', page: number }` or
49
+ * `{ type: 'ellipsis', key: string }`.
50
+ */
51
+ items: PaginationPageItem[];
52
+ /** Navigate to a specific page (1-indexed, clamped to valid range). */
53
+ goTo: (page: number) => void;
54
+ /** Navigate to the next page (no-op if already on the last page). */
55
+ next: () => void;
56
+ /** Navigate to the previous page (no-op if already on the first page). */
57
+ prev: () => void;
58
+ /** Navigate to the first page. */
59
+ first: () => void;
60
+ /** Navigate to the last page. */
61
+ last: () => void;
62
+ }
63
+ /**
64
+ * Headless hook for pagination logic.
65
+ *
66
+ * @description
67
+ * Computes the current page, total pages, slice indices, and the ordered list
68
+ * of page items (numbers + ellipses) to render. Supports both controlled and
69
+ * uncontrolled modes. Pair with any custom pagination UI or with the
70
+ * `<Pagination>` visual components.
71
+ *
72
+ * @example
73
+ * ```tsx
74
+ * const { currentPage, totalPages, items, next, prev, goTo, canGoPrev, canGoNext } =
75
+ * usePagination({ totalItems: 200, pageSize: 20 });
76
+ * ```
77
+ */
78
+ export declare function usePagination({ totalItems, pageSize, initialPage, page: controlledPage, onPageChange, siblingCount, }: UsePaginationProps): UsePaginationReturn;
@@ -1 +1,3 @@
1
1
  export * from './rich-text-editor';
2
+ export { useRichTextEditor } from './use-rich-text-editor';
3
+ export type { UseRichTextEditorProps, UseRichTextEditorReturn, ActiveFormats } from './use-rich-text-editor';
@@ -0,0 +1,107 @@
1
+ export interface ActiveFormats {
2
+ bold: boolean;
3
+ italic: boolean;
4
+ underline: boolean;
5
+ justifyLeft: boolean;
6
+ justifyCenter: boolean;
7
+ justifyRight: boolean;
8
+ insertUnorderedList: boolean;
9
+ insertOrderedList: boolean;
10
+ link: boolean;
11
+ h1: boolean;
12
+ h2: boolean;
13
+ h3: boolean;
14
+ p: boolean;
15
+ }
16
+ export interface UseRichTextEditorProps {
17
+ /** Current HTML value of the editor */
18
+ value: string;
19
+ /** Called whenever the editor content changes */
20
+ onChange?: (value: string) => void;
21
+ }
22
+ export interface UseRichTextEditorReturn {
23
+ /** Attach to the `contenteditable` div */
24
+ editorRef: React.RefObject<HTMLDivElement>;
25
+ /** Attach to the search `<input>` */
26
+ searchInputRef: React.RefObject<HTMLInputElement>;
27
+ /** Attach to the link URL `<input>` */
28
+ linkInputRef: React.RefObject<HTMLInputElement>;
29
+ /** Map of currently active formatting commands */
30
+ activeFormats: ActiveFormats;
31
+ /** Whether the inline search bar is open */
32
+ isSearchOpen: boolean;
33
+ setIsSearchOpen: (open: boolean) => void;
34
+ /** Current search query string */
35
+ searchQuery: string;
36
+ setSearchQuery: (query: string) => void;
37
+ /** Current link URL being edited */
38
+ linkUrl: string;
39
+ setLinkUrl: (url: string) => void;
40
+ /** Whether the link popover is open */
41
+ isLinkOpen: boolean;
42
+ /**
43
+ * True when the popover was opened with a non-collapsed text selection
44
+ * (or with the cursor inside an existing link). Use this to decide whether
45
+ * to show the link-insert form vs. the "select text first" hint.
46
+ */
47
+ hasSavedSelection: boolean;
48
+ /** Word count of the editor content */
49
+ wordCount: number;
50
+ /** Character count of the editor content */
51
+ characterCount: number;
52
+ /** Re-read the current selection and update `activeFormats` */
53
+ updateActiveFormats: () => void;
54
+ /** Execute a `document.execCommand` and sync state */
55
+ execCommand: (command: string, value?: string) => void;
56
+ /** Called on every `input` event of the editor */
57
+ handleInput: () => void;
58
+ /** Search forward or backward for `searchQuery` */
59
+ performSearch: (text: string, backward?: boolean) => void;
60
+ /** Create or update a hyperlink at the current selection */
61
+ handleCreateLink: () => void;
62
+ /** Remove the hyperlink at the current cursor position */
63
+ handleUnlink: () => void;
64
+ /** Handle link popover open/close (saves selection, pre-fills URL) */
65
+ onLinkPopoverOpenChange: (open: boolean) => void;
66
+ }
67
+ /**
68
+ * `useRichTextEditor` — Headless hook for the RichTextEditor component.
69
+ *
70
+ * Encapsulates all state, refs, and DOM-manipulation logic for a
71
+ * `contenteditable`-based rich text editor. Use this hook when you need to
72
+ * build a fully custom editor UI while reusing the same formatting logic as
73
+ * the default `RichTextEditor` component.
74
+ *
75
+ * @example
76
+ * ```tsx
77
+ * import { useRichTextEditor } from 'xertica-ui/ui';
78
+ *
79
+ * function MyEditor({ value, onChange }) {
80
+ * const {
81
+ * editorRef,
82
+ * activeFormats,
83
+ * execCommand,
84
+ * handleInput,
85
+ * wordCount,
86
+ * } = useRichTextEditor({ value, onChange });
87
+ *
88
+ * return (
89
+ * <div>
90
+ * <button
91
+ * onClick={() => execCommand('bold')}
92
+ * style={{ fontWeight: activeFormats.bold ? 'bold' : 'normal' }}
93
+ * >
94
+ * B
95
+ * </button>
96
+ * <div
97
+ * ref={editorRef}
98
+ * contentEditable
99
+ * onInput={handleInput}
100
+ * />
101
+ * <span>{wordCount} words</span>
102
+ * </div>
103
+ * );
104
+ * }
105
+ * ```
106
+ */
107
+ export declare function useRichTextEditor({ value, onChange, }: UseRichTextEditorProps): UseRichTextEditorReturn;
@@ -1 +1,3 @@
1
- export * from './stepper';
1
+ export { Stepper, Step, useStepperContext } from './stepper';
2
+ export { useStepper } from './use-stepper';
3
+ export type { UseStepperProps, UseStepperReturn } from './use-stepper';
@@ -4,7 +4,7 @@ interface StepperContextValue {
4
4
  totalSteps: number;
5
5
  orientation: 'horizontal' | 'vertical';
6
6
  }
7
- declare const useStepper: () => StepperContextValue;
7
+ declare const useStepperContext: () => StepperContextValue;
8
8
  interface StepperProps extends React.HTMLAttributes<HTMLDivElement> {
9
9
  currentStep: number;
10
10
  /** Layout direction. @default "horizontal" */
@@ -33,4 +33,4 @@ interface StepProps extends React.HTMLAttributes<HTMLDivElement> {
33
33
  error?: boolean;
34
34
  }
35
35
  declare const Step: React.ForwardRefExoticComponent<StepProps & React.RefAttributes<HTMLDivElement>>;
36
- export { Stepper, Step, useStepper };
36
+ export { Stepper, Step, useStepperContext };