@dotrly/sdk 0.2.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.
- package/README.md +313 -0
- package/dist/chunk-6VSTRIAD.js +8 -0
- package/dist/chunk-6VSTRIAD.js.map +1 -0
- package/dist/chunk-7RGKC52K.cjs +8 -0
- package/dist/chunk-7RGKC52K.cjs.map +1 -0
- package/dist/components/ui/index.cjs +2 -0
- package/dist/components/ui/index.cjs.map +1 -0
- package/dist/components/ui/index.d.cts +576 -0
- package/dist/components/ui/index.d.ts +576 -0
- package/dist/components/ui/index.js +2 -0
- package/dist/components/ui/index.js.map +1 -0
- package/dist/index.cjs +10 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +294 -0
- package/dist/index.d.ts +294 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { ClassValue } from 'clsx';
|
|
2
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertAction, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AspectRatio, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, Calendar, CalendarDayButton, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxSeparator, ComboboxTrigger, ComboboxValue, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, 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, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, HoverCard, HoverCardContent, HoverCardTrigger, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Label, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buttonGroupVariants, buttonVariants, navigationMenuTriggerStyle, tabsListVariants, toggleVariants, useCarousel, useComboboxAnchor, useSidebar } from './components/ui/index.js';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { ReactNode, CSSProperties } from 'react';
|
|
6
|
+
import 'radix-ui';
|
|
7
|
+
import 'class-variance-authority/types';
|
|
8
|
+
import 'class-variance-authority';
|
|
9
|
+
import 'react-day-picker';
|
|
10
|
+
import 'embla-carousel-react';
|
|
11
|
+
import 'recharts';
|
|
12
|
+
import '@base-ui/react';
|
|
13
|
+
import 'cmdk';
|
|
14
|
+
import 'vaul';
|
|
15
|
+
import 'input-otp';
|
|
16
|
+
import 'sonner';
|
|
17
|
+
|
|
18
|
+
declare function cn(...inputs: ClassValue[]): string;
|
|
19
|
+
|
|
20
|
+
type KeyboardBehavior = 'padding' | 'height' | 'position';
|
|
21
|
+
interface KeyboardAvoidingViewProps {
|
|
22
|
+
children: ReactNode;
|
|
23
|
+
behavior?: KeyboardBehavior;
|
|
24
|
+
keyboardVerticalOffset?: number;
|
|
25
|
+
style?: CSSProperties;
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* KeyboardAvoidingView - Automatically adjusts content when keyboard opens
|
|
30
|
+
*
|
|
31
|
+
* @param behavior - How to adjust: 'padding' | 'height' | 'position'
|
|
32
|
+
* @param keyboardVerticalOffset - Additional offset to add
|
|
33
|
+
*/
|
|
34
|
+
declare function KeyboardAvoidingView({ children, behavior, keyboardVerticalOffset, style, className }: KeyboardAvoidingViewProps): react_jsx_runtime.JSX.Element;
|
|
35
|
+
type SafeAreaEdge = 'top' | 'bottom' | 'left' | 'right';
|
|
36
|
+
interface SafeAreaViewProps {
|
|
37
|
+
children: ReactNode;
|
|
38
|
+
edges?: SafeAreaEdge[];
|
|
39
|
+
style?: CSSProperties;
|
|
40
|
+
className?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* SafeAreaView - Container that respects safe area insets
|
|
44
|
+
*
|
|
45
|
+
* @param edges - Which edges to apply safe area to (default: all)
|
|
46
|
+
*/
|
|
47
|
+
declare function SafeAreaView({ children, edges, style, className }: SafeAreaViewProps): react_jsx_runtime.JSX.Element;
|
|
48
|
+
interface PlatformHeaderProps {
|
|
49
|
+
title: string;
|
|
50
|
+
showBack?: boolean;
|
|
51
|
+
onBack?: () => void;
|
|
52
|
+
className?: string;
|
|
53
|
+
rightElement?: ReactNode;
|
|
54
|
+
}
|
|
55
|
+
declare function PlatformHeader({ title, showBack, onBack, className, rightElement }: PlatformHeaderProps): react_jsx_runtime.JSX.Element;
|
|
56
|
+
|
|
57
|
+
type TimerMode = 'focus' | 'shortBreak' | 'longBreak';
|
|
58
|
+
type StoryState = 'egg' | 'cracked' | 'chick' | 'alien' | 'ghost';
|
|
59
|
+
declare function useFocusTimer(): {
|
|
60
|
+
seconds: number;
|
|
61
|
+
initialTime: number;
|
|
62
|
+
isActive: boolean;
|
|
63
|
+
mode: TimerMode;
|
|
64
|
+
task: string;
|
|
65
|
+
storyState: StoryState;
|
|
66
|
+
soundEnabled: boolean;
|
|
67
|
+
setSeconds: React.Dispatch<React.SetStateAction<number>>;
|
|
68
|
+
setInitialTime: React.Dispatch<React.SetStateAction<number>>;
|
|
69
|
+
setIsActive: React.Dispatch<React.SetStateAction<boolean>>;
|
|
70
|
+
setMode: React.Dispatch<React.SetStateAction<TimerMode>>;
|
|
71
|
+
setTask: React.Dispatch<React.SetStateAction<string>>;
|
|
72
|
+
setStoryState: React.Dispatch<React.SetStateAction<StoryState>>;
|
|
73
|
+
setSoundEnabled: React.Dispatch<React.SetStateAction<boolean>>;
|
|
74
|
+
toggleTimer: () => void;
|
|
75
|
+
giveUp: () => void;
|
|
76
|
+
switchMode: (newMode: TimerMode) => void;
|
|
77
|
+
resetTimer: () => void;
|
|
78
|
+
setCustomTime: (mins: number) => void;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
declare function useIsMobile(): boolean;
|
|
82
|
+
|
|
83
|
+
interface KeyboardState {
|
|
84
|
+
isOpen: boolean;
|
|
85
|
+
height: number;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* useKeyboard - Track virtual keyboard state on mobile devices
|
|
89
|
+
*
|
|
90
|
+
* Uses visualViewport API to detect keyboard height and provides
|
|
91
|
+
* a safe area offset for positioning UI elements above the keyboard.
|
|
92
|
+
*
|
|
93
|
+
* @returns {KeyboardState} - { isOpen: boolean, height: number }
|
|
94
|
+
*/
|
|
95
|
+
declare function useKeyboard(): KeyboardState;
|
|
96
|
+
/**
|
|
97
|
+
* useRelayClose - Get the close function for closing the current app
|
|
98
|
+
*
|
|
99
|
+
* Works with both iframe and blob URL contexts.
|
|
100
|
+
*
|
|
101
|
+
* @returns {() => void} - Function to close the current app
|
|
102
|
+
*/
|
|
103
|
+
declare function useRelayClose(): () => void;
|
|
104
|
+
|
|
105
|
+
interface SafeAreaInsets {
|
|
106
|
+
top: number;
|
|
107
|
+
bottom: number;
|
|
108
|
+
left: number;
|
|
109
|
+
right: number;
|
|
110
|
+
}
|
|
111
|
+
interface SafeAreaProviderProps {
|
|
112
|
+
children: ReactNode;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* SafeAreaProvider - Provides safe area insets to child components
|
|
116
|
+
*
|
|
117
|
+
* Automatically detects safe areas from:
|
|
118
|
+
* 1. CSS env() values (iOS Safari)
|
|
119
|
+
* 2. Parent Shell postMessage (when running in Relay Shell)
|
|
120
|
+
*/
|
|
121
|
+
declare function SafeAreaProvider({ children }: SafeAreaProviderProps): react_jsx_runtime.JSX.Element;
|
|
122
|
+
/**
|
|
123
|
+
* useSafeArea - Get safe area insets
|
|
124
|
+
*
|
|
125
|
+
* @returns SafeAreaInsets with top, bottom, left, right values in pixels
|
|
126
|
+
*/
|
|
127
|
+
declare function useSafeArea(): SafeAreaInsets;
|
|
128
|
+
type ColorScheme = 'light' | 'dark';
|
|
129
|
+
/**
|
|
130
|
+
* useColorScheme - Get current system color scheme
|
|
131
|
+
*
|
|
132
|
+
* @returns 'light' | 'dark'
|
|
133
|
+
*/
|
|
134
|
+
declare function useColorScheme(): ColorScheme;
|
|
135
|
+
/**
|
|
136
|
+
* useStatusBar - Control the status bar appearance
|
|
137
|
+
*
|
|
138
|
+
* @param color - Hex color for the status bar
|
|
139
|
+
*/
|
|
140
|
+
declare function useStatusBar(color: string): void;
|
|
141
|
+
/**
|
|
142
|
+
* useBackHandler - Handle back navigation
|
|
143
|
+
*
|
|
144
|
+
* @param handler - Return true to prevent default back behavior
|
|
145
|
+
*/
|
|
146
|
+
declare function useBackHandler(handler: () => boolean): void;
|
|
147
|
+
type AppState = 'active' | 'background' | 'inactive';
|
|
148
|
+
/**
|
|
149
|
+
* useAppState - Track app foreground/background state
|
|
150
|
+
*
|
|
151
|
+
* @returns Current app state
|
|
152
|
+
*/
|
|
153
|
+
declare function useAppState(): AppState;
|
|
154
|
+
|
|
155
|
+
interface NotificationOptions {
|
|
156
|
+
body?: string;
|
|
157
|
+
icon?: string;
|
|
158
|
+
image?: string;
|
|
159
|
+
badge?: string;
|
|
160
|
+
tag?: string;
|
|
161
|
+
data?: any;
|
|
162
|
+
vibrate?: number[];
|
|
163
|
+
timestamp?: number;
|
|
164
|
+
renotify?: boolean;
|
|
165
|
+
silent?: boolean;
|
|
166
|
+
requireInteraction?: boolean;
|
|
167
|
+
actions?: NotificationAction[];
|
|
168
|
+
}
|
|
169
|
+
interface NotificationAction {
|
|
170
|
+
action: string;
|
|
171
|
+
title: string;
|
|
172
|
+
icon?: string;
|
|
173
|
+
}
|
|
174
|
+
interface UseNotificationsReturn {
|
|
175
|
+
permission: NotificationPermission;
|
|
176
|
+
requestPermission: () => Promise<NotificationPermission>;
|
|
177
|
+
sendNotification: (title: string, options?: NotificationOptions) => void;
|
|
178
|
+
scheduleNotification: (title: string, delayMs: number, options?: NotificationOptions) => void;
|
|
179
|
+
clearBadge: () => Promise<void>;
|
|
180
|
+
setBadge: (count: number) => Promise<void>;
|
|
181
|
+
}
|
|
182
|
+
declare function useNotifications(): UseNotificationsReturn;
|
|
183
|
+
|
|
184
|
+
interface ClipboardItem {
|
|
185
|
+
type: 'text' | 'image' | 'html';
|
|
186
|
+
content: string | Blob;
|
|
187
|
+
timestamp: number;
|
|
188
|
+
}
|
|
189
|
+
interface UseClipboardReturn {
|
|
190
|
+
clipboardContent: string | null;
|
|
191
|
+
history: ClipboardItem[];
|
|
192
|
+
copyText: (text: string) => Promise<void>;
|
|
193
|
+
copyImage: (blob: Blob) => Promise<void>;
|
|
194
|
+
readText: () => Promise<string>;
|
|
195
|
+
readContent: () => Promise<ClipboardItems>;
|
|
196
|
+
clearHistory: () => void;
|
|
197
|
+
}
|
|
198
|
+
declare function useClipboard(): UseClipboardReturn;
|
|
199
|
+
|
|
200
|
+
interface LocationState {
|
|
201
|
+
loading: boolean;
|
|
202
|
+
accuracy: number | null;
|
|
203
|
+
altitude: number | null;
|
|
204
|
+
altitudeAccuracy: number | null;
|
|
205
|
+
heading: number | null;
|
|
206
|
+
latitude: number | null;
|
|
207
|
+
longitude: number | null;
|
|
208
|
+
speed: number | null;
|
|
209
|
+
timestamp: number | null;
|
|
210
|
+
error: GeolocationPositionError | null;
|
|
211
|
+
}
|
|
212
|
+
interface Geofence {
|
|
213
|
+
id: string;
|
|
214
|
+
latitude: number;
|
|
215
|
+
longitude: number;
|
|
216
|
+
radius: number;
|
|
217
|
+
}
|
|
218
|
+
interface UseGeolocationReturn extends LocationState {
|
|
219
|
+
getLocation: () => void;
|
|
220
|
+
watchLocation: (options?: PositionOptions) => void;
|
|
221
|
+
clearWatch: () => void;
|
|
222
|
+
checkGeofence: (fence: Geofence) => boolean;
|
|
223
|
+
distanceTo: (lat: number, lng: number) => number;
|
|
224
|
+
}
|
|
225
|
+
declare function useGeolocation(options?: PositionOptions): UseGeolocationReturn;
|
|
226
|
+
|
|
227
|
+
interface CameraState {
|
|
228
|
+
stream: MediaStream | null;
|
|
229
|
+
error: Error | null;
|
|
230
|
+
permission: PermissionState | 'unknown';
|
|
231
|
+
isRecording: boolean;
|
|
232
|
+
devices: MediaDeviceInfo[];
|
|
233
|
+
}
|
|
234
|
+
interface CameraOptions {
|
|
235
|
+
video?: boolean | MediaTrackConstraints;
|
|
236
|
+
audio?: boolean | MediaTrackConstraints;
|
|
237
|
+
}
|
|
238
|
+
interface UseCameraReturn extends CameraState {
|
|
239
|
+
startCamera: (options?: CameraOptions) => Promise<MediaStream | undefined>;
|
|
240
|
+
stopCamera: () => void;
|
|
241
|
+
takePhoto: () => Promise<string | undefined>;
|
|
242
|
+
startRecording: () => void;
|
|
243
|
+
stopRecording: () => Promise<Blob | undefined>;
|
|
244
|
+
startScreenShare: (options?: DisplayMediaStreamOptions) => Promise<MediaStream | undefined>;
|
|
245
|
+
switchDevice: (deviceId: string, kind: 'video' | 'audio') => Promise<void>;
|
|
246
|
+
getDevices: () => Promise<MediaDeviceInfo[]>;
|
|
247
|
+
}
|
|
248
|
+
declare function useCamera(): UseCameraReturn;
|
|
249
|
+
|
|
250
|
+
interface OllamaModel {
|
|
251
|
+
name: string;
|
|
252
|
+
modified_at: string;
|
|
253
|
+
size: number;
|
|
254
|
+
digest: string;
|
|
255
|
+
details: {
|
|
256
|
+
parent_model: string;
|
|
257
|
+
format: string;
|
|
258
|
+
family: string;
|
|
259
|
+
families: string[];
|
|
260
|
+
parameter_size: string;
|
|
261
|
+
quantization_level: string;
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
interface OllamaResponse {
|
|
265
|
+
model: string;
|
|
266
|
+
created_at: string;
|
|
267
|
+
response?: string;
|
|
268
|
+
message?: {
|
|
269
|
+
role: string;
|
|
270
|
+
content: string;
|
|
271
|
+
};
|
|
272
|
+
done: boolean;
|
|
273
|
+
context?: number[];
|
|
274
|
+
total_duration?: number;
|
|
275
|
+
load_duration?: number;
|
|
276
|
+
prompt_eval_count?: number;
|
|
277
|
+
prompt_eval_duration?: number;
|
|
278
|
+
eval_count?: number;
|
|
279
|
+
eval_duration?: number;
|
|
280
|
+
}
|
|
281
|
+
interface UseOllamaReturn {
|
|
282
|
+
available: boolean;
|
|
283
|
+
loading: boolean;
|
|
284
|
+
models: OllamaModel[];
|
|
285
|
+
refreshModels: () => Promise<void>;
|
|
286
|
+
generate: (model: string, prompt: string, options?: any) => Promise<OllamaResponse>;
|
|
287
|
+
chat: (model: string, messages: {
|
|
288
|
+
role: string;
|
|
289
|
+
content: string;
|
|
290
|
+
}[], options?: any) => Promise<OllamaResponse>;
|
|
291
|
+
}
|
|
292
|
+
declare function useOllama(): UseOllamaReturn;
|
|
293
|
+
|
|
294
|
+
export { type AppState, type CameraOptions, type CameraState, type ClipboardItem, type ColorScheme, type Geofence, KeyboardAvoidingView, type LocationState, type NotificationAction, type NotificationOptions, type OllamaModel, type OllamaResponse, PlatformHeader, type SafeAreaInsets, SafeAreaProvider, SafeAreaView, type StoryState, type TimerMode, type UseCameraReturn, type UseClipboardReturn, type UseGeolocationReturn, type UseNotificationsReturn, type UseOllamaReturn, cn, useAppState, useBackHandler, useCamera, useClipboard, useColorScheme, useFocusTimer, useGeolocation, useIsMobile, useKeyboard, useNotifications, useOllama, useRelayClose, useSafeArea, useStatusBar };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import{$ as ot,$a as oo,$b as nn,$c as rr,$d as ra,A as Ie,Aa as It,Ab as Ro,Ac as An,Ad as Ar,Ae as Aa,B as Re,Ba as Rt,Bb as Ao,Bc as Tn,Bd as Tr,Be as Ta,C as Ae,Ca as At,Cb as To,Cc as On,Cd as Or,Ce as Oa,D as Te,Da as Tt,Db as Oo,Dc as Ln,Dd as Lr,De as La,E as Oe,Ea as Ot,Eb as Lo,Ec as Hn,Ed as Hr,Ee as Ha,F as Le,Fa as Lt,Fb as Ho,Fc as Bn,Fd as Br,Fe as Ba,G as He,Ga as Ht,Gb as Bo,Gc as _n,Gd as _r,Ge as _a,H as Be,Ha as Bt,Hb as _o,Hc as Dn,Hd as Dr,He as Da,I as _e,Ia as _t,Ib as Do,Ic as Un,Id as Ur,J as De,Ja as Dt,Jb as Uo,Jc as Vn,Jd as Vr,K as Ue,Ka as Ut,Kb as Vo,Kc as Gn,Kd as Gr,L as Ve,La as Vt,Lb as Go,Lc as Fn,Ld as Fr,M as Ge,Ma as Gt,Mb as Fo,Mc as Kn,Md as Kr,N as Fe,Na as Ft,Nb as Ko,Nc as $n,Nd as $r,O as Ke,Oa as Kt,Ob as $o,Oc as qn,Od as qr,P as $e,Pa as $t,Pb as qo,Pc as zn,Pd as zr,Q as qe,Qa as qt,Qb as zo,Qc as jn,Qd as jr,R as ze,Ra as zt,Rb as jo,Rc as Wn,Rd as Wr,S as je,Sa as jt,Sb as Wo,Sc as Yn,Sd as Yr,T as We,Ta as Wt,Tb as Yo,Tc as Jn,Td as Jr,U as Ye,Ua as Yt,Ub as Jo,Uc as Xn,Ud as Xr,V as Je,Va as Jt,Vb as Xo,Vc as Qn,Vd as Qr,W as Xe,Wa as Xt,Wb as Qo,Wc as Zn,Wd as Zr,X as Qe,Xa as Qt,Xb as Zo,Xc as er,Xd as ea,Y as Ze,Ya as Zt,Yb as en,Yc as tr,Yd as ta,Z as et,Za as eo,Zb as tn,Zc as or,Zd as oa,_ as tt,_a as to,_b as on,_c as nr,_d as na,a as O,aa as nt,ab as no,ac as rn,ad as ar,ae as aa,b as re,ba as rt,bb as ro,bc as an,bd as ir,be as ia,c as ae,ca as at,cb as ao,cc as sn,cd as sr,ce as sa,d as ie,da as it,db as io,dc as cn,dd as cr,de as ca,e as se,ea as st,eb as so,ec as ln,ed as lr,ee as la,f as ce,fa as ct,fb as co,fc as dn,fd as dr,fe as da,g as le,ga as lt,gb as lo,gc as un,gd as ur,ge as ua,h as de,ha as dt,hb as uo,hc as mn,hd as mr,he as ma,i as ue,ia as ut,ib as mo,ic as pn,id as pr,ie as pa,j as me,ja as mt,jb as po,jc as fn,jd as fr,je as fa,k as pe,ka as pt,kb as fo,kc as gn,kd as gr,ke as ga,l as fe,la as ft,lb as go,lc as hn,ld as hr,le as ha,m as ge,ma as gt,mb as ho,mc as vn,md as vr,me as va,n as he,na as ht,nb as vo,nc as wn,nd as wr,ne as wa,o as ve,oa as vt,ob as wo,oc as bn,od as br,oe as ba,p as we,pa as wt,pb as bo,pc as yn,pd as yr,pe as ya,q as be,qa as bt,qb as yo,qc as Sn,qd as Sr,qe as Sa,r as ye,ra as yt,rb as So,rc as xn,rd as xr,re as xa,s as Se,sa as St,sb as xo,sc as En,sd as Er,se as Ea,t as xe,ta as xt,tb as Eo,tc as Pn,td as Pr,te as Pa,u as Ee,ua as Et,ub as Po,uc as Cn,ud as Cr,ue as Ca,v as Pe,va as Pt,vb as Co,vc as kn,vd as kr,ve as ka,w as Ce,wa as Ct,wb as ko,wc as Mn,wd as Mr,we as Ma,x as ke,xa as kt,xb as Mo,xc as Nn,xd as Nr,xe as Na,y as Me,ya as Mt,yb as No,yc as In,yd as Ir,ye as Ia,z as Ne,za as Nt,zb as Io,zc as Rn,zd as Rr,ze as Ra}from"./chunk-6VSTRIAD.js";import{useState as $,useEffect as q,useCallback as z,useRef as j}from"react";function L(){let[r,e]=$({isOpen:!1,height:0}),s=j(typeof window<"u"?window.innerHeight:0);return q(()=>{if(!/iPad|iPhone|iPod|Android/.test(navigator.userAgent))return;let o=()=>{if(!window.visualViewport)return;let f=window.visualViewport,m=window.innerHeight;m>s.current&&(s.current=m);let a=m-f.height;a<=0&&(a=s.current-m);let n=a>100;e({isOpen:n,height:n?a:0})};window.visualViewport&&(window.visualViewport.addEventListener("resize",o),window.visualViewport.addEventListener("scroll",o));let d=()=>{setTimeout(()=>{s.current=window.innerHeight,o()},100)};window.addEventListener("orientationchange",d),window.screen?.orientation&&window.screen.orientation.addEventListener("change",d);let u=f=>{let m=f.target;(m.tagName==="INPUT"||m.tagName==="TEXTAREA")&&setTimeout(o,100)},l=()=>{setTimeout(()=>{e({isOpen:!1,height:0})},100)};return document.addEventListener("focusin",u),document.addEventListener("focusout",l),o(),()=>{window.visualViewport?.removeEventListener("resize",o),window.visualViewport?.removeEventListener("scroll",o),document.removeEventListener("focusin",u),document.removeEventListener("focusout",l)}},[]),r}function Va(){return z(()=>{window.postMessage("relay:close","*"),window.parent!==window&&window.parent.postMessage("relay:close","*"),window.opener&&window.opener.postMessage("relay:close","*")},[])}import{useState as I,useEffect as P,createContext as W,useContext as Y}from"react";import{jsx as J}from"react/jsx-runtime";var H={top:0,bottom:0,left:0,right:0},B=W(H);function qa({children:r}){let[e,s]=I(H);return P(()=>{let c=()=>{let d=getComputedStyle(document.documentElement),u=n=>{let t=d.getPropertyValue(`--safe-area-inset-${n}`);return parseInt(t)||0},l=u("top"),f=u("bottom"),m=u("left"),a=u("right");if(l===0&&f===0){let n=document.createElement("div");n.style.cssText=`
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: env(safe-area-inset-top, 0px);
|
|
4
|
+
bottom: env(safe-area-inset-bottom, 0px);
|
|
5
|
+
left: env(safe-area-inset-left, 0px);
|
|
6
|
+
right: env(safe-area-inset-right, 0px);
|
|
7
|
+
pointer-events: none;
|
|
8
|
+
visibility: hidden;
|
|
9
|
+
`,document.body.appendChild(n);let t=n.getBoundingClientRect();l=t.top,f=window.innerHeight-t.bottom,m=t.left,a=window.innerWidth-t.right,document.body.removeChild(n)}s({top:l,bottom:f,left:m,right:a})},o=d=>{d.data?.type==="relay:safearea"&&s(d.data.insets)};return c(),window.addEventListener("message",o),window.addEventListener("resize",c),()=>{window.removeEventListener("message",o),window.removeEventListener("resize",c)}},[]),J(B.Provider,{value:e,children:r})}function R(){return Y(B)}function za(){let[r,e]=I(()=>window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");return P(()=>{let s=window.matchMedia("(prefers-color-scheme: dark)"),c=o=>{e(o.matches?"dark":"light")};return s.addEventListener("change",c),()=>s.removeEventListener("change",c)},[]),r}function ja(r){P(()=>{let e=document.querySelector('meta[name="theme-color"]');e||(e=document.createElement("meta"),e.setAttribute("name","theme-color"),document.head.appendChild(e)),e.setAttribute("content",r),window.parent?.postMessage({type:"relay:statusbar",color:r},"*")},[r])}function Wa(r){P(()=>{let e=c=>{c.data==="relay:back"&&(r()||window.parent?.postMessage("relay:close","*"))},s=c=>{r()&&window.history.pushState(null,"",window.location.href)};return window.history.pushState(null,"",window.location.href),window.addEventListener("message",e),window.addEventListener("popstate",s),()=>{window.removeEventListener("message",e),window.removeEventListener("popstate",s)}},[r])}function Ya(){let[r,e]=I("active");return P(()=>{let s=()=>{e(document.hidden?"background":"active")},c=o=>{o.data==="relay:foreground"&&e("active"),o.data==="relay:background"&&e("background")};return document.addEventListener("visibilitychange",s),window.addEventListener("message",c),()=>{document.removeEventListener("visibilitychange",s),window.removeEventListener("message",c)}},[]),r}import{jsx as b,jsxs as _}from"react/jsx-runtime";function ti({children:r,behavior:e="padding",keyboardVerticalOffset:s=0,style:c,className:o}){let d=L(),u=d.height+s,l={...c,transition:"all 0.2s ease-out"};if(d.isOpen)switch(e){case"padding":l.paddingBottom=u;break;case"height":l.height=`calc(100% - ${u}px)`;break;case"position":l.transform=`translateY(-${u}px)`;break}return b("div",{style:l,className:o,children:r})}function oi({children:r,edges:e=["top","bottom","left","right"],style:s,className:c}){let o=R(),d={...s,paddingTop:e.includes("top")?o.top:s?.paddingTop,paddingBottom:e.includes("bottom")?o.bottom:s?.paddingBottom,paddingLeft:e.includes("left")?o.left:s?.paddingLeft,paddingRight:e.includes("right")?o.right:s?.paddingRight};return b("div",{style:d,className:c,children:r})}function ni({title:r,showBack:e=!0,onBack:s,className:c,rightElement:o}){let d=R();return b("div",{className:O("bg-background border-b flex flex-col z-50",c),style:{paddingTop:d.top},children:_("div",{className:"h-14 flex items-center justify-between px-4",children:[_("div",{className:"flex items-center gap-4 flex-1",children:[e&&b("button",{onClick:s||(()=>window.history.back()),className:"p-2 -ml-2 hover:bg-muted rounded-full transition-colors",children:b("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:b("path",{d:"M19 12H5M12 19l-7-7 7-7"})})}),b("h1",{className:"text-lg font-semibold truncate",children:r})]}),o&&b("div",{className:"flex-none",children:o})]})})}import{useState as S,useEffect as D}from"react";function si(){let[r,e]=S(1500),[s,c]=S(1500),[o,d]=S(!1),[u,l]=S("focus"),[f,m]=S(""),[a,n]=S("egg"),[t,i]=S(!1);D(()=>{let h=null;if(o&&r>0)h=setInterval(()=>{e(w=>w-1)},1e3);else if(r===0&&o&&(d(!1),u==="focus")){let w=Math.random()<.01;n(w?"alien":"chick")}return()=>{h&&clearInterval(h)}},[o,r,u]),D(()=>{if(!o&&(a==="chick"||a==="alien"||a==="ghost")||u!=="focus")return;let h=1-r/s;h<.5?n("egg"):h>=.5&&h<1&&n("cracked")},[r,s,o,a,u]);let p=()=>d(!o),g=()=>{d(!1),n("ghost")},v=h=>{d(!1),l(h),n("egg");let w=1500;h==="shortBreak"&&(w=300),h==="longBreak"&&(w=900),e(w),c(w)};return{seconds:r,initialTime:s,isActive:o,mode:u,task:f,storyState:a,soundEnabled:t,setSeconds:e,setInitialTime:c,setIsActive:d,setMode:l,setTask:m,setStoryState:n,setSoundEnabled:i,toggleTimer:p,giveUp:g,switchMode:v,resetTimer:()=>{d(!1),v(u)},setCustomTime:h=>{d(!1),e(h*60),c(h*60),n("egg")}}}import{useState as X,useCallback as C,useEffect as Q}from"react";function di(){let[r,e]=X("default");Q(()=>{"Notification"in window&&e(Notification.permission)},[]);let s=C(async()=>{if(!("Notification"in window))return console.warn("Notifications not supported"),"denied";let l=await Notification.requestPermission();return e(l),l},[]),c=C((l,f)=>{if(!("Notification"in window))return;let m=f;if(!f?.icon){let a=document.querySelector('link[rel="apple-touch-icon"]')||document.querySelector('link[rel="icon"]');a&&(m={...f,icon:a.href})}Notification.permission==="granted"?new Notification(l,m):Notification.permission!=="denied"&&Notification.requestPermission().then(a=>{a==="granted"&&new Notification(l,m)})},[]),o=C((l,f,m)=>{setTimeout(()=>{c(l,m)},f)},[c]),d=C(async l=>{if("setAppBadge"in navigator)try{await navigator.setAppBadge(l)}catch(f){console.error("Error setting badge:",f)}},[]),u=C(async()=>{if("clearAppBadge"in navigator)try{await navigator.clearAppBadge()}catch(l){console.error("Error clearing badge:",l)}},[]);return{permission:r,requestPermission:s,sendNotification:c,scheduleNotification:o,setBadge:d,clearBadge:u}}import{useState as U,useCallback as E,useEffect as V}from"react";var A="relay_clipboard_history",Z=10;function pi(){let[r,e]=U(null),[s,c]=U([]);V(()=>{try{let a=localStorage.getItem(A);if(a){let n=JSON.parse(a);c(n)}}catch(a){console.error("Failed to load clipboard history",a)}},[]);let o=E(a=>{c(n=>{let t=[a,...n].slice(0,Z),i=t.filter(p=>p.type==="text");try{localStorage.setItem(A,JSON.stringify(i))}catch(p){console.error("Failed to save clipboard history",p)}return t})},[]),d=E(async a=>{if(!navigator.clipboard){console.warn("Clipboard API not supported");return}try{await navigator.clipboard.writeText(a),e(a),o({type:"text",content:a,timestamp:Date.now()})}catch(n){throw console.error("Failed to copy text:",n),n}},[o]),u=E(async a=>{if(!navigator.clipboard){console.warn("Clipboard API not supported");return}try{await navigator.clipboard.write([new ClipboardItem({[a.type]:a})]),o({type:"image",content:a,timestamp:Date.now()})}catch(n){throw console.error("Failed to copy image:",n),n}},[o]),l=E(async()=>{if(!navigator.clipboard)return console.warn("Clipboard API not supported"),"";try{let a=await navigator.clipboard.readText();return e(a),a}catch(a){throw console.error("Failed to read text:",a),a}},[]),f=E(async()=>{if(!navigator.clipboard)return console.warn("Clipboard API not supported"),[];try{return await navigator.clipboard.read()}catch(a){throw console.error("Failed to read content:",a),a}},[]),m=E(()=>{c([]),localStorage.removeItem(A)},[]);return V(()=>{let a=()=>{l().catch(()=>{})};return window.addEventListener("focus",a),()=>window.removeEventListener("focus",a)},[l]),{clipboardContent:r,history:s,copyText:d,copyImage:u,readText:l,readContent:f,clearHistory:m}}import{useState as ee,useCallback as x,useEffect as te,useRef as oe}from"react";function hi(r){let[e,s]=ee({loading:!0,accuracy:null,altitude:null,altitudeAccuracy:null,heading:null,latitude:null,longitude:null,speed:null,timestamp:null,error:null}),c=oe(null),o=x(n=>{s({loading:!1,accuracy:n.coords.accuracy,altitude:n.coords.altitude,altitudeAccuracy:n.coords.altitudeAccuracy,heading:n.coords.heading,latitude:n.coords.latitude,longitude:n.coords.longitude,speed:n.coords.speed,timestamp:n.timestamp,error:null})},[]),d=x(n=>{s(t=>({...t,loading:!1,error:n}))},[]),u=x(()=>{if(!navigator.geolocation){s(n=>({...n,loading:!1,error:{code:0,message:"Geolocation not supported",PERMISSION_DENIED:1,POSITION_UNAVAILABLE:2,TIMEOUT:3}}));return}s(n=>({...n,loading:!0})),navigator.geolocation.getCurrentPosition(o,d,r)},[o,d,r]),l=x(n=>{navigator.geolocation&&(c.current!==null&&navigator.geolocation.clearWatch(c.current),c.current=navigator.geolocation.watchPosition(o,d,n||r))},[o,d,r]),f=x(()=>{c.current!==null&&(navigator.geolocation.clearWatch(c.current),c.current=null)},[]),m=x((n,t)=>{if(e.latitude===null||e.longitude===null)return 1/0;let i=6371e3,p=e.latitude*Math.PI/180,g=n*Math.PI/180,v=(n-e.latitude)*Math.PI/180,k=(t-e.longitude)*Math.PI/180,N=Math.sin(v/2)*Math.sin(v/2)+Math.cos(p)*Math.cos(g)*Math.sin(k/2)*Math.sin(k/2),h=2*Math.atan2(Math.sqrt(N),Math.sqrt(1-N));return i*h},[e.latitude,e.longitude]),a=x(n=>m(n.latitude,n.longitude)<=n.radius,[m]);return te(()=>()=>{c.current!==null&&navigator.geolocation.clearWatch(c.current)},[]),{...e,getLocation:u,watchLocation:l,clearWatch:f,checkGeofence:a,distanceTo:m}}import{useState as ne,useCallback as y,useRef as G,useEffect as F}from"react";function bi(){let[r,e]=ne({stream:null,error:null,permission:"unknown",isRecording:!1,devices:[]}),s=G(null),c=G([]),o=y(async()=>{if(!navigator.mediaDevices?.enumerateDevices)return[];try{let t=await navigator.mediaDevices.enumerateDevices();return e(i=>({...i,devices:t})),t}catch(t){return console.error("Error enumerating devices:",t),[]}},[]);F(()=>(o(),navigator.mediaDevices?.addEventListener("devicechange",o),()=>{navigator.mediaDevices?.removeEventListener("devicechange",o)}),[o]);let d=y(async(t={video:!0,audio:!1})=>{try{let i=await navigator.mediaDevices.getUserMedia(t);return e(p=>({...p,stream:i,error:null,permission:"granted"})),i}catch(i){let p=i;e(g=>({...g,error:p,permission:"denied"})),console.error("Error starting camera:",i)}},[]),u=y(()=>{r.stream&&(r.stream.getTracks().forEach(t=>t.stop()),e(t=>({...t,stream:null,isRecording:!1})))},[r.stream]),l=y(async(t={video:!0})=>{try{let i=await navigator.mediaDevices.getDisplayMedia(t);return e(p=>({...p,stream:i,error:null,permission:"granted"})),i}catch(i){let p=i;e(g=>({...g,error:p,permission:"denied"})),console.error("Error starting screen share:",i)}},[]),f=y(async()=>{if(!r.stream||!r.stream.getVideoTracks()[0])return;let i=document.createElement("video");i.srcObject=r.stream,await i.play();let p=document.createElement("canvas");p.width=i.videoWidth,p.height=i.videoHeight;let g=p.getContext("2d");if(!g)return;g.drawImage(i,0,0);let v=p.toDataURL("image/png");return i.pause(),i.srcObject=null,v},[r.stream]),m=y(()=>{if(r.stream)try{let t=new MediaRecorder(r.stream);s.current=t,c.current=[],t.ondataavailable=i=>{i.data.size>0&&c.current.push(i.data)},t.start(),e(i=>({...i,isRecording:!0}))}catch(t){console.error("Error starting recording:",t),e(i=>({...i,error:t}))}},[r.stream]),a=y(async()=>{if(!(!s.current||s.current.state==="inactive"))return new Promise(t=>{s.current&&(s.current.onstop=()=>{let i=new Blob(c.current,{type:"video/webm"});e(p=>({...p,isRecording:!1})),t(i)},s.current.stop())})},[]),n=y(async(t,i)=>{u();let p={[i]:{deviceId:{exact:t}}};await d(p)},[d,u]);return F(()=>()=>{u()},[]),{...r,startCamera:d,stopCamera:u,takePhoto:f,startRecording:m,stopRecording:a,startScreenShare:l,switchDevice:n,getDevices:o}}import{useState as T,useCallback as M,useEffect as K}from"react";function xi(){let[r,e]=T(!1),[s,c]=T(!1),[o,d]=T([]),l=(()=>{if(typeof window>"u")return"http://localhost:5378";let t=window.__RELAY_HELPER_HOST__;if(t)return t;let{protocol:i,hostname:p,port:g}=window.location;return g==="5378"||g==="5379"?"":`${i}//${p}:${i==="https:"?5379:5378}`})(),f=M(async()=>{try{let i=await(await fetch(`${l}/api/config`)).json();e(i.ollama?.available??!1)}catch{e(!1)}},[]),m=M(async()=>{c(!0);try{let t=await fetch(`${l}/api/ollama/api/tags`);if(t.ok){let i=await t.json();d(i.models||[])}}catch(t){console.error("Failed to fetch Ollama models:",t)}finally{c(!1)}},[]);K(()=>{f();let t=setInterval(f,3e4);return()=>clearInterval(t)},[f]),K(()=>{r&&m()},[r,m]);let a=M(async(t,i,p={})=>{let g=await fetch(`${l}/api/ollama/api/generate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,prompt:i,stream:!1,...p})});if(!g.ok)throw new Error(`Ollama generation failed: ${g.statusText}`);return await g.json()},[]),n=M(async(t,i,p={})=>{let g=await fetch(`${l}/api/ollama/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,messages:i,stream:!1,...p})});if(!g.ok)throw new Error(`Ollama chat failed: ${g.statusText}`);return await g.json()},[]);return{available:r,loading:s,models:o,refreshModels:m,generate:a,chat:n}}export{re as Accordion,se as AccordionContent,ae as AccordionItem,ie as AccordionTrigger,xe as Alert,Ce as AlertAction,Pe as AlertDescription,de as AlertDialog,ye as AlertDialogAction,Se as AlertDialogCancel,fe as AlertDialogContent,be as AlertDialogDescription,he as AlertDialogFooter,ge as AlertDialogHeader,ve as AlertDialogMedia,pe as AlertDialogOverlay,me as AlertDialogPortal,we as AlertDialogTitle,ue as AlertDialogTrigger,Ee as AlertTitle,ke as AspectRatio,Me as Avatar,Re as AvatarBadge,Ie as AvatarFallback,Ae as AvatarGroup,Te as AvatarGroupCount,Ne as AvatarImage,Le as Badge,He as Breadcrumb,Ge as BreadcrumbEllipsis,_e as BreadcrumbItem,De as BreadcrumbLink,Be as BreadcrumbList,Ue as BreadcrumbPage,Ve as BreadcrumbSeparator,le as Button,$e as ButtonGroup,ze as ButtonGroupSeparator,qe as ButtonGroupText,je as Calendar,We as CalendarDayButton,Ye as Card,Ze as CardAction,et as CardContent,Qe as CardDescription,tt as CardFooter,Je as CardHeader,Xe as CardTitle,nt as Carousel,rt as CarouselContent,at as CarouselItem,st as CarouselNext,it as CarouselPrevious,ct as ChartContainer,mt as ChartLegend,pt as ChartLegendContent,lt as ChartStyle,dt as ChartTooltip,ut as ChartTooltipContent,ft as Checkbox,gt as Collapsible,vt as CollapsibleContent,ht as CollapsibleTrigger,kt as Combobox,Ut as ComboboxChip,Dt as ComboboxChips,Vt as ComboboxChipsInput,Ht as ComboboxCollection,Rt as ComboboxContent,Bt as ComboboxEmpty,Ot as ComboboxGroup,It as ComboboxInput,Tt as ComboboxItem,Lt as ComboboxLabel,At as ComboboxList,_t as ComboboxSeparator,Nt as ComboboxTrigger,Mt as ComboboxValue,Qt as Command,Zt as CommandDialog,oo as CommandEmpty,no as CommandGroup,eo as CommandInput,ao as CommandItem,to as CommandList,ro as CommandSeparator,io as CommandShortcut,so as ContextMenu,wo as ContextMenuCheckboxItem,fo as ContextMenuContent,lo as ContextMenuGroup,go as ContextMenuItem,yo as ContextMenuLabel,uo as ContextMenuPortal,po as ContextMenuRadioGroup,bo as ContextMenuRadioItem,So as ContextMenuSeparator,xo as ContextMenuShortcut,mo as ContextMenuSub,vo as ContextMenuSubContent,ho as ContextMenuSubTrigger,co as ContextMenuTrigger,Ft as Dialog,qt as DialogClose,jt as DialogContent,Xt as DialogDescription,Yt as DialogFooter,Wt as DialogHeader,zt as DialogOverlay,$t as DialogPortal,Jt as DialogTitle,Kt as DialogTrigger,Eo as Drawer,ko as DrawerClose,No as DrawerContent,To as DrawerDescription,Ro as DrawerFooter,Io as DrawerHeader,Mo as DrawerOverlay,Co as DrawerPortal,Ao as DrawerTitle,Po as DrawerTrigger,Oo as DropdownMenu,Uo as DropdownMenuCheckboxItem,Bo as DropdownMenuContent,_o as DropdownMenuGroup,Do as DropdownMenuItem,Fo as DropdownMenuLabel,Lo as DropdownMenuPortal,Vo as DropdownMenuRadioGroup,Go as DropdownMenuRadioItem,Ko as DropdownMenuSeparator,$o as DropdownMenuShortcut,qo as DropdownMenuSub,jo as DropdownMenuSubContent,zo as DropdownMenuSubTrigger,Ho as DropdownMenuTrigger,Wo as Empty,Zo as EmptyContent,Qo as EmptyDescription,Yo as EmptyHeader,Jo as EmptyMedia,Xo as EmptyTitle,rn as Field,an as FieldContent,ln as FieldDescription,un as FieldError,nn as FieldGroup,sn as FieldLabel,on as FieldLegend,dn as FieldSeparator,tn as FieldSet,cn as FieldTitle,mn as HoverCard,fn as HoverCardContent,pn as HoverCardTrigger,wt as Input,yt as InputGroup,St as InputGroupAddon,xt as InputGroupButton,Pt as InputGroupInput,Et as InputGroupText,Ct as InputGroupTextarea,gn as InputOTP,hn as InputOTPGroup,wn as InputOTPSeparator,vn as InputOTPSlot,Sn as Item,kn as ItemActions,En as ItemContent,Cn as ItemDescription,Nn as ItemFooter,bn as ItemGroup,Mn as ItemHeader,xn as ItemMedia,yn as ItemSeparator,Pn as ItemTitle,In as Kbd,Rn as KbdGroup,ti as KeyboardAvoidingView,en as Label,An as Menubar,Un as MenubarCheckboxItem,_n as MenubarContent,On as MenubarGroup,Dn as MenubarItem,Gn as MenubarLabel,Tn as MenubarMenu,Ln as MenubarPortal,Hn as MenubarRadioGroup,Vn as MenubarRadioItem,Fn as MenubarSeparator,Kn as MenubarShortcut,$n as MenubarSub,zn as MenubarSubContent,qn as MenubarSubTrigger,Bn as MenubarTrigger,jn as NavigationMenu,Qn as NavigationMenuContent,tr as NavigationMenuIndicator,Yn as NavigationMenuItem,er as NavigationMenuLink,Wn as NavigationMenuList,Xn as NavigationMenuTrigger,Zn as NavigationMenuViewport,or as Pagination,nr as PaginationContent,cr as PaginationEllipsis,rr as PaginationItem,ar as PaginationLink,sr as PaginationNext,ir as PaginationPrevious,ni as PlatformHeader,lr as Popover,mr as PopoverAnchor,ur as PopoverContent,gr as PopoverDescription,pr as PopoverHeader,fr as PopoverTitle,dr as PopoverTrigger,hr as Progress,vr as RadioGroup,wr as RadioGroupItem,Sr as ResizableHandle,yr as ResizablePanel,br as ResizablePanelGroup,qa as SafeAreaProvider,oi as SafeAreaView,xr as ScrollArea,Er as ScrollBar,Pr as Select,Nr as SelectContent,Cr as SelectGroup,Rr as SelectItem,Ir as SelectLabel,Or as SelectScrollDownButton,Tr as SelectScrollUpButton,Ar as SelectSeparator,Mr as SelectTrigger,kr as SelectValue,Fe as Separator,Lr as Sheet,Br as SheetClose,_r as SheetContent,Gr as SheetDescription,Ur as SheetFooter,Dr as SheetHeader,Vr as SheetTitle,Hr as SheetTrigger,Jr as Sidebar,ra as SidebarContent,oa as SidebarFooter,aa as SidebarGroup,sa as SidebarGroupAction,ca as SidebarGroupContent,ia as SidebarGroupLabel,ta as SidebarHeader,ea as SidebarInput,Zr as SidebarInset,la as SidebarMenu,ma as SidebarMenuAction,pa as SidebarMenuBadge,ua as SidebarMenuButton,da as SidebarMenuItem,fa as SidebarMenuSkeleton,ga as SidebarMenuSub,va as SidebarMenuSubButton,ha as SidebarMenuSubItem,Yr as SidebarProvider,Qr as SidebarRail,na as SidebarSeparator,Xr as SidebarTrigger,Fr as Skeleton,wa as Slider,ya as Spinner,Sa as Switch,xa as Table,Pa as TableBody,Ia as TableCaption,Na as TableCell,Ca as TableFooter,Ma as TableHead,Ea as TableHeader,ka as TableRow,Ra as Tabs,La as TabsContent,Ta as TabsList,Oa as TabsTrigger,bt as Textarea,ba as Toaster,Ba as Toggle,_a as ToggleGroup,Da as ToggleGroupItem,$r as Tooltip,zr as TooltipContent,Kr as TooltipProvider,qr as TooltipTrigger,Oe as badgeVariants,Ke as buttonGroupVariants,ce as buttonVariants,O as cn,Jn as navigationMenuTriggerStyle,Aa as tabsListVariants,Ha as toggleVariants,Ya as useAppState,Wa as useBackHandler,bi as useCamera,ot as useCarousel,pi as useClipboard,za as useColorScheme,Gt as useComboboxAnchor,si as useFocusTimer,hi as useGeolocation,jr as useIsMobile,L as useKeyboard,di as useNotifications,xi as useOllama,Va as useRelayClose,R as useSafeArea,Wr as useSidebar,ja as useStatusBar};
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/use-keyboard.ts","../src/hooks/use-platform.tsx","../src/components/platform.tsx","../src/hooks/use-focus-timer.ts","../src/hooks/use-notifications.ts","../src/hooks/use-clipboard.ts","../src/hooks/use-geolocation.ts","../src/hooks/use-camera.ts","../src/hooks/use-ollama.ts"],"sourcesContent":["import { useState, useEffect, useCallback, useRef } from 'react';\n\ninterface KeyboardState {\n isOpen: boolean;\n height: number;\n}\n\n/**\n * useKeyboard - Track virtual keyboard state on mobile devices\n * \n * Uses visualViewport API to detect keyboard height and provides\n * a safe area offset for positioning UI elements above the keyboard.\n * \n * @returns {KeyboardState} - { isOpen: boolean, height: number }\n */\nexport function useKeyboard(): KeyboardState {\n const [state, setState] = useState<KeyboardState>({\n isOpen: false,\n height: 0\n });\n\n // Track maximum height to detect resizing keyboards\n const maxHeight = useRef(typeof window !== 'undefined' ? window.innerHeight : 0);\n\n useEffect(() => {\n // Check if we're on a mobile device\n const isMobile = /iPad|iPhone|iPod|Android/.test(navigator.userAgent);\n if (!isMobile) return;\n\n const updateKeyboardState = () => {\n if (!window.visualViewport) return;\n\n const viewport = window.visualViewport;\n const currentHeight = window.innerHeight;\n\n // Update baseline if window grows (keyboard closed or orientation change)\n if (currentHeight > maxHeight.current) {\n maxHeight.current = currentHeight;\n }\n\n // 1. Check for overlay keyboard (viewport shrinks, window stays same)\n // This happens on iOS by default\n let keyboardHeight = currentHeight - viewport.height;\n\n // 2. Check for resizing keyboard (window shrinks)\n // This happens on Android and iOS with interactive-widget=resizes-content\n if (keyboardHeight <= 0) {\n keyboardHeight = maxHeight.current - currentHeight;\n }\n\n // Consider keyboard open if height is more than 100px\n const isOpen = keyboardHeight > 100;\n\n setState({\n isOpen,\n height: isOpen ? keyboardHeight : 0\n });\n };\n\n // Listen to visualViewport changes\n if (window.visualViewport) {\n window.visualViewport.addEventListener('resize', updateKeyboardState);\n window.visualViewport.addEventListener('scroll', updateKeyboardState);\n }\n\n // Handle orientation changes to reset baseline\n const handleOrientationChange = () => {\n // Small delay to let resize happen\n setTimeout(() => {\n maxHeight.current = window.innerHeight;\n updateKeyboardState();\n }, 100);\n };\n\n window.addEventListener('orientationchange', handleOrientationChange);\n if (window.screen?.orientation) {\n window.screen.orientation.addEventListener('change', handleOrientationChange);\n }\n\n // Also listen for focus/blur on inputs as fallback\n const handleFocusIn = (e: FocusEvent) => {\n const target = e.target as HTMLElement;\n if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {\n // Small delay to let keyboard animate\n setTimeout(updateKeyboardState, 100);\n }\n };\n\n const handleFocusOut = () => {\n // Small delay to let keyboard animate closed\n setTimeout(() => {\n setState({ isOpen: false, height: 0 });\n }, 100);\n };\n\n document.addEventListener('focusin', handleFocusIn);\n document.addEventListener('focusout', handleFocusOut);\n\n // Initial check\n updateKeyboardState();\n\n return () => {\n window.visualViewport?.removeEventListener('resize', updateKeyboardState);\n window.visualViewport?.removeEventListener('scroll', updateKeyboardState);\n document.removeEventListener('focusin', handleFocusIn);\n document.removeEventListener('focusout', handleFocusOut);\n };\n }, []);\n\n return state;\n}\n\n/**\n * useRelayClose - Get the close function for closing the current app\n * \n * Works with both iframe and blob URL contexts.\n * \n * @returns {() => void} - Function to close the current app\n */\nexport function useRelayClose(): () => void {\n const close = useCallback(() => {\n // 1. PostMessage to self (works in Relay Shell with direct rendering)\n window.postMessage('relay:close', '*');\n\n // 2. PostMessage to parent (works in iframe)\n if (window.parent !== window) {\n window.parent.postMessage('relay:close', '*');\n }\n\n // 3. PostMessage with opener (works if opened as popup)\n if (window.opener) {\n window.opener.postMessage('relay:close', '*');\n }\n }, []);\n\n return close;\n}\n","import { useState, useEffect, useCallback, createContext, useContext, ReactNode } from 'react';\n\n// ============================================\n// SAFE AREA TYPES & CONTEXT\n// ============================================\n\nexport interface SafeAreaInsets {\n top: number;\n bottom: number;\n left: number;\n right: number;\n}\n\nconst defaultInsets: SafeAreaInsets = {\n top: 0,\n bottom: 0,\n left: 0,\n right: 0\n};\n\nconst SafeAreaContext = createContext<SafeAreaInsets>(defaultInsets);\n\n// ============================================\n// SAFE AREA PROVIDER\n// ============================================\n\ninterface SafeAreaProviderProps {\n children: ReactNode;\n}\n\n/**\n * SafeAreaProvider - Provides safe area insets to child components\n * \n * Automatically detects safe areas from:\n * 1. CSS env() values (iOS Safari)\n * 2. Parent Shell postMessage (when running in Relay Shell)\n */\nexport function SafeAreaProvider({ children }: SafeAreaProviderProps) {\n const [insets, setInsets] = useState<SafeAreaInsets>(defaultInsets);\n\n useEffect(() => {\n // Method 1: Read from CSS env() values\n const computeInsets = () => {\n const style = getComputedStyle(document.documentElement);\n const getEnv = (name: string) => {\n const value = style.getPropertyValue(`--safe-area-inset-${name}`);\n return parseInt(value) || 0;\n };\n\n // Try to get from CSS custom properties first\n let top = getEnv('top');\n let bottom = getEnv('bottom');\n let left = getEnv('left');\n let right = getEnv('right');\n\n // If CSS props not set, try to read from env() directly\n if (top === 0 && bottom === 0) {\n // Create a temp element to measure env() values\n const temp = document.createElement('div');\n temp.style.cssText = `\n position: fixed;\n top: env(safe-area-inset-top, 0px);\n bottom: env(safe-area-inset-bottom, 0px);\n left: env(safe-area-inset-left, 0px);\n right: env(safe-area-inset-right, 0px);\n pointer-events: none;\n visibility: hidden;\n `;\n document.body.appendChild(temp);\n const rect = temp.getBoundingClientRect();\n top = rect.top;\n bottom = window.innerHeight - rect.bottom;\n left = rect.left;\n right = window.innerWidth - rect.right;\n document.body.removeChild(temp);\n }\n\n setInsets({ top, bottom, left, right });\n };\n\n // Method 2: Listen for Shell messages\n const handleMessage = (event: MessageEvent) => {\n if (event.data?.type === 'relay:safearea') {\n setInsets(event.data.insets);\n }\n };\n\n computeInsets();\n window.addEventListener('message', handleMessage);\n window.addEventListener('resize', computeInsets);\n\n return () => {\n window.removeEventListener('message', handleMessage);\n window.removeEventListener('resize', computeInsets);\n };\n }, []);\n\n return (\n <SafeAreaContext.Provider value={insets}>\n {children}\n </SafeAreaContext.Provider>\n );\n}\n\n// ============================================\n// SAFE AREA HOOKS\n// ============================================\n\n/**\n * useSafeArea - Get safe area insets\n * \n * @returns SafeAreaInsets with top, bottom, left, right values in pixels\n */\nexport function useSafeArea(): SafeAreaInsets {\n return useContext(SafeAreaContext);\n}\n\n// ============================================\n// COLOR SCHEME\n// ============================================\n\nexport type ColorScheme = 'light' | 'dark';\n\n/**\n * useColorScheme - Get current system color scheme\n * \n * @returns 'light' | 'dark'\n */\nexport function useColorScheme(): ColorScheme {\n const [scheme, setScheme] = useState<ColorScheme>(() =>\n window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n );\n\n useEffect(() => {\n const media = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => {\n setScheme(e.matches ? 'dark' : 'light');\n };\n media.addEventListener('change', handler);\n return () => media.removeEventListener('change', handler);\n }, []);\n\n return scheme;\n}\n\n// ============================================\n// STATUS BAR\n// ============================================\n\n/**\n * useStatusBar - Control the status bar appearance\n * \n * @param color - Hex color for the status bar\n */\nexport function useStatusBar(color: string): void {\n useEffect(() => {\n // Update meta theme-color\n let meta = document.querySelector('meta[name=\"theme-color\"]');\n if (!meta) {\n meta = document.createElement('meta');\n meta.setAttribute('name', 'theme-color');\n document.head.appendChild(meta);\n }\n meta.setAttribute('content', color);\n\n // Notify parent Shell\n window.parent?.postMessage({ type: 'relay:statusbar', color }, '*');\n }, [color]);\n}\n\n// ============================================\n// BACK HANDLER\n// ============================================\n\n/**\n * useBackHandler - Handle back navigation\n * \n * @param handler - Return true to prevent default back behavior\n */\nexport function useBackHandler(handler: () => boolean): void {\n useEffect(() => {\n const handleMessage = (event: MessageEvent) => {\n if (event.data === 'relay:back') {\n const handled = handler();\n if (!handled) {\n // Allow default close behavior\n window.parent?.postMessage('relay:close', '*');\n }\n }\n };\n\n // Also handle browser back button\n const handlePopState = (event: PopStateEvent) => {\n const handled = handler();\n if (handled) {\n // Push a dummy state to prevent navigation\n window.history.pushState(null, '', window.location.href);\n }\n };\n\n // Push initial state for popstate handling\n window.history.pushState(null, '', window.location.href);\n\n window.addEventListener('message', handleMessage);\n window.addEventListener('popstate', handlePopState);\n\n return () => {\n window.removeEventListener('message', handleMessage);\n window.removeEventListener('popstate', handlePopState);\n };\n }, [handler]);\n}\n\n// ============================================\n// APP STATE\n// ============================================\n\nexport type AppState = 'active' | 'background' | 'inactive';\n\n/**\n * useAppState - Track app foreground/background state\n * \n * @returns Current app state\n */\nexport function useAppState(): AppState {\n const [state, setState] = useState<AppState>('active');\n\n useEffect(() => {\n const handleVisibility = () => {\n setState(document.hidden ? 'background' : 'active');\n };\n\n const handleMessage = (event: MessageEvent) => {\n if (event.data === 'relay:foreground') setState('active');\n if (event.data === 'relay:background') setState('background');\n };\n\n document.addEventListener('visibilitychange', handleVisibility);\n window.addEventListener('message', handleMessage);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibility);\n window.removeEventListener('message', handleMessage);\n };\n }, []);\n\n return state;\n}\n","import React, { ReactNode, CSSProperties } from 'react';\nimport { useKeyboard } from '../hooks/use-keyboard';\nimport { useSafeArea } from '../hooks/use-platform';\nimport { cn } from '../lib/utils';\n\n// ============================================\n// KEYBOARD AVOIDING VIEW\n// ============================================\n\ntype KeyboardBehavior = 'padding' | 'height' | 'position';\n\ninterface KeyboardAvoidingViewProps {\n children: ReactNode;\n behavior?: KeyboardBehavior;\n keyboardVerticalOffset?: number;\n style?: CSSProperties;\n className?: string;\n}\n\n/**\n * KeyboardAvoidingView - Automatically adjusts content when keyboard opens\n * \n * @param behavior - How to adjust: 'padding' | 'height' | 'position'\n * @param keyboardVerticalOffset - Additional offset to add\n */\nexport function KeyboardAvoidingView({\n children,\n behavior = 'padding',\n keyboardVerticalOffset = 0,\n style,\n className\n}: KeyboardAvoidingViewProps) {\n const keyboard = useKeyboard();\n const offset = keyboard.height + keyboardVerticalOffset;\n\n const computedStyle: CSSProperties = {\n ...style,\n transition: 'all 0.2s ease-out',\n };\n\n if (keyboard.isOpen) {\n switch (behavior) {\n case 'padding':\n computedStyle.paddingBottom = offset;\n break;\n case 'height':\n computedStyle.height = `calc(100% - ${offset}px)`;\n break;\n case 'position':\n computedStyle.transform = `translateY(-${offset}px)`;\n break;\n }\n }\n\n return (\n <div style={computedStyle} className={className}>\n {children}\n </div>\n );\n}\n\n// ============================================\n// SAFE AREA VIEW\n// ============================================\n\ntype SafeAreaEdge = 'top' | 'bottom' | 'left' | 'right';\n\ninterface SafeAreaViewProps {\n children: ReactNode;\n edges?: SafeAreaEdge[];\n style?: CSSProperties;\n className?: string;\n}\n\n/**\n * SafeAreaView - Container that respects safe area insets\n * \n * @param edges - Which edges to apply safe area to (default: all)\n */\nexport function SafeAreaView({\n children,\n edges = ['top', 'bottom', 'left', 'right'],\n style,\n className\n}: SafeAreaViewProps) {\n const insets = useSafeArea();\n\n const computedStyle: CSSProperties = {\n ...style,\n paddingTop: edges.includes('top') ? insets.top : style?.paddingTop,\n paddingBottom: edges.includes('bottom') ? insets.bottom : style?.paddingBottom,\n paddingLeft: edges.includes('left') ? insets.left : style?.paddingLeft,\n paddingRight: edges.includes('right') ? insets.right : style?.paddingRight,\n };\n\n return (\n <div style={computedStyle} className={className}>\n {children}\n </div>\n );\n}\n\n// ============================================\n// PLATFORM HEADER\n// ============================================\n\ninterface PlatformHeaderProps {\n title: string;\n showBack?: boolean;\n onBack?: () => void;\n className?: string;\n rightElement?: ReactNode;\n}\n\nexport function PlatformHeader({\n title,\n showBack = true,\n onBack,\n className,\n rightElement\n}: PlatformHeaderProps) {\n const insets = useSafeArea();\n\n return (\n <div \n className={cn(\"bg-background border-b flex flex-col z-50\", className)}\n style={{ paddingTop: insets.top }}\n >\n <div className=\"h-14 flex items-center justify-between px-4\">\n <div className=\"flex items-center gap-4 flex-1\">\n {showBack && (\n <button \n onClick={onBack || (() => window.history.back())}\n className=\"p-2 -ml-2 hover:bg-muted rounded-full transition-colors\"\n >\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M19 12H5M12 19l-7-7 7-7\" />\n </svg>\n </button>\n )}\n <h1 className=\"text-lg font-semibold truncate\">{title}</h1>\n </div>\n {rightElement && (\n <div className=\"flex-none\">\n {rightElement}\n </div>\n )}\n </div>\n </div>\n );\n}\n","import { useState, useEffect } from 'react';\n\nexport type TimerMode = 'focus' | 'shortBreak' | 'longBreak';\nexport type StoryState = 'egg' | 'cracked' | 'chick' | 'alien' | 'ghost';\n\nexport function useFocusTimer() {\n const [seconds, setSeconds] = useState(25 * 60);\n const [initialTime, setInitialTime] = useState(25 * 60);\n const [isActive, setIsActive] = useState(false);\n const [mode, setMode] = useState<TimerMode>('focus');\n const [task, setTask] = useState('');\n const [storyState, setStoryState] = useState<StoryState>('egg');\n const [soundEnabled, setSoundEnabled] = useState(false);\n\n useEffect(() => {\n let interval: any = null;\n\n if (isActive && seconds > 0) {\n interval = setInterval(() => {\n setSeconds((s) => s - 1);\n }, 1000);\n } else if (seconds === 0 && isActive) {\n // Timer Finished\n setIsActive(false);\n if (mode === 'focus') {\n const isAbducted = Math.random() < 0.01;\n setStoryState(isAbducted ? 'alien' : 'chick');\n }\n }\n\n return () => {\n if (interval) clearInterval(interval);\n };\n }, [isActive, seconds, mode]);\n\n // Update Visuals based on progress\n useEffect(() => {\n if (!isActive && (storyState === 'chick' || storyState === 'alien' || storyState === 'ghost')) return;\n\n // Don't change chick state during break\n if (mode !== 'focus') return;\n\n const progress = 1 - (seconds / initialTime);\n\n if (progress < 0.5) {\n setStoryState('egg');\n } else if (progress >= 0.5 && progress < 1) {\n setStoryState('cracked');\n }\n }, [seconds, initialTime, isActive, storyState, mode]);\n\n const toggleTimer = () => setIsActive(!isActive);\n\n const giveUp = () => {\n setIsActive(false);\n setStoryState('ghost');\n };\n\n const switchMode = (newMode: TimerMode) => {\n setIsActive(false);\n setMode(newMode);\n setStoryState('egg'); // Reset chick for new session\n\n // Set Times\n let newTime = 25 * 60;\n if (newMode === 'shortBreak') newTime = 5 * 60;\n if (newMode === 'longBreak') newTime = 15 * 60;\n\n setSeconds(newTime);\n setInitialTime(newTime);\n };\n\n const resetTimer = () => {\n setIsActive(false);\n switchMode(mode); // Re-init current mode\n };\n\n const setCustomTime = (mins: number) => {\n setIsActive(false);\n setSeconds(mins * 60);\n setInitialTime(mins * 60);\n setStoryState('egg');\n };\n\n return {\n seconds,\n initialTime,\n isActive,\n mode,\n task,\n storyState,\n soundEnabled,\n setSeconds,\n setInitialTime,\n setIsActive,\n setMode,\n setTask,\n setStoryState,\n setSoundEnabled,\n toggleTimer,\n giveUp,\n switchMode,\n resetTimer,\n setCustomTime,\n };\n}\n","import { useState, useCallback, useEffect } from 'react';\n\nexport interface NotificationOptions {\n body?: string;\n icon?: string;\n image?: string;\n badge?: string;\n tag?: string;\n data?: any;\n vibrate?: number[];\n timestamp?: number;\n renotify?: boolean;\n silent?: boolean;\n requireInteraction?: boolean;\n actions?: NotificationAction[];\n}\n\nexport interface NotificationAction {\n action: string;\n title: string;\n icon?: string;\n}\n\nexport interface UseNotificationsReturn {\n permission: NotificationPermission;\n requestPermission: () => Promise<NotificationPermission>;\n sendNotification: (title: string, options?: NotificationOptions) => void;\n scheduleNotification: (title: string, delayMs: number, options?: NotificationOptions) => void;\n clearBadge: () => Promise<void>;\n setBadge: (count: number) => Promise<void>;\n}\n\nexport function useNotifications(): UseNotificationsReturn {\n const [permission, setPermission] = useState<NotificationPermission>('default');\n\n useEffect(() => {\n if ('Notification' in window) {\n setPermission(Notification.permission);\n }\n }, []);\n\n const requestPermission = useCallback(async () => {\n if (!('Notification' in window)) {\n console.warn('Notifications not supported');\n return 'denied';\n }\n const perm = await Notification.requestPermission();\n setPermission(perm);\n return perm;\n }, []);\n\n const sendNotification = useCallback((title: string, options?: NotificationOptions) => {\n if (!('Notification' in window)) return;\n \n // Auto-detect icon if not provided\n let notificationOptions = options;\n if (!options?.icon) {\n // Try to find apple-touch-icon or shortcut icon\n const iconLink = document.querySelector('link[rel=\"apple-touch-icon\"]') || \n document.querySelector('link[rel=\"icon\"]');\n if (iconLink) {\n notificationOptions = {\n ...options,\n icon: (iconLink as HTMLLinkElement).href\n };\n }\n }\n\n if (Notification.permission === 'granted') {\n new Notification(title, notificationOptions);\n } else if (Notification.permission !== 'denied') {\n Notification.requestPermission().then((perm) => {\n if (perm === 'granted') {\n new Notification(title, notificationOptions);\n }\n });\n }\n }, []);\n\n const scheduleNotification = useCallback((title: string, delayMs: number, options?: NotificationOptions) => {\n setTimeout(() => {\n sendNotification(title, options);\n }, delayMs);\n }, [sendNotification]);\n\n const setBadge = useCallback(async (count: number) => {\n if ('setAppBadge' in navigator) {\n try {\n await (navigator as any).setAppBadge(count);\n } catch (e) {\n console.error('Error setting badge:', e);\n }\n }\n }, []);\n\n const clearBadge = useCallback(async () => {\n if ('clearAppBadge' in navigator) {\n try {\n await (navigator as any).clearAppBadge();\n } catch (e) {\n console.error('Error clearing badge:', e);\n }\n }\n }, []);\n\n return {\n permission,\n requestPermission,\n sendNotification,\n scheduleNotification,\n setBadge,\n clearBadge\n };\n}\n","import { useState, useCallback, useEffect } from 'react';\n\nexport interface ClipboardItem {\n type: 'text' | 'image' | 'html';\n content: string | Blob;\n timestamp: number;\n}\n\nexport interface UseClipboardReturn {\n clipboardContent: string | null;\n history: ClipboardItem[];\n copyText: (text: string) => Promise<void>;\n copyImage: (blob: Blob) => Promise<void>;\n readText: () => Promise<string>;\n readContent: () => Promise<ClipboardItems>;\n clearHistory: () => void;\n}\n\nconst HISTORY_KEY = 'relay_clipboard_history';\nconst MAX_HISTORY = 10;\n\nexport function useClipboard(): UseClipboardReturn {\n const [clipboardContent, setClipboardContent] = useState<string | null>(null);\n const [history, setHistory] = useState<ClipboardItem[]>([]);\n\n // Load history from local storage on mount\n useEffect(() => {\n try {\n const savedHistory = localStorage.getItem(HISTORY_KEY);\n if (savedHistory) {\n // Note: We can only restore text items easily from localStorage\n const parsed = JSON.parse(savedHistory);\n setHistory(parsed);\n }\n } catch (e) {\n console.error('Failed to load clipboard history', e);\n }\n }, []);\n\n const addToHistory = useCallback((item: ClipboardItem) => {\n setHistory(prev => {\n const newHistory = [item, ...prev].slice(0, MAX_HISTORY);\n // Only save text items to localStorage to avoid quota issues\n const textOnlyHistory = newHistory.filter(i => i.type === 'text');\n try {\n localStorage.setItem(HISTORY_KEY, JSON.stringify(textOnlyHistory));\n } catch (e) {\n console.error('Failed to save clipboard history', e);\n }\n return newHistory;\n });\n }, []);\n\n const copyText = useCallback(async (text: string) => {\n if (!navigator.clipboard) {\n console.warn('Clipboard API not supported');\n return;\n }\n try {\n await navigator.clipboard.writeText(text);\n setClipboardContent(text);\n addToHistory({\n type: 'text',\n content: text,\n timestamp: Date.now()\n });\n } catch (e) {\n console.error('Failed to copy text:', e);\n throw e;\n }\n }, [addToHistory]);\n\n const copyImage = useCallback(async (blob: Blob) => {\n if (!navigator.clipboard) {\n console.warn('Clipboard API not supported');\n return;\n }\n try {\n await navigator.clipboard.write([\n new ClipboardItem({\n [blob.type]: blob\n })\n ]);\n addToHistory({\n type: 'image',\n content: blob, // Note: This won't be persisted to localStorage\n timestamp: Date.now()\n });\n } catch (e) {\n console.error('Failed to copy image:', e);\n throw e;\n }\n }, [addToHistory]);\n\n const readText = useCallback(async () => {\n if (!navigator.clipboard) {\n console.warn('Clipboard API not supported');\n return '';\n }\n try {\n const text = await navigator.clipboard.readText();\n setClipboardContent(text);\n return text;\n } catch (e) {\n console.error('Failed to read text:', e);\n throw e;\n }\n }, []);\n\n const readContent = useCallback(async () => {\n if (!navigator.clipboard) {\n console.warn('Clipboard API not supported');\n return [] as unknown as ClipboardItems;\n }\n try {\n return await navigator.clipboard.read();\n } catch (e) {\n console.error('Failed to read content:', e);\n throw e;\n }\n }, []);\n\n const clearHistory = useCallback(() => {\n setHistory([]);\n localStorage.removeItem(HISTORY_KEY);\n }, []);\n\n // Listen for clipboard changes (focus based)\n useEffect(() => {\n const handleFocus = () => {\n readText().catch(() => {});\n };\n window.addEventListener('focus', handleFocus);\n return () => window.removeEventListener('focus', handleFocus);\n }, [readText]);\n\n return {\n clipboardContent,\n history,\n copyText,\n copyImage,\n readText,\n readContent,\n clearHistory\n };\n}\n","import { useState, useCallback, useEffect, useRef } from 'react';\n\nexport interface LocationState {\n loading: boolean;\n accuracy: number | null;\n altitude: number | null;\n altitudeAccuracy: number | null;\n heading: number | null;\n latitude: number | null;\n longitude: number | null;\n speed: number | null;\n timestamp: number | null;\n error: GeolocationPositionError | null;\n}\n\nexport interface Geofence {\n id: string;\n latitude: number;\n longitude: number;\n radius: number; // meters\n}\n\nexport interface UseGeolocationReturn extends LocationState {\n getLocation: () => void;\n watchLocation: (options?: PositionOptions) => void;\n clearWatch: () => void;\n checkGeofence: (fence: Geofence) => boolean;\n distanceTo: (lat: number, lng: number) => number;\n}\n\nexport function useGeolocation(options?: PositionOptions): UseGeolocationReturn {\n const [state, setState] = useState<LocationState>({\n loading: true,\n accuracy: null,\n altitude: null,\n altitudeAccuracy: null,\n heading: null,\n latitude: null,\n longitude: null,\n speed: null,\n timestamp: null,\n error: null,\n });\n\n const watchId = useRef<number | null>(null);\n\n const onEvent = useCallback((position: GeolocationPosition) => {\n setState({\n loading: false,\n accuracy: position.coords.accuracy,\n altitude: position.coords.altitude,\n altitudeAccuracy: position.coords.altitudeAccuracy,\n heading: position.coords.heading,\n latitude: position.coords.latitude,\n longitude: position.coords.longitude,\n speed: position.coords.speed,\n timestamp: position.timestamp,\n error: null,\n });\n }, []);\n\n const onError = useCallback((error: GeolocationPositionError) => {\n setState((s) => ({\n ...s,\n loading: false,\n error,\n }));\n }, []);\n\n const getLocation = useCallback(() => {\n if (!navigator.geolocation) {\n setState((s) => ({\n ...s,\n loading: false,\n error: {\n code: 0,\n message: 'Geolocation not supported',\n PERMISSION_DENIED: 1,\n POSITION_UNAVAILABLE: 2,\n TIMEOUT: 3,\n } as GeolocationPositionError,\n }));\n return;\n }\n\n setState((s) => ({ ...s, loading: true }));\n navigator.geolocation.getCurrentPosition(onEvent, onError, options);\n }, [onEvent, onError, options]);\n\n const watchLocation = useCallback((watchOptions?: PositionOptions) => {\n if (!navigator.geolocation) return;\n \n if (watchId.current !== null) {\n navigator.geolocation.clearWatch(watchId.current);\n }\n\n watchId.current = navigator.geolocation.watchPosition(\n onEvent,\n onError,\n watchOptions || options\n );\n }, [onEvent, onError, options]);\n\n const clearWatch = useCallback(() => {\n if (watchId.current !== null) {\n navigator.geolocation.clearWatch(watchId.current);\n watchId.current = null;\n }\n }, []);\n\n // Helper to calculate distance in meters (Haversine formula)\n const distanceTo = useCallback((lat: number, lng: number) => {\n if (state.latitude === null || state.longitude === null) return Infinity;\n\n const R = 6371e3; // metres\n const φ1 = state.latitude * Math.PI / 180;\n const φ2 = lat * Math.PI / 180;\n const Δφ = (lat - state.latitude) * Math.PI / 180;\n const Δλ = (lng - state.longitude) * Math.PI / 180;\n\n const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +\n Math.cos(φ1) * Math.cos(φ2) *\n Math.sin(Δλ / 2) * Math.sin(Δλ / 2);\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\n return R * c;\n }, [state.latitude, state.longitude]);\n\n const checkGeofence = useCallback((fence: Geofence) => {\n const distance = distanceTo(fence.latitude, fence.longitude);\n return distance <= fence.radius;\n }, [distanceTo]);\n\n useEffect(() => {\n return () => {\n if (watchId.current !== null) {\n navigator.geolocation.clearWatch(watchId.current);\n }\n };\n }, []);\n\n return {\n ...state,\n getLocation,\n watchLocation,\n clearWatch,\n checkGeofence,\n distanceTo,\n };\n}\n","import { useState, useCallback, useRef, useEffect } from 'react';\n\nexport interface CameraState {\n stream: MediaStream | null;\n error: Error | null;\n permission: PermissionState | 'unknown';\n isRecording: boolean;\n devices: MediaDeviceInfo[];\n}\n\nexport interface CameraOptions {\n video?: boolean | MediaTrackConstraints;\n audio?: boolean | MediaTrackConstraints;\n}\n\nexport interface UseCameraReturn extends CameraState {\n startCamera: (options?: CameraOptions) => Promise<MediaStream | undefined>;\n stopCamera: () => void;\n takePhoto: () => Promise<string | undefined>;\n startRecording: () => void;\n stopRecording: () => Promise<Blob | undefined>;\n startScreenShare: (options?: DisplayMediaStreamOptions) => Promise<MediaStream | undefined>;\n switchDevice: (deviceId: string, kind: 'video' | 'audio') => Promise<void>;\n getDevices: () => Promise<MediaDeviceInfo[]>;\n}\n\nexport function useCamera(): UseCameraReturn {\n const [state, setState] = useState<CameraState>({\n stream: null,\n error: null,\n permission: 'unknown',\n isRecording: false,\n devices: []\n });\n\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const chunksRef = useRef<Blob[]>([]);\n\n const getDevices = useCallback(async () => {\n if (!navigator.mediaDevices?.enumerateDevices) return [];\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n setState(s => ({ ...s, devices }));\n return devices;\n } catch (e) {\n console.error('Error enumerating devices:', e);\n return [];\n }\n }, []);\n\n // Initial device list\n useEffect(() => {\n getDevices();\n navigator.mediaDevices?.addEventListener('devicechange', getDevices);\n return () => {\n navigator.mediaDevices?.removeEventListener('devicechange', getDevices);\n };\n }, [getDevices]);\n\n const startCamera = useCallback(async (options: CameraOptions = { video: true, audio: false }) => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia(options);\n setState(s => ({ ...s, stream, error: null, permission: 'granted' }));\n return stream;\n } catch (e) {\n const error = e as Error;\n setState(s => ({ ...s, error, permission: 'denied' }));\n console.error('Error starting camera:', e);\n }\n }, []);\n\n const stopCamera = useCallback(() => {\n if (state.stream) {\n state.stream.getTracks().forEach(track => track.stop());\n setState(s => ({ ...s, stream: null, isRecording: false }));\n }\n }, [state.stream]);\n\n const startScreenShare = useCallback(async (options: DisplayMediaStreamOptions = { video: true }) => {\n try {\n const stream = await navigator.mediaDevices.getDisplayMedia(options);\n setState(s => ({ ...s, stream, error: null, permission: 'granted' }));\n return stream;\n } catch (e) {\n const error = e as Error;\n setState(s => ({ ...s, error, permission: 'denied' }));\n console.error('Error starting screen share:', e);\n }\n }, []);\n\n const takePhoto = useCallback(async () => {\n if (!state.stream) return;\n\n const videoTrack = state.stream.getVideoTracks()[0];\n if (!videoTrack) return;\n\n // Create a video element to capture the frame\n const video = document.createElement('video');\n video.srcObject = state.stream;\n await video.play();\n\n const canvas = document.createElement('canvas');\n canvas.width = video.videoWidth;\n canvas.height = video.videoHeight;\n \n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n \n ctx.drawImage(video, 0, 0);\n const dataUrl = canvas.toDataURL('image/png');\n \n // Cleanup\n video.pause();\n video.srcObject = null;\n \n return dataUrl;\n }, [state.stream]);\n\n const startRecording = useCallback(() => {\n if (!state.stream) return;\n\n try {\n const mediaRecorder = new MediaRecorder(state.stream);\n mediaRecorderRef.current = mediaRecorder;\n chunksRef.current = [];\n\n mediaRecorder.ondataavailable = (e) => {\n if (e.data.size > 0) {\n chunksRef.current.push(e.data);\n }\n };\n\n mediaRecorder.start();\n setState(s => ({ ...s, isRecording: true }));\n } catch (e) {\n console.error('Error starting recording:', e);\n setState(s => ({ ...s, error: e as Error }));\n }\n }, [state.stream]);\n\n const stopRecording = useCallback(async () => {\n if (!mediaRecorderRef.current || mediaRecorderRef.current.state === 'inactive') return;\n\n return new Promise<Blob>((resolve) => {\n if (!mediaRecorderRef.current) return;\n \n mediaRecorderRef.current.onstop = () => {\n const blob = new Blob(chunksRef.current, { type: 'video/webm' });\n setState(s => ({ ...s, isRecording: false }));\n resolve(blob);\n };\n\n mediaRecorderRef.current.stop();\n });\n }, []);\n\n const switchDevice = useCallback(async (deviceId: string, kind: 'video' | 'audio') => {\n stopCamera();\n const constraints = {\n [kind]: { deviceId: { exact: deviceId } }\n };\n await startCamera(constraints);\n }, [startCamera, stopCamera]);\n\n useEffect(() => {\n return () => {\n stopCamera();\n };\n }, []);\n\n return {\n ...state,\n startCamera,\n stopCamera,\n takePhoto,\n startRecording,\n stopRecording,\n startScreenShare,\n switchDevice,\n getDevices\n };\n}\n","import { useState, useCallback, useEffect } from 'react';\n\nexport interface OllamaModel {\n name: string;\n modified_at: string;\n size: number;\n digest: string;\n details: {\n parent_model: string;\n format: string;\n family: string;\n families: string[];\n parameter_size: string;\n quantization_level: string;\n };\n}\n\nexport interface OllamaResponse {\n model: string;\n created_at: string;\n response?: string; // for /api/generate\n message?: { // for /api/chat\n role: string;\n content: string;\n };\n done: boolean;\n context?: number[];\n total_duration?: number;\n load_duration?: number;\n prompt_eval_count?: number;\n prompt_eval_duration?: number;\n eval_count?: number;\n eval_duration?: number;\n}\n\nexport interface UseOllamaReturn {\n available: boolean;\n loading: boolean;\n models: OllamaModel[];\n refreshModels: () => Promise<void>;\n generate: (model: string, prompt: string, options?: any) => Promise<OllamaResponse>;\n chat: (model: string, messages: { role: string; content: string }[], options?: any) => Promise<OllamaResponse>;\n}\n\nexport function useOllama(): UseOllamaReturn {\n const [available, setAvailable] = useState(false);\n const [loading, setLoading] = useState(false);\n const [models, setModels] = useState<OllamaModel[]>([]);\n\n /**\n * Helper Discovery Logic:\n * 1. Prioritize Shell-injected host (window.__RELAY_HELPER_HOST__)\n * 2. Fallback to relative paths if served by the Helper\n * 3. Fallback to dynamic host detection (for PWA/IP access)\n */\n const getHelperUrl = () => {\n if (typeof window === 'undefined') return 'http://localhost:5378';\n\n // @ts-ignore - Injected by Relay Shell\n const injectedHost = window.__RELAY_HELPER_HOST__;\n if (injectedHost) return injectedHost;\n\n const { protocol, hostname, port: currentPort } = window.location;\n\n // If we are served by the Helper itself, use relative paths\n if (currentPort === '5378' || currentPort === '5379') {\n return '';\n }\n\n // Fallback for development or standalone PWAs\n const isHttps = protocol === 'https:';\n const helperPort = isHttps ? 5379 : 5378;\n return `${protocol}//${hostname}:${helperPort}`;\n };\n\n const HELPER_URL = getHelperUrl();\n\n const checkStatus = useCallback(async () => {\n try {\n const res = await fetch(`${HELPER_URL}/api/config`);\n const data = await res.json();\n setAvailable(data.ollama?.available ?? false);\n } catch (e) {\n setAvailable(false);\n }\n }, []);\n\n const refreshModels = useCallback(async () => {\n setLoading(true);\n try {\n const res = await fetch(`${HELPER_URL}/api/ollama/api/tags`);\n if (res.ok) {\n const data = await res.json();\n setModels(data.models || []);\n }\n } catch (e) {\n console.error('Failed to fetch Ollama models:', e);\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n checkStatus();\n const interval = setInterval(checkStatus, 30000);\n return () => clearInterval(interval);\n }, [checkStatus]);\n\n useEffect(() => {\n if (available) {\n refreshModels();\n }\n }, [available, refreshModels]);\n\n const generate = useCallback(async (model: string, prompt: string, options = {}): Promise<OllamaResponse> => {\n const res = await fetch(`${HELPER_URL}/api/ollama/api/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model, prompt, stream: false, ...options })\n });\n\n if (!res.ok) throw new Error(`Ollama generation failed: ${res.statusText}`);\n return await res.json();\n }, []);\n\n const chat = useCallback(async (model: string, messages: { role: string; content: string }[], options = {}): Promise<OllamaResponse> => {\n const res = await fetch(`${HELPER_URL}/api/ollama/api/chat`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model, messages, stream: false, ...options })\n });\n\n if (!res.ok) throw new Error(`Ollama chat failed: ${res.statusText}`);\n return await res.json();\n }, []);\n\n return {\n available,\n loading,\n models,\n refreshModels,\n generate,\n chat\n };\n}\n"],"mappings":"0pFAAA,OAAS,YAAAA,EAAU,aAAAC,EAAW,eAAAC,EAAa,UAAAC,MAAc,QAelD,SAASC,GAA6B,CACzC,GAAM,CAACC,EAAOC,CAAQ,EAAIN,EAAwB,CAC9C,OAAQ,GACR,OAAQ,CACZ,CAAC,EAGKO,EAAYJ,EAAO,OAAO,OAAW,IAAc,OAAO,YAAc,CAAC,EAE/E,OAAAF,EAAU,IAAM,CAGZ,GAAI,CADa,2BAA2B,KAAK,UAAU,SAAS,EACrD,OAEf,IAAMO,EAAsB,IAAM,CAC9B,GAAI,CAAC,OAAO,eAAgB,OAE5B,IAAMC,EAAW,OAAO,eAClBC,EAAgB,OAAO,YAGzBA,EAAgBH,EAAU,UAC1BA,EAAU,QAAUG,GAKxB,IAAIC,EAAiBD,EAAgBD,EAAS,OAI1CE,GAAkB,IAClBA,EAAiBJ,EAAU,QAAUG,GAIzC,IAAME,EAASD,EAAiB,IAEhCL,EAAS,CACL,OAAAM,EACA,OAAQA,EAASD,EAAiB,CACtC,CAAC,CACL,EAGI,OAAO,iBACP,OAAO,eAAe,iBAAiB,SAAUH,CAAmB,EACpE,OAAO,eAAe,iBAAiB,SAAUA,CAAmB,GAIxE,IAAMK,EAA0B,IAAM,CAElC,WAAW,IAAM,CACbN,EAAU,QAAU,OAAO,YAC3BC,EAAoB,CACxB,EAAG,GAAG,CACV,EAEA,OAAO,iBAAiB,oBAAqBK,CAAuB,EAChE,OAAO,QAAQ,aACf,OAAO,OAAO,YAAY,iBAAiB,SAAUA,CAAuB,EAIhF,IAAMC,EAAiBC,GAAkB,CACrC,IAAMC,EAASD,EAAE,QACbC,EAAO,UAAY,SAAWA,EAAO,UAAY,aAEjD,WAAWR,EAAqB,GAAG,CAE3C,EAEMS,EAAiB,IAAM,CAEzB,WAAW,IAAM,CACbX,EAAS,CAAE,OAAQ,GAAO,OAAQ,CAAE,CAAC,CACzC,EAAG,GAAG,CACV,EAEA,gBAAS,iBAAiB,UAAWQ,CAAa,EAClD,SAAS,iBAAiB,WAAYG,CAAc,EAGpDT,EAAoB,EAEb,IAAM,CACT,OAAO,gBAAgB,oBAAoB,SAAUA,CAAmB,EACxE,OAAO,gBAAgB,oBAAoB,SAAUA,CAAmB,EACxE,SAAS,oBAAoB,UAAWM,CAAa,EACrD,SAAS,oBAAoB,WAAYG,CAAc,CAC3D,CACJ,EAAG,CAAC,CAAC,EAEEZ,CACX,CASO,SAASa,IAA4B,CAgBxC,OAfchB,EAAY,IAAM,CAE5B,OAAO,YAAY,cAAe,GAAG,EAGjC,OAAO,SAAW,QAClB,OAAO,OAAO,YAAY,cAAe,GAAG,EAI5C,OAAO,QACP,OAAO,OAAO,YAAY,cAAe,GAAG,CAEpD,EAAG,CAAC,CAAC,CAGT,CCxIA,OAAS,YAAAiB,EAAU,aAAAC,EAAwB,iBAAAC,EAAe,cAAAC,MAA6B,QAkG/E,cAAAC,MAAA,oBArFR,IAAMC,EAAgC,CAClC,IAAK,EACL,OAAQ,EACR,KAAM,EACN,MAAO,CACX,EAEMC,EAAkBJ,EAA8BG,CAAa,EAiB5D,SAASE,GAAiB,CAAE,SAAAC,CAAS,EAA0B,CAClE,GAAM,CAACC,EAAQC,CAAS,EAAIV,EAAyBK,CAAa,EAElE,OAAAJ,EAAU,IAAM,CAEZ,IAAMU,EAAgB,IAAM,CACxB,IAAMC,EAAQ,iBAAiB,SAAS,eAAe,EACjDC,EAAUC,GAAiB,CAC7B,IAAMC,EAAQH,EAAM,iBAAiB,qBAAqBE,CAAI,EAAE,EAChE,OAAO,SAASC,CAAK,GAAK,CAC9B,EAGIC,EAAMH,EAAO,KAAK,EAClBI,EAASJ,EAAO,QAAQ,EACxBK,EAAOL,EAAO,MAAM,EACpBM,EAAQN,EAAO,OAAO,EAG1B,GAAIG,IAAQ,GAAKC,IAAW,EAAG,CAE3B,IAAMG,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UASrB,SAAS,KAAK,YAAYA,CAAI,EAC9B,IAAMC,EAAOD,EAAK,sBAAsB,EACxCJ,EAAMK,EAAK,IACXJ,EAAS,OAAO,YAAcI,EAAK,OACnCH,EAAOG,EAAK,KACZF,EAAQ,OAAO,WAAaE,EAAK,MACjC,SAAS,KAAK,YAAYD,CAAI,CAClC,CAEAV,EAAU,CAAE,IAAAM,EAAK,OAAAC,EAAQ,KAAAC,EAAM,MAAAC,CAAM,CAAC,CAC1C,EAGMG,EAAiBC,GAAwB,CACvCA,EAAM,MAAM,OAAS,kBACrBb,EAAUa,EAAM,KAAK,MAAM,CAEnC,EAEA,OAAAZ,EAAc,EACd,OAAO,iBAAiB,UAAWW,CAAa,EAChD,OAAO,iBAAiB,SAAUX,CAAa,EAExC,IAAM,CACT,OAAO,oBAAoB,UAAWW,CAAa,EACnD,OAAO,oBAAoB,SAAUX,CAAa,CACtD,CACJ,EAAG,CAAC,CAAC,EAGDP,EAACE,EAAgB,SAAhB,CAAyB,MAAOG,EAC5B,SAAAD,EACL,CAER,CAWO,SAASgB,GAA8B,CAC1C,OAAOrB,EAAWG,CAAe,CACrC,CAaO,SAASmB,IAA8B,CAC1C,GAAM,CAACC,EAAQC,CAAS,EAAI3B,EAAsB,IAC9C,OAAO,WAAW,8BAA8B,EAAE,QAAU,OAAS,OACzE,EAEA,OAAAC,EAAU,IAAM,CACZ,IAAM2B,EAAQ,OAAO,WAAW,8BAA8B,EACxDC,EAAWC,GAA2B,CACxCH,EAAUG,EAAE,QAAU,OAAS,OAAO,CAC1C,EACA,OAAAF,EAAM,iBAAiB,SAAUC,CAAO,EACjC,IAAMD,EAAM,oBAAoB,SAAUC,CAAO,CAC5D,EAAG,CAAC,CAAC,EAEEH,CACX,CAWO,SAASK,GAAaC,EAAqB,CAC9C/B,EAAU,IAAM,CAEZ,IAAIgC,EAAO,SAAS,cAAc,0BAA0B,EACvDA,IACDA,EAAO,SAAS,cAAc,MAAM,EACpCA,EAAK,aAAa,OAAQ,aAAa,EACvC,SAAS,KAAK,YAAYA,CAAI,GAElCA,EAAK,aAAa,UAAWD,CAAK,EAGlC,OAAO,QAAQ,YAAY,CAAE,KAAM,kBAAmB,MAAAA,CAAM,EAAG,GAAG,CACtE,EAAG,CAACA,CAAK,CAAC,CACd,CAWO,SAASE,GAAeL,EAA8B,CACzD5B,EAAU,IAAM,CACZ,IAAMqB,EAAiBC,GAAwB,CACvCA,EAAM,OAAS,eACCM,EAAQ,GAGpB,OAAO,QAAQ,YAAY,cAAe,GAAG,EAGzD,EAGMM,EAAkBZ,GAAyB,CAC7BM,EAAQ,GAGpB,OAAO,QAAQ,UAAU,KAAM,GAAI,OAAO,SAAS,IAAI,CAE/D,EAGA,cAAO,QAAQ,UAAU,KAAM,GAAI,OAAO,SAAS,IAAI,EAEvD,OAAO,iBAAiB,UAAWP,CAAa,EAChD,OAAO,iBAAiB,WAAYa,CAAc,EAE3C,IAAM,CACT,OAAO,oBAAoB,UAAWb,CAAa,EACnD,OAAO,oBAAoB,WAAYa,CAAc,CACzD,CACJ,EAAG,CAACN,CAAO,CAAC,CAChB,CAaO,SAASO,IAAwB,CACpC,GAAM,CAACC,EAAOC,CAAQ,EAAItC,EAAmB,QAAQ,EAErD,OAAAC,EAAU,IAAM,CACZ,IAAMsC,EAAmB,IAAM,CAC3BD,EAAS,SAAS,OAAS,aAAe,QAAQ,CACtD,EAEMhB,EAAiBC,GAAwB,CACvCA,EAAM,OAAS,oBAAoBe,EAAS,QAAQ,EACpDf,EAAM,OAAS,oBAAoBe,EAAS,YAAY,CAChE,EAEA,gBAAS,iBAAiB,mBAAoBC,CAAgB,EAC9D,OAAO,iBAAiB,UAAWjB,CAAa,EAEzC,IAAM,CACT,SAAS,oBAAoB,mBAAoBiB,CAAgB,EACjE,OAAO,oBAAoB,UAAWjB,CAAa,CACvD,CACJ,EAAG,CAAC,CAAC,EAEEe,CACX,CChMQ,cAAAG,EA0EQ,QAAAC,MA1ER,oBA9BD,SAASC,GAAqB,CACjC,SAAAC,EACA,SAAAC,EAAW,UACX,uBAAAC,EAAyB,EACzB,MAAAC,EACA,UAAAC,CACJ,EAA8B,CAC1B,IAAMC,EAAWC,EAAY,EACvBC,EAASF,EAAS,OAASH,EAE3BM,EAA+B,CACjC,GAAGL,EACH,WAAY,mBAChB,EAEA,GAAIE,EAAS,OACT,OAAQJ,EAAU,CACd,IAAK,UACDO,EAAc,cAAgBD,EAC9B,MACJ,IAAK,SACDC,EAAc,OAAS,eAAeD,CAAM,MAC5C,MACJ,IAAK,WACDC,EAAc,UAAY,eAAeD,CAAM,MAC/C,KACR,CAGJ,OACIV,EAAC,OAAI,MAAOW,EAAe,UAAWJ,EACjC,SAAAJ,EACL,CAER,CAoBO,SAASS,GAAa,CACzB,SAAAT,EACA,MAAAU,EAAQ,CAAC,MAAO,SAAU,OAAQ,OAAO,EACzC,MAAAP,EACA,UAAAC,CACJ,EAAsB,CAClB,IAAMO,EAASC,EAAY,EAErBJ,EAA+B,CACjC,GAAGL,EACH,WAAYO,EAAM,SAAS,KAAK,EAAIC,EAAO,IAAMR,GAAO,WACxD,cAAeO,EAAM,SAAS,QAAQ,EAAIC,EAAO,OAASR,GAAO,cACjE,YAAaO,EAAM,SAAS,MAAM,EAAIC,EAAO,KAAOR,GAAO,YAC3D,aAAcO,EAAM,SAAS,OAAO,EAAIC,EAAO,MAAQR,GAAO,YAClE,EAEA,OACIN,EAAC,OAAI,MAAOW,EAAe,UAAWJ,EACjC,SAAAJ,EACL,CAER,CAcO,SAASa,GAAe,CAC3B,MAAAC,EACA,SAAAC,EAAW,GACX,OAAAC,EACA,UAAAZ,EACA,aAAAa,CACJ,EAAwB,CACpB,IAAMN,EAASC,EAAY,EAE3B,OACIf,EAAC,OACG,UAAWqB,EAAG,4CAA6Cd,CAAS,EACpE,MAAO,CAAE,WAAYO,EAAO,GAAI,EAEhC,SAAAb,EAAC,OAAI,UAAU,8CACX,UAAAA,EAAC,OAAI,UAAU,iCACV,UAAAiB,GACGlB,EAAC,UACG,QAASmB,IAAW,IAAM,OAAO,QAAQ,KAAK,GAC9C,UAAU,0DAEV,SAAAnB,EAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,OAAO,eAAe,YAAY,IAC1F,SAAAA,EAAC,QAAK,EAAE,0BAA0B,EACtC,EACJ,EAEJA,EAAC,MAAG,UAAU,iCAAkC,SAAAiB,EAAM,GAC1D,EACCG,GACGpB,EAAC,OAAI,UAAU,YACV,SAAAoB,EACL,GAER,EACJ,CAER,CCtJA,OAAS,YAAAE,EAAU,aAAAC,MAAiB,QAK7B,SAASC,IAAgB,CAC5B,GAAM,CAACC,EAASC,CAAU,EAAIJ,EAAS,IAAO,EACxC,CAACK,EAAaC,CAAc,EAAIN,EAAS,IAAO,EAChD,CAACO,EAAUC,CAAW,EAAIR,EAAS,EAAK,EACxC,CAACS,EAAMC,CAAO,EAAIV,EAAoB,OAAO,EAC7C,CAACW,EAAMC,CAAO,EAAIZ,EAAS,EAAE,EAC7B,CAACa,EAAYC,CAAa,EAAId,EAAqB,KAAK,EACxD,CAACe,EAAcC,CAAe,EAAIhB,EAAS,EAAK,EAEtDC,EAAU,IAAM,CACZ,IAAIgB,EAAgB,KAEpB,GAAIV,GAAYJ,EAAU,EACtBc,EAAW,YAAY,IAAM,CACzBb,EAAYc,GAAMA,EAAI,CAAC,CAC3B,EAAG,GAAI,UACAf,IAAY,GAAKI,IAExBC,EAAY,EAAK,EACbC,IAAS,SAAS,CAClB,IAAMU,EAAa,KAAK,OAAO,EAAI,IACnCL,EAAcK,EAAa,QAAU,OAAO,CAChD,CAGJ,MAAO,IAAM,CACLF,GAAU,cAAcA,CAAQ,CACxC,CACJ,EAAG,CAACV,EAAUJ,EAASM,CAAI,CAAC,EAG5BR,EAAU,IAAM,CAIZ,GAHI,CAACM,IAAaM,IAAe,SAAWA,IAAe,SAAWA,IAAe,UAGjFJ,IAAS,QAAS,OAEtB,IAAMW,EAAW,EAAKjB,EAAUE,EAE5Be,EAAW,GACXN,EAAc,KAAK,EACZM,GAAY,IAAOA,EAAW,GACrCN,EAAc,SAAS,CAE/B,EAAG,CAACX,EAASE,EAAaE,EAAUM,EAAYJ,CAAI,CAAC,EAErD,IAAMY,EAAc,IAAMb,EAAY,CAACD,CAAQ,EAEzCe,EAAS,IAAM,CACjBd,EAAY,EAAK,EACjBM,EAAc,OAAO,CACzB,EAEMS,EAAcC,GAAuB,CACvChB,EAAY,EAAK,EACjBE,EAAQc,CAAO,EACfV,EAAc,KAAK,EAGnB,IAAIW,EAAU,KACVD,IAAY,eAAcC,EAAU,KACpCD,IAAY,cAAaC,EAAU,KAEvCrB,EAAWqB,CAAO,EAClBnB,EAAemB,CAAO,CAC1B,EAcA,MAAO,CACH,QAAAtB,EACA,YAAAE,EACA,SAAAE,EACA,KAAAE,EACA,KAAAE,EACA,WAAAE,EACA,aAAAE,EACA,WAAAX,EACA,eAAAE,EACA,YAAAE,EACA,QAAAE,EACA,QAAAE,EACA,cAAAE,EACA,gBAAAE,EACA,YAAAK,EACA,OAAAC,EACA,WAAAC,EACA,WA9Be,IAAM,CACrBf,EAAY,EAAK,EACjBe,EAAWd,CAAI,CACnB,EA4BI,cA1BmBiB,GAAiB,CACpClB,EAAY,EAAK,EACjBJ,EAAWsB,EAAO,EAAE,EACpBpB,EAAeoB,EAAO,EAAE,EACxBZ,EAAc,KAAK,CACvB,CAsBA,CACJ,CCzGA,OAAS,YAAAa,EAAU,eAAAC,EAAa,aAAAC,MAAiB,QAgC1C,SAASC,IAA2C,CACvD,GAAM,CAACC,EAAYC,CAAa,EAAIL,EAAiC,SAAS,EAE9EE,EAAU,IAAM,CACR,iBAAkB,QAClBG,EAAc,aAAa,UAAU,CAE7C,EAAG,CAAC,CAAC,EAEL,IAAMC,EAAoBL,EAAY,SAAY,CAC9C,GAAI,EAAE,iBAAkB,QACpB,eAAQ,KAAK,6BAA6B,EACnC,SAEX,IAAMM,EAAO,MAAM,aAAa,kBAAkB,EAClD,OAAAF,EAAcE,CAAI,EACXA,CACX,EAAG,CAAC,CAAC,EAECC,EAAmBP,EAAY,CAACQ,EAAeC,IAAkC,CACnF,GAAI,EAAE,iBAAkB,QAAS,OAGjC,IAAIC,EAAsBD,EAC1B,GAAI,CAACA,GAAS,KAAM,CAEhB,IAAME,EAAW,SAAS,cAAc,8BAA8B,GACvD,SAAS,cAAc,kBAAkB,EACpDA,IACAD,EAAsB,CAClB,GAAGD,EACH,KAAOE,EAA6B,IACxC,EAER,CAEI,aAAa,aAAe,UAC5B,IAAI,aAAaH,EAAOE,CAAmB,EACpC,aAAa,aAAe,UACnC,aAAa,kBAAkB,EAAE,KAAMJ,GAAS,CACxCA,IAAS,WACT,IAAI,aAAaE,EAAOE,CAAmB,CAEnD,CAAC,CAET,EAAG,CAAC,CAAC,EAECE,EAAuBZ,EAAY,CAACQ,EAAeK,EAAiBJ,IAAkC,CACxG,WAAW,IAAM,CACbF,EAAiBC,EAAOC,CAAO,CACnC,EAAGI,CAAO,CACd,EAAG,CAACN,CAAgB,CAAC,EAEfO,EAAWd,EAAY,MAAOe,GAAkB,CAClD,GAAI,gBAAiB,UACjB,GAAI,CACA,MAAO,UAAkB,YAAYA,CAAK,CAC9C,OAASC,EAAG,CACR,QAAQ,MAAM,uBAAwBA,CAAC,CAC3C,CAER,EAAG,CAAC,CAAC,EAECC,EAAajB,EAAY,SAAY,CACvC,GAAI,kBAAmB,UACnB,GAAI,CACA,MAAO,UAAkB,cAAc,CAC3C,OAASgB,EAAG,CACR,QAAQ,MAAM,wBAAyBA,CAAC,CAC5C,CAER,EAAG,CAAC,CAAC,EAEL,MAAO,CACH,WAAAb,EACA,kBAAAE,EACA,iBAAAE,EACA,qBAAAK,EACA,SAAAE,EACA,WAAAG,CACJ,CACJ,CCjHA,OAAS,YAAAC,EAAU,eAAAC,EAAa,aAAAC,MAAiB,QAkBjD,IAAMC,EAAc,0BACdC,EAAc,GAEb,SAASC,IAAmC,CAC/C,GAAM,CAACC,EAAkBC,CAAmB,EAAIP,EAAwB,IAAI,EACtE,CAACQ,EAASC,CAAU,EAAIT,EAA0B,CAAC,CAAC,EAG1DE,EAAU,IAAM,CACZ,GAAI,CACA,IAAMQ,EAAe,aAAa,QAAQP,CAAW,EACrD,GAAIO,EAAc,CAEd,IAAMC,EAAS,KAAK,MAAMD,CAAY,EACtCD,EAAWE,CAAM,CACrB,CACJ,OAASC,EAAG,CACR,QAAQ,MAAM,mCAAoCA,CAAC,CACvD,CACJ,EAAG,CAAC,CAAC,EAEL,IAAMC,EAAeZ,EAAaa,GAAwB,CACtDL,EAAWM,GAAQ,CACf,IAAMC,EAAa,CAACF,EAAM,GAAGC,CAAI,EAAE,MAAM,EAAGX,CAAW,EAEjDa,EAAkBD,EAAW,OAAOE,GAAKA,EAAE,OAAS,MAAM,EAChE,GAAI,CACA,aAAa,QAAQf,EAAa,KAAK,UAAUc,CAAe,CAAC,CACrE,OAASL,EAAG,CACR,QAAQ,MAAM,mCAAoCA,CAAC,CACvD,CACA,OAAOI,CACX,CAAC,CACL,EAAG,CAAC,CAAC,EAECG,EAAWlB,EAAY,MAAOmB,GAAiB,CACjD,GAAI,CAAC,UAAU,UAAW,CACtB,QAAQ,KAAK,6BAA6B,EAC1C,MACJ,CACA,GAAI,CACA,MAAM,UAAU,UAAU,UAAUA,CAAI,EACxCb,EAAoBa,CAAI,EACxBP,EAAa,CACT,KAAM,OACN,QAASO,EACT,UAAW,KAAK,IAAI,CACxB,CAAC,CACL,OAASR,EAAG,CACR,cAAQ,MAAM,uBAAwBA,CAAC,EACjCA,CACV,CACJ,EAAG,CAACC,CAAY,CAAC,EAEXQ,EAAYpB,EAAY,MAAOqB,GAAe,CAChD,GAAI,CAAC,UAAU,UAAW,CACtB,QAAQ,KAAK,6BAA6B,EAC1C,MACJ,CACA,GAAI,CACA,MAAM,UAAU,UAAU,MAAM,CAC5B,IAAI,cAAc,CACd,CAACA,EAAK,IAAI,EAAGA,CACjB,CAAC,CACL,CAAC,EACDT,EAAa,CACT,KAAM,QACN,QAASS,EACT,UAAW,KAAK,IAAI,CACxB,CAAC,CACL,OAASV,EAAG,CACR,cAAQ,MAAM,wBAAyBA,CAAC,EAClCA,CACV,CACJ,EAAG,CAACC,CAAY,CAAC,EAEXU,EAAWtB,EAAY,SAAY,CACrC,GAAI,CAAC,UAAU,UACX,eAAQ,KAAK,6BAA6B,EACnC,GAEX,GAAI,CACA,IAAMmB,EAAO,MAAM,UAAU,UAAU,SAAS,EAChD,OAAAb,EAAoBa,CAAI,EACjBA,CACX,OAASR,EAAG,CACR,cAAQ,MAAM,uBAAwBA,CAAC,EACjCA,CACV,CACJ,EAAG,CAAC,CAAC,EAECY,EAAcvB,EAAY,SAAY,CACxC,GAAI,CAAC,UAAU,UACX,eAAQ,KAAK,6BAA6B,EACnC,CAAC,EAEZ,GAAI,CACA,OAAO,MAAM,UAAU,UAAU,KAAK,CAC1C,OAASW,EAAG,CACR,cAAQ,MAAM,0BAA2BA,CAAC,EACpCA,CACV,CACJ,EAAG,CAAC,CAAC,EAECa,EAAexB,EAAY,IAAM,CACnCQ,EAAW,CAAC,CAAC,EACb,aAAa,WAAWN,CAAW,CACvC,EAAG,CAAC,CAAC,EAGL,OAAAD,EAAU,IAAM,CACZ,IAAMwB,EAAc,IAAM,CACtBH,EAAS,EAAE,MAAM,IAAM,CAAC,CAAC,CAC7B,EACA,cAAO,iBAAiB,QAASG,CAAW,EACrC,IAAM,OAAO,oBAAoB,QAASA,CAAW,CAChE,EAAG,CAACH,CAAQ,CAAC,EAEN,CACH,iBAAAjB,EACA,QAAAE,EACA,SAAAW,EACA,UAAAE,EACA,SAAAE,EACA,YAAAC,EACA,aAAAC,CACJ,CACJ,CCjJA,OAAS,YAAAE,GAAU,eAAAC,EAAa,aAAAC,GAAW,UAAAC,OAAc,QA8BlD,SAASC,GAAeC,EAAiD,CAC5E,GAAM,CAACC,EAAOC,CAAQ,EAAIP,GAAwB,CAC9C,QAAS,GACT,SAAU,KACV,SAAU,KACV,iBAAkB,KAClB,QAAS,KACT,SAAU,KACV,UAAW,KACX,MAAO,KACP,UAAW,KACX,MAAO,IACX,CAAC,EAEKQ,EAAUL,GAAsB,IAAI,EAEpCM,EAAUR,EAAaS,GAAkC,CAC3DH,EAAS,CACL,QAAS,GACT,SAAUG,EAAS,OAAO,SAC1B,SAAUA,EAAS,OAAO,SAC1B,iBAAkBA,EAAS,OAAO,iBAClC,QAASA,EAAS,OAAO,QACzB,SAAUA,EAAS,OAAO,SAC1B,UAAWA,EAAS,OAAO,UAC3B,MAAOA,EAAS,OAAO,MACvB,UAAWA,EAAS,UACpB,MAAO,IACX,CAAC,CACL,EAAG,CAAC,CAAC,EAECC,EAAUV,EAAaW,GAAoC,CAC7DL,EAAUM,IAAO,CACb,GAAGA,EACH,QAAS,GACT,MAAAD,CACJ,EAAE,CACN,EAAG,CAAC,CAAC,EAECE,EAAcb,EAAY,IAAM,CAClC,GAAI,CAAC,UAAU,YAAa,CACxBM,EAAUM,IAAO,CACb,GAAGA,EACH,QAAS,GACT,MAAO,CACH,KAAM,EACN,QAAS,4BACT,kBAAmB,EACnB,qBAAsB,EACtB,QAAS,CACb,CACJ,EAAE,EACF,MACJ,CAEAN,EAAUM,IAAO,CAAE,GAAGA,EAAG,QAAS,EAAK,EAAE,EACzC,UAAU,YAAY,mBAAmBJ,EAASE,EAASN,CAAO,CACtE,EAAG,CAACI,EAASE,EAASN,CAAO,CAAC,EAExBU,EAAgBd,EAAae,GAAmC,CAC7D,UAAU,cAEXR,EAAQ,UAAY,MACpB,UAAU,YAAY,WAAWA,EAAQ,OAAO,EAGpDA,EAAQ,QAAU,UAAU,YAAY,cACpCC,EACAE,EACAK,GAAgBX,CACpB,EACJ,EAAG,CAACI,EAASE,EAASN,CAAO,CAAC,EAExBY,EAAahB,EAAY,IAAM,CAC7BO,EAAQ,UAAY,OACpB,UAAU,YAAY,WAAWA,EAAQ,OAAO,EAChDA,EAAQ,QAAU,KAE1B,EAAG,CAAC,CAAC,EAGCU,EAAajB,EAAY,CAACkB,EAAaC,IAAgB,CACzD,GAAId,EAAM,WAAa,MAAQA,EAAM,YAAc,KAAM,MAAO,KAEhE,IAAMe,EAAI,OACJC,EAAKhB,EAAM,SAAW,KAAK,GAAK,IAChCiB,EAAKJ,EAAM,KAAK,GAAK,IACrBK,GAAML,EAAMb,EAAM,UAAY,KAAK,GAAK,IACxCmB,GAAML,EAAMd,EAAM,WAAa,KAAK,GAAK,IAEzCoB,EAAI,KAAK,IAAIF,EAAK,CAAC,EAAI,KAAK,IAAIA,EAAK,CAAC,EACxC,KAAK,IAAIF,CAAE,EAAI,KAAK,IAAIC,CAAE,EAC1B,KAAK,IAAIE,EAAK,CAAC,EAAI,KAAK,IAAIA,EAAK,CAAC,EAChCE,EAAI,EAAI,KAAK,MAAM,KAAK,KAAKD,CAAC,EAAG,KAAK,KAAK,EAAIA,CAAC,CAAC,EAEvD,OAAOL,EAAIM,CACf,EAAG,CAACrB,EAAM,SAAUA,EAAM,SAAS,CAAC,EAE9BsB,EAAgB3B,EAAa4B,GACdX,EAAWW,EAAM,SAAUA,EAAM,SAAS,GACxCA,EAAM,OAC1B,CAACX,CAAU,CAAC,EAEf,OAAAhB,GAAU,IACC,IAAM,CACLM,EAAQ,UAAY,MACpB,UAAU,YAAY,WAAWA,EAAQ,OAAO,CAExD,EACD,CAAC,CAAC,EAEE,CACH,GAAGF,EACH,YAAAQ,EACA,cAAAC,EACA,WAAAE,EACA,cAAAW,EACA,WAAAV,CACJ,CACJ,CCrJA,OAAS,YAAAY,GAAU,eAAAC,EAAa,UAAAC,EAAQ,aAAAC,MAAiB,QA0BlD,SAASC,IAA6B,CACzC,GAAM,CAACC,EAAOC,CAAQ,EAAIN,GAAsB,CAC5C,OAAQ,KACR,MAAO,KACP,WAAY,UACZ,YAAa,GACb,QAAS,CAAC,CACd,CAAC,EAEKO,EAAmBL,EAA6B,IAAI,EACpDM,EAAYN,EAAe,CAAC,CAAC,EAE7BO,EAAaR,EAAY,SAAY,CACvC,GAAI,CAAC,UAAU,cAAc,iBAAkB,MAAO,CAAC,EACvD,GAAI,CACA,IAAMS,EAAU,MAAM,UAAU,aAAa,iBAAiB,EAC9D,OAAAJ,EAASK,IAAM,CAAE,GAAGA,EAAG,QAAAD,CAAQ,EAAE,EAC1BA,CACX,OAASE,EAAG,CACR,eAAQ,MAAM,6BAA8BA,CAAC,EACtC,CAAC,CACZ,CACJ,EAAG,CAAC,CAAC,EAGLT,EAAU,KACNM,EAAW,EACX,UAAU,cAAc,iBAAiB,eAAgBA,CAAU,EAC5D,IAAM,CACT,UAAU,cAAc,oBAAoB,eAAgBA,CAAU,CAC1E,GACD,CAACA,CAAU,CAAC,EAEf,IAAMI,EAAcZ,EAAY,MAAOa,EAAyB,CAAE,MAAO,GAAM,MAAO,EAAM,IAAM,CAC9F,GAAI,CACA,IAAMC,EAAS,MAAM,UAAU,aAAa,aAAaD,CAAO,EAChE,OAAAR,EAASK,IAAM,CAAE,GAAGA,EAAG,OAAAI,EAAQ,MAAO,KAAM,WAAY,SAAU,EAAE,EAC7DA,CACX,OAASH,EAAG,CACR,IAAMI,EAAQJ,EACdN,EAASK,IAAM,CAAE,GAAGA,EAAG,MAAAK,EAAO,WAAY,QAAS,EAAE,EACrD,QAAQ,MAAM,yBAA0BJ,CAAC,CAC7C,CACJ,EAAG,CAAC,CAAC,EAECK,EAAahB,EAAY,IAAM,CAC7BI,EAAM,SACNA,EAAM,OAAO,UAAU,EAAE,QAAQa,GAASA,EAAM,KAAK,CAAC,EACtDZ,EAASK,IAAM,CAAE,GAAGA,EAAG,OAAQ,KAAM,YAAa,EAAM,EAAE,EAElE,EAAG,CAACN,EAAM,MAAM,CAAC,EAEXc,EAAmBlB,EAAY,MAAOa,EAAqC,CAAE,MAAO,EAAK,IAAM,CACjG,GAAI,CACA,IAAMC,EAAS,MAAM,UAAU,aAAa,gBAAgBD,CAAO,EACnE,OAAAR,EAASK,IAAM,CAAE,GAAGA,EAAG,OAAAI,EAAQ,MAAO,KAAM,WAAY,SAAU,EAAE,EAC7DA,CACX,OAASH,EAAG,CACR,IAAMI,EAAQJ,EACdN,EAASK,IAAM,CAAE,GAAGA,EAAG,MAAAK,EAAO,WAAY,QAAS,EAAE,EACrD,QAAQ,MAAM,+BAAgCJ,CAAC,CACnD,CACJ,EAAG,CAAC,CAAC,EAECQ,EAAYnB,EAAY,SAAY,CAItC,GAHI,CAACI,EAAM,QAGP,CADeA,EAAM,OAAO,eAAe,EAAE,CAAC,EACjC,OAGjB,IAAMgB,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,UAAYhB,EAAM,OACxB,MAAMgB,EAAM,KAAK,EAEjB,IAAMC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,MAAQD,EAAM,WACrBC,EAAO,OAASD,EAAM,YAEtB,IAAME,EAAMD,EAAO,WAAW,IAAI,EAClC,GAAI,CAACC,EAAK,OAEVA,EAAI,UAAUF,EAAO,EAAG,CAAC,EACzB,IAAMG,EAAUF,EAAO,UAAU,WAAW,EAG5C,OAAAD,EAAM,MAAM,EACZA,EAAM,UAAY,KAEXG,CACX,EAAG,CAACnB,EAAM,MAAM,CAAC,EAEXoB,EAAiBxB,EAAY,IAAM,CACrC,GAAKI,EAAM,OAEX,GAAI,CACA,IAAMqB,EAAgB,IAAI,cAAcrB,EAAM,MAAM,EACpDE,EAAiB,QAAUmB,EAC3BlB,EAAU,QAAU,CAAC,EAErBkB,EAAc,gBAAmBd,GAAM,CAC/BA,EAAE,KAAK,KAAO,GACdJ,EAAU,QAAQ,KAAKI,EAAE,IAAI,CAErC,EAEAc,EAAc,MAAM,EACpBpB,EAASK,IAAM,CAAE,GAAGA,EAAG,YAAa,EAAK,EAAE,CAC/C,OAASC,EAAG,CACR,QAAQ,MAAM,4BAA6BA,CAAC,EAC5CN,EAASK,IAAM,CAAE,GAAGA,EAAG,MAAOC,CAAW,EAAE,CAC/C,CACJ,EAAG,CAACP,EAAM,MAAM,CAAC,EAEXsB,EAAgB1B,EAAY,SAAY,CAC1C,GAAI,GAACM,EAAiB,SAAWA,EAAiB,QAAQ,QAAU,YAEpE,OAAO,IAAI,QAAeqB,GAAY,CAC7BrB,EAAiB,UAEtBA,EAAiB,QAAQ,OAAS,IAAM,CACpC,IAAMsB,EAAO,IAAI,KAAKrB,EAAU,QAAS,CAAE,KAAM,YAAa,CAAC,EAC/DF,EAASK,IAAM,CAAE,GAAGA,EAAG,YAAa,EAAM,EAAE,EAC5CiB,EAAQC,CAAI,CAChB,EAEAtB,EAAiB,QAAQ,KAAK,EAClC,CAAC,CACL,EAAG,CAAC,CAAC,EAECuB,EAAe7B,EAAY,MAAO8B,EAAkBC,IAA4B,CAClFf,EAAW,EACX,IAAMgB,EAAc,CAChB,CAACD,CAAI,EAAG,CAAE,SAAU,CAAE,MAAOD,CAAS,CAAE,CAC5C,EACA,MAAMlB,EAAYoB,CAAW,CACjC,EAAG,CAACpB,EAAaI,CAAU,CAAC,EAE5B,OAAAd,EAAU,IACC,IAAM,CACTc,EAAW,CACf,EACD,CAAC,CAAC,EAEE,CACH,GAAGZ,EACH,YAAAQ,EACA,WAAAI,EACA,UAAAG,EACA,eAAAK,EACA,cAAAE,EACA,iBAAAR,EACA,aAAAW,EACA,WAAArB,CACJ,CACJ,CCrLA,OAAS,YAAAyB,EAAU,eAAAC,EAAa,aAAAC,MAAiB,QA4C1C,SAASC,IAA6B,CACzC,GAAM,CAACC,EAAWC,CAAY,EAAIL,EAAS,EAAK,EAC1C,CAACM,EAASC,CAAU,EAAIP,EAAS,EAAK,EACtC,CAACQ,EAAQC,CAAS,EAAIT,EAAwB,CAAC,CAAC,EA4BhDU,GApBe,IAAM,CACvB,GAAI,OAAO,OAAW,IAAa,MAAO,wBAG1C,IAAMC,EAAe,OAAO,sBAC5B,GAAIA,EAAc,OAAOA,EAEzB,GAAM,CAAE,SAAAC,EAAU,SAAAC,EAAU,KAAMC,CAAY,EAAI,OAAO,SAGzD,OAAIA,IAAgB,QAAUA,IAAgB,OACnC,GAMJ,GAAGF,CAAQ,KAAKC,CAAQ,IAFfD,IAAa,SACA,KAAO,IACS,EACjD,GAEgC,EAE1BG,EAAcd,EAAY,SAAY,CACxC,GAAI,CAEA,IAAMe,EAAO,MADD,MAAM,MAAM,GAAGN,CAAU,aAAa,GAC3B,KAAK,EAC5BL,EAAaW,EAAK,QAAQ,WAAa,EAAK,CAChD,MAAY,CACRX,EAAa,EAAK,CACtB,CACJ,EAAG,CAAC,CAAC,EAECY,EAAgBhB,EAAY,SAAY,CAC1CM,EAAW,EAAI,EACf,GAAI,CACA,IAAMW,EAAM,MAAM,MAAM,GAAGR,CAAU,sBAAsB,EAC3D,GAAIQ,EAAI,GAAI,CACR,IAAMF,EAAO,MAAME,EAAI,KAAK,EAC5BT,EAAUO,EAAK,QAAU,CAAC,CAAC,CAC/B,CACJ,OAASG,EAAG,CACR,QAAQ,MAAM,iCAAkCA,CAAC,CACrD,QAAE,CACEZ,EAAW,EAAK,CACpB,CACJ,EAAG,CAAC,CAAC,EAELL,EAAU,IAAM,CACZa,EAAY,EACZ,IAAMK,EAAW,YAAYL,EAAa,GAAK,EAC/C,MAAO,IAAM,cAAcK,CAAQ,CACvC,EAAG,CAACL,CAAW,CAAC,EAEhBb,EAAU,IAAM,CACRE,GACAa,EAAc,CAEtB,EAAG,CAACb,EAAWa,CAAa,CAAC,EAE7B,IAAMI,EAAWpB,EAAY,MAAOqB,EAAeC,EAAgBC,EAAU,CAAC,IAA+B,CACzG,IAAMN,EAAM,MAAM,MAAM,GAAGR,CAAU,2BAA4B,CAC7D,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CAAE,MAAAY,EAAO,OAAAC,EAAQ,OAAQ,GAAO,GAAGC,CAAQ,CAAC,CACrE,CAAC,EAED,GAAI,CAACN,EAAI,GAAI,MAAM,IAAI,MAAM,6BAA6BA,EAAI,UAAU,EAAE,EAC1E,OAAO,MAAMA,EAAI,KAAK,CAC1B,EAAG,CAAC,CAAC,EAECO,EAAOxB,EAAY,MAAOqB,EAAeI,EAA+CF,EAAU,CAAC,IAA+B,CACpI,IAAMN,EAAM,MAAM,MAAM,GAAGR,CAAU,uBAAwB,CACzD,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CAAE,MAAAY,EAAO,SAAAI,EAAU,OAAQ,GAAO,GAAGF,CAAQ,CAAC,CACvE,CAAC,EAED,GAAI,CAACN,EAAI,GAAI,MAAM,IAAI,MAAM,uBAAuBA,EAAI,UAAU,EAAE,EACpE,OAAO,MAAMA,EAAI,KAAK,CAC1B,EAAG,CAAC,CAAC,EAEL,MAAO,CACH,UAAAd,EACA,QAAAE,EACA,OAAAE,EACA,cAAAS,EACA,SAAAI,EACA,KAAAI,CACJ,CACJ","names":["useState","useEffect","useCallback","useRef","useKeyboard","state","setState","maxHeight","updateKeyboardState","viewport","currentHeight","keyboardHeight","isOpen","handleOrientationChange","handleFocusIn","e","target","handleFocusOut","useRelayClose","useState","useEffect","createContext","useContext","jsx","defaultInsets","SafeAreaContext","SafeAreaProvider","children","insets","setInsets","computeInsets","style","getEnv","name","value","top","bottom","left","right","temp","rect","handleMessage","event","useSafeArea","useColorScheme","scheme","setScheme","media","handler","e","useStatusBar","color","meta","useBackHandler","handlePopState","useAppState","state","setState","handleVisibility","jsx","jsxs","KeyboardAvoidingView","children","behavior","keyboardVerticalOffset","style","className","keyboard","useKeyboard","offset","computedStyle","SafeAreaView","edges","insets","useSafeArea","PlatformHeader","title","showBack","onBack","rightElement","cn","useState","useEffect","useFocusTimer","seconds","setSeconds","initialTime","setInitialTime","isActive","setIsActive","mode","setMode","task","setTask","storyState","setStoryState","soundEnabled","setSoundEnabled","interval","s","isAbducted","progress","toggleTimer","giveUp","switchMode","newMode","newTime","mins","useState","useCallback","useEffect","useNotifications","permission","setPermission","requestPermission","perm","sendNotification","title","options","notificationOptions","iconLink","scheduleNotification","delayMs","setBadge","count","e","clearBadge","useState","useCallback","useEffect","HISTORY_KEY","MAX_HISTORY","useClipboard","clipboardContent","setClipboardContent","history","setHistory","savedHistory","parsed","e","addToHistory","item","prev","newHistory","textOnlyHistory","i","copyText","text","copyImage","blob","readText","readContent","clearHistory","handleFocus","useState","useCallback","useEffect","useRef","useGeolocation","options","state","setState","watchId","onEvent","position","onError","error","s","getLocation","watchLocation","watchOptions","clearWatch","distanceTo","lat","lng","R","φ1","φ2","Δφ","Δλ","a","c","checkGeofence","fence","useState","useCallback","useRef","useEffect","useCamera","state","setState","mediaRecorderRef","chunksRef","getDevices","devices","s","e","startCamera","options","stream","error","stopCamera","track","startScreenShare","takePhoto","video","canvas","ctx","dataUrl","startRecording","mediaRecorder","stopRecording","resolve","blob","switchDevice","deviceId","kind","constraints","useState","useCallback","useEffect","useOllama","available","setAvailable","loading","setLoading","models","setModels","HELPER_URL","injectedHost","protocol","hostname","currentPort","checkStatus","data","refreshModels","res","e","interval","generate","model","prompt","options","chat","messages"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dotrly/sdk",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "The official SDK for building Relay apps.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsup",
|
|
14
|
+
"dev": "tsup --watch",
|
|
15
|
+
"lint": "tsc"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"react": "^19.0.0",
|
|
19
|
+
"react-dom": "^19.0.0",
|
|
20
|
+
"tailwindcss": ">=3"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@base-ui/react": "^1.1.0",
|
|
24
|
+
"@fontsource-variable/inter": "^5.2.8",
|
|
25
|
+
"@tailwindcss/vite": "^4.1.17",
|
|
26
|
+
"class-variance-authority": "^0.7.1",
|
|
27
|
+
"clsx": "^2.1.1",
|
|
28
|
+
"cmdk": "^1.1.1",
|
|
29
|
+
"date-fns": "^4.1.0",
|
|
30
|
+
"embla-carousel-react": "^8.6.0",
|
|
31
|
+
"input-otp": "^1.4.2",
|
|
32
|
+
"lucide-react": "^0.562.0",
|
|
33
|
+
"next-themes": "^0.4.6",
|
|
34
|
+
"radix-ui": "^1.0.1",
|
|
35
|
+
"react-day-picker": "^9.13.0",
|
|
36
|
+
"react-resizable-panels": "^4.4.1",
|
|
37
|
+
"recharts": "^2.15.0",
|
|
38
|
+
"shadcn": "^2.1.8",
|
|
39
|
+
"sonner": "^1.7.2",
|
|
40
|
+
"tailwind-merge": "^2.6.0",
|
|
41
|
+
"tw-animate-css": "^1.4.0",
|
|
42
|
+
"vaul": "^1.1.2"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"tsup": "^8.0.2",
|
|
46
|
+
"typescript": "^5.7.3",
|
|
47
|
+
"@types/react": "^19.0.0",
|
|
48
|
+
"@types/react-dom": "^19.0.0",
|
|
49
|
+
"@types/node": "^24.10.1",
|
|
50
|
+
"autoprefixer": "^10.4.20",
|
|
51
|
+
"postcss": "^8.4.49"
|
|
52
|
+
}
|
|
53
|
+
}
|