@hex-core/components 1.6.0 → 1.7.0

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.
@@ -2830,6 +2830,42 @@ declare const spacerVariants: (props?: ({
2830
2830
  export { spacerVariants }
2831
2831
  export { spacerVariants as spacerVariants_alias_1 }
2832
2832
 
2833
+ /**
2834
+ * Renders a mic toggle button wired to the Web Speech API.
2835
+ * @param props - controlled listening state + transcript callback
2836
+ * @returns A button element that toggles speech recognition
2837
+ */
2838
+ declare function SpeechRecognition({ isListening, onListeningChange, onTranscript, onError, lang, continuous, interimResults, startLabel, stopLabel, notSupportedLabel, disabled, className, ...rest }: SpeechRecognitionProps): JSX.Element;
2839
+ export { SpeechRecognition }
2840
+ export { SpeechRecognition as SpeechRecognition_alias_1 }
2841
+
2842
+ declare interface SpeechRecognitionProps extends Omit<React_2.ButtonHTMLAttributes<HTMLButtonElement>, "onError"> {
2843
+ /** Controlled listening state. */
2844
+ isListening: boolean;
2845
+ /** Called when listening starts/stops (user toggle or browser auto-end). */
2846
+ onListeningChange: (listening: boolean) => void;
2847
+ /** Called per transcript chunk. `isFinal` indicates a finalized phrase. */
2848
+ onTranscript: (text: string, isFinal: boolean) => void;
2849
+ /** Called on browser error (e.g. "not-allowed", "no-speech", "network"). */
2850
+ onError?: (error: string, message?: string) => void;
2851
+ /** BCP-47 language tag. Default `"en-US"`. */
2852
+ lang?: string;
2853
+ /** Keep listening across pauses. Default `true`. */
2854
+ continuous?: boolean;
2855
+ /** Emit interim (in-progress) results. Default `true`. */
2856
+ interimResults?: boolean;
2857
+ /** Accessible name when idle. Default `"Start dictation"`. */
2858
+ startLabel?: string;
2859
+ /** Accessible name when listening. Default `"Stop dictation"`. */
2860
+ stopLabel?: string;
2861
+ /** Accessible name + tooltip when the browser lacks the API. */
2862
+ notSupportedLabel?: string;
2863
+ }
2864
+ export { SpeechRecognitionProps }
2865
+ export { SpeechRecognitionProps as SpeechRecognitionProps_alias_1 }
2866
+
2867
+ export declare const speechRecognitionSchema: ComponentSchemaDefinition;
2868
+
2833
2869
  /**
2834
2870
  * Vertical flex flow with token-bound gap. Children stack top-to-bottom.
2835
2871
  * @param props - Stack props including `gap`, `align`, and `justify` variant keys.
package/dist/index.d.ts CHANGED
@@ -298,6 +298,8 @@ export { MessageList } from './_tsup-dts-rollup.js';
298
298
  export { MessageListProps } from './_tsup-dts-rollup.js';
299
299
  export { Composer } from './_tsup-dts-rollup.js';
300
300
  export { ComposerProps } from './_tsup-dts-rollup.js';
301
+ export { SpeechRecognition } from './_tsup-dts-rollup.js';
302
+ export { SpeechRecognitionProps } from './_tsup-dts-rollup.js';
301
303
  export { LoadingIndicator } from './_tsup-dts-rollup.js';
302
304
  export { loadingIndicatorVariants } from './_tsup-dts-rollup.js';
303
305
  export { LoadingIndicatorProps } from './_tsup-dts-rollup.js';
package/dist/index.js CHANGED
@@ -4977,6 +4977,145 @@ function Composer({
4977
4977
  }
4978
4978
  );
4979
4979
  }
4980
+ function getSpeechRecognitionCtor() {
4981
+ if (typeof window === "undefined") return null;
4982
+ const w = window;
4983
+ return w.SpeechRecognition ?? w.webkitSpeechRecognition ?? null;
4984
+ }
4985
+ function SpeechRecognition({
4986
+ isListening,
4987
+ onListeningChange,
4988
+ onTranscript,
4989
+ onError,
4990
+ lang = "en-US",
4991
+ continuous = true,
4992
+ interimResults = true,
4993
+ startLabel = "Start dictation",
4994
+ stopLabel = "Stop dictation",
4995
+ notSupportedLabel = "Speech recognition not supported in this browser",
4996
+ disabled,
4997
+ className,
4998
+ ...rest
4999
+ }) {
5000
+ const recognitionRef = React44.useRef(null);
5001
+ const [isSupported, setIsSupported] = React44.useState(true);
5002
+ const onTranscriptRef = React44.useRef(onTranscript);
5003
+ const onListeningChangeRef = React44.useRef(onListeningChange);
5004
+ const onErrorRef = React44.useRef(onError);
5005
+ onTranscriptRef.current = onTranscript;
5006
+ onListeningChangeRef.current = onListeningChange;
5007
+ onErrorRef.current = onError;
5008
+ const mountedRef = React44.useRef(true);
5009
+ React44.useEffect(
5010
+ () => () => {
5011
+ mountedRef.current = false;
5012
+ },
5013
+ []
5014
+ );
5015
+ const rebuildingRef = React44.useRef(false);
5016
+ const isListeningRef = React44.useRef(isListening);
5017
+ isListeningRef.current = isListening;
5018
+ React44.useEffect(() => {
5019
+ const Ctor = getSpeechRecognitionCtor();
5020
+ setIsSupported(Ctor !== null);
5021
+ }, []);
5022
+ React44.useEffect(() => {
5023
+ if (!isListening) return;
5024
+ const Ctor = getSpeechRecognitionCtor();
5025
+ if (!Ctor) return;
5026
+ const instance = new Ctor();
5027
+ instance.continuous = continuous;
5028
+ instance.interimResults = interimResults;
5029
+ instance.lang = lang;
5030
+ instance.onresult = (event) => {
5031
+ if (!mountedRef.current) return;
5032
+ for (let i = event.resultIndex; i < event.results.length; i++) {
5033
+ const result = event.results[i];
5034
+ const transcript = result[0]?.transcript ?? "";
5035
+ if (transcript) onTranscriptRef.current(transcript, result.isFinal);
5036
+ }
5037
+ };
5038
+ instance.onerror = (event) => {
5039
+ if (!mountedRef.current) return;
5040
+ onErrorRef.current?.(event.error, event.message);
5041
+ if (event.error !== "aborted") onListeningChangeRef.current(false);
5042
+ };
5043
+ instance.onend = () => {
5044
+ if (!mountedRef.current) return;
5045
+ if (rebuildingRef.current) return;
5046
+ onListeningChangeRef.current(false);
5047
+ };
5048
+ recognitionRef.current = instance;
5049
+ try {
5050
+ instance.start();
5051
+ } catch (err) {
5052
+ onErrorRef.current?.("start-failed", err instanceof Error ? err.message : String(err));
5053
+ onListeningChangeRef.current(false);
5054
+ }
5055
+ return () => {
5056
+ rebuildingRef.current = isListeningRef.current;
5057
+ instance.onresult = null;
5058
+ instance.onerror = null;
5059
+ instance.onend = null;
5060
+ try {
5061
+ instance.abort();
5062
+ } catch {
5063
+ }
5064
+ recognitionRef.current = null;
5065
+ queueMicrotask(() => {
5066
+ rebuildingRef.current = false;
5067
+ });
5068
+ };
5069
+ }, [isListening, continuous, interimResults, lang]);
5070
+ const tooltip = !isSupported ? notSupportedLabel : isListening ? stopLabel : startLabel;
5071
+ const accessibleName = isSupported ? startLabel : notSupportedLabel;
5072
+ const isDisabled = disabled || !isSupported;
5073
+ return /* @__PURE__ */ jsx(
5074
+ "button",
5075
+ {
5076
+ type: "button",
5077
+ ...rest,
5078
+ disabled: isDisabled,
5079
+ "aria-label": accessibleName,
5080
+ "aria-pressed": isListening,
5081
+ title: tooltip,
5082
+ onClick: (event) => {
5083
+ rest.onClick?.(event);
5084
+ if (event.defaultPrevented || isDisabled) return;
5085
+ onListeningChange(!isListening);
5086
+ },
5087
+ className: cn(
5088
+ "inline-flex h-9 w-9 items-center justify-center rounded-md border bg-background",
5089
+ "text-foreground transition-colors duration-[var(--duration-normal,200ms)] ease-out",
5090
+ "hover:bg-accent hover:text-accent-foreground",
5091
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
5092
+ "disabled:cursor-not-allowed disabled:opacity-50",
5093
+ isListening && "animate-pulse border-destructive text-destructive",
5094
+ className
5095
+ ),
5096
+ children: /* @__PURE__ */ jsxs(
5097
+ "svg",
5098
+ {
5099
+ "aria-hidden": true,
5100
+ viewBox: "0 0 16 16",
5101
+ width: "14",
5102
+ height: "14",
5103
+ fill: "none",
5104
+ stroke: "currentColor",
5105
+ strokeWidth: "1.5",
5106
+ strokeLinecap: "round",
5107
+ strokeLinejoin: "round",
5108
+ children: [
5109
+ /* @__PURE__ */ jsx("rect", { x: "6", y: "2", width: "4", height: "8", rx: "2" }),
5110
+ /* @__PURE__ */ jsx("path", { d: "M3.5 7.5a4.5 4.5 0 0 0 9 0" }),
5111
+ /* @__PURE__ */ jsx("path", { d: "M8 12v2" }),
5112
+ /* @__PURE__ */ jsx("path", { d: "M5.5 14h5" })
5113
+ ]
5114
+ }
5115
+ )
5116
+ }
5117
+ );
5118
+ }
4980
5119
  var loadingIndicatorVariants = cva("inline-flex items-center gap-2 text-muted-foreground", {
4981
5120
  variants: {
4982
5121
  size: {
@@ -5670,6 +5809,6 @@ function FileIcon2(props) {
5670
5809
  );
5671
5810
  }
5672
5811
 
5673
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AspectRatio, Attachment, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Citation, Cluster, CodeBlock, CodeBlockCopy2 as CodeBlockCopy, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorPicker, Combobox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Composer, Container, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuTrigger, DataTable, DatePicker, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuTrigger, Dropzone, Empty, ErrorState, FileTree, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, Grid, HoverCard, HoverCardContent, HoverCardTrigger, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Label, Loading, LoadingIndicator, Markdown, Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarSeparator, MenubarShortcut, MenubarTrigger, Message, MessageActions, MessageList, MultiCombobox, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, Reasoning, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarItem, SidebarProvider, SidebarTrigger, Skeleton, Slider, Spacer, Stack, Stepper, Suggestion, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, Textarea, TimePicker, Timeline, Toaster, Toggle, ToggleGroup, ToggleGroupItem, ToolCall, Toolbar, ToolbarButton, ToolbarLink, ToolbarSeparator, ToolbarToggleGroup, ToolbarToggleItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Tree, alertVariants, attachmentVariants, badgeVariants, buttonVariants, clusterVariants, cn, containerVariants, emptyVariants, errorStateVariants, formatHslTriplet, gridVariants, hexToHslTriplet, hslToRgb, hslTripletToHex, loadingIndicatorVariants, loadingVariants, messageVariants, navigationMenuTriggerStyle, parseHslTriplet, rgbToHsl, spacerVariants, stackVariants, tagVariants, toggleVariants, toolbarVariants, useFormField, useSidebar };
5812
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AspectRatio, Attachment, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Citation, Cluster, CodeBlock, CodeBlockCopy2 as CodeBlockCopy, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorPicker, Combobox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Composer, Container, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuTrigger, DataTable, DatePicker, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuTrigger, Dropzone, Empty, ErrorState, FileTree, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, Grid, HoverCard, HoverCardContent, HoverCardTrigger, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Label, Loading, LoadingIndicator, Markdown, Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarSeparator, MenubarShortcut, MenubarTrigger, Message, MessageActions, MessageList, MultiCombobox, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, Reasoning, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarItem, SidebarProvider, SidebarTrigger, Skeleton, Slider, Spacer, SpeechRecognition, Stack, Stepper, Suggestion, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, Textarea, TimePicker, Timeline, Toaster, Toggle, ToggleGroup, ToggleGroupItem, ToolCall, Toolbar, ToolbarButton, ToolbarLink, ToolbarSeparator, ToolbarToggleGroup, ToolbarToggleItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Tree, alertVariants, attachmentVariants, badgeVariants, buttonVariants, clusterVariants, cn, containerVariants, emptyVariants, errorStateVariants, formatHslTriplet, gridVariants, hexToHslTriplet, hslToRgb, hslTripletToHex, loadingIndicatorVariants, loadingVariants, messageVariants, navigationMenuTriggerStyle, parseHslTriplet, rgbToHsl, spacerVariants, stackVariants, tagVariants, toggleVariants, toolbarVariants, useFormField, useSidebar };
5674
5813
  //# sourceMappingURL=index.js.map
5675
5814
  //# sourceMappingURL=index.js.map