@fayz-ai/ui 0.15.0 → 0.17.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.
Files changed (78) hide show
  1. package/dist/analytics/context.d.ts +15 -1
  2. package/dist/analytics/context.d.ts.map +1 -1
  3. package/dist/analytics/index.d.ts +1 -1
  4. package/dist/analytics/index.d.ts.map +1 -1
  5. package/dist/{chunk-J7F3Z52K.js → chunk-DFOAKWYB.js} +4 -4
  6. package/dist/chunk-DFOAKWYB.js.map +1 -0
  7. package/dist/{chunk-KD2V3TAX.js → chunk-E44WOPCR.js} +61 -49
  8. package/dist/chunk-E44WOPCR.js.map +1 -0
  9. package/dist/{chunk-FFJ2C5YH.js → chunk-HKGTF2YA.js} +41 -16
  10. package/dist/chunk-HKGTF2YA.js.map +1 -0
  11. package/dist/{chunk-NA3GE4H3.js → chunk-OBIU37AX.js} +365 -252
  12. package/dist/chunk-OBIU37AX.js.map +1 -0
  13. package/dist/{chunk-SLWTKHNY.js → chunk-Z2ITFPGL.js} +380 -83
  14. package/dist/chunk-Z2ITFPGL.js.map +1 -0
  15. package/dist/{chunk-5KMAEQA3.js → chunk-ZLPYNHXH.js} +56 -21
  16. package/dist/chunk-ZLPYNHXH.js.map +1 -0
  17. package/dist/dashboard/OnboardingWidget.d.ts +7 -1
  18. package/dist/dashboard/OnboardingWidget.d.ts.map +1 -1
  19. package/dist/dashboard/SidebarOnboarding.d.ts +7 -1
  20. package/dist/dashboard/SidebarOnboarding.d.ts.map +1 -1
  21. package/dist/dashboard/index.js +3 -3
  22. package/dist/hooks/useIsWide.d.ts +16 -0
  23. package/dist/hooks/useIsWide.d.ts.map +1 -0
  24. package/dist/index.d.ts +5 -3
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +278 -10
  27. package/dist/index.js.map +1 -1
  28. package/dist/layout/AppShell.d.ts +25 -2
  29. package/dist/layout/AppShell.d.ts.map +1 -1
  30. package/dist/layout/ModulePage.d.ts +4 -0
  31. package/dist/layout/ModulePage.d.ts.map +1 -1
  32. package/dist/layout/SaveBar.d.ts.map +1 -1
  33. package/dist/layout/Sidebar.d.ts.map +1 -1
  34. package/dist/layout/Topbar.d.ts +5 -1
  35. package/dist/layout/Topbar.d.ts.map +1 -1
  36. package/dist/layout/index.d.ts +1 -1
  37. package/dist/layout/index.d.ts.map +1 -1
  38. package/dist/layout/index.js +3 -3
  39. package/dist/primitives/checkbox.d.ts +4 -0
  40. package/dist/primitives/checkbox.d.ts.map +1 -1
  41. package/dist/primitives/index.d.ts +3 -0
  42. package/dist/primitives/index.d.ts.map +1 -1
  43. package/dist/primitives/index.js +4 -4
  44. package/dist/primitives/list-view.d.ts +5 -1
  45. package/dist/primitives/list-view.d.ts.map +1 -1
  46. package/dist/primitives/modal.d.ts.map +1 -1
  47. package/dist/primitives/page-actions.d.ts +55 -0
  48. package/dist/primitives/page-actions.d.ts.map +1 -0
  49. package/dist/primitives/page-header.d.ts +5 -2
  50. package/dist/primitives/page-header.d.ts.map +1 -1
  51. package/dist/primitives/page-toolbar.d.ts.map +1 -1
  52. package/dist/primitives/refresh-button.d.ts.map +1 -1
  53. package/dist/primitives/row-actions.d.ts +11 -0
  54. package/dist/primitives/row-actions.d.ts.map +1 -0
  55. package/dist/primitives/whatsapp-icon.d.ts +7 -0
  56. package/dist/primitives/whatsapp-icon.d.ts.map +1 -0
  57. package/dist/stores/index.d.ts +1 -1
  58. package/dist/stores/index.d.ts.map +1 -1
  59. package/dist/stores/layout.store.d.ts +1 -0
  60. package/dist/stores/layout.store.d.ts.map +1 -1
  61. package/dist/stores/page-header.store.d.ts +39 -5
  62. package/dist/stores/page-header.store.d.ts.map +1 -1
  63. package/dist/styles.css +188 -3
  64. package/dist/tour/TourSpotlight.d.ts +29 -0
  65. package/dist/tour/TourSpotlight.d.ts.map +1 -0
  66. package/dist/tour/index.d.ts +4 -0
  67. package/dist/tour/index.d.ts.map +1 -0
  68. package/dist/tour/tour.store.d.ts +22 -0
  69. package/dist/tour/tour.store.d.ts.map +1 -0
  70. package/dist/tour/types.d.ts +28 -0
  71. package/dist/tour/types.d.ts.map +1 -0
  72. package/package.json +2 -2
  73. package/dist/chunk-5KMAEQA3.js.map +0 -1
  74. package/dist/chunk-FFJ2C5YH.js.map +0 -1
  75. package/dist/chunk-J7F3Z52K.js.map +0 -1
  76. package/dist/chunk-KD2V3TAX.js.map +0 -1
  77. package/dist/chunk-NA3GE4H3.js.map +0 -1
  78. package/dist/chunk-SLWTKHNY.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
- import { Popover, PopoverTrigger, PopoverContent, Input, Hint, DatePicker } from './chunk-SLWTKHNY.js';
2
- export { Badge, Breadcrumb, BulkActionBar, ChevronPager, CurrencyInput, DatePicker, FilterChip, Hint, Input, ListView, Markdown, MarkdownEditor, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger, PhoneField, PhoneLink, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, RefreshButton, SearchCombobox, SearchField, SearchSelect, SegmentedControl, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, StatTiles, Tabs, TabsContent, TabsList, TabsTrigger, Thumbnail, TimePicker, ToastProvider, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, formatPhone, normalizePhone, renderMarkdown, toast, useRowSelection } from './chunk-SLWTKHNY.js';
3
- export { AppShellSkeleton, ContentSplit, ContentSplitTrigger, PageTrail, navigateToCrumb, usePageTrail, usePageTrailParent } from './chunk-J7F3Z52K.js';
4
- export { AppShell, BackStyleProvider, HeaderTabs, ModuleLayoutProvider, ModulePage, NavTransitionProvider, PageHeader, PageHeaderActions, PageHeaderCrumb, PageRail, PageTabs, PageTransition, RailNavItem, SaveBar, SaveBarProvider, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SubpageHeader, Topbar, useBackHandler, useBackStyle, useModuleHeaderActionsSlot, useModuleHeaderSlot, useModuleLayout, useNavTransition, useRailRow, useSaveBar } from './chunk-NA3GE4H3.js';
1
+ import { Popover, PopoverTrigger, PopoverContent, Input, Hint, DatePicker } from './chunk-Z2ITFPGL.js';
2
+ export { Badge, Breadcrumb, BulkActionBar, ChevronPager, CurrencyInput, DatePicker, FilterChip, Hint, Input, ListView, Markdown, MarkdownEditor, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger, PageActionBar, PhoneField, PhoneLink, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, RefreshButton, RowActions, SearchCombobox, SearchField, SearchSelect, SegmentedControl, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, StatTiles, Tabs, TabsContent, TabsList, TabsTrigger, Thumbnail, TimePicker, ToastProvider, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, WHATSAPP_BRAND_COLOR, WhatsAppIcon, badgeVariants, formatPhone, normalizePhone, renderMarkdown, setRowActionsLabel, toast, useRowSelection } from './chunk-Z2ITFPGL.js';
3
+ export { AppShellSkeleton, ContentSplit, ContentSplitTrigger, PageTrail, navigateToCrumb, usePageTrail, usePageTrailParent } from './chunk-DFOAKWYB.js';
4
+ export { AppShell, BackStyleProvider, HeaderTabs, ModuleLayoutProvider, ModulePage, NavTransitionProvider, PageHeader, PageHeaderActions, PageHeaderCrumb, PageRail, PageTabs, PageTransition, RailNavItem, SaveBar, SaveBarProvider, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SubpageHeader, Topbar, bottomNavReachesAll, useBackHandler, useBackStyle, useModuleHeaderActionsSlot, useModuleHeaderSlot, useModuleLayout, useNavTransition, useRailRow, useSaveBar } from './chunk-OBIU37AX.js';
5
5
  export { ThemeProvider, createFayzTheme, createTheme, darkTheme, fayzThemePresets, lightTheme, useTheme, useThemeStore } from './chunk-VDAYIQX4.js';
6
- import { ChartWidget, Sparkline, DashboardGrid } from './chunk-5KMAEQA3.js';
7
- export { ChartWidget, DEFAULT_RANGE_OPTIONS, DashboardCanvas, DashboardCustomizeMenu, DashboardGrid, DashboardNavigateProvider, DashboardRangeControl, DashboardRangeProvider, GoldCard, KpiCard, OnboardingWidget, SidebarOnboarding, TableWidget, WidgetGrid, defineChartWidget, defineCustomWidget, defineKpiWidget, defineOnboardingWidget, defineTableWidget, formatKpiValue, renderIcon, resolveDashboardLayout, useDashboardNavigate, useDashboardPreferences, useDashboardRange, useOnboardingProgress } from './chunk-5KMAEQA3.js';
8
- import { Skeleton, ToolbarButton, PageToolbar, Dropdown, DropdownTrigger, DropdownContent, DropdownItem, Card, CardContent, RangeControl, DropdownSeparator } from './chunk-KD2V3TAX.js';
9
- export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, DataTable, Dropdown, DropdownCheckboxItem, DropdownContent, DropdownGroup, DropdownItem, DropdownLabel, DropdownPortal, DropdownRadioGroup, DropdownRadioItem, DropdownSeparator, DropdownShortcut, DropdownSub, DropdownSubContent, DropdownSubTrigger, DropdownTrigger, PageToolbar, RangeControl, Skeleton, TableSkeleton, ToolbarAction, ToolbarButton } from './chunk-KD2V3TAX.js';
10
- export { PageHeaderOutlet, useHasPageActions, useHasPageHeaderBack, useHasPageHeaderHost, useHasPageHeaderOutlet, useLayoutStore, usePageHeader, usePageHeaderHost, usePageHeaderSlot, useRegisterPageActions } from './chunk-FFJ2C5YH.js';
6
+ import { ChartWidget, Sparkline, DashboardGrid } from './chunk-ZLPYNHXH.js';
7
+ export { ChartWidget, DEFAULT_RANGE_OPTIONS, DashboardCanvas, DashboardCustomizeMenu, DashboardGrid, DashboardNavigateProvider, DashboardRangeControl, DashboardRangeProvider, GoldCard, KpiCard, OnboardingWidget, SidebarOnboarding, TableWidget, WidgetGrid, defineChartWidget, defineCustomWidget, defineKpiWidget, defineOnboardingWidget, defineTableWidget, formatKpiValue, renderIcon, resolveDashboardLayout, useDashboardNavigate, useDashboardPreferences, useDashboardRange, useOnboardingProgress } from './chunk-ZLPYNHXH.js';
8
+ import { Skeleton, ToolbarButton, PageToolbar, Dropdown, DropdownTrigger, DropdownContent, DropdownItem, Card, CardContent, RangeControl, DropdownSeparator } from './chunk-E44WOPCR.js';
9
+ export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, DataTable, Dropdown, DropdownCheckboxItem, DropdownContent, DropdownGroup, DropdownItem, DropdownLabel, DropdownPortal, DropdownRadioGroup, DropdownRadioItem, DropdownSeparator, DropdownShortcut, DropdownSub, DropdownSubContent, DropdownSubTrigger, DropdownTrigger, PageToolbar, RangeControl, Skeleton, TableSkeleton, ToolbarAction, ToolbarButton, WIDE_QUERY, useIsWide } from './chunk-E44WOPCR.js';
10
+ export { PageHeaderOutlet, PageTitlePortal, useHasPageActions, useHasPageHeaderBack, useHasPageHeaderHost, useHasPageHeaderOutlet, useLayoutStore, usePageHeader, usePageHeaderClaimed, usePageHeaderHost, useRegisterPageActions } from './chunk-HKGTF2YA.js';
11
11
  export { Wizard, WizardField, useWizard } from './chunk-AASANYXN.js';
12
12
  export { ConfirmDialog, ImageDrop, OptionCards, OptionChips, StepProgress, Switch } from './chunk-3OVZ5JJQ.js';
13
13
  import { cn, Button } from './chunk-OKZ6WQB3.js';
@@ -18,6 +18,8 @@ import * as AvatarPrimitive from '@radix-ui/react-avatar';
18
18
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
19
19
  import { Construction, DatabaseZap, AlertCircle, SlidersHorizontal, Search, ChevronRight, GitCompareArrows, Check, X, TrendingUp, TrendingDown, Info, ArrowUpRight } from 'lucide-react';
20
20
  import { useTranslation, getCurrentLocale } from '@fayz-ai/core';
21
+ import { createPortal } from 'react-dom';
22
+ import { create } from 'zustand';
21
23
 
22
24
  var Avatar = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
23
25
  AvatarPrimitive.Root,
@@ -530,6 +532,26 @@ function useAnalyticsCard(card, options) {
530
532
  );
531
533
  return { result, summary, previousSummary, loading, error, engineMissing, refetch };
532
534
  }
535
+ function useAnalyticsCardRows(card) {
536
+ const { provider, state } = useAnalyticsContext();
537
+ return React2.useCallback(async (limit = EXPORT_ROW_CAP) => {
538
+ const resolved = withResolvedGrain(card, state.dateRange);
539
+ const rows = [];
540
+ for (let page = 1; rows.length < limit; page++) {
541
+ const res = await provider.run(resolved, {
542
+ ...state,
543
+ compare: "none",
544
+ page,
545
+ pageSize: EXPORT_PAGE_SIZE
546
+ });
547
+ rows.push(...resolveRowRatios(res.rows, resolved.query.measures));
548
+ if (res.rows.length < EXPORT_PAGE_SIZE || rows.length >= (res.total ?? rows.length)) break;
549
+ }
550
+ return rows.slice(0, limit);
551
+ }, [provider, state, card]);
552
+ }
553
+ var EXPORT_PAGE_SIZE = 1e3;
554
+ var EXPORT_ROW_CAP = 2e4;
533
555
  var CHART_TYPES = { line: "line", bar: "bar", area: "area", donut: "pie" };
534
556
  function CardChrome({
535
557
  card,
@@ -1097,7 +1119,253 @@ function ActiveFilterChip({ label, value, filterKey }) {
1097
1119
  )
1098
1120
  ] });
1099
1121
  }
1122
+ var navigator;
1123
+ function setTourNavigator(fn) {
1124
+ navigator = fn;
1125
+ }
1126
+ function getTourNavigator() {
1127
+ return navigator;
1128
+ }
1129
+ var useTourStore = create((set, get) => ({
1130
+ tour: null,
1131
+ index: 0,
1132
+ lastOutcome: null,
1133
+ start: (tour) => {
1134
+ if (!tour.stops.length) return;
1135
+ set({ tour, index: 0, lastOutcome: null });
1136
+ },
1137
+ next: () => {
1138
+ const { tour, index } = get();
1139
+ if (!tour) return;
1140
+ if (index >= tour.stops.length - 1) {
1141
+ get().stop(true);
1142
+ return;
1143
+ }
1144
+ set({ index: index + 1 });
1145
+ },
1146
+ prev: () => set((s) => ({ index: Math.max(0, s.index - 1) })),
1147
+ goTo: (index) => set((s) => s.tour ? { index: Math.min(Math.max(0, index), s.tour.stops.length - 1) } : s),
1148
+ stop: (completed = false) => set((s) => ({
1149
+ tour: null,
1150
+ index: 0,
1151
+ lastOutcome: s.tour ? { tourId: s.tour.id, completed } : s.lastOutcome
1152
+ }))
1153
+ }));
1154
+ function currentStop(state) {
1155
+ return state.tour?.stops[state.index];
1156
+ }
1157
+ var DEFAULT_LABELS = {
1158
+ next: "Pr\xF3ximo",
1159
+ waiting: "Fa\xE7a agora \u2014 eu espero",
1160
+ back: "Voltar",
1161
+ done: "Entendi",
1162
+ skip: "Pular",
1163
+ stepOf: "{current} de {total}",
1164
+ notFound: "Essa parte n\xE3o est\xE1 nesta tela \u2014 siga em frente que eu te mostro depois."
1165
+ };
1166
+ var PAD = 8;
1167
+ var ANCHOR_TIMEOUT_MS = 4e3;
1168
+ var BUBBLE_WIDTH = 300;
1169
+ var GAP = 14;
1170
+ function readRect(el) {
1171
+ const r = el.getBoundingClientRect();
1172
+ return { top: r.top - PAD, left: r.left - PAD, width: r.width + PAD * 2, height: r.height + PAD * 2 };
1173
+ }
1174
+ function TourSpotlight({ labels, className }) {
1175
+ const l = { ...DEFAULT_LABELS, ...labels };
1176
+ const tour = useTourStore((s) => s.tour);
1177
+ const index = useTourStore((s) => s.index);
1178
+ const next = useTourStore((s) => s.next);
1179
+ const prev = useTourStore((s) => s.prev);
1180
+ const stop = useTourStore((s) => s.stop);
1181
+ const stopDef = tour?.stops[index];
1182
+ const [rect, setRect] = React2.useState(null);
1183
+ const [missing, setMissing] = React2.useState(false);
1184
+ React2.useEffect(() => {
1185
+ if (!stopDef) return;
1186
+ setRect(null);
1187
+ setMissing(false);
1188
+ if (stopDef.route) getTourNavigator()?.(stopDef.route);
1189
+ let raf = 0;
1190
+ const deadline = Date.now() + ANCHOR_TIMEOUT_MS;
1191
+ const hunt = () => {
1192
+ const el = document.querySelector(`[data-tour~="${CSS.escape(stopDef.anchor)}"]`);
1193
+ if (el) {
1194
+ el.scrollIntoView({ block: "center", inline: "nearest", behavior: "smooth" });
1195
+ setRect(readRect(el));
1196
+ return;
1197
+ }
1198
+ if (Date.now() > deadline) {
1199
+ setMissing(true);
1200
+ return;
1201
+ }
1202
+ raf = requestAnimationFrame(hunt);
1203
+ };
1204
+ raf = requestAnimationFrame(hunt);
1205
+ return () => cancelAnimationFrame(raf);
1206
+ }, [stopDef?.anchor, stopDef?.route, tour?.id]);
1207
+ React2.useEffect(() => {
1208
+ if (!stopDef || missing) return;
1209
+ const anchor = stopDef.anchor;
1210
+ const handover = Boolean(stopDef.waitForUser);
1211
+ let frame = 0;
1212
+ let absent = 0;
1213
+ const sync = () => {
1214
+ const el = document.querySelector(`[data-tour~="${CSS.escape(anchor)}"]`);
1215
+ if (el) {
1216
+ absent = 0;
1217
+ setRect(readRect(el));
1218
+ return;
1219
+ }
1220
+ if (!handover) return;
1221
+ absent += 1;
1222
+ if (absent >= 3) stop(false);
1223
+ };
1224
+ const onFrame = () => {
1225
+ cancelAnimationFrame(frame);
1226
+ frame = requestAnimationFrame(sync);
1227
+ };
1228
+ window.addEventListener("scroll", onFrame, true);
1229
+ window.addEventListener("resize", onFrame);
1230
+ const interval = window.setInterval(sync, 400);
1231
+ return () => {
1232
+ cancelAnimationFrame(frame);
1233
+ window.clearInterval(interval);
1234
+ window.removeEventListener("scroll", onFrame, true);
1235
+ window.removeEventListener("resize", onFrame);
1236
+ };
1237
+ }, [stopDef?.anchor, stopDef?.waitForUser, missing, stop]);
1238
+ React2.useEffect(() => {
1239
+ if (!tour) return;
1240
+ const onKey = (e) => {
1241
+ if (e.key === "Escape") stop(false);
1242
+ if (e.key === "ArrowRight" && !tour.stops[index]?.waitForUser) next();
1243
+ if (e.key === "ArrowLeft") prev();
1244
+ };
1245
+ window.addEventListener("keydown", onKey);
1246
+ return () => window.removeEventListener("keydown", onKey);
1247
+ }, [tour, index, next, prev, stop]);
1248
+ if (!tour || !stopDef || typeof document === "undefined") return null;
1249
+ const total = tour.stops.length;
1250
+ const isLast = index === total - 1;
1251
+ const bubble = placeBubble(rect, stopDef.placement);
1252
+ const body = /* @__PURE__ */ jsxs("div", { className: cn("pointer-events-none fixed inset-0 z-[120]", className), role: "dialog", "aria-modal": "false", children: [
1253
+ rect && !missing ? /* @__PURE__ */ jsxs(Fragment, { children: [
1254
+ /* @__PURE__ */ jsx(Dim, { style: { top: 0, left: 0, width: "100%", height: Math.max(0, rect.top) }, onClick: () => stop(false) }),
1255
+ /* @__PURE__ */ jsx(Dim, { style: { top: rect.top, left: 0, width: Math.max(0, rect.left), height: rect.height }, onClick: () => stop(false) }),
1256
+ /* @__PURE__ */ jsx(
1257
+ Dim,
1258
+ {
1259
+ style: { top: rect.top, left: rect.left + rect.width, right: 0, height: rect.height },
1260
+ onClick: () => stop(false)
1261
+ }
1262
+ ),
1263
+ /* @__PURE__ */ jsx(Dim, { style: { top: rect.top + rect.height, left: 0, width: "100%", bottom: 0 }, onClick: () => stop(false) }),
1264
+ /* @__PURE__ */ jsx(
1265
+ "div",
1266
+ {
1267
+ "aria-hidden": true,
1268
+ className: "fz-spotlight-ring pointer-events-none absolute motion-safe:transition-[top,left,width,height] motion-safe:duration-300",
1269
+ style: { top: rect.top, left: rect.left, width: rect.width, height: rect.height }
1270
+ }
1271
+ )
1272
+ ] }) : /* @__PURE__ */ jsx(Dim, { style: { inset: 0 }, onClick: () => stop(false) }),
1273
+ /* @__PURE__ */ jsxs(
1274
+ "div",
1275
+ {
1276
+ className: cn(
1277
+ "pointer-events-auto absolute w-[300px] max-w-[calc(100vw-24px)] rounded-xl border border-border bg-popover p-4 text-popover-foreground shadow-2xl",
1278
+ "motion-safe:animate-in motion-safe:fade-in motion-safe:zoom-in-95 motion-safe:duration-200"
1279
+ ),
1280
+ style: bubble,
1281
+ children: [
1282
+ /* @__PURE__ */ jsx(
1283
+ "button",
1284
+ {
1285
+ type: "button",
1286
+ onClick: () => stop(false),
1287
+ "aria-label": l.skip,
1288
+ className: "absolute right-2 top-2 rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
1289
+ children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
1290
+ }
1291
+ ),
1292
+ /* @__PURE__ */ jsx("p", { className: "pr-6 text-sm font-semibold leading-snug", children: stopDef.title }),
1293
+ (missing ? l.notFound : stopDef.body) && /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-[13px] leading-relaxed text-muted-foreground", children: missing ? l.notFound : stopDef.body }),
1294
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 flex items-center gap-2", children: [
1295
+ /* @__PURE__ */ jsx("span", { className: "text-[11px] tabular-nums text-muted-foreground", children: l.stepOf.replace("{current}", String(index + 1)).replace("{total}", String(total)) }),
1296
+ /* @__PURE__ */ jsx("span", { className: "flex-1" }),
1297
+ stopDef.waitForUser && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 text-[12px] font-medium text-primary", children: [
1298
+ /* @__PURE__ */ jsxs("span", { className: "relative flex h-1.5 w-1.5", children: [
1299
+ /* @__PURE__ */ jsx("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-primary/70" }),
1300
+ /* @__PURE__ */ jsx("span", { className: "relative inline-flex h-1.5 w-1.5 rounded-full bg-primary" })
1301
+ ] }),
1302
+ l.waiting
1303
+ ] }),
1304
+ index > 0 && !stopDef.waitForUser && /* @__PURE__ */ jsx(
1305
+ "button",
1306
+ {
1307
+ type: "button",
1308
+ onClick: prev,
1309
+ className: "rounded-button px-2.5 py-1.5 text-[12.5px] font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
1310
+ children: l.back
1311
+ }
1312
+ ),
1313
+ !stopDef.waitForUser && /* @__PURE__ */ jsx(
1314
+ "button",
1315
+ {
1316
+ type: "button",
1317
+ onClick: next,
1318
+ className: "rounded-button bg-primary px-3 py-1.5 text-[12.5px] font-semibold text-primary-foreground shadow-button-primary transition-colors hover:bg-primary/90",
1319
+ children: isLast ? l.done : l.next
1320
+ }
1321
+ )
1322
+ ] })
1323
+ ]
1324
+ }
1325
+ )
1326
+ ] });
1327
+ return createPortal(body, document.body);
1328
+ }
1329
+ function Dim({ style, onClick }) {
1330
+ return /* @__PURE__ */ jsx(
1331
+ "div",
1332
+ {
1333
+ onClick,
1334
+ className: "pointer-events-auto absolute motion-safe:transition-all motion-safe:duration-300",
1335
+ style: { backgroundColor: "rgb(0 0 0 / 0.55)", ...style }
1336
+ }
1337
+ );
1338
+ }
1339
+ function placeBubble(rect, placement) {
1340
+ if (typeof window === "undefined" || !rect) {
1341
+ return { top: "50%", left: "50%", transform: "translate(-50%, -50%)" };
1342
+ }
1343
+ const vw = window.innerWidth;
1344
+ const vh = window.innerHeight;
1345
+ const belowRoom = vh - (rect.top + rect.height);
1346
+ const rightRoom = vw - (rect.left + rect.width);
1347
+ let side = placement && placement !== "auto" ? placement : belowRoom > 220 ? "bottom" : rect.top > 220 ? "top" : rightRoom > 340 ? "right" : "left";
1348
+ if (side === "bottom" && belowRoom < 180) side = "top";
1349
+ if (side === "top" && rect.top < 180) side = "bottom";
1350
+ const clampX = (x) => Math.min(Math.max(12, x), Math.max(12, vw - BUBBLE_WIDTH - 12));
1351
+ const clampY = (y) => Math.min(Math.max(12, y), Math.max(12, vh - 190));
1352
+ switch (side) {
1353
+ case "top":
1354
+ return { left: clampX(rect.left + rect.width / 2 - BUBBLE_WIDTH / 2), bottom: Math.max(12, vh - rect.top + GAP) };
1355
+ case "left":
1356
+ return { left: Math.max(12, rect.left - BUBBLE_WIDTH - GAP), top: clampY(rect.top) };
1357
+ case "right":
1358
+ return { left: clampX(rect.left + rect.width + GAP), top: clampY(rect.top) };
1359
+ default:
1360
+ return { left: clampX(rect.left + rect.width / 2 - BUBBLE_WIDTH / 2), top: clampY(rect.top + rect.height + GAP) };
1361
+ }
1362
+ }
1363
+
1364
+ // src/tour/types.ts
1365
+ function tourAnchor(anchor) {
1366
+ return { "data-tour": anchor };
1367
+ }
1100
1368
 
1101
- export { AnalyticsCard, AnalyticsContextProvider, AnalyticsControls, AnalyticsFilterPicker, AnalyticsGrid, Avatar, AvatarFallback, AvatarImage, BATCH_WINDOW_MS, autoGrain, collectFilters, comparisonRange, createBatchingProvider, deltaPercent, errorMessage, formatAnalyticsValue, formatBucket, formatCompact, formatDuration, isEngineMissing, num, parseDay, rangeLengthDays, resolveRangePreset, resolveRatios, resolveRowRatios, toBreakdown, toChartData, toDayString, toSpark, trendOf, useAnalyticsCard, useAnalyticsContext, useAnalyticsContextOptional, vizCategory, vizMeasures };
1369
+ export { AnalyticsCard, AnalyticsContextProvider, AnalyticsControls, AnalyticsFilterPicker, AnalyticsGrid, Avatar, AvatarFallback, AvatarImage, BATCH_WINDOW_MS, TourSpotlight, autoGrain, collectFilters, comparisonRange, createBatchingProvider, currentStop, deltaPercent, errorMessage, formatAnalyticsValue, formatBucket, formatCompact, formatDuration, getTourNavigator, isEngineMissing, num, parseDay, rangeLengthDays, resolveRangePreset, resolveRatios, resolveRowRatios, setTourNavigator, toBreakdown, toChartData, toDayString, toSpark, tourAnchor, trendOf, useAnalyticsCard, useAnalyticsCardRows, useAnalyticsContext, useAnalyticsContextOptional, useTourStore, vizCategory, vizMeasures };
1102
1370
  //# sourceMappingURL=index.js.map
1103
1371
  //# sourceMappingURL=index.js.map