@fayz-ai/admin 0.12.0 → 0.14.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 (42) hide show
  1. package/dist/SubscriptionPage-4KP7DKA2.js +7 -0
  2. package/dist/{SubscriptionPage-NLZAZO4P.js.map → SubscriptionPage-4KP7DKA2.js.map} +1 -1
  3. package/dist/app/AdminShell.d.ts.map +1 -1
  4. package/dist/{chunk-5O2UJAQ7.js → chunk-B6NVEKAJ.js} +2 -6
  5. package/dist/chunk-B6NVEKAJ.js.map +1 -0
  6. package/dist/components/billing/SubscriptionPage.d.ts.map +1 -1
  7. package/dist/components/chat/AssistantInvite.d.ts.map +1 -1
  8. package/dist/components/connect/ConnectorsTab.d.ts.map +1 -1
  9. package/dist/components/connect/connector-map.generated.d.ts.map +1 -1
  10. package/dist/components/organization/PermissionProfilesTab.d.ts.map +1 -1
  11. package/dist/components/organization/TeamTab.d.ts.map +1 -1
  12. package/dist/components/plugins/PluginSettingsPanel.d.ts +11 -1
  13. package/dist/components/plugins/PluginSettingsPanel.d.ts.map +1 -1
  14. package/dist/components/settings/FieldRulesSettings.d.ts.map +1 -1
  15. package/dist/components/settings/SettingsPage.d.ts.map +1 -1
  16. package/dist/crud/CrudDetailPage.d.ts.map +1 -1
  17. package/dist/crud/CrudListView.d.ts +10 -2
  18. package/dist/crud/CrudListView.d.ts.map +1 -1
  19. package/dist/crud/CrudPage.d.ts +4 -1
  20. package/dist/crud/CrudPage.d.ts.map +1 -1
  21. package/dist/crud/archetype-lookup.d.ts +9 -0
  22. package/dist/crud/archetype-lookup.d.ts.map +1 -1
  23. package/dist/crud/archetypes/OrderDetailView.d.ts.map +1 -1
  24. package/dist/crud/archetypes/OrderFormView.d.ts +4 -1
  25. package/dist/crud/archetypes/OrderFormView.d.ts.map +1 -1
  26. package/dist/crud/archetypes/OrderListView.d.ts +1 -1
  27. package/dist/crud/archetypes/OrderListView.d.ts.map +1 -1
  28. package/dist/hooks/useModuleNavigation.d.ts.map +1 -1
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +774 -639
  32. package/dist/index.js.map +1 -1
  33. package/dist/plugins/QuickActionsButton.d.ts +13 -4
  34. package/dist/plugins/QuickActionsButton.d.ts.map +1 -1
  35. package/dist/plugins/WidgetSlot.d.ts +12 -1
  36. package/dist/plugins/WidgetSlot.d.ts.map +1 -1
  37. package/dist/projects/ProjectsSettings.d.ts.map +1 -1
  38. package/dist/types/entity-lookup.d.ts +9 -0
  39. package/dist/types/entity-lookup.d.ts.map +1 -1
  40. package/package.json +8 -8
  41. package/dist/SubscriptionPage-NLZAZO4P.js +0 -7
  42. package/dist/chunk-5O2UJAQ7.js.map +0 -1
package/dist/index.js CHANGED
@@ -2,8 +2,8 @@ export { getScheduleBlockConfig, setScheduleBlockConfig, subscribeScheduleBlockC
2
2
  import { getFayzSupabaseClientOptional, createFayzSupabaseClient, createSupabaseOrgAdapter, createMockOrgAdapter, getFayzSupabaseClient } from './chunk-OI7RYSTM.js';
3
3
  export { createFayzSupabaseClient, createMockOrgAdapter, createSupabaseOrgAdapter, getFayzSupabaseClient, getFayzSupabaseClientOptional } from './chunk-OI7RYSTM.js';
4
4
  export { ImportWizard } from './chunk-UMRN6427.js';
5
- import { useLimitGuard, invalidateLimit, useLimit, useUpgradeModalStore, cn as cn$1, checkAccess, guardLimit, featureDisplayName, PlanFeatureItem, useAccessOptional, AccessProvider, CORE_LIMIT_DECLARATIONS, entityDerivedLimitDeclarations, getPlanEntitlements, resolvePlanCurrency } from './chunk-5O2UJAQ7.js';
6
- export { AccessProvider, UPGRADE_URL, agentDenial, checkAccess, getAccessSnapshot, guardLimit, invalidateLimit, isEntitledByPlan, resolveAccess, useAccess, useAccessOptional, useLimit, useLimitGuard, useModuleNavAccess, useUpgradeModalStore } from './chunk-5O2UJAQ7.js';
5
+ import { useLimitGuard, invalidateLimit, useLimit, useUpgradeModalStore, cn as cn$1, checkAccess, guardLimit, featureDisplayName, PlanFeatureItem, useAccessOptional, AccessProvider, CORE_LIMIT_DECLARATIONS, entityDerivedLimitDeclarations, getPlanEntitlements, resolvePlanCurrency } from './chunk-B6NVEKAJ.js';
6
+ export { AccessProvider, UPGRADE_URL, agentDenial, checkAccess, getAccessSnapshot, guardLimit, invalidateLimit, isEntitledByPlan, resolveAccess, useAccess, useAccessOptional, useLimit, useLimitGuard, useModuleNavAccess, useUpgradeModalStore } from './chunk-B6NVEKAJ.js';
7
7
  import { useTranslation as useTranslation$1 } from './chunk-YUHCC7JY.js';
8
8
  import { useBillingStore, resolvePlanBadge } from './chunk-VN5NTK26.js';
9
9
  export { useBillingStore } from './chunk-VN5NTK26.js';
@@ -11,16 +11,16 @@ import { useOrganizationStore, useTenantOptional, OrgProvider, useOrgAdapterOpti
11
11
  export { ORG_CACHE_TTL_MS, OrgProvider, clearOrgSnapshot, getPersistedOrgId, readOrgSnapshot, useOrgAdapter, useOrgAdapterOptional, useOrganizationStore, useTenant, useTenantOptional } from './chunk-PNAJODZM.js';
12
12
  import { usePermissionOptional, usePermissionsStore, PermissionsProvider } from './chunk-VTEP2AQX.js';
13
13
  export { PermissionsProvider, useHasPermission, usePermission, usePermissionOptional, usePermissions, usePermissionsStore } from './chunk-VTEP2AQX.js';
14
- import * as React63 from 'react';
15
- import React63__default, { createContext, useMemo, useState, useRef, useCallback, useEffect, useContext } from 'react';
14
+ import * as React65 from 'react';
15
+ import React65__default, { createContext, useMemo, useState, useRef, useCallback, useEffect, useContext } from 'react';
16
16
  import { hashRouterAdapter, getSupabaseClientOptional, deriveEntityKey, registerEntity, getActiveTenantId, resolveDataProvider, bulkRemove, emitDomainEvent, entityEventKey, useTranslation, useDataChanged, emitDataChanged, exportCSV, formatDateTime as formatDateTime$1, formatDate as formatDate$1, formatCurrency as formatCurrency$1, bulkCreate, matchesRange, isConnectorCategory, reportAppError, usePluginRuntimeOptional, getWidgetsForZone, resolvePluginComponent, setCurrentLocale, resolvePluginRuntime, PluginRuntimeProvider, I18nProvider, getAllEntities, defineApp, registerScaffold, getCountry, DEFAULT_COUNTRY, useActiveTenantId, maskPhone, useConnectorsForPlugin, renderApp as renderApp$1, unmaskPhone, parseRangeFilter, isFilterObject, connectionKey, useManifest, usePluginRuntime, installGlobalErrorHandlers, mergeTranslations, coreTranslations, attachPersistentCache, getPersistentCache, createMockProvider, listConnections, connectorPlanes, connectorPermissions, connectorEntities, preferredPlane, connectorDirection, searchEverything, registerEventSink, getComponent, getPluginFactory, connectorSettings, groupedPermissions, invocationPlane, missingRequiredSettings, isSettingSet, connectorSubscribesTo, eventKeyMatches } from '@fayz-ai/core';
17
17
  export { ConnectorRuntimeTokenUnavailableError, createSafeDataProvider, formatDate, formatDateTime, getActiveLocale, getActiveTenantId, getConnectorRuntimeTokenSource, getCurrentLocale, getSupabaseClientOptional, preloadLocale, resolveBackendEnv, setConnectorRuntimeTokenSource, setCurrentLocale, tl, useActiveTenantId } from '@fayz-ai/core';
18
18
  import { usePasswordSetupGate, SetPasswordPage, AuthGate, AuthProvider, createAuthRuntime } from '@fayz-ai/plugin-auth';
19
19
  export { LoginPage } from '@fayz-ai/plugin-auth';
20
- import { toast, usePageTrailParent, navigateToCrumb, Button, PageHeader, ConfirmDialog, FilterChip, Dropdown, DropdownTrigger, Hint, cn, DropdownContent, DropdownLabel, DropdownItem, DropdownSeparator, RefreshButton, HeaderTabs, StatTiles, BulkActionBar, Card, DataTable, Modal, ModalContent, ModalHeader, ModalTitle, ModalDescription, ModalFooter, Badge, getLucideIcon, ICON_MAP, Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody, useLayoutStore, Skeleton, Input, useSaveBar, useBackHandler, SubpageHeader, Separator, Tabs, TabsList, TabsTrigger, TabsContent, CardContent, ToastProvider, NavTransitionProvider, ListView, Thumbnail, SearchSelect, CurrencyInput, SearchField, ChevronPager, useModuleLayout, Popover, PopoverTrigger, PopoverContent, PhoneLink, normalizePhone, ModalPortal, ModalOverlay, ModalBody, SearchCombobox, usePageTrail, AppShellSkeleton, ModuleLayoutProvider, AppShell, PageTransition, createFayzTheme, Checkbox, MarkdownEditor, Switch, Markdown, PageTrail, Avatar, AvatarImage, AvatarFallback, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, CardTitle, CardDescription, DropdownSub, DropdownSubTrigger, DropdownSubContent, DropdownRadioGroup, DropdownRadioItem, CardHeader, CardFooter } from '@fayz-ai/ui';
20
+ import { toast, usePageTrailParent, navigateToCrumb, Button, PageHeader, ConfirmDialog, FilterChip, Dropdown, DropdownTrigger, Hint, cn, DropdownContent, DropdownLabel, DropdownItem, DropdownSeparator, RefreshButton, PageHeaderActions, PageTabs, StatTiles, Card, BulkActionBar, DataTable, Modal, ModalContent, ModalHeader, ModalTitle, ModalDescription, ModalFooter, Badge, useModuleLayout, ICON_MAP, getLucideIcon, Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody, useLayoutStore, Skeleton, Input, useSaveBar, useBackHandler, SubpageHeader, Separator, Tabs, TabsList, TabsTrigger, TabsContent, CardContent, ToastProvider, NavTransitionProvider, ListView, Thumbnail, SearchSelect, CurrencyInput, SearchField, ChevronPager, Popover, PopoverTrigger, PopoverContent, PhoneLink, normalizePhone, ModalPortal, ModalOverlay, ModalBody, SearchCombobox, usePageTrail, AppShellSkeleton, ModuleLayoutProvider, AppShell, PageTransition, PageRail, RailNavItem, createFayzTheme, Checkbox, MarkdownEditor, Switch, Markdown, PageTrail, Avatar, AvatarImage, AvatarFallback, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, CardTitle, CardDescription, DropdownSub, DropdownSubTrigger, DropdownSubContent, DropdownRadioGroup, DropdownRadioItem, CardHeader, CardFooter } from '@fayz-ai/ui';
21
21
  export { createFayzTheme, fayzThemePresets } from '@fayz-ai/ui';
22
22
  import * as LucideIcons3 from 'lucide-react';
23
- import { Globe, Store, LayoutTemplate, Trash2, Upload, Search, ArrowDown, ArrowUp, ArrowUpDown, Check, Download, ChevronLeft, ChevronRight, AlertTriangle, Pencil, Inbox, Package, X, Sparkles, Plug, Loader2, ArrowDownToLine, ArrowUpFromLine, CheckCircle2, Crown, ArrowRight, ArrowLeft, SquarePen, Settings2, MessageSquare, RotateCcw, Copy, ChevronsUpDown, ExternalLink, PenSquare, RefreshCw, Plus, XCircle, Clock, Star, Edit, Eye, ShoppingBag, ChevronDown, Settings, Mail, MessageCircle, Cake, Calendar, TableProperties, Mic, BookOpen, Paperclip, ShieldCheck, Infinity, Play, Square, StickyNote, ArrowUpRight, Pause, CalendarDays, CircleCheckBig, UserX, Ban, CircleAlert, CircleEllipsis, FileText, CircleDashed, Power, File, FileImage, FileSpreadsheet, AlertCircle, CreditCard, Users, MapPin, SlidersHorizontal, Puzzle, Building2, User, Shield, Palette, ShieldAlert, UserCog, LogOut, Bell, PinOff, Pin, ImagePlus, Database, Radio, Zap, Save, UserPlus, MoreHorizontal, Sun, Moon, Monitor, Languages, CheckCheck, Info, CheckSquare2, Camera, KeyRound, Bug, Wrench, Heart, Briefcase, BarChart3, Tag, Truck } from 'lucide-react';
23
+ import { Globe, Store, LayoutTemplate, Trash2, Upload, Search, ArrowDown, ArrowUp, ArrowUpDown, Check, Download, ChevronLeft, ChevronRight, AlertTriangle, Pencil, Plus, ChevronDown, Inbox, Package, X, Sparkles, Plug, Loader2, ArrowDownToLine, ArrowUpFromLine, CheckCircle2, Crown, ArrowRight, ArrowLeft, SquarePen, Settings2, MessageSquare, RotateCcw, Copy, ChevronsUpDown, ExternalLink, PenSquare, RefreshCw, XCircle, Clock, Star, Edit, Eye, ShoppingBag, Settings, Mail, MessageCircle, Cake, Calendar, TableProperties, Mic, BookOpen, Paperclip, ShieldCheck, Infinity, Play, Square, StickyNote, ArrowUpRight, Pause, CalendarDays, CircleCheckBig, UserX, Ban, CircleAlert, CircleEllipsis, FileText, CircleDashed, Power, File, FileImage, FileSpreadsheet, AlertCircle, CreditCard, Users, MapPin, SlidersHorizontal, Puzzle, Building2, User, Shield, Palette, ShieldAlert, UserCog, LogOut, Bell, PinOff, Pin, ImagePlus, Database, Radio, Zap, Save, UserPlus, MoreHorizontal, Sun, Moon, Monitor, Languages, CheckCheck, Info, CheckSquare2, Camera, KeyRound, Bug, Wrench, Heart, Briefcase, BarChart3, Tag, Truck } from 'lucide-react';
24
24
  import { create, useStore } from 'zustand';
25
25
  import { useAuthStore, useAuth } from '@fayz-ai/auth';
26
26
  export { useAuth } from '@fayz-ai/auth';
@@ -843,7 +843,7 @@ function getServerVersion() {
843
843
  return 0;
844
844
  }
845
845
  function useAssistantActivity() {
846
- React63.useSyncExternalStore(subscribe, getVersion, getServerVersion);
846
+ React65.useSyncExternalStore(subscribe, getVersion, getServerVersion);
847
847
  return pickActivity(activities);
848
848
  }
849
849
  function pickActivity(list) {
@@ -853,18 +853,18 @@ function pickActivity(list) {
853
853
  return pool.find((a) => a.kind === "recording") ?? pool[0];
854
854
  }
855
855
  function useAssistantLaunchers() {
856
- React63.useSyncExternalStore(subscribe, getVersion, getServerVersion);
856
+ React65.useSyncExternalStore(subscribe, getVersion, getServerVersion);
857
857
  return launchers;
858
858
  }
859
859
  function usePublishAssistantActivity(activity) {
860
860
  const id = activity?.id;
861
861
  const key = activity ? `${activity.id}|${activity.kind}|${activity.label}|${activity.state}|${activity.elapsedMs ?? ""}|${(activity.actions ?? []).map((a) => a.intent).join(",")}` : null;
862
- const ref = React63.useRef(activity);
862
+ const ref = React65.useRef(activity);
863
863
  ref.current = activity;
864
- React63.useEffect(() => {
864
+ React65.useEffect(() => {
865
865
  if (ref.current) publishAssistantActivity(ref.current);
866
866
  }, [key]);
867
- React63.useEffect(() => {
867
+ React65.useEffect(() => {
868
868
  if (!id) return;
869
869
  return () => withdrawAssistantActivity(id);
870
870
  }, [id]);
@@ -872,12 +872,12 @@ function usePublishAssistantActivity(activity) {
872
872
  function useRegisterAssistantLauncher(launcher) {
873
873
  const id = launcher?.id;
874
874
  const key = launcher ? `${launcher.id}|${launcher.label}|${launcher.disabled ? "1" : "0"}` : null;
875
- const ref = React63.useRef(launcher);
875
+ const ref = React65.useRef(launcher);
876
876
  ref.current = launcher;
877
- React63.useEffect(() => {
877
+ React65.useEffect(() => {
878
878
  if (ref.current) registerAssistantLauncher(ref.current);
879
879
  }, [key]);
880
- React63.useEffect(() => {
880
+ React65.useEffect(() => {
881
881
  if (!id) return;
882
882
  return () => unregisterAssistantLauncher(id);
883
883
  }, [id]);
@@ -941,17 +941,17 @@ function useRightRailPanel(panel) {
941
941
  const icon = panel?.icon;
942
942
  const badgeCount = panel?.badge?.count;
943
943
  const badgeTone = panel?.badge?.tone;
944
- const initial = React63.useRef({ label, icon });
945
- React63.useEffect(() => {
944
+ const initial = React65.useRef({ label, icon });
945
+ React65.useEffect(() => {
946
946
  if (!id || !Component2) return;
947
947
  register({ id, label: initial.current.label ?? id, order, Component: Component2, icon: initial.current.icon });
948
948
  return () => unregister(id);
949
949
  }, [id, order, Component2, register, unregister]);
950
- React63.useEffect(() => {
950
+ React65.useEffect(() => {
951
951
  if (!id) return;
952
952
  updateMeta(id, { label, icon });
953
953
  }, [id, label, icon, updateMeta]);
954
- React63.useEffect(() => {
954
+ React65.useEffect(() => {
955
955
  if (!id) return;
956
956
  updateBadge(id, badgeCount !== void 0 ? { count: badgeCount, tone: badgeTone } : void 0);
957
957
  }, [id, badgeCount, badgeTone, updateBadge]);
@@ -1046,7 +1046,7 @@ function AssistantInvite({ className, ...def }) {
1046
1046
  const { id, persona, headline, pitch, description, placeholder, auto } = def;
1047
1047
  const suggestions = def.suggestions;
1048
1048
  const suggestionKey = JSON.stringify(suggestions ?? []);
1049
- React63.useEffect(() => {
1049
+ React65.useEffect(() => {
1050
1050
  if (!hasAssistant) return;
1051
1051
  setInvite({
1052
1052
  id,
@@ -1060,11 +1060,11 @@ function AssistantInvite({ className, ...def }) {
1060
1060
  });
1061
1061
  return () => setInvite(null, id);
1062
1062
  }, [hasAssistant, id, persona, headline, pitch, description, placeholder, auto, suggestionKey, setInvite]);
1063
- const anchorRef = React63.useRef(null);
1064
- const [box, setBox] = React63.useState(null);
1063
+ const anchorRef = React65.useRef(null);
1064
+ const [box, setBox] = React65.useState(null);
1065
1065
  const docked = stage === "dock" && !railOpen && hasAssistant;
1066
1066
  const showing = hasAssistant && (stage === "hero" || docked);
1067
- React63.useEffect(() => {
1067
+ React65.useEffect(() => {
1068
1068
  if (!showing) return;
1069
1069
  const el = anchorRef.current;
1070
1070
  if (!el) return;
@@ -1085,7 +1085,7 @@ function AssistantInvite({ className, ...def }) {
1085
1085
  }, [showing]);
1086
1086
  const setDockBox = useAssistantInviteStore((s) => s.setDockBox);
1087
1087
  const wide = useWideViewport();
1088
- React63.useEffect(() => {
1088
+ React65.useEffect(() => {
1089
1089
  if (!docked || !wide || !box) {
1090
1090
  setDockBox(null);
1091
1091
  return;
@@ -1099,7 +1099,7 @@ function AssistantInvite({ className, ...def }) {
1099
1099
  function useAsk() {
1100
1100
  const queuePrompt = useChatStore((s) => s.queuePrompt);
1101
1101
  const dismiss = useAssistantInviteStore((s) => s.dismiss);
1102
- return React63.useCallback(
1102
+ return React65.useCallback(
1103
1103
  (text) => {
1104
1104
  const trimmed = text.trim();
1105
1105
  if (!trimmed) return;
@@ -1117,9 +1117,9 @@ function InviteHero({
1117
1117
  const { t } = useTranslation$1();
1118
1118
  const user = useAuthStore((s) => s.user);
1119
1119
  const ask = useAsk();
1120
- const [draft, setDraft] = React63.useState("");
1120
+ const [draft, setDraft] = React65.useState("");
1121
1121
  const name = (user?.fullName || user?.email || "").split(/[\s@]/)[0];
1122
- React63.useEffect(() => {
1122
+ React65.useEffect(() => {
1123
1123
  const onKey = (event) => {
1124
1124
  if (event.key === "Escape") onDismiss();
1125
1125
  };
@@ -1181,8 +1181,8 @@ function InviteHero({
1181
1181
  );
1182
1182
  }
1183
1183
  function useMorphIn(skip = false) {
1184
- const [entered, setEntered] = React63.useState(() => skip || prefersReducedMotion());
1185
- React63.useEffect(() => {
1184
+ const [entered, setEntered] = React65.useState(() => skip || prefersReducedMotion());
1185
+ React65.useEffect(() => {
1186
1186
  if (entered) return;
1187
1187
  let second = 0;
1188
1188
  const first = requestAnimationFrame(() => {
@@ -1201,10 +1201,10 @@ function prefersReducedMotion() {
1201
1201
  var lastDockExit = null;
1202
1202
  var RESUME_WINDOW_MS = 700;
1203
1203
  function useWideViewport() {
1204
- const [wide, setWide] = React63.useState(
1204
+ const [wide, setWide] = React65.useState(
1205
1205
  () => typeof window !== "undefined" && !!window.matchMedia?.("(min-width: 768px)").matches
1206
1206
  );
1207
- React63.useEffect(() => {
1207
+ React65.useEffect(() => {
1208
1208
  const query = window.matchMedia?.("(min-width: 768px)");
1209
1209
  if (!query) return;
1210
1210
  const sync = () => setWide(query.matches);
@@ -1235,16 +1235,22 @@ function InviteDock({ def, left, maxWidth }) {
1235
1235
  const setOpen = useChatStore((s) => s.setOpen);
1236
1236
  const railOpen = useRightRailStore((s) => s.open);
1237
1237
  const railWidth = useRightRailStore((s) => s.width);
1238
- const [draft, setDraft] = React63.useState("");
1239
- const resumed = React63.useRef(
1238
+ const [draft, setDraft] = React65.useState("");
1239
+ const resumed = React65.useRef(
1240
1240
  !!lastDockExit && lastDockExit.id === def.id && Date.now() - lastDockExit.at < RESUME_WINDOW_MS
1241
1241
  ).current;
1242
- React63.useEffect(() => () => {
1242
+ React65.useEffect(() => () => {
1243
1243
  lastDockExit = { id: def.id, at: Date.now() };
1244
1244
  }, [def.id]);
1245
1245
  const entered = useMorphIn(resumed);
1246
1246
  const width = Math.min(maxWidth, DOCK_MAX_WIDTH);
1247
1247
  const morph = morphStyles({ left, width }, railOpen, railWidth);
1248
+ const [settled, setSettled] = React65.useState(resumed);
1249
+ React65.useEffect(() => {
1250
+ if (!entered || settled) return;
1251
+ const id = setTimeout(() => setSettled(true), MORPH_MS + 60);
1252
+ return () => clearTimeout(id);
1253
+ }, [entered, settled]);
1248
1254
  return /* @__PURE__ */ jsx(
1249
1255
  "div",
1250
1256
  {
@@ -1255,7 +1261,8 @@ function InviteDock({ def, left, maxWidth }) {
1255
1261
  // Arrives as the FAB and unrolls leftward into a composer. The circle it
1256
1262
  // grows out of is the one that just disappeared from that exact spot.
1257
1263
  ...entered ? morph.open : morph.collapsed,
1258
- transition: prefersReducedMotion() ? void 0 : morph.transition
1264
+ transition: prefersReducedMotion() ? void 0 : morph.transition,
1265
+ ...settled ? { transform: "none", clipPath: "none", marginLeft: -width / 2 } : null
1259
1266
  },
1260
1267
  children: /* @__PURE__ */ jsx(
1261
1268
  InviteComposer,
@@ -1373,7 +1380,7 @@ function MorphBackPill() {
1373
1380
  const railWidth = useRightRailStore((s) => s.width);
1374
1381
  const { t } = useTranslation$1();
1375
1382
  const collapsed = useMorphIn();
1376
- React63.useEffect(() => {
1383
+ React65.useEffect(() => {
1377
1384
  if (prefersReducedMotion()) {
1378
1385
  endLeave();
1379
1386
  return;
@@ -1909,12 +1916,12 @@ function detectActivePluginId(runtime) {
1909
1916
  function useAITools() {
1910
1917
  const runtime = usePluginRuntimeOptional();
1911
1918
  const access = useAccessOptional();
1912
- const surfaceVersion = React63.useSyncExternalStore(subscribeSurfaces, getSurfaceVersion, getSurfaceVersion);
1919
+ const surfaceVersion = React65.useSyncExternalStore(subscribeSurfaces, getSurfaceVersion, getSurfaceVersion);
1913
1920
  const features = usePermissionsStore((s) => s.features);
1914
1921
  const profiles = usePermissionsStore((s) => s.profiles);
1915
1922
  const hasSystem = useSystemPermission();
1916
1923
  const canManagePermissions = hasSystem("manage_permissions");
1917
- return React63.useMemo(() => {
1924
+ return React65.useMemo(() => {
1918
1925
  const hasPermission = runtime?.context.hasPermission;
1919
1926
  const can = access.can;
1920
1927
  const verticalId = runtime?.context.tenant?.verticalId;
@@ -1997,8 +2004,8 @@ function navigateTo(to) {
1997
2004
  adapter.navigate(normalizeAdminPath(to));
1998
2005
  }
1999
2006
  function useAdminPath() {
2000
- const [path, setPath] = React63.useState(() => normalizeAdminPath(adapter.getCurrentPath() || "/"));
2001
- React63.useEffect(() => {
2007
+ const [path, setPath] = React65.useState(() => normalizeAdminPath(adapter.getCurrentPath() || "/"));
2008
+ React65.useEffect(() => {
2002
2009
  return adapter.onPathChange((p) => {
2003
2010
  setPath(normalizeAdminPath(p || "/"));
2004
2011
  if (typeof window !== "undefined") window.scrollTo(0, 0);
@@ -3245,6 +3252,20 @@ async function executeRpcTool(rpcName, args, userId) {
3245
3252
 
3246
3253
  // src/components/connect/connector-map.generated.ts
3247
3254
  var SDK_INTEGRATIONS = [
3255
+ {
3256
+ slug: "99food",
3257
+ name: "99Food",
3258
+ description: "Traga para a cozinha cada pedido feito no 99Food, e avise o 99Food quando ele for confirmado e sair.",
3259
+ icon: "Bike",
3260
+ logoUrl: "https://assets.fayz.ai/connectors/99food.jpeg",
3261
+ category: "marketplace",
3262
+ direction: "inbound",
3263
+ planes: ["sync"],
3264
+ moduleId: "orders",
3265
+ status: "available",
3266
+ connectorId: "99food",
3267
+ declaredBy: { pluginId: "orders", package: "@fayz-ai/plugin-orders" }
3268
+ },
3248
3269
  {
3249
3270
  slug: "abacatepay",
3250
3271
  name: "AbacatePay",
@@ -3314,6 +3335,20 @@ var SDK_INTEGRATIONS = [
3314
3335
  status: "soon",
3315
3336
  declaredBy: { pluginId: "agenda", package: "@fayz-ai/plugin-agenda" }
3316
3337
  },
3338
+ {
3339
+ slug: "cielo",
3340
+ name: "Cielo",
3341
+ description: "Traga para o Financeiro tudo que entrou na Cielo \u2014 cr\xE9dito, d\xE9bito e Pix \u2014 com a taxa e a data do repasse.",
3342
+ icon: "CreditCard",
3343
+ logoUrl: "https://assets.fayz.ai/connectors/cielo.jpg",
3344
+ category: "payments",
3345
+ direction: "inbound",
3346
+ planes: ["sync"],
3347
+ moduleId: "financial",
3348
+ status: "available",
3349
+ connectorId: "cielo",
3350
+ declaredBy: { pluginId: "financial", package: "@fayz-ai/plugin-financial" }
3351
+ },
3317
3352
  {
3318
3353
  slug: "google-analytics",
3319
3354
  name: "Google Analytics",
@@ -3382,6 +3417,34 @@ var SDK_INTEGRATIONS = [
3382
3417
  status: "soon",
3383
3418
  declaredBy: { pluginId: "crm", package: "@fayz-ai/plugin-crm" }
3384
3419
  },
3420
+ {
3421
+ slug: "ifood",
3422
+ name: "iFood",
3423
+ description: "Traga para a cozinha cada pedido feito no iFood, e avise o iFood quando ele for confirmado e sair.",
3424
+ icon: "Bike",
3425
+ logoUrl: "https://assets.fayz.ai/connectors/ifood.jpg",
3426
+ category: "marketplace",
3427
+ direction: "inbound",
3428
+ planes: ["sync"],
3429
+ moduleId: "orders",
3430
+ status: "available",
3431
+ connectorId: "ifood",
3432
+ declaredBy: { pluginId: "orders", package: "@fayz-ai/plugin-orders" }
3433
+ },
3434
+ {
3435
+ slug: "keeta",
3436
+ name: "Keeta",
3437
+ description: "Traga para a cozinha cada pedido feito no Keeta, e avise o Keeta quando ele for confirmado e sair.",
3438
+ icon: "Bike",
3439
+ logoUrl: "https://assets.fayz.ai/connectors/keeta.jpeg",
3440
+ category: "marketplace",
3441
+ direction: "inbound",
3442
+ planes: ["sync"],
3443
+ moduleId: "orders",
3444
+ status: "available",
3445
+ connectorId: "keeta",
3446
+ declaredBy: { pluginId: "orders", package: "@fayz-ai/plugin-orders" }
3447
+ },
3385
3448
  {
3386
3449
  slug: "kiwify",
3387
3450
  name: "Kiwify",
@@ -3439,11 +3502,16 @@ var SDK_INTEGRATIONS = [
3439
3502
  },
3440
3503
  {
3441
3504
  slug: "mercadopago",
3442
- name: "MercadoPago",
3505
+ name: "Mercado Pago",
3506
+ description: "Traga para o Financeiro tudo que entrou no Mercado Pago \u2014 Pix, cart\xE3o e maquininha \u2014 com a taxa e a data do repasse.",
3507
+ icon: "CreditCard",
3443
3508
  logoUrl: "https://assets.fayz.ai/connectors/mercadopago.png",
3444
3509
  category: "payments",
3510
+ direction: "inbound",
3511
+ planes: ["sync"],
3445
3512
  moduleId: "financial",
3446
- status: "soon",
3513
+ status: "available",
3514
+ connectorId: "mercadopago",
3447
3515
  declaredBy: { pluginId: "financial", package: "@fayz-ai/plugin-financial" }
3448
3516
  },
3449
3517
  {
@@ -3464,6 +3532,20 @@ var SDK_INTEGRATIONS = [
3464
3532
  status: "soon",
3465
3533
  declaredBy: { pluginId: "financial", package: "@fayz-ai/plugin-financial" }
3466
3534
  },
3535
+ {
3536
+ slug: "pagbank",
3537
+ name: "PagBank",
3538
+ description: "Traga para o Financeiro tudo que entrou no PagBank \u2014 Pix, cart\xE3o e maquininha \u2014 com a taxa e a data do repasse.",
3539
+ icon: "CreditCard",
3540
+ logoUrl: "https://assets.fayz.ai/connectors/pagbank_pagseguro.png",
3541
+ category: "payments",
3542
+ direction: "inbound",
3543
+ planes: ["sync"],
3544
+ moduleId: "financial",
3545
+ status: "available",
3546
+ connectorId: "pagbank",
3547
+ declaredBy: { pluginId: "financial", package: "@fayz-ai/plugin-financial" }
3548
+ },
3467
3549
  {
3468
3550
  slug: "ranklayer",
3469
3551
  name: "RankLayer",
@@ -3508,10 +3590,15 @@ var SDK_INTEGRATIONS = [
3508
3590
  {
3509
3591
  slug: "stone",
3510
3592
  name: "Stone",
3593
+ description: "Traga para o Financeiro tudo que entrou na Stone \u2014 cr\xE9dito, d\xE9bito, Pix e vale \u2014 com a taxa e a data do repasse.",
3594
+ icon: "CreditCard",
3511
3595
  logoUrl: "https://assets.fayz.ai/connectors/stone.jpeg",
3512
3596
  category: "payments",
3597
+ direction: "inbound",
3598
+ planes: ["sync"],
3513
3599
  moduleId: "financial",
3514
- status: "soon",
3600
+ status: "available",
3601
+ connectorId: "stone",
3515
3602
  declaredBy: { pluginId: "financial", package: "@fayz-ai/plugin-financial" }
3516
3603
  },
3517
3604
  {
@@ -3943,8 +4030,8 @@ function loadCatalog() {
3943
4030
  return catalogPromise;
3944
4031
  }
3945
4032
  function useConnectorCatalog() {
3946
- const [catalog, setCatalog] = React63__default.useState(null);
3947
- React63__default.useEffect(() => {
4033
+ const [catalog, setCatalog] = React65__default.useState(null);
4034
+ React65__default.useEffect(() => {
3948
4035
  let cancelled = false;
3949
4036
  void loadCatalog().then((list) => {
3950
4037
  if (!cancelled) setCatalog(list);
@@ -3968,7 +4055,7 @@ function refreshConnectors() {
3968
4055
  _revisionListeners.forEach((listener) => listener());
3969
4056
  }
3970
4057
  function useConnectorsRevision() {
3971
- return React63__default.useSyncExternalStore(
4058
+ return React65__default.useSyncExternalStore(
3972
4059
  (listener) => {
3973
4060
  _revisionListeners.add(listener);
3974
4061
  return () => _revisionListeners.delete(listener);
@@ -3987,11 +4074,11 @@ function loadGrants(key, fetcher) {
3987
4074
  }
3988
4075
  function useInstalledModuleIds() {
3989
4076
  const runtime = usePluginRuntimeOptional();
3990
- return React63__default.useMemo(() => (runtime?.plugins ?? []).map((p) => p.id), [runtime]);
4077
+ return React65__default.useMemo(() => (runtime?.plugins ?? []).map((p) => p.id), [runtime]);
3991
4078
  }
3992
4079
  function useInstalledDefinitions(hostPluginId) {
3993
4080
  const runtime = usePluginRuntimeOptional();
3994
- return React63__default.useMemo(() => {
4081
+ return React65__default.useMemo(() => {
3995
4082
  const byHost = runtime?.connectorsByHost;
3996
4083
  if (!byHost) return [];
3997
4084
  if (hostPluginId) return byHost.get(hostPluginId) ?? [];
@@ -4004,12 +4091,12 @@ function useConnectors(options = {}) {
4004
4091
  const catalog = useConnectorCatalog();
4005
4092
  const tenant = useTenantOptional();
4006
4093
  const tenantId2 = tenant?.org?.id;
4007
- const connection = React63__default.useMemo(() => resolveFayzAgentConnection(), []);
4008
- const [installed, setInstalled] = React63__default.useState(null);
4009
- const [grants, setGrants] = React63__default.useState(null);
4010
- const [error, setError] = React63__default.useState(null);
4094
+ const connection = React65__default.useMemo(() => resolveFayzAgentConnection(), []);
4095
+ const [installed, setInstalled] = React65__default.useState(null);
4096
+ const [grants, setGrants] = React65__default.useState(null);
4097
+ const [error, setError] = React65__default.useState(null);
4011
4098
  const nonce = useConnectorsRevision();
4012
- const call = React63__default.useCallback(
4099
+ const call = React65__default.useCallback(
4013
4100
  async (path, init) => {
4014
4101
  if (!connection) throw new Error("Este app n\xE3o est\xE1 ligado a um projeto Fayz.");
4015
4102
  const supabase = getFayzSupabaseClientOptional();
@@ -4029,7 +4116,7 @@ function useConnectors(options = {}) {
4029
4116
  },
4030
4117
  [connection]
4031
4118
  );
4032
- React63__default.useEffect(() => {
4119
+ React65__default.useEffect(() => {
4033
4120
  let cancelled = false;
4034
4121
  void loadConnectorStatuses(definitions, tenantId2).then((list) => {
4035
4122
  if (!cancelled) setInstalled(list);
@@ -4038,7 +4125,7 @@ function useConnectors(options = {}) {
4038
4125
  cancelled = true;
4039
4126
  };
4040
4127
  }, [definitions, tenantId2, nonce]);
4041
- React63__default.useEffect(() => {
4128
+ React65__default.useEffect(() => {
4042
4129
  if (!includeGrants || !connection || !tenantId2) {
4043
4130
  setGrants(includeGrants ? null : []);
4044
4131
  return;
@@ -4062,7 +4149,7 @@ function useConnectors(options = {}) {
4062
4149
  cancelled = true;
4063
4150
  };
4064
4151
  }, [call, tenantId2, includeGrants, connection, nonce]);
4065
- const revokeGrant = React63__default.useCallback(
4152
+ const revokeGrant = React65__default.useCallback(
4066
4153
  async (connector) => {
4067
4154
  const response = await call(`/${connector.id}`, { method: "DELETE" });
4068
4155
  if (!response.ok) {
@@ -4075,7 +4162,7 @@ function useConnectors(options = {}) {
4075
4162
  [call]
4076
4163
  );
4077
4164
  const waitingGrants = includeGrants && !!connection && !!tenantId2 && grants === null;
4078
- const connectors = React63__default.useMemo(() => {
4165
+ const connectors = React65__default.useMemo(() => {
4079
4166
  if (installed === null || waitingGrants) return null;
4080
4167
  return buildConnectorList({
4081
4168
  installed,
@@ -4744,9 +4831,9 @@ function prefersReducedMotion2() {
4744
4831
  return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
4745
4832
  }
4746
4833
  function TypewriterText({ text, speed = 26, onDone }) {
4747
- const [displayed, setDisplayed] = React63.useState("");
4748
- const indexRef = React63.useRef(0);
4749
- React63.useEffect(() => {
4834
+ const [displayed, setDisplayed] = React65.useState("");
4835
+ const indexRef = React65.useRef(0);
4836
+ React65.useEffect(() => {
4750
4837
  if (prefersReducedMotion2()) {
4751
4838
  setDisplayed(text);
4752
4839
  onDone?.();
@@ -4830,11 +4917,11 @@ function ChatFab({ className, apiEndpoint, systemPrompt, agent, voice, mobile })
4830
4917
  const { contextualSuggestions } = useAITools();
4831
4918
  const { sendMessage } = useChat({ apiEndpoint, systemPrompt, agent });
4832
4919
  const { t } = useTranslation$1();
4833
- const [phase, setPhase] = React63.useState("idle");
4834
- const [activeSuggestion, setActiveSuggestion] = React63.useState(null);
4835
- const timersRef = React63.useRef([]);
4836
- const prevSuggestionRef = React63.useRef(null);
4837
- React63.useEffect(ensureStyles, []);
4920
+ const [phase, setPhase] = React65.useState("idle");
4921
+ const [activeSuggestion, setActiveSuggestion] = React65.useState(null);
4922
+ const timersRef = React65.useRef([]);
4923
+ const prevSuggestionRef = React65.useRef(null);
4924
+ React65.useEffect(ensureStyles, []);
4838
4925
  const clearTimers = () => {
4839
4926
  timersRef.current.forEach(clearTimeout);
4840
4927
  timersRef.current = [];
@@ -4846,10 +4933,10 @@ function ChatFab({ className, apiEndpoint, systemPrompt, agent, voice, mobile })
4846
4933
  const topLabel = topSuggestion?.label ?? null;
4847
4934
  const invited = useAssistantInviteStore((s) => !!s.invite && s.stage === "dock");
4848
4935
  const morphingBack = useAssistantInviteStore((s) => !!s.leaving);
4849
- const [wide, setWide] = React63.useState(
4936
+ const [wide, setWide] = React65.useState(
4850
4937
  () => typeof window !== "undefined" && !!window.matchMedia?.("(min-width: 768px)").matches
4851
4938
  );
4852
- React63.useEffect(() => {
4939
+ React65.useEffect(() => {
4853
4940
  const query = window.matchMedia?.("(min-width: 768px)");
4854
4941
  if (!query) return;
4855
4942
  const sync = () => setWide(query.matches);
@@ -4858,7 +4945,7 @@ function ChatFab({ className, apiEndpoint, systemPrompt, agent, voice, mobile })
4858
4945
  return () => query.removeEventListener("change", sync);
4859
4946
  }, []);
4860
4947
  const teaserAllowed = !hasMessages && !activity && !invited && !teaserDismissed() && teaserShownCount() < TEASER_MAX_PER_SESSION;
4861
- React63.useEffect(() => {
4948
+ React65.useEffect(() => {
4862
4949
  if (expanded || !topSuggestion || !topLabel || !teaserAllowed || teaserSeen().includes(topLabel)) {
4863
4950
  if (phase !== "idle") {
4864
4951
  clearTimers();
@@ -4889,14 +4976,14 @@ function ChatFab({ className, apiEndpoint, systemPrompt, agent, voice, mobile })
4889
4976
  }, 9e3);
4890
4977
  return clearTimers;
4891
4978
  }, [topLabel, expanded, teaserAllowed]);
4892
- React63.useEffect(() => {
4979
+ React65.useEffect(() => {
4893
4980
  if (expanded && phase !== "idle") {
4894
4981
  clearTimers();
4895
4982
  setPhase("idle");
4896
4983
  }
4897
4984
  }, [expanded]);
4898
- const [entrance, setEntrance] = React63.useState("pending");
4899
- React63.useEffect(() => {
4985
+ const [entrance, setEntrance] = React65.useState("pending");
4986
+ React65.useEffect(() => {
4900
4987
  if (!currentOrg || entrance !== "pending") return;
4901
4988
  if (prefersReducedMotion2()) {
4902
4989
  setEntrance("done");
@@ -4906,9 +4993,9 @@ function ChatFab({ className, apiEndpoint, systemPrompt, agent, voice, mobile })
4906
4993
  const timer = setTimeout(() => setEntrance("done"), 1600);
4907
4994
  return () => clearTimeout(timer);
4908
4995
  }, [currentOrg, entrance]);
4909
- const [poppingBack, setPoppingBack] = React63.useState(false);
4910
- const wasMorphing = React63.useRef(false);
4911
- React63.useEffect(() => {
4996
+ const [poppingBack, setPoppingBack] = React65.useState(false);
4997
+ const wasMorphing = React65.useRef(false);
4998
+ React65.useEffect(() => {
4912
4999
  const was = wasMorphing.current;
4913
5000
  wasMorphing.current = morphingBack;
4914
5001
  if (!was || morphingBack || prefersReducedMotion2()) return;
@@ -5148,7 +5235,7 @@ function ChatFab({ className, apiEndpoint, systemPrompt, agent, voice, mobile })
5148
5235
  var MAX_SUGGESTIONS = 5;
5149
5236
  function ChatSuggestions({ suggestions, onSelect, onDismiss, compact }) {
5150
5237
  const { t } = useTranslation$1();
5151
- const [open, setOpen] = React63.useState(true);
5238
+ const [open, setOpen] = React65.useState(true);
5152
5239
  const visible = suggestions.slice(0, compact ? 3 : MAX_SUGGESTIONS);
5153
5240
  if (!visible.length) return null;
5154
5241
  return /* @__PURE__ */ jsxs(
@@ -5227,8 +5314,8 @@ function SuggestionRow({
5227
5314
  detail,
5228
5315
  onSelect
5229
5316
  }) {
5230
- const labelRef = React63.useRef(null);
5231
- const [showDetail, setShowDetail] = React63.useState(false);
5317
+ const labelRef = React65.useRef(null);
5318
+ const [showDetail, setShowDetail] = React65.useState(false);
5232
5319
  const evaluate = () => {
5233
5320
  const el = labelRef.current;
5234
5321
  const clipped = !!el && el.scrollWidth > el.clientWidth + 1;
@@ -5318,8 +5405,8 @@ function ChatToolsPanel({ toolGroups, onClose }) {
5318
5405
  }
5319
5406
  function AutoApprovalsSection() {
5320
5407
  const { t } = useTranslation$1();
5321
- const [rules, setRules] = React63.useState(() => listAutoApprovals());
5322
- React63.useEffect(() => subscribeAutoApprovals(() => setRules(listAutoApprovals())), []);
5408
+ const [rules, setRules] = React65.useState(() => listAutoApprovals());
5409
+ React65.useEffect(() => subscribeAutoApprovals(() => setRules(listAutoApprovals())), []);
5323
5410
  if (!rules.length) return null;
5324
5411
  return /* @__PURE__ */ jsxs("div", { className: "border-b border-border/40 px-3 py-2.5", children: [
5325
5412
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 px-1 pb-1.5", children: [
@@ -5386,9 +5473,9 @@ function ConnectorMark({
5386
5473
  connector,
5387
5474
  size = "md"
5388
5475
  }) {
5389
- const candidates = React63__default.useMemo(() => markCandidates(connector), [connector.logoUrl, connector.name]);
5390
- const [attempt, setAttempt] = React63__default.useState(0);
5391
- React63__default.useEffect(() => setAttempt(0), [connector.id]);
5476
+ const candidates = React65__default.useMemo(() => markCandidates(connector), [connector.logoUrl, connector.name]);
5477
+ const [attempt, setAttempt] = React65__default.useState(0);
5478
+ React65__default.useEffect(() => setAttempt(0), [connector.id]);
5392
5479
  const box = size === "sm" ? "h-9 w-9" : "h-10 w-10";
5393
5480
  const glyph = size === "sm" ? "h-4 w-4" : "h-5 w-5";
5394
5481
  if (connector.builtIn) {
@@ -5658,15 +5745,15 @@ function ConnectorSyncActions({
5658
5745
  actions,
5659
5746
  onRan
5660
5747
  }) {
5661
- const [running, setRunning] = React63__default.useState(null);
5662
- const [open, setOpen] = React63__default.useState(null);
5663
- const [pending, setPending] = React63__default.useState(null);
5664
- const [hidden, setHidden] = React63__default.useState(() => /* @__PURE__ */ new Set());
5665
- const [queued, setQueued] = React63__default.useState({});
5666
- const [nonce, setNonce] = React63__default.useState(0);
5667
- const [expanded, setExpanded] = React63__default.useState(false);
5668
- const [resolved, setResolved] = React63__default.useState(false);
5669
- React63__default.useEffect(() => {
5748
+ const [running, setRunning] = React65__default.useState(null);
5749
+ const [open, setOpen] = React65__default.useState(null);
5750
+ const [pending, setPending] = React65__default.useState(null);
5751
+ const [hidden, setHidden] = React65__default.useState(() => /* @__PURE__ */ new Set());
5752
+ const [queued, setQueued] = React65__default.useState({});
5753
+ const [nonce, setNonce] = React65__default.useState(0);
5754
+ const [expanded, setExpanded] = React65__default.useState(false);
5755
+ const [resolved, setResolved] = React65__default.useState(false);
5756
+ React65__default.useEffect(() => {
5670
5757
  let cancelled = false;
5671
5758
  setResolved(false);
5672
5759
  void Promise.all(
@@ -5851,10 +5938,10 @@ function formatRelative(iso, t) {
5851
5938
  }
5852
5939
  function useConnectorRuns(connector) {
5853
5940
  const listRuns = connector.definition?.listRuns;
5854
- const [runs, setRuns] = React63__default.useState([]);
5855
- const [loading, setLoading] = React63__default.useState(!!listRuns);
5856
- const [nonce, setNonce] = React63__default.useState(0);
5857
- React63__default.useEffect(() => {
5941
+ const [runs, setRuns] = React65__default.useState([]);
5942
+ const [loading, setLoading] = React65__default.useState(!!listRuns);
5943
+ const [nonce, setNonce] = React65__default.useState(0);
5944
+ React65__default.useEffect(() => {
5858
5945
  if (!listRuns) {
5859
5946
  setRuns([]);
5860
5947
  setLoading(false);
@@ -5876,7 +5963,7 @@ function useConnectorRuns(connector) {
5876
5963
  return {
5877
5964
  runs,
5878
5965
  loading,
5879
- reload: React63__default.useCallback(() => setNonce((n) => n + 1), []),
5966
+ reload: React65__default.useCallback(() => setNonce((n) => n + 1), []),
5880
5967
  failing: isFailing(runs)
5881
5968
  };
5882
5969
  }
@@ -6088,13 +6175,13 @@ function ConnectorSettingsPanel({
6088
6175
  const { t } = useTranslation$1();
6089
6176
  const def = connector.definition;
6090
6177
  const settings = def ? connectorSettings(def) : [];
6091
- const [values, setValues] = React63__default.useState(
6178
+ const [values, setValues] = React65__default.useState(
6092
6179
  () => initialValues(settings, {})
6093
6180
  );
6094
- const [loaded, setLoaded] = React63__default.useState(false);
6095
- const [saving, setSaving] = React63__default.useState(false);
6096
- const [dirty, setDirty] = React63__default.useState(false);
6097
- React63__default.useEffect(() => {
6181
+ const [loaded, setLoaded] = React65__default.useState(false);
6182
+ const [saving, setSaving] = React65__default.useState(false);
6183
+ const [dirty, setDirty] = React65__default.useState(false);
6184
+ React65__default.useEffect(() => {
6098
6185
  if (settings.length === 0 || !def?.getSettings) return;
6099
6186
  let cancelled = false;
6100
6187
  setLoaded(false);
@@ -6345,13 +6432,13 @@ function ConnectorInstall({
6345
6432
  }) {
6346
6433
  const { t } = useTranslation$1();
6347
6434
  const def = connector.definition;
6348
- const [plane, setPlane] = React63__default.useState(
6435
+ const [plane, setPlane] = React65__default.useState(
6349
6436
  connector.planes.includes("agentic") ? "agentic" : connector.planes[0]
6350
6437
  );
6351
- const [values, setValues] = React63__default.useState({});
6352
- const secrets = React63__default.useRef({});
6353
- const [busy, setBusy] = React63__default.useState(null);
6354
- React63__default.useEffect(() => {
6438
+ const [values, setValues] = React65__default.useState({});
6439
+ const secrets = React65__default.useRef({});
6440
+ const [busy, setBusy] = React65__default.useState(null);
6441
+ React65__default.useEffect(() => {
6355
6442
  setValues({});
6356
6443
  secrets.current = {};
6357
6444
  setBusy(null);
@@ -6392,13 +6479,13 @@ function ConnectorHome({
6392
6479
  const needsSetup = connector.state === "needs_setup";
6393
6480
  const settingsAvailable = hasOperatingSettings(connector);
6394
6481
  const runsAvailable = hasRunHistory(connector);
6395
- const [tab, setTab] = React63__default.useState(
6482
+ const [tab, setTab] = React65__default.useState(
6396
6483
  needsSetup && settingsAvailable ? "settings" : "overview"
6397
6484
  );
6398
- const [busy, setBusy] = React63__default.useState(null);
6485
+ const [busy, setBusy] = React65__default.useState(null);
6399
6486
  const run = useRunner(setBusy, onChanged);
6400
6487
  const runs = useConnectorRuns(connector);
6401
- React63__default.useEffect(() => {
6488
+ React65__default.useEffect(() => {
6402
6489
  setTab(needsSetup && settingsAvailable ? "settings" : "overview");
6403
6490
  setBusy(null);
6404
6491
  }, [connector.id]);
@@ -6475,7 +6562,7 @@ function ConnectorHome({
6475
6562
  }
6476
6563
  function useRunner(setBusy, onChanged) {
6477
6564
  const { t } = useTranslation$1();
6478
- return React63__default.useCallback(
6565
+ return React65__default.useCallback(
6479
6566
  async (kind, fn, okMessage) => {
6480
6567
  setBusy(kind);
6481
6568
  try {
@@ -6584,7 +6671,7 @@ function ConnectPanel({
6584
6671
  const tenantId2 = useTenantOptional()?.org?.id;
6585
6672
  const needsSink = needsCredentialSink(def);
6586
6673
  const sinkMissing = needsSink && !getConnectorCredentialSink();
6587
- const [formKey, setFormKey] = React63__default.useState(0);
6674
+ const [formKey, setFormKey] = React65__default.useState(0);
6588
6675
  if (def.authKind === "oauth") {
6589
6676
  return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
6590
6677
  /* @__PURE__ */ jsx(Note, { children: t("connectors.authorize.oauthOnly") }),
@@ -6716,7 +6803,7 @@ function GrantRevoke({
6716
6803
  onRevoke
6717
6804
  }) {
6718
6805
  const { t } = useTranslation$1();
6719
- const [revoking, setRevoking] = React63__default.useState(false);
6806
+ const [revoking, setRevoking] = React65__default.useState(false);
6720
6807
  if (connector.revocable === false) {
6721
6808
  return /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("connectors.partOfApp") });
6722
6809
  }
@@ -6755,13 +6842,13 @@ function ConnectorsPanel({ onClose }) {
6755
6842
  const { connectors, reload, revokeGrant, agentAvailable, tenantReady } = useConnectors();
6756
6843
  const selectedId = useConnectorsSurface((s) => s.selected);
6757
6844
  const select = useConnectorsSurface((s) => s.select);
6758
- const [query, setQuery] = React63__default.useState("");
6759
- const [failure, setFailure] = React63__default.useState(null);
6760
- const selected = React63__default.useMemo(
6845
+ const [query, setQuery] = React65__default.useState("");
6846
+ const [failure, setFailure] = React65__default.useState(null);
6847
+ const selected = React65__default.useMemo(
6761
6848
  () => (connectors ?? []).find((c) => c.id === selectedId) ?? null,
6762
6849
  [connectors, selectedId]
6763
6850
  );
6764
- const filtered = React63__default.useMemo(
6851
+ const filtered = React65__default.useMemo(
6765
6852
  () => filterConnectors(connectors ?? [], "outbound", query),
6766
6853
  [connectors, query]
6767
6854
  );
@@ -6863,20 +6950,20 @@ function useDictation({
6863
6950
  onInterim
6864
6951
  }) {
6865
6952
  const resolvedLocale = locale ?? (typeof navigator !== "undefined" ? navigator.language || "pt-BR" : "pt-BR");
6866
- const [state, setState] = React63.useState("idle");
6867
- const [error, setError] = React63.useState(null);
6868
- const sessionRef = React63.useRef(null);
6869
- const callbacks = React63.useRef({ onTranscript, onInterim });
6953
+ const [state, setState] = React65.useState("idle");
6954
+ const [error, setError] = React65.useState(null);
6955
+ const sessionRef = React65.useRef(null);
6956
+ const callbacks = React65.useRef({ onTranscript, onInterim });
6870
6957
  callbacks.current = { onTranscript, onInterim };
6871
- const supported = React63.useMemo(
6958
+ const supported = React65.useMemo(
6872
6959
  () => isDictationSupported(!!transcribeEndpoint),
6873
6960
  [transcribeEndpoint]
6874
6961
  );
6875
- const finish = React63.useCallback(() => {
6962
+ const finish = React65.useCallback(() => {
6876
6963
  sessionRef.current = null;
6877
6964
  setState("idle");
6878
6965
  }, []);
6879
- const start = React63.useCallback(() => {
6966
+ const start = React65.useCallback(() => {
6880
6967
  if (sessionRef.current || !supported) return;
6881
6968
  stopSpeaking();
6882
6969
  setError(null);
@@ -6897,28 +6984,28 @@ function useDictation({
6897
6984
  }
6898
6985
  );
6899
6986
  }, [finish, resolvedLocale, supported, transcribeEndpoint]);
6900
- const stop = React63.useCallback(() => {
6987
+ const stop = React65.useCallback(() => {
6901
6988
  if (!sessionRef.current) return;
6902
6989
  if (transcribeEndpoint) setState("transcribing");
6903
6990
  sessionRef.current.stop();
6904
6991
  }, [transcribeEndpoint]);
6905
- const cancel = React63.useCallback(() => {
6992
+ const cancel = React65.useCallback(() => {
6906
6993
  sessionRef.current?.cancel();
6907
6994
  sessionRef.current = null;
6908
6995
  setState("idle");
6909
6996
  setError(null);
6910
6997
  }, []);
6911
- const toggle = React63.useCallback(() => {
6998
+ const toggle = React65.useCallback(() => {
6912
6999
  if (state === "listening" || state === "transcribing") stop();
6913
7000
  else start();
6914
7001
  }, [state, start, stop]);
6915
- React63.useEffect(() => () => sessionRef.current?.cancel(), []);
7002
+ React65.useEffect(() => () => sessionRef.current?.cancel(), []);
6916
7003
  return { supported, state, error, start, stop, cancel, toggle, clearError: () => setError(null) };
6917
7004
  }
6918
7005
  function useMicLevels(active2, bandCount = 28, externalStream) {
6919
- const levelsRef = React63.useRef(new Float32Array(bandCount));
6920
- const [available, setAvailable] = React63.useState(false);
6921
- React63.useEffect(() => {
7006
+ const levelsRef = React65.useRef(new Float32Array(bandCount));
7007
+ const [available, setAvailable] = React65.useState(false);
7008
+ React65.useEffect(() => {
6922
7009
  if (!active2) {
6923
7010
  levelsRef.current.fill(0);
6924
7011
  setAvailable(false);
@@ -6987,8 +7074,8 @@ var KIND_ICON = {
6987
7074
  binary: File
6988
7075
  };
6989
7076
  function useFileDrop(enabled, onFiles) {
6990
- const [dragging, setDragging] = React63.useState(false);
6991
- const depth = React63.useRef(0);
7077
+ const [dragging, setDragging] = React65.useState(false);
7078
+ const depth = React65.useRef(0);
6992
7079
  const carriesFiles = (event) => Array.from(event.dataTransfer?.types ?? []).includes("Files");
6993
7080
  const reset = () => {
6994
7081
  depth.current = 0;
@@ -7048,7 +7135,7 @@ function AttachmentChips({
7048
7135
  onRemove
7049
7136
  }) {
7050
7137
  const { t } = useTranslation$1();
7051
- const [openId, setOpenId] = React63.useState(null);
7138
+ const [openId, setOpenId] = React65.useState(null);
7052
7139
  if (!attachments.length) return null;
7053
7140
  const opened = attachments.find((a) => a.id === openId);
7054
7141
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -7159,8 +7246,8 @@ function ChatComposer({
7159
7246
  onToggleSuggestions
7160
7247
  }) {
7161
7248
  const { t } = useTranslation$1();
7162
- const [input, setInput] = React63.useState("");
7163
- const textareaRef = React63.useRef(null);
7249
+ const [input, setInput] = React65.useState("");
7250
+ const textareaRef = React65.useRef(null);
7164
7251
  const voiceStartRequested = useChatStore((s) => s.voiceStartRequested);
7165
7252
  const consumeVoiceStart = useChatStore((s) => s.consumeVoiceStart);
7166
7253
  const draft = useChatStore((s) => s.draft);
@@ -7168,13 +7255,13 @@ function ChatComposer({
7168
7255
  const attachments = useChatStore((s) => s.attachments);
7169
7256
  const addAttachments = useChatStore((s) => s.addAttachments);
7170
7257
  const removeAttachment = useChatStore((s) => s.removeAttachment);
7171
- const fileInputRef = React63.useRef(null);
7258
+ const fileInputRef = React65.useRef(null);
7172
7259
  const autoSend = voice?.autoSend === true;
7173
7260
  const micEnabled = voice?.input !== false;
7174
7261
  const canAttach = isConfigured && !blocked && !isStreaming;
7175
7262
  const parsing = attachments.some((a) => a.status === "parsing");
7176
7263
  const readyAttachments = attachments.filter((a) => a.status === "ready").length;
7177
- const submit = React63.useCallback(
7264
+ const submit = React65.useCallback(
7178
7265
  (text) => {
7179
7266
  const trimmed = text.trim();
7180
7267
  if (!trimmed && !readyAttachments || parsing || isStreaming || !isConfigured || blocked) return;
@@ -7207,7 +7294,7 @@ function ChatComposer({
7207
7294
  const WAVEFORM_BANDS = 56;
7208
7295
  const activity = useAssistantActivity();
7209
7296
  const sessionRecording = activity?.kind === "recording" && activity.state === "running";
7210
- const sessionStream = React63.useMemo(
7297
+ const sessionStream = React65.useMemo(
7211
7298
  () => sessionRecording ? activity?.stream?.() ?? null : null,
7212
7299
  [sessionRecording, activity]
7213
7300
  );
@@ -7219,12 +7306,12 @@ function ChatComposer({
7219
7306
  );
7220
7307
  const sessionPause = activity?.actions?.find((a) => a.intent === "pause" || a.intent === "resume");
7221
7308
  const sessionOwnsMic = activity?.kind === "recording" && (activity.state === "running" || activity.state === "paused");
7222
- React63.useEffect(() => {
7309
+ React65.useEffect(() => {
7223
7310
  if (!voiceStartRequested) return;
7224
7311
  consumeVoiceStart();
7225
7312
  if (showMic) dictation.start();
7226
7313
  }, [voiceStartRequested, showMic]);
7227
- React63.useEffect(() => {
7314
+ React65.useEffect(() => {
7228
7315
  if (!draft) return;
7229
7316
  setInput(draft);
7230
7317
  setDraft("");
@@ -7234,7 +7321,7 @@ function ChatComposer({
7234
7321
  el.setSelectionRange(draft.length, draft.length);
7235
7322
  }
7236
7323
  }, [draft, setDraft]);
7237
- React63.useLayoutEffect(() => {
7324
+ React65.useLayoutEffect(() => {
7238
7325
  const el = textareaRef.current;
7239
7326
  if (!el) return;
7240
7327
  const style = getComputedStyle(el);
@@ -7431,8 +7518,8 @@ function LiveWaveform({
7431
7518
  compact,
7432
7519
  tone = "primary"
7433
7520
  }) {
7434
- const barsRef = React63.useRef([]);
7435
- React63.useEffect(() => {
7521
+ const barsRef = React65.useRef([]);
7522
+ React65.useEffect(() => {
7436
7523
  if (!live) return;
7437
7524
  let frame = 0;
7438
7525
  const draw = () => {
@@ -7713,7 +7800,7 @@ function ConnectorSuggestionCard({ card }) {
7713
7800
  const setOpen = useChatStore((s) => s.setOpen);
7714
7801
  const category = categoryLabel(card.category);
7715
7802
  const live = isConnectorState(card.state) ? card.state : null;
7716
- const go = React63.useCallback(() => {
7803
+ const go = React65.useCallback(() => {
7717
7804
  if (panelAvailable && card.id) {
7718
7805
  openConnectorsPanel({ id: card.id });
7719
7806
  return;
@@ -7770,7 +7857,7 @@ function humanizeToolName(name) {
7770
7857
  }
7771
7858
  function ToolCallRow({ call }) {
7772
7859
  const { t } = useTranslation$1();
7773
- const [open, setOpen] = React63.useState(false);
7860
+ const [open, setOpen] = React65.useState(false);
7774
7861
  const failed = call.declined || /"error"\s*:/.test(call.result ?? "");
7775
7862
  return /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-xl border border-border/50 bg-muted/30", children: [
7776
7863
  /* @__PURE__ */ jsxs(
@@ -7833,7 +7920,7 @@ function ToolCallRow({ call }) {
7833
7920
  }
7834
7921
  function MessageBubble({ message, isPending }) {
7835
7922
  const isUser = message.role === "user";
7836
- const routedLinks = React63.useMemo(
7923
+ const routedLinks = React65.useMemo(
7837
7924
  () => (message.links ?? []).filter(
7838
7925
  (l) => !!l.path || !!resolveEntityRoute(l.archetype, l.kind, l.entityKey)
7839
7926
  ),
@@ -7908,9 +7995,9 @@ function ConfirmActionCard({
7908
7995
  onResolve
7909
7996
  }) {
7910
7997
  const { t } = useTranslation$1();
7911
- const schema = React63.useMemo(() => action.fields ?? [], [action.fields]);
7998
+ const schema = React65.useMemo(() => action.fields ?? [], [action.fields]);
7912
7999
  const partial = action.partial === true;
7913
- const seedValues = React63.useCallback(
8000
+ const seedValues = React65.useCallback(
7914
8001
  (params) => {
7915
8002
  if (partial) return { ...params };
7916
8003
  const seeded = {};
@@ -7919,17 +8006,17 @@ function ConfirmActionCard({
7919
8006
  },
7920
8007
  [schema, partial]
7921
8008
  );
7922
- const [values, setValues] = React63.useState(() => seedValues(action.params));
7923
- const [showAll, setShowAll] = React63.useState(false);
7924
- React63.useEffect(() => setValues(seedValues(action.params)), [action.params, seedValues]);
8009
+ const [values, setValues] = React65.useState(() => seedValues(action.params));
8010
+ const [showAll, setShowAll] = React65.useState(false);
8011
+ React65.useEffect(() => setValues(seedValues(action.params)), [action.params, seedValues]);
7925
8012
  const isSet = (v) => v !== void 0 && v !== null && v !== "";
7926
- const primaryKeys = React63.useMemo(() => {
8013
+ const primaryKeys = React65.useMemo(() => {
7927
8014
  const keys = Object.keys(action.params).filter((k) => isSet(action.params[k]));
7928
8015
  if (partial) return keys;
7929
8016
  for (const f of schema) if (f.required && !keys.includes(f.key)) keys.push(f.key);
7930
8017
  return keys;
7931
8018
  }, [action.params, schema, partial]);
7932
- const extraKeys = React63.useMemo(
8019
+ const extraKeys = React65.useMemo(
7933
8020
  () => schema.map((f) => f.key).filter((k) => !primaryKeys.includes(k) && k !== "id"),
7934
8021
  [schema, primaryKeys]
7935
8022
  );
@@ -7946,20 +8033,20 @@ function ConfirmActionCard({
7946
8033
  const translatedTool = t(toolKey);
7947
8034
  const heading = action.title ?? (translatedTool !== toolKey ? translatedTool : humanizeToolName(action.toolName));
7948
8035
  const ruleLabel = action.scopeLabel ?? heading;
7949
- const missingRequiredKeys = React63.useMemo(
8036
+ const missingRequiredKeys = React65.useMemo(
7950
8037
  () => partial ? [] : schema.filter((f) => f.required && !isSet(values[f.key])).map((f) => f.key),
7951
8038
  [schema, values, partial]
7952
8039
  );
7953
8040
  const canConfirm = missingRequiredKeys.length === 0;
7954
- const submitted = React63.useCallback(
8041
+ const submitted = React65.useCallback(
7955
8042
  () => partial ? Object.fromEntries(Object.entries(values).filter(([, v]) => isSet(v))) : values,
7956
8043
  [partial, values]
7957
8044
  );
7958
- const approve = React63.useCallback(() => {
8045
+ const approve = React65.useCallback(() => {
7959
8046
  if (canConfirm) onResolve(true, submitted());
7960
8047
  }, [canConfirm, onResolve, submitted]);
7961
- const decline = React63.useCallback(() => onResolve(false), [onResolve]);
7962
- const approveAlways = React63.useCallback(() => {
8048
+ const decline = React65.useCallback(() => onResolve(false), [onResolve]);
8049
+ const approveAlways = React65.useCallback(() => {
7963
8050
  if (!canConfirm) return;
7964
8051
  grantAutoApproval({
7965
8052
  toolName: action.toolName,
@@ -7969,7 +8056,7 @@ function ConfirmActionCard({
7969
8056
  });
7970
8057
  onResolve(true, submitted());
7971
8058
  }, [canConfirm, action.toolName, action.scope, ruleLabel, destructive, onResolve, submitted]);
7972
- React63.useEffect(() => {
8059
+ React65.useEffect(() => {
7973
8060
  const handler = (event) => {
7974
8061
  const target = event.target;
7975
8062
  const typing = target?.tagName === "INPUT" || target?.tagName === "TEXTAREA" || target?.tagName === "SELECT";
@@ -8303,7 +8390,7 @@ function UpgradePrompt({ feature, inline, className }) {
8303
8390
  const currentPlan = plans.find((p) => p.id === currentPlanId);
8304
8391
  const currentPrice = currentPlan?.price ?? 0;
8305
8392
  const currentPlanName = currentPlan?.name ?? tr("billing.free", "Free");
8306
- const featureName = React63.useMemo(() => {
8393
+ const featureName = React65.useMemo(() => {
8307
8394
  if (!feature) return null;
8308
8395
  const label = features.find((f) => f.id === feature)?.label;
8309
8396
  if (label) return featureDisplayName(label);
@@ -8311,7 +8398,7 @@ function UpgradePrompt({ feature, inline, className }) {
8311
8398
  const named = t(key);
8312
8399
  return named && named !== key ? named : featureDisplayName(feature);
8313
8400
  }, [features, feature, t]);
8314
- const unlockingPlans = React63.useMemo(
8401
+ const unlockingPlans = React65.useMemo(
8315
8402
  () => plans.filter((p) => p.id !== currentPlanId && p.price > currentPrice && planUnlocks(p, feature)).sort((a, b) => a.price - b.price),
8316
8403
  [plans, currentPlanId, currentPrice, feature]
8317
8404
  );
@@ -8489,30 +8576,30 @@ function ChatConversation({
8489
8576
  usable && !pendingAction && !isStreaming,
8490
8577
  addAttachments
8491
8578
  );
8492
- React63.useEffect(ensureIntroStyles, []);
8579
+ React65.useEffect(ensureIntroStyles, []);
8493
8580
  const conversationsLoaded = useChatStore((s) => s.conversationsLoaded);
8494
- const hasHistoryBackend = React63.useMemo(
8581
+ const hasHistoryBackend = React65.useMemo(
8495
8582
  () => !apiEndpoint && !!resolveFayzAgentConnection(agent),
8496
8583
  [apiEndpoint, agent]
8497
8584
  );
8498
8585
  const conversationsPending = hasHistoryBackend && !conversationsLoaded;
8499
- const [view, setView] = React63.useState(
8586
+ const [view, setView] = React65.useState(
8500
8587
  () => useChatStore.getState().messages.length > 0 ? "thread" : "list"
8501
8588
  );
8502
- const [drawer, setDrawer] = React63.useState("none");
8503
- const [atBottom, setAtBottom] = React63.useState(true);
8504
- const scrollRef = React63.useRef(null);
8589
+ const [drawer, setDrawer] = React65.useState("none");
8590
+ const [atBottom, setAtBottom] = React65.useState(true);
8591
+ const scrollRef = React65.useRef(null);
8505
8592
  const hasMessages = messages.length > 0;
8506
8593
  const totalTools = toolGroups.reduce((sum, g) => sum + g.tools.length, 0);
8507
- const scrollToBottom = React63.useCallback((behavior = "smooth") => {
8594
+ const scrollToBottom = React65.useCallback((behavior = "smooth") => {
8508
8595
  const el = scrollRef.current;
8509
8596
  if (!el) return;
8510
8597
  el.scrollTo({ top: el.scrollHeight, behavior });
8511
8598
  }, []);
8512
- React63.useEffect(() => {
8599
+ React65.useEffect(() => {
8513
8600
  if (atBottom) scrollToBottom();
8514
8601
  }, [messages, activeTools, pendingAction, atBottom, scrollToBottom]);
8515
- React63.useEffect(() => {
8602
+ React65.useEffect(() => {
8516
8603
  loadConversations();
8517
8604
  setSuggestionsOpen(useChatStore.getState().messages.length === 0);
8518
8605
  return () => stopSpeaking();
@@ -8529,7 +8616,7 @@ function ChatConversation({
8529
8616
  };
8530
8617
  const queuedPrompt = useChatStore((s) => s.queuedPrompt);
8531
8618
  const consumeQueuedPrompt = useChatStore((s) => s.consumeQueuedPrompt);
8532
- React63.useEffect(() => {
8619
+ React65.useEffect(() => {
8533
8620
  if (!queuedPrompt) return;
8534
8621
  const prompt = consumeQueuedPrompt();
8535
8622
  if (prompt && usable) send(prompt);
@@ -8537,7 +8624,7 @@ function ChatConversation({
8537
8624
  const toggleDrawer = (next) => setDrawer((current) => current === next ? "none" : next);
8538
8625
  const connectorsPending = useConnectorsSurface((s) => s.pending);
8539
8626
  const consumeConnectorsRequest = useConnectorsSurface((s) => s.consume);
8540
- React63.useEffect(() => {
8627
+ React65.useEffect(() => {
8541
8628
  if (!connectorsPending) return;
8542
8629
  setDrawer("connectors");
8543
8630
  consumeConnectorsRequest();
@@ -8824,7 +8911,7 @@ function HeaderButton({
8824
8911
  function useDelegateToAssistant() {
8825
8912
  const queuePrompt = useChatStore((s) => s.queuePrompt);
8826
8913
  const openPanel = useRightRailStore((s) => s.openPanel);
8827
- return React63.useCallback(
8914
+ return React65.useCallback(
8828
8915
  (prompt) => {
8829
8916
  queuePrompt(prompt);
8830
8917
  openPanel("chat");
@@ -8883,12 +8970,12 @@ function NotesPanel() {
8883
8970
  const user = useAuthStore((s) => s.user);
8884
8971
  const currentOrg = useOrganizationStore((s) => s.currentOrg);
8885
8972
  const key = storageKey2(currentOrg?.id ?? "local", user?.id ?? "anon");
8886
- const [notes, setNotes] = React63.useState(() => loadNotes(key));
8887
- const [openId, setOpenId] = React63.useState(null);
8888
- const [search, setSearch] = React63.useState("");
8889
- const [preview, setPreview] = React63.useState(false);
8890
- const [confirmingDelete, setConfirmingDelete] = React63.useState(null);
8891
- React63.useEffect(() => {
8973
+ const [notes, setNotes] = React65.useState(() => loadNotes(key));
8974
+ const [openId, setOpenId] = React65.useState(null);
8975
+ const [search, setSearch] = React65.useState("");
8976
+ const [preview, setPreview] = React65.useState(false);
8977
+ const [confirmingDelete, setConfirmingDelete] = React65.useState(null);
8978
+ React65.useEffect(() => {
8892
8979
  setNotes(loadNotes(key));
8893
8980
  setOpenId(null);
8894
8981
  }, [key]);
@@ -9121,10 +9208,10 @@ ${note.content}`
9121
9208
  function NoteTodosSection({ noteId, noteTitle, tr }) {
9122
9209
  const adapter2 = useNotesTasksBridge((s) => s.adapter);
9123
9210
  const delegate = useDelegateToAssistant();
9124
- const [todos, setTodos] = React63.useState([]);
9125
- const [draft, setDraft] = React63.useState("");
9126
- const [busy, setBusy] = React63.useState(false);
9127
- React63.useEffect(() => {
9211
+ const [todos, setTodos] = React65.useState([]);
9212
+ const [draft, setDraft] = React65.useState("");
9213
+ const [busy, setBusy] = React65.useState(false);
9214
+ React65.useEffect(() => {
9128
9215
  if (!adapter2) return;
9129
9216
  let alive = true;
9130
9217
  adapter2.listTodos(noteId).then((rows) => {
@@ -9275,11 +9362,11 @@ function NotesRailPanel() {
9275
9362
  const currentOrg = useOrganizationStore((s) => s.currentOrg);
9276
9363
  const key = storageKey2(currentOrg?.id ?? "local", user?.id ?? "anon");
9277
9364
  const count = useNotesCount((s) => s.count);
9278
- React63.useEffect(() => {
9365
+ React65.useEffect(() => {
9279
9366
  useNotesCount.getState().setCount(loadNotes(key).length);
9280
9367
  }, [key]);
9281
9368
  useRightRailPanel(
9282
- React63.useMemo(
9369
+ React65.useMemo(
9283
9370
  () => ({ id: "notes", label, icon: StickyNote, order: 30, badge: { count }, Component: NotesPanel }),
9284
9371
  [label, count]
9285
9372
  )
@@ -9933,7 +10020,7 @@ function useGlobalSearch() {
9933
10020
  );
9934
10021
  return { search, select, canOpen, targetCount: targets.length };
9935
10022
  }
9936
- var RouteErrorBoundary = class extends React63.Component {
10023
+ var RouteErrorBoundary = class extends React65.Component {
9937
10024
  constructor() {
9938
10025
  super(...arguments);
9939
10026
  this.state = { crashed: false, report: null };
@@ -9975,7 +10062,7 @@ var RouteErrorBoundary = class extends React63.Component {
9975
10062
  }
9976
10063
  };
9977
10064
  function RouteErrorScreen({ report, tr, onBack, onRetry, backLabel }) {
9978
- const [copied, setCopied] = React63.useState(false);
10065
+ const [copied, setCopied] = React65.useState(false);
9979
10066
  const copyDetails = () => {
9980
10067
  if (!report || typeof navigator === "undefined" || !navigator.clipboard) return;
9981
10068
  const details = [
@@ -10022,16 +10109,21 @@ function RouteErrorScreen({ report, tr, onBack, onRetry, backLabel }) {
10022
10109
  ] })
10023
10110
  ] });
10024
10111
  }
10112
+ var WidgetSurfaceContext = React65.createContext("rail");
10113
+ function useWidgetSurface() {
10114
+ return React65.useContext(WidgetSurfaceContext);
10115
+ }
10025
10116
  function WidgetSlot({
10026
10117
  zone,
10027
10118
  contextOverrides,
10119
+ surface,
10028
10120
  ...props
10029
10121
  }) {
10030
10122
  const runtime = usePluginRuntimeOptional();
10031
10123
  if (!runtime) return null;
10032
10124
  const widgets = getWidgetsForZone(runtime, zone, contextOverrides);
10033
10125
  if (!widgets.length) return null;
10034
- return /* @__PURE__ */ jsx(Fragment, { children: widgets.map((widget, i) => {
10126
+ return /* @__PURE__ */ jsx(WidgetSurfaceContext.Provider, { value: surface ?? "rail", children: widgets.map((widget, i) => {
10035
10127
  const Component2 = resolvePluginComponent(widget);
10036
10128
  if (!Component2) return null;
10037
10129
  const w = widget;
@@ -10063,7 +10155,7 @@ function useNavContribution(id, entries2) {
10063
10155
  const setContribution = useNavContributionsStore((s) => s.setContribution);
10064
10156
  const clearContribution = useNavContributionsStore((s) => s.clearContribution);
10065
10157
  const key = JSON.stringify(entries2);
10066
- React63.useEffect(() => {
10158
+ React65.useEffect(() => {
10067
10159
  setContribution(id, entries2);
10068
10160
  return () => clearContribution(id);
10069
10161
  }, [id, key]);
@@ -10093,7 +10185,7 @@ function useContextualNav(nav) {
10093
10185
  const setNav = useContextualNavStore((s) => s.setNav);
10094
10186
  const clearNav = useContextualNavStore((s) => s.clearNav);
10095
10187
  const key = nav ? JSON.stringify(nav) : null;
10096
- React63.useEffect(() => {
10188
+ React65.useEffect(() => {
10097
10189
  if (!nav) return;
10098
10190
  setNav(nav);
10099
10191
  return () => clearNav(nav.base);
@@ -10244,10 +10336,10 @@ function SeuSiteWidget({ fallback, onEdit }) {
10244
10336
  const load = useFayzProjectsStore((s) => s.load);
10245
10337
  const loadedFor = useFayzProjectsStore((s) => s.loadedFor);
10246
10338
  const collapsed = useLayoutStore((s) => s.sidebarCollapsed);
10247
- const [selectedId, setSelectedId] = React63.useState(null);
10248
- const [hovered, setHovered] = React63.useState(false);
10249
- const [primed, setPrimed] = React63.useState(false);
10250
- const closeTimer = React63.useRef(null);
10339
+ const [selectedId, setSelectedId] = React65.useState(null);
10340
+ const [hovered, setHovered] = React65.useState(false);
10341
+ const [primed, setPrimed] = React65.useState(false);
10342
+ const closeTimer = React65.useRef(null);
10251
10343
  const cancelClose = () => {
10252
10344
  if (closeTimer.current) {
10253
10345
  clearTimeout(closeTimer.current);
@@ -10263,8 +10355,8 @@ function SeuSiteWidget({ fallback, onEdit }) {
10263
10355
  cancelClose();
10264
10356
  closeTimer.current = setTimeout(() => setHovered(false), 140);
10265
10357
  };
10266
- React63.useEffect(() => () => cancelClose(), []);
10267
- React63.useEffect(() => {
10358
+ React65.useEffect(() => () => cancelClose(), []);
10359
+ React65.useEffect(() => {
10268
10360
  if (loadedFor !== (currentOrgId ?? null)) void load(currentOrgId);
10269
10361
  }, [currentOrgId, loadedFor, load]);
10270
10362
  const active2 = projects.find((p) => p.id === selectedId) ?? defaultProjectOf(projects) ?? synthFromFallback(fallback);
@@ -10353,10 +10445,10 @@ function SitePreview({
10353
10445
  onEdit,
10354
10446
  tr
10355
10447
  }) {
10356
- const [nonce, setNonce] = React63.useState(0);
10357
- const [loading, setLoading] = React63.useState(true);
10448
+ const [nonce, setNonce] = React65.useState(0);
10449
+ const [loading, setLoading] = React65.useState(true);
10358
10450
  const url = project.previewUrl;
10359
- React63.useEffect(() => {
10451
+ React65.useEffect(() => {
10360
10452
  setLoading(true);
10361
10453
  }, [nonce, url]);
10362
10454
  const action = "flex items-center gap-1.5 rounded-button px-2 py-1 text-[11.5px] font-medium text-sidebar-foreground/80 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground disabled:cursor-not-allowed disabled:opacity-40";
@@ -10453,8 +10545,8 @@ function RightRail({ frame = true }) {
10453
10545
  const openPanel = useRightRailStore((s) => s.openPanel);
10454
10546
  const close = useRightRailStore((s) => s.close);
10455
10547
  const setWidth = useRightRailStore((s) => s.setWidth);
10456
- const rootRef = React63.useRef(null);
10457
- React63.useEffect(() => {
10548
+ const rootRef = React65.useRef(null);
10549
+ React65.useEffect(() => {
10458
10550
  if (!open) return;
10459
10551
  const el = rootRef.current;
10460
10552
  if (!el) return;
@@ -10679,9 +10771,9 @@ var TYPE_COLORS = {
10679
10771
  fix: "text-success"
10680
10772
  };
10681
10773
  function ChangelogFeed({ changelogUrl, className }) {
10682
- const [entries2, setEntries] = React63.useState([]);
10683
- const [loading, setLoading] = React63.useState(false);
10684
- React63.useEffect(() => {
10774
+ const [entries2, setEntries] = React65.useState([]);
10775
+ const [loading, setLoading] = React65.useState(false);
10776
+ React65.useEffect(() => {
10685
10777
  if (!changelogUrl) return;
10686
10778
  setLoading(true);
10687
10779
  fetch(changelogUrl).then((r) => r.json()).then((data) => setEntries(data)).catch(() => setEntries([])).finally(() => setLoading(false));
@@ -10744,7 +10836,7 @@ function NotificationInbox({
10744
10836
  changelogUrl,
10745
10837
  className
10746
10838
  }) {
10747
- const [activeTab, setActiveTab] = React63.useState("inbox");
10839
+ const [activeTab, setActiveTab] = React65.useState("inbox");
10748
10840
  const unreadCount = notifications.filter((n) => !n.read).length;
10749
10841
  const inboxNotifications = notifications.filter((n) => n.category !== "changelog");
10750
10842
  return /* @__PURE__ */ jsxs("div", { className: cn$1("flex w-80 flex-col", className), children: [
@@ -10840,15 +10932,15 @@ function NotificationInbox({
10840
10932
  ] });
10841
10933
  }
10842
10934
  function ConnectConsentPage({ appName, logo }) {
10843
- const [state, setState] = React63__default.useState({ status: "loading" });
10844
- const [tenantId2, setTenantId] = React63__default.useState("");
10845
- const request = React63__default.useMemo(
10935
+ const [state, setState] = React65__default.useState({ status: "loading" });
10936
+ const [tenantId2, setTenantId] = React65__default.useState("");
10937
+ const request = React65__default.useMemo(
10846
10938
  () => new URLSearchParams(window.location.search).get("request") ?? "",
10847
10939
  []
10848
10940
  );
10849
- const connection = React63__default.useMemo(() => resolveFayzAgentConnection(), []);
10941
+ const connection = React65__default.useMemo(() => resolveFayzAgentConnection(), []);
10850
10942
  const product = appName ?? document.title ?? "este app";
10851
- const authorizedFetch = React63__default.useCallback(
10943
+ const authorizedFetch = React65__default.useCallback(
10852
10944
  async (path, init) => {
10853
10945
  if (!connection) throw new Error("Este app n\xE3o est\xE1 ligado a um projeto Fayz.");
10854
10946
  const supabase = getFayzSupabaseClientOptional();
@@ -10872,7 +10964,7 @@ function ConnectConsentPage({ appName, logo }) {
10872
10964
  },
10873
10965
  [connection]
10874
10966
  );
10875
- React63__default.useEffect(() => {
10967
+ React65__default.useEffect(() => {
10876
10968
  let cancelled = false;
10877
10969
  (async () => {
10878
10970
  if (!request) {
@@ -11113,25 +11205,25 @@ function AddConnectorPanel({
11113
11205
  onSelect
11114
11206
  }) {
11115
11207
  const { t } = useTranslation$1();
11116
- const [query, setQuery] = React63__default.useState("");
11208
+ const [query, setQuery] = React65__default.useState("");
11117
11209
  const modules = useInstalledModuleIds();
11118
11210
  const catalog = useConnectorCatalog();
11119
11211
  const scoped = !!categories?.length;
11120
- const addable = React63__default.useMemo(
11212
+ const addable = React65__default.useMemo(
11121
11213
  () => inCategories(addableConnectors(connectors ?? []), categories),
11122
11214
  [connectors, categories]
11123
11215
  );
11124
- const shelf = React63__default.useMemo(() => {
11216
+ const shelf = React65__default.useMemo(() => {
11125
11217
  if (connectors === null) return [];
11126
11218
  return inCategories(
11127
11219
  shelfIntegrations({ present: connectors, installedModules: modules, catalog: catalog ?? [] }),
11128
11220
  categories
11129
11221
  );
11130
11222
  }, [connectors, modules, catalog, categories]);
11131
- const filtered = React63__default.useMemo(() => filterConnectors(addable, "all", query), [addable, query]);
11132
- const filteredShelf = React63__default.useMemo(() => filterAvailable(shelf, query), [shelf, query]);
11133
- const soon = React63__default.useMemo(() => comingSoonHere(filteredShelf), [filteredShelf]);
11134
- const elsewhere = React63__default.useMemo(() => withAnotherModule(filteredShelf), [filteredShelf]);
11223
+ const filtered = React65__default.useMemo(() => filterConnectors(addable, "all", query), [addable, query]);
11224
+ const filteredShelf = React65__default.useMemo(() => filterAvailable(shelf, query), [shelf, query]);
11225
+ const soon = React65__default.useMemo(() => comingSoonHere(filteredShelf), [filteredShelf]);
11226
+ const elsewhere = React65__default.useMemo(() => withAnotherModule(filteredShelf), [filteredShelf]);
11135
11227
  const searchable = addable.length + shelf.length > 6;
11136
11228
  return /* @__PURE__ */ jsx(Modal, { open, onOpenChange, children: /* @__PURE__ */ jsxs(ModalContent, { size: "2xl", children: [
11137
11229
  /* @__PURE__ */ jsxs(ModalHeader, { children: [
@@ -11290,20 +11382,20 @@ function AddConnectorButton({ onClick }) {
11290
11382
  function ConnectorsTab() {
11291
11383
  const { t } = useTranslation$1();
11292
11384
  const { connectors, error, reload, revokeGrant, agentAvailable, tenantReady } = useConnectors();
11293
- const [adding, setAdding] = React63__default.useState(false);
11294
- const [selected, setSelected] = React63__default.useState(null);
11295
- const [filter, setFilter] = React63__default.useState("all");
11296
- const [failure, setFailure] = React63__default.useState(null);
11385
+ const [adding, setAdding] = React65__default.useState(false);
11386
+ const [selected, setSelected] = React65__default.useState(null);
11387
+ const [filter, setFilter] = React65__default.useState("all");
11388
+ const [failure, setFailure] = React65__default.useState(null);
11297
11389
  const assistantAvailable = useConnectorsPanelAvailable();
11298
- const openJourney = React63__default.useCallback(
11390
+ const openJourney = React65__default.useCallback(
11299
11391
  (connector) => {
11300
11392
  if (assistantAvailable) openConnectorsPanel(connector);
11301
11393
  else setSelected(connector);
11302
11394
  },
11303
11395
  [assistantAvailable]
11304
11396
  );
11305
- const visible = React63__default.useMemo(() => filterConnectors(connectors ?? [], filter), [connectors, filter]);
11306
- React63__default.useEffect(() => {
11397
+ const visible = React65__default.useMemo(() => filterConnectors(connectors ?? [], filter), [connectors, filter]);
11398
+ React65__default.useEffect(() => {
11307
11399
  if (!selected || !connectors) return;
11308
11400
  const fresh = connectors.find((c) => c.id === selected.id);
11309
11401
  if (fresh && fresh !== selected) setSelected(fresh);
@@ -11316,23 +11408,17 @@ function ConnectorsTab() {
11316
11408
  return /* @__PURE__ */ jsx(Empty, { title: t("connectors.noOrg"), body: t("connectors.noOrgBody") });
11317
11409
  }
11318
11410
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
11319
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
11320
- /* @__PURE__ */ jsxs("div", { children: [
11321
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: t("settings.connectors") }),
11322
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: t("connectors.hubSubtitle") })
11323
- ] }),
11324
- /* @__PURE__ */ jsxs(
11325
- "button",
11326
- {
11327
- onClick: () => setAdding(true),
11328
- className: "inline-flex shrink-0 items-center gap-1.5 rounded-lg bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:opacity-90",
11329
- children: [
11330
- /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
11331
- t("connectors.add")
11332
- ]
11333
- }
11334
- )
11335
- ] }),
11411
+ /* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsxs(
11412
+ "button",
11413
+ {
11414
+ onClick: () => setAdding(true),
11415
+ className: "inline-flex shrink-0 items-center gap-1.5 rounded-lg bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:opacity-90",
11416
+ children: [
11417
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
11418
+ t("connectors.add")
11419
+ ]
11420
+ }
11421
+ ) }),
11336
11422
  /* @__PURE__ */ jsx(
11337
11423
  AddConnectorPanel,
11338
11424
  {
@@ -11349,7 +11435,7 @@ function ConnectorsTab() {
11349
11435
  (connectors?.length ?? 0) > 4 && /* @__PURE__ */ jsx(Filters, { value: filter, onChange: setFilter }),
11350
11436
  connectors === null && /* @__PURE__ */ jsx(ConnectionsSkeleton, {}),
11351
11437
  connectors !== null && visible.length === 0 && /* @__PURE__ */ jsx(Empty, { title: t("connectors.emptyTitle"), body: t("connectors.emptyBody") }),
11352
- visible.length > 0 && /* @__PURE__ */ jsx("ul", { className: "divide-y divide-border overflow-hidden rounded-xl border border-border", children: visible.map((c) => /* @__PURE__ */ jsx(ConnectorRow, { connector: c, onOpen: openJourney }, c.id)) }),
11438
+ visible.length > 0 && /* @__PURE__ */ jsx("ul", { className: "fayz-glass-surface divide-y divide-border overflow-hidden rounded-card border bg-card text-card-foreground shadow-sm", children: visible.map((c) => /* @__PURE__ */ jsx(ConnectorRow, { connector: c, onOpen: openJourney }, c.id)) }),
11353
11439
  /* @__PURE__ */ jsx(
11354
11440
  ConnectorDetail,
11355
11441
  {
@@ -11384,7 +11470,7 @@ function Filters({ value, onChange }) {
11384
11470
  )) });
11385
11471
  }
11386
11472
  function ConnectionsSkeleton() {
11387
- return /* @__PURE__ */ jsx("ul", { className: "divide-y divide-border overflow-hidden rounded-xl border border-border", "aria-hidden": true, children: [0, 1].map((i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-4 p-4", children: [
11473
+ return /* @__PURE__ */ jsx("ul", { className: "fayz-glass-surface divide-y divide-border overflow-hidden rounded-card border bg-card text-card-foreground shadow-sm", "aria-hidden": true, children: [0, 1].map((i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-4 p-4", children: [
11388
11474
  /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-10 shrink-0 rounded-lg" }),
11389
11475
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-2 py-0.5", children: [
11390
11476
  /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-40" }),
@@ -11463,7 +11549,7 @@ function oauthFailureMessage(t, result) {
11463
11549
  function useConnectorOAuthReturn() {
11464
11550
  const { t } = useTranslation$1();
11465
11551
  const runtime = usePluginRuntimeOptional();
11466
- React63__default.useEffect(() => {
11552
+ React65__default.useEffect(() => {
11467
11553
  if (typeof window === "undefined") return;
11468
11554
  const result = readConnectorOAuthReturn(window.location.search);
11469
11555
  if (!result) return;
@@ -11498,8 +11584,8 @@ function ConnectorDeliveries({
11498
11584
  limit = 10
11499
11585
  }) {
11500
11586
  const { t } = useTranslation$1();
11501
- const [rows, setRows] = React63__default.useState(null);
11502
- React63__default.useEffect(() => {
11587
+ const [rows, setRows] = React65__default.useState(null);
11588
+ React65__default.useEffect(() => {
11503
11589
  let cancelled = false;
11504
11590
  void load({ limit }).then((r) => {
11505
11591
  if (!cancelled) setRows(r);
@@ -11573,11 +11659,11 @@ var CURRENCIES = [
11573
11659
  function CompanySettings({ tenant, onSave }) {
11574
11660
  const { t } = useTranslation$1();
11575
11661
  const { locale: uiLocale, setLocale: setUiLocale } = useLocaleStore();
11576
- const [name, setName] = React63.useState(tenant?.name ?? "");
11577
- const [timezone, setTimezone] = React63.useState(tenant?.settings?.timezone ?? "UTC");
11578
- const [currency, setCurrency] = React63.useState(tenant?.settings?.currency ?? "USD");
11579
- const [saving, setSaving] = React63.useState(false);
11580
- React63.useEffect(() => {
11662
+ const [name, setName] = React65.useState(tenant?.name ?? "");
11663
+ const [timezone, setTimezone] = React65.useState(tenant?.settings?.timezone ?? "UTC");
11664
+ const [currency, setCurrency] = React65.useState(tenant?.settings?.currency ?? "USD");
11665
+ const [saving, setSaving] = React65.useState(false);
11666
+ React65.useEffect(() => {
11581
11667
  if (tenant) {
11582
11668
  setName(tenant.name);
11583
11669
  setTimezone(tenant.settings?.timezone ?? "UTC");
@@ -11715,10 +11801,10 @@ function getInitials(name) {
11715
11801
  }
11716
11802
  function UserProfile({ user, onSave, onAvatarChange }) {
11717
11803
  const { t } = useTranslation$1();
11718
- const [fullName, setFullName] = React63.useState(user?.fullName ?? "");
11719
- const [saving, setSaving] = React63.useState(false);
11720
- const fileInputRef = React63.useRef(null);
11721
- React63.useEffect(() => {
11804
+ const [fullName, setFullName] = React65.useState(user?.fullName ?? "");
11805
+ const [saving, setSaving] = React65.useState(false);
11806
+ const fileInputRef = React65.useRef(null);
11807
+ React65.useEffect(() => {
11722
11808
  if (user) {
11723
11809
  setFullName(user.fullName);
11724
11810
  }
@@ -11823,8 +11909,8 @@ function UserProfile({ user, onSave, onAvatarChange }) {
11823
11909
  function ConnectedUserProfile() {
11824
11910
  const user = useAuthStore((s) => s.user);
11825
11911
  const setUser = useAuthStore((s) => s.setUser);
11826
- const [profile, setProfile] = React63.useState(null);
11827
- React63.useEffect(() => {
11912
+ const [profile, setProfile] = React65.useState(null);
11913
+ React65.useEffect(() => {
11828
11914
  const supabase = getFayzSupabaseClientOptional();
11829
11915
  if (!user || !supabase) return;
11830
11916
  let cancelled = false;
@@ -11924,9 +12010,9 @@ function SecuritySettings({
11924
12010
  onTenantSecurityChange
11925
12011
  }) {
11926
12012
  const { t } = useTranslation$1();
11927
- const [resetting, setResetting] = React63.useState(false);
11928
- const [resetSent, setResetSent] = React63.useState(false);
11929
- const [savingTenant, setSavingTenant] = React63.useState(false);
12013
+ const [resetting, setResetting] = React65.useState(false);
12014
+ const [resetSent, setResetSent] = React65.useState(false);
12015
+ const [savingTenant, setSavingTenant] = React65.useState(false);
11930
12016
  const handleResetPassword = async () => {
11931
12017
  if (!onResetPassword) return;
11932
12018
  setResetting(true);
@@ -12102,8 +12188,8 @@ function FileUploadField({
12102
12188
  hint
12103
12189
  }) {
12104
12190
  const { t } = useTranslation$1();
12105
- const inputRef = React63.useRef(null);
12106
- const [preview, setPreview] = React63.useState(null);
12191
+ const inputRef = React65.useRef(null);
12192
+ const [preview, setPreview] = React65.useState(null);
12107
12193
  const handleChange = (e) => {
12108
12194
  const file = e.target.files?.[0];
12109
12195
  if (file) {
@@ -12170,14 +12256,14 @@ function FileUploadField({
12170
12256
  }
12171
12257
  function BrandingSettings({ branding, onSave }) {
12172
12258
  const { t } = useTranslation$1();
12173
- const [primaryColor, setPrimaryColor] = React63.useState(branding?.primaryColor ?? "#000000");
12174
- const [accentColor, setAccentColor] = React63.useState(branding?.accentColor ?? "#6366f1");
12175
- const [logoFile, setLogoFile] = React63.useState(null);
12176
- const [faviconFile, setFaviconFile] = React63.useState(null);
12177
- const [logoUrl, setLogoUrl] = React63.useState(branding?.logoUrl ?? "");
12178
- const [faviconUrl, setFaviconUrl] = React63.useState(branding?.faviconUrl ?? "");
12179
- const [saving, setSaving] = React63.useState(false);
12180
- React63.useEffect(() => {
12259
+ const [primaryColor, setPrimaryColor] = React65.useState(branding?.primaryColor ?? "#000000");
12260
+ const [accentColor, setAccentColor] = React65.useState(branding?.accentColor ?? "#6366f1");
12261
+ const [logoFile, setLogoFile] = React65.useState(null);
12262
+ const [faviconFile, setFaviconFile] = React65.useState(null);
12263
+ const [logoUrl, setLogoUrl] = React65.useState(branding?.logoUrl ?? "");
12264
+ const [faviconUrl, setFaviconUrl] = React65.useState(branding?.faviconUrl ?? "");
12265
+ const [saving, setSaving] = React65.useState(false);
12266
+ React65.useEffect(() => {
12181
12267
  if (branding) {
12182
12268
  setPrimaryColor(branding.primaryColor ?? "#000000");
12183
12269
  setAccentColor(branding.accentColor ?? "#6366f1");
@@ -12383,9 +12469,9 @@ function ProjectsSettings() {
12383
12469
  const projects = useFayzProjectsStore((s) => s.projects);
12384
12470
  const load = useFayzProjectsStore((s) => s.load);
12385
12471
  const refresh = useFayzProjectsStore((s) => s.refresh);
12386
- const [adding, setAdding] = React63.useState(false);
12387
- const [editing, setEditing] = React63.useState(null);
12388
- React63.useEffect(() => {
12472
+ const [adding, setAdding] = React65.useState(false);
12473
+ const [editing, setEditing] = React65.useState(null);
12474
+ React65.useEffect(() => {
12389
12475
  void load(currentOrgId);
12390
12476
  }, [currentOrgId, load]);
12391
12477
  const onCreate = async (input) => {
@@ -12407,16 +12493,10 @@ function ProjectsSettings() {
12407
12493
  await refresh();
12408
12494
  };
12409
12495
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
12410
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
12411
- /* @__PURE__ */ jsxs("div", { children: [
12412
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Sites e projetos fayz" }),
12413
- /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: "Os projetos fayz deste workspace \u2014 sites, lojas e landing pages. O projeto padr\xE3o aparece no menu como \u201CSeu site\u201D." })
12414
- ] }),
12415
- !adding && /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => setAdding(true), children: [
12416
- /* @__PURE__ */ jsx(Plus, { className: "mr-1.5 h-4 w-4" }),
12417
- " Adicionar"
12418
- ] })
12419
- ] }),
12496
+ !adding && /* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => setAdding(true), children: [
12497
+ /* @__PURE__ */ jsx(Plus, { className: "mr-1.5 h-4 w-4" }),
12498
+ " Adicionar"
12499
+ ] }) }),
12420
12500
  adding && /* @__PURE__ */ jsx(ProjectForm, { onCancel: () => setAdding(false), onSubmit: onCreate }),
12421
12501
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
12422
12502
  projects.length === 0 && !adding && /* @__PURE__ */ jsx("p", { className: "rounded-card border border-dashed border-border p-6 text-center text-sm text-muted-foreground", children: "Nenhum projeto ainda. Adicione o site do cliente (id do projeto fayz + URLs de preview e editor)." }),
@@ -12457,12 +12537,12 @@ function ProjectRow({ project, onEdit, onDelete, onSetDefault }) {
12457
12537
  ] });
12458
12538
  }
12459
12539
  function ProjectForm({ initial, onCancel, onSubmit }) {
12460
- const [name, setName] = React63.useState(initial?.name ?? "");
12461
- const [kind, setKind] = React63.useState(initial?.kind ?? "site");
12462
- const [fayzProjectId, setFayzProjectId] = React63.useState(initial?.fayzProjectId ?? "");
12463
- const [previewUrl, setPreviewUrl] = React63.useState(initial?.previewUrl ?? "");
12464
- const [isDefault, setIsDefault] = React63.useState(initial?.isDefault ?? false);
12465
- const [storefrontEnabled, setStorefrontEnabled] = React63.useState(initial?.storefrontEnabled ?? false);
12540
+ const [name, setName] = React65.useState(initial?.name ?? "");
12541
+ const [kind, setKind] = React65.useState(initial?.kind ?? "site");
12542
+ const [fayzProjectId, setFayzProjectId] = React65.useState(initial?.fayzProjectId ?? "");
12543
+ const [previewUrl, setPreviewUrl] = React65.useState(initial?.previewUrl ?? "");
12544
+ const [isDefault, setIsDefault] = React65.useState(initial?.isDefault ?? false);
12545
+ const [storefrontEnabled, setStorefrontEnabled] = React65.useState(initial?.storefrontEnabled ?? false);
12466
12546
  const submit = () => onSubmit({
12467
12547
  name: name.trim() || "Meu site",
12468
12548
  kind,
@@ -12499,12 +12579,25 @@ function ProjectForm({ initial, onCancel, onSubmit }) {
12499
12579
  ] })
12500
12580
  ] });
12501
12581
  }
12582
+ function useIsWide() {
12583
+ const query = "(min-width: 768px)";
12584
+ const [wide, setWide] = React65.useState(
12585
+ () => typeof window === "undefined" ? true : window.matchMedia(query).matches
12586
+ );
12587
+ React65.useEffect(() => {
12588
+ const mq = window.matchMedia(query);
12589
+ const onChange = () => setWide(mq.matches);
12590
+ mq.addEventListener("change", onChange);
12591
+ return () => mq.removeEventListener("change", onChange);
12592
+ }, []);
12593
+ return wide;
12594
+ }
12502
12595
  function useCoreSettingsTabs({
12503
12596
  showCompany = true,
12504
12597
  showBranding = true
12505
12598
  } = {}) {
12506
12599
  const { t } = useTranslation$1();
12507
- return React63.useMemo(() => [
12600
+ return React65.useMemo(() => [
12508
12601
  ...showCompany ? [{ id: "general", label: t("settings.general"), icon: /* @__PURE__ */ jsx(Building2, { className: "h-4 w-4" }), iconName: "Building2", component: /* @__PURE__ */ jsx(ConnectedCompanySettings, {}) }] : [],
12509
12602
  { id: "profile", label: t("settings.profile"), icon: /* @__PURE__ */ jsx(User, { className: "h-4 w-4" }), iconName: "User", component: /* @__PURE__ */ jsx(ConnectedUserProfile, {}) },
12510
12603
  { id: "security", label: t("settings.security"), icon: /* @__PURE__ */ jsx(Shield, { className: "h-4 w-4" }), iconName: "Shield", component: /* @__PURE__ */ jsx(ConnectedSecuritySettings, {}) },
@@ -12530,6 +12623,7 @@ function SettingsPage({
12530
12623
  activeTabId
12531
12624
  }) {
12532
12625
  const { t } = useTranslation$1();
12626
+ const wide = useIsWide();
12533
12627
  const defaultTabs = useCoreSettingsTabs({ showCompany, showBranding });
12534
12628
  const baseTabs = tabs ?? defaultTabs;
12535
12629
  const resolvedTabs = extraTabs ? [...baseTabs, ...extraTabs] : baseTabs;
@@ -12542,10 +12636,10 @@ function SettingsPage({
12542
12636
  }
12543
12637
  return null;
12544
12638
  }
12545
- const [activeTab, setActiveTab] = React63.useState(() => {
12639
+ const [activeTab, setActiveTab] = React65.useState(() => {
12546
12640
  return getTabFromHash() ?? defaultTab ?? null;
12547
12641
  });
12548
- React63.useEffect(() => {
12642
+ React65.useEffect(() => {
12549
12643
  const handler = () => {
12550
12644
  const tab = getTabFromHash();
12551
12645
  if (tab) setActiveTab(tab);
@@ -12568,7 +12662,7 @@ function SettingsPage({
12568
12662
  setActiveTab(null);
12569
12663
  window.location.hash = "/settings";
12570
12664
  };
12571
- const sections = React63.useMemo(() => {
12665
+ const sections = React65.useMemo(() => {
12572
12666
  const out = [];
12573
12667
  for (const tab of resolvedTabs) {
12574
12668
  const heading = tab.isPlugin ? tab.group ?? t("common.plugins") : null;
@@ -12595,40 +12689,39 @@ function SettingsPage({
12595
12689
  ) }, tab.id)) })
12596
12690
  ] }, section.key)) });
12597
12691
  return /* @__PURE__ */ jsxs("div", { className: cn$1("fz-container space-y-6", className), children: [
12598
- !controlled && showingContent && /* @__PURE__ */ jsxs(
12692
+ !controlled && showingContent && !wide && /* @__PURE__ */ jsxs(
12599
12693
  "button",
12600
12694
  {
12601
12695
  onClick: handleBack,
12602
- className: "flex items-center gap-1.5 text-sm text-muted-foreground transition-colors hover:text-foreground md:hidden",
12696
+ className: "flex items-center gap-1.5 text-sm text-muted-foreground transition-colors hover:text-foreground",
12603
12697
  children: [
12604
12698
  /* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4" }),
12605
12699
  t("settings.title")
12606
12700
  ]
12607
12701
  }
12608
12702
  ),
12609
- !showingContent && /* @__PURE__ */ jsxs("div", { className: "md:hidden", children: [
12703
+ !showingContent && !wide && /* @__PURE__ */ jsxs("div", { children: [
12610
12704
  /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight", children: t("settings.title") }),
12611
12705
  /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("settings.subtitle") })
12612
12706
  ] }),
12613
12707
  beforeContent,
12614
- /* @__PURE__ */ jsxs("div", { className: "hidden md:flex md:gap-6", children: [
12615
- !hideNav && /* @__PURE__ */ jsx("nav", { className: "w-52 shrink-0", children: /* @__PURE__ */ jsx("ul", { className: "space-y-0.5", children: resolvedTabs.map((tab) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
12616
- "button",
12708
+ !hideNav && /* @__PURE__ */ jsx(PageRail, { children: /* @__PURE__ */ jsx("nav", { className: "hidden w-52 shrink-0 overflow-y-auto border-r border-border p-3 md:block", children: sections.map((section, i) => /* @__PURE__ */ jsxs("div", { className: i > 0 ? "mt-3 border-t border-border pt-3" : void 0, children: [
12709
+ section.heading && /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: section.heading }),
12710
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: section.items.map((tab) => /* @__PURE__ */ jsx(
12711
+ RailNavItem,
12617
12712
  {
12618
- onClick: () => handleSelectTab(tab.id),
12619
- className: cn$1(
12620
- "flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors",
12621
- desktopTab === tab.id ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50 hover:text-foreground"
12622
- ),
12623
- children: [
12624
- tab.icon && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: tab.icon }),
12625
- /* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: tab.label })
12626
- ]
12627
- }
12628
- ) }, tab.id)) }) }),
12629
- /* @__PURE__ */ jsx("div", { className: "fz-container min-w-0 flex-1", children: withTrail(desktopTabDef?.component ?? null, desktopTabDef) })
12630
- ] }),
12631
- /* @__PURE__ */ jsx("div", { className: "md:hidden", children: showingContent ? /* @__PURE__ */ jsx("div", { className: "fz-container", children: activeContent }) : settingsIndex }),
12713
+ item: {
12714
+ id: tab.id,
12715
+ label: tab.label,
12716
+ icon: tab.iconName,
12717
+ active: desktopTab === tab.id,
12718
+ onClick: () => handleSelectTab(tab.id)
12719
+ }
12720
+ },
12721
+ tab.id
12722
+ )) })
12723
+ ] }, section.key)) }) }),
12724
+ wide ? /* @__PURE__ */ jsx("div", { className: "fz-container min-w-0", children: withTrail(desktopTabDef?.component ?? null, desktopTabDef) }) : showingContent ? /* @__PURE__ */ jsx("div", { className: "fz-container", children: activeContent }) : settingsIndex,
12632
12725
  afterContent
12633
12726
  ] });
12634
12727
  }
@@ -12647,10 +12740,10 @@ function InviteMemberDialog({ open, onOpenChange, defaultEmail }) {
12647
12740
  const profiles = usePermissionsStore((s) => s.profiles);
12648
12741
  const setInvites = useInviteStore((s) => s.setInvites);
12649
12742
  const { user } = useAuthStore();
12650
- const [emails, setEmails] = React63.useState([defaultEmail ?? ""]);
12651
- const [profileId, setProfileId] = React63.useState(profiles[1]?.id ?? profiles[0]?.id ?? "");
12652
- const [sending, setSending] = React63.useState(false);
12653
- const [sent, setSent] = React63.useState(false);
12743
+ const [emails, setEmails] = React65.useState([defaultEmail ?? ""]);
12744
+ const [profileId, setProfileId] = React65.useState(profiles[1]?.id ?? profiles[0]?.id ?? "");
12745
+ const [sending, setSending] = React65.useState(false);
12746
+ const [sent, setSent] = React65.useState(false);
12654
12747
  const addEmail = () => setEmails((prev) => [...prev, ""]);
12655
12748
  const updateEmail = (idx, value) => {
12656
12749
  setEmails((prev) => {
@@ -12747,14 +12840,14 @@ function TeamTab() {
12747
12840
  const { user } = useAuthStore();
12748
12841
  const hasSystemPermission = useSystemPermission();
12749
12842
  const personMode = teamPersonKinds.length > 0 && typeof adapter2?.listTeam === "function";
12750
- const [team, setTeam] = React63.useState(null);
12751
- const [inviteOpen, setInviteOpen] = React63.useState(false);
12843
+ const [team, setTeam] = React65.useState(null);
12844
+ const [inviteOpen, setInviteOpen] = React65.useState(false);
12752
12845
  const guardSeats = useLimitGuard("users");
12753
12846
  const handleOpenInvite = async () => {
12754
12847
  if (await guardSeats(1) === "blocked") return;
12755
12848
  setInviteOpen(true);
12756
12849
  };
12757
- const reloadTeam = React63.useCallback(async () => {
12850
+ const reloadTeam = React65.useCallback(async () => {
12758
12851
  if (!adapter2 || !currentOrg) return;
12759
12852
  if (personMode && adapter2.listTeam) {
12760
12853
  setTeam(await adapter2.listTeam(currentOrg.id, teamPersonKinds));
@@ -12762,12 +12855,12 @@ function TeamTab() {
12762
12855
  setMembers(await adapter2.listMembers(currentOrg.id));
12763
12856
  }
12764
12857
  }, [adapter2, currentOrg?.id, personMode, teamPersonKinds, setMembers]);
12765
- React63.useEffect(() => {
12858
+ React65.useEffect(() => {
12766
12859
  if (personMode && adapter2?.listTeam && currentOrg) {
12767
12860
  dedup("team:people:" + currentOrg.id, () => adapter2.listTeam(currentOrg.id, teamPersonKinds)).then(setTeam).catch(() => setTeam([]));
12768
12861
  }
12769
12862
  }, [personMode, adapter2, currentOrg?.id, teamPersonKinds.join(",")]);
12770
- React63.useEffect(() => {
12863
+ React65.useEffect(() => {
12771
12864
  if (adapter2 && currentOrg) {
12772
12865
  dedup("team:invites:" + currentOrg.id, () => adapter2.listInvites(currentOrg.id)).then(setInvites).catch(() => {
12773
12866
  });
@@ -12842,18 +12935,13 @@ function TeamTab() {
12842
12935
  const pendingInvites = invites.filter((i) => i.status === "pending");
12843
12936
  return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
12844
12937
  /* @__PURE__ */ jsxs("div", { children: [
12845
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
12846
- /* @__PURE__ */ jsxs("div", { children: [
12847
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: t("organization.team.title") }),
12848
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("organization.team.memberCount", { count: String(rows.length), plural: rows.length !== 1 ? "s" : "" }) })
12849
- ] }),
12850
- canManageTeam && /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => {
12851
- void handleOpenInvite();
12852
- }, children: [
12853
- /* @__PURE__ */ jsx(UserPlus, { className: "h-4 w-4 mr-1" }),
12854
- t("organization.team.invite")
12855
- ] })
12856
- ] }),
12938
+ canManageTeam && /* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => {
12939
+ void handleOpenInvite();
12940
+ }, children: [
12941
+ /* @__PURE__ */ jsx(UserPlus, { className: "h-4 w-4 mr-1" }),
12942
+ t("organization.team.invite")
12943
+ ] }) }),
12944
+ /* @__PURE__ */ jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: t("organization.team.memberCount", { count: String(rows.length), plural: rows.length !== 1 ? "s" : "" }) }),
12857
12945
  /* @__PURE__ */ jsx(Card, { className: "overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full", children: [
12858
12946
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b bg-muted/50", children: [
12859
12947
  /* @__PURE__ */ jsx("th", { className: "text-left p-3 text-sm font-medium text-muted-foreground", children: t("organization.team.member") }),
@@ -12975,13 +13063,13 @@ var SYSTEM_PERMISSIONS = [
12975
13063
  ];
12976
13064
  function PermissionMatrixEditor({ features, profile, onSave, onCancel, saving, isNew, parentLabel }) {
12977
13065
  const { t } = useTranslation$1();
12978
- const [name, setName] = React63.useState(profile?.name ?? "");
12979
- const [description, setDescription] = React63.useState(profile?.description ?? "");
12980
- const [systemPerms, setSystemPerms] = React63.useState(profile?.systemPermissions ?? []);
12981
- const [grants, setGrants] = React63.useState(profile?.grants ?? {});
12982
- const [collapsed, setCollapsed] = React63.useState(/* @__PURE__ */ new Set());
12983
- const [search, setSearch] = React63.useState("");
12984
- const initial = React63.useRef({
13066
+ const [name, setName] = React65.useState(profile?.name ?? "");
13067
+ const [description, setDescription] = React65.useState(profile?.description ?? "");
13068
+ const [systemPerms, setSystemPerms] = React65.useState(profile?.systemPermissions ?? []);
13069
+ const [grants, setGrants] = React65.useState(profile?.grants ?? {});
13070
+ const [collapsed, setCollapsed] = React65.useState(/* @__PURE__ */ new Set());
13071
+ const [search, setSearch] = React65.useState("");
13072
+ const initial = React65.useRef({
12985
13073
  name: profile?.name ?? "",
12986
13074
  description: profile?.description ?? "",
12987
13075
  systemPerms: JSON.stringify(profile?.systemPermissions ?? []),
@@ -13019,7 +13107,7 @@ function PermissionMatrixEditor({ features, profile, onSave, onCancel, saving, i
13019
13107
  saveLabel: isNew ? t("organization.permissions.createProfile") : t("organization.permissions.updateProfile")
13020
13108
  });
13021
13109
  useBackHandler(onCancel);
13022
- const groups = React63.useMemo(() => {
13110
+ const groups = React65.useMemo(() => {
13023
13111
  const filtered = search ? features.filter((f) => f.label.toLowerCase().includes(search.toLowerCase())) : features;
13024
13112
  const map = /* @__PURE__ */ new Map();
13025
13113
  for (const f of filtered) {
@@ -13088,7 +13176,7 @@ function PermissionMatrixEditor({ features, profile, onSave, onCancel, saving, i
13088
13176
  }
13089
13177
  ) }) })
13090
13178
  ] }, sp.id)),
13091
- Array.from(groups.entries()).map(([groupName, groupFeatures]) => /* @__PURE__ */ jsxs(React63.Fragment, { children: [
13179
+ Array.from(groups.entries()).map(([groupName, groupFeatures]) => /* @__PURE__ */ jsxs(React65.Fragment, { children: [
13092
13180
  /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: 5, className: "p-2 px-3", children: /* @__PURE__ */ jsxs(
13093
13181
  "button",
13094
13182
  {
@@ -13129,11 +13217,11 @@ function PermissionProfilesTab() {
13129
13217
  const startImpersonation = usePermissionsStore((s) => s.startImpersonation);
13130
13218
  const canPreview = (realProfile?.systemPermissions ?? []).includes("manage_permissions") ?? false;
13131
13219
  const { t } = useTranslation$1();
13132
- const [editingProfile, setEditingProfile] = React63.useState(null);
13133
- const [creating, setCreating] = React63.useState(false);
13134
- const [duplicateSource, setDuplicateSource] = React63.useState(null);
13135
- const [saving, setSaving] = React63.useState(false);
13136
- const [error, setError] = React63.useState(null);
13220
+ const [editingProfile, setEditingProfile] = React65.useState(null);
13221
+ const [creating, setCreating] = React65.useState(false);
13222
+ const [duplicateSource, setDuplicateSource] = React65.useState(null);
13223
+ const [saving, setSaving] = React65.useState(false);
13224
+ const [error, setError] = React65.useState(null);
13137
13225
  const handleDuplicate = (profile) => {
13138
13226
  setEditingProfile(null);
13139
13227
  setCreating(false);
@@ -13143,7 +13231,7 @@ function PermissionProfilesTab() {
13143
13231
  isSystem: false
13144
13232
  });
13145
13233
  };
13146
- const memberCountByProfile = React63.useMemo(() => {
13234
+ const memberCountByProfile = React65.useMemo(() => {
13147
13235
  const counts = {};
13148
13236
  for (const m of members) {
13149
13237
  counts[m.profileId] = (counts[m.profileId] ?? 0) + 1;
@@ -13200,16 +13288,10 @@ function PermissionProfilesTab() {
13200
13288
  );
13201
13289
  }
13202
13290
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
13203
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
13204
- /* @__PURE__ */ jsxs("div", { children: [
13205
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: t("organization.permissions.title") }),
13206
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("organization.permissions.subtitle") })
13207
- ] }),
13208
- /* @__PURE__ */ jsxs(Button, { onClick: () => setCreating(true), size: "sm", children: [
13209
- /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-1" }),
13210
- t("organization.permissions.createProfile")
13211
- ] })
13212
- ] }),
13291
+ /* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsxs(Button, { onClick: () => setCreating(true), size: "sm", children: [
13292
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-1" }),
13293
+ t("organization.permissions.createProfile")
13294
+ ] }) }),
13213
13295
  error && /* @__PURE__ */ jsx("p", { className: "rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm text-destructive", children: error }),
13214
13296
  /* @__PURE__ */ jsx("div", { className: "grid gap-3", children: profiles.length === 0 ? (
13215
13297
  // Roles load via central org hydration; show skeletons until they arrive.
@@ -13908,7 +13990,7 @@ function SubjectFormLayout({ fields, allFields, fieldGroups, values, onChange, r
13908
13990
  const IconComponent = getLucideIcon(entityIcon ?? "Heart") ?? Heart;
13909
13991
  return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
13910
13992
  /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(CardContent, { className: "pt-5", children: /* @__PURE__ */ jsxs("div", { className: "flex gap-5", children: [
13911
- /* @__PURE__ */ jsx("div", { className: "flex h-20 w-20 shrink-0 items-center justify-center rounded-2xl bg-primary/10 text-primary", children: React63__default.createElement(IconComponent, { className: "h-8 w-8" }) }),
13993
+ /* @__PURE__ */ jsx("div", { className: "flex h-20 w-20 shrink-0 items-center justify-center rounded-2xl bg-primary/10 text-primary", children: React65__default.createElement(IconComponent, { className: "h-8 w-8" }) }),
13912
13994
  /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-4", children: [
13913
13995
  /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4", children: [
13914
13996
  nameField && /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-1.5", children: [
@@ -14256,11 +14338,11 @@ function ImageSlot({
14256
14338
  canEdit
14257
14339
  }) {
14258
14340
  const t = useTranslation();
14259
- const inputRef = React63__default.useRef(null);
14260
- const [url, setUrl] = React63__default.useState(() => image.get(row));
14261
- const [busy, setBusy] = React63__default.useState(false);
14262
- const [error, setError] = React63__default.useState(null);
14263
- React63__default.useEffect(() => {
14341
+ const inputRef = React65__default.useRef(null);
14342
+ const [url, setUrl] = React65__default.useState(() => image.get(row));
14343
+ const [busy, setBusy] = React65__default.useState(false);
14344
+ const [error, setError] = React65__default.useState(null);
14345
+ React65__default.useEffect(() => {
14264
14346
  setUrl(image.get(row));
14265
14347
  }, [image.get(row)]);
14266
14348
  const pick = () => {
@@ -14354,7 +14436,7 @@ function CrudFormPage({ entityDef, mode, initialData, onSubmit, onCancel, namePl
14354
14436
  const computeInit = () => mode === "edit" && initialData ? { ...getDefaultValues(formFields), ...initialData } : getDefaultValues(formFields);
14355
14437
  const [values, setValues] = useState(computeInit);
14356
14438
  const [saving, setSaving] = useState(false);
14357
- const initialRef = React63__default.useRef(JSON.stringify(values));
14439
+ const initialRef = React65__default.useRef(JSON.stringify(values));
14358
14440
  useEffect(() => {
14359
14441
  const init = computeInit();
14360
14442
  setValues(init);
@@ -14725,6 +14807,57 @@ function LimitGate({ limitKey, children, className }) {
14725
14807
  }
14726
14808
  );
14727
14809
  }
14810
+ function QuickActionsButton({ actions, label, variant: variantProp, className }) {
14811
+ const [open, setOpen] = useState(false);
14812
+ const ref = useRef(null);
14813
+ const moduleLayout = useModuleLayout();
14814
+ const variant = variantProp ?? (moduleLayout === "tabs" ? "default" : "outline");
14815
+ useEffect(() => {
14816
+ function handler(e) {
14817
+ if (ref.current && !ref.current.contains(e.target)) setOpen(false);
14818
+ }
14819
+ document.addEventListener("mousedown", handler);
14820
+ return () => document.removeEventListener("mousedown", handler);
14821
+ }, []);
14822
+ if (actions.length === 0) return null;
14823
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("relative", className), children: [
14824
+ /* @__PURE__ */ jsxs(
14825
+ Button,
14826
+ {
14827
+ variant,
14828
+ size: "sm",
14829
+ onClick: () => setOpen(!open),
14830
+ className: cn(open && variant === "outline" && "bg-muted"),
14831
+ children: [
14832
+ /* @__PURE__ */ jsx(Plus, { className: cn("h-3.5 w-3.5 transition-transform duration-200", open && "rotate-45") }),
14833
+ /* @__PURE__ */ jsx("span", { children: label ?? "New" }),
14834
+ /* @__PURE__ */ jsx(ChevronDown, { className: cn("-mr-0.5 h-3.5 w-3.5 opacity-70 transition-transform duration-200", open && "rotate-180") })
14835
+ ]
14836
+ }
14837
+ ),
14838
+ open && /* @__PURE__ */ jsx("div", { className: "fayz-glass-surface absolute top-full right-0 z-50 mt-2 w-64 rounded-xl border bg-popover shadow-lg overflow-hidden animate-in fade-in-0 zoom-in-95 origin-top-right", children: /* @__PURE__ */ jsx("div", { className: "p-1.5", children: actions.map((action) => {
14839
+ const Icon = action.icon ? ICON_MAP[action.icon] ?? Plus : Plus;
14840
+ return /* @__PURE__ */ jsxs(
14841
+ "button",
14842
+ {
14843
+ onClick: () => {
14844
+ action.action();
14845
+ setOpen(false);
14846
+ },
14847
+ className: "w-full flex items-center gap-3 rounded-lg px-3 py-2.5 text-left hover:bg-muted/50 transition-colors group",
14848
+ children: [
14849
+ /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-muted group-hover:bg-primary/10 transition-colors shrink-0", children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" }) }),
14850
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
14851
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: action.label }),
14852
+ action.description && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground leading-tight", children: action.description })
14853
+ ] })
14854
+ ]
14855
+ },
14856
+ action.id
14857
+ );
14858
+ }) }) })
14859
+ ] });
14860
+ }
14728
14861
  var ALL_TAB = "__all__";
14729
14862
  function getEntityIcon(name) {
14730
14863
  const icons = LucideIcons3;
@@ -14755,6 +14888,7 @@ function CrudListView({
14755
14888
  onExport,
14756
14889
  feature,
14757
14890
  readOnly,
14891
+ embedded,
14758
14892
  emptyMessage,
14759
14893
  navTabs,
14760
14894
  activeNavTab,
@@ -14822,22 +14956,35 @@ function CrudListView({
14822
14956
  }] : []
14823
14957
  ];
14824
14958
  const selectable = display === "table" && barActions.length > 0;
14825
- const facetTab = facets?.find((f) => f.display === "tabs");
14826
- const headerTabs = navTabs?.length ? navTabs.map((t2) => ({ value: t2.id, label: t2.label, icon: t2.icon })) : facetTab ? [
14827
- { value: ALL_TAB, label: facetTab.allLabel ?? t("crud.list.allFacet") },
14828
- ...facetTab.options.map((o) => ({ value: o.value, label: o.label }))
14829
- ] : null;
14830
- const headerTabValue = navTabs?.length ? activeNavTab ?? navTabs[0].id : activeFilters?.[facetTab?.field ?? ""] ?? ALL_TAB;
14959
+ const hasSelection = selectable && selectedIds.length > 0;
14960
+ const headerTabs = navTabs?.length ? navTabs.map((t2) => ({ value: t2.id, label: t2.label, icon: t2.icon })) : null;
14961
+ const headerTabValue = activeNavTab ?? navTabs?.[0]?.id ?? ALL_TAB;
14831
14962
  const onHeaderTabChange = (next) => {
14832
- if (navTabs?.length) navTabs.find((t2) => t2.id === next)?.onSelect();
14833
- else if (facetTab) onFacetChange?.(facetTab.field, next === ALL_TAB ? void 0 : next);
14963
+ navTabs?.find((t2) => t2.id === next)?.onSelect();
14834
14964
  };
14835
- const pillFacets = facets?.filter((f) => f !== facetTab);
14836
- const newButton = onNew && !readOnly ? /* @__PURE__ */ jsx(Button, { onClick: onNew, children: addLabel ?? t("crud.list.addEntity", { entity: entityDef.name }) }) : null;
14837
- const gatedNewButton = newButton ? (() => {
14838
- const roleGated = feature ? /* @__PURE__ */ jsx(PermissionGate, { feature, action: "create", children: newButton }) : newButton;
14965
+ const pillFacets = facets;
14966
+ const newLabel = addLabel ?? t("crud.list.addEntity", { entity: entityDef.name });
14967
+ const plainNewLabel = newLabel.replace(/^\+\s*/, "");
14968
+ const newButton = onNew && !readOnly ? onImport ? /* @__PURE__ */ jsx(
14969
+ QuickActionsButton,
14970
+ {
14971
+ variant: "default",
14972
+ label: plainNewLabel,
14973
+ actions: [
14974
+ { id: "new", label: plainNewLabel, description: t("crud.list.newHint"), icon: "Plus", action: onNew },
14975
+ { id: "import", label: t("crud.import.action"), description: t("crud.import.hint"), icon: "Upload", action: onImport }
14976
+ ]
14977
+ }
14978
+ ) : /* @__PURE__ */ jsx(Button, { onClick: onNew, children: newLabel }) : onImport ? /* @__PURE__ */ jsxs(Button, { variant: "outline", onClick: onImport, children: [
14979
+ /* @__PURE__ */ jsx(Upload, { className: "mr-2 h-4 w-4" }),
14980
+ t("crud.import.action")
14981
+ ] }) : null;
14982
+ const gate = (node) => {
14983
+ const roleGated = feature ? /* @__PURE__ */ jsx(PermissionGate, { feature, action: "create", children: node }) : node;
14839
14984
  return entityDef.limitKey ? /* @__PURE__ */ jsx(LimitGate, { limitKey: entityDef.limitKey, children: roleGated }) : roleGated;
14840
- })() : null;
14985
+ };
14986
+ const gatedNewButton = newButton ? gate(newButton) : null;
14987
+ const gatedCreateButton = onNew && !readOnly ? gate(/* @__PURE__ */ jsx(Button, { onClick: onNew, children: newLabel })) : null;
14841
14988
  const isFiltered = Boolean(search?.trim()) || Object.values(activeFilters ?? {}).some((v) => v != null);
14842
14989
  const EmptyIcon = getEntityIcon(entityDef.icon);
14843
14990
  const emptyState = /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 py-6", children: [
@@ -14845,18 +14992,13 @@ function CrudListView({
14845
14992
  /* @__PURE__ */ jsx("p", { className: "text-base font-semibold text-foreground", children: emptyMessage ?? (isFiltered ? t("crud.list.emptyFiltered", { entities: namePlural.toLowerCase() }) : t("crud.list.empty", { entities: namePlural.toLowerCase() })) }),
14846
14993
  !isFiltered && /* @__PURE__ */ jsxs(Fragment, { children: [
14847
14994
  /* @__PURE__ */ jsx("p", { className: "max-w-sm text-sm text-muted-foreground", children: t("crud.list.emptyHint", { entities: namePlural.toLowerCase() }) }),
14848
- gatedNewButton && /* @__PURE__ */ jsx("div", { className: "mt-3", children: gatedNewButton })
14995
+ gatedCreateButton && /* @__PURE__ */ jsx("div", { className: "mt-3", children: gatedCreateButton })
14849
14996
  ] })
14850
14997
  ] });
14851
- const actions = /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
14998
+ const actions = headerActions || gatedNewButton ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
14852
14999
  headerActions,
14853
- onImport && /* @__PURE__ */ jsxs(Button, { variant: "outline", onClick: onImport, children: [
14854
- /* @__PURE__ */ jsx(Upload, { className: "mr-2 h-4 w-4" }),
14855
- t("crud.import.action")
14856
- ] }),
14857
- onImport && gatedNewButton && /* @__PURE__ */ jsx("span", { className: "h-6 w-px bg-border", "aria-hidden": true }),
14858
15000
  gatedNewButton
14859
- ] });
15001
+ ] }) : null;
14860
15002
  const sortableColumns = useMemo(() => {
14861
15003
  const declared = entityDef.fields.filter((f) => f.sortable !== false).map((f) => ({ key: f.key, label: f.label }));
14862
15004
  const has = new Set(declared.map((f) => f.key));
@@ -14977,18 +15119,21 @@ function CrudListView({
14977
15119
  ] })
14978
15120
  ] }) : null;
14979
15121
  return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
14980
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
14981
- headerTabs ? /* @__PURE__ */ jsx(
14982
- HeaderTabs,
14983
- {
14984
- tabs: headerTabs,
14985
- value: headerTabValue,
14986
- onChange: onHeaderTabChange,
14987
- "aria-label": namePlural
14988
- }
14989
- ) : /* @__PURE__ */ jsx("span", {}),
14990
- actions
14991
- ] }),
15122
+ actions && (embedded ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center justify-end gap-3", children: actions }) : /* @__PURE__ */ jsx(PageHeaderActions, { children: actions })),
15123
+ headerTabs && // The same band a module's sub-nav draws, closed by the hairline that
15124
+ // crosses the page. Alunos ▸ Equipe and Financeiro ▸ Mensalidades are
15125
+ // the same kind of move — switching what the page shows — so they are
15126
+ // the same object on screen.
15127
+ /* @__PURE__ */ jsx(
15128
+ PageTabs,
15129
+ {
15130
+ className: "mb-0",
15131
+ tabs: headerTabs,
15132
+ value: headerTabValue,
15133
+ onChange: onHeaderTabChange,
15134
+ "aria-label": namePlural
15135
+ }
15136
+ ),
14992
15137
  error && /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-destructive/30 bg-destructive/5 px-4 py-3 text-sm", children: [
14993
15138
  /* @__PURE__ */ jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-destructive" }),
14994
15139
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
@@ -14998,16 +15143,6 @@ function CrudListView({
14998
15143
  onRefresh && /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: "ml-auto shrink-0", onClick: onRefresh, children: t("crud.list.refresh") })
14999
15144
  ] }),
15000
15145
  stats && stats.length > 0 && /* @__PURE__ */ jsx(StatTiles, { tiles: stats, loading: isInitialLoad }),
15001
- selectable && /* @__PURE__ */ jsx(
15002
- BulkActionBar,
15003
- {
15004
- count: selectedIds.length,
15005
- total: items?.length ?? 0,
15006
- onSelectAll: () => setRawSelection((items ?? []).map((r) => r.id)),
15007
- onClear: () => setRawSelection([]),
15008
- actions: barActions
15009
- }
15010
- ),
15011
15146
  display === "cards" ? (
15012
15147
  // The card grid keeps the search box floating above it: there is no
15013
15148
  // table chrome for a toolbar to sit flush against.
@@ -15044,11 +15179,21 @@ function CrudListView({
15044
15179
  same rows, so a search box floating on the page background above a
15045
15180
  separate table card read as two unrelated controls. */
15046
15181
  /* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
15047
- (searchBox || facetChips || tableTools) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-2", children: [
15182
+ (searchBox || facetChips || tableTools || hasSelection) && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-2", children: hasSelection ? /* @__PURE__ */ jsx(
15183
+ BulkActionBar,
15184
+ {
15185
+ variant: "inline",
15186
+ count: selectedIds.length,
15187
+ total: items?.length ?? 0,
15188
+ onSelectAll: () => setRawSelection((items ?? []).map((r) => r.id)),
15189
+ onClear: () => setRawSelection([]),
15190
+ actions: barActions
15191
+ }
15192
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
15048
15193
  /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: searchBox }),
15049
15194
  facetChips,
15050
15195
  tableTools
15051
- ] }),
15196
+ ] }) }),
15052
15197
  /* @__PURE__ */ jsx(
15053
15198
  DataTable,
15054
15199
  {
@@ -15444,7 +15589,7 @@ function AddressesTab({ item }) {
15444
15589
  )
15445
15590
  ] });
15446
15591
  }
15447
- var ScheduleEditor = React63__default.lazy(
15592
+ var ScheduleEditor = React65__default.lazy(
15448
15593
  () => import('./ScheduleEditor-S3QI5MHO.js').then((m) => ({ default: m.ScheduleEditor }))
15449
15594
  );
15450
15595
  function ComingSoon({ icon: Icon, title, description }) {
@@ -15525,7 +15670,7 @@ function ScheduleTab({ item }) {
15525
15670
  }
15526
15671
  );
15527
15672
  }
15528
- return /* @__PURE__ */ jsx(React63__default.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(ScheduleEditor, { assigneeId: item.id }) });
15673
+ return /* @__PURE__ */ jsx(React65__default.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(ScheduleEditor, { assigneeId: item.id }) });
15529
15674
  }
15530
15675
  var PERSON_DETAIL_TABS = [
15531
15676
  { id: "schedule", label: "Schedule", icon: "CalendarDays", component: ScheduleTab, visibleFor: ["staff"] },
@@ -15831,6 +15976,10 @@ var SUBJECT_DETAIL_TABS = [
15831
15976
  { id: "history", label: "History", component: SubjectHistoryTab },
15832
15977
  { id: "documents", label: "Documents", component: SubjectDocumentsTab }
15833
15978
  ];
15979
+ function ActionSlot({ embedded, children }) {
15980
+ if (embedded) return /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-1.5", children });
15981
+ return /* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children }) });
15982
+ }
15834
15983
  function formatValue3(field, value, t) {
15835
15984
  if (value == null || value === "") return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/50", children: "\u2014" });
15836
15985
  if (field.renderCell) return field.renderCell(value, {});
@@ -15902,7 +16051,7 @@ function InlineEditor({
15902
16051
  }) {
15903
16052
  const [draft, setDraft] = useState(value ?? "");
15904
16053
  const [saving, setSaving] = useState(false);
15905
- const inputRef = React63__default.useRef(null);
16054
+ const inputRef = React65__default.useRef(null);
15906
16055
  useEffect(() => {
15907
16056
  inputRef.current?.focus();
15908
16057
  if (inputRef.current instanceof HTMLInputElement) inputRef.current.select();
@@ -16178,7 +16327,7 @@ function CrudDetailPage({
16178
16327
  const newHash = value === "overview" ? detailPath : `${detailPath}/${value}`;
16179
16328
  window.history.replaceState(null, "", `#${newHash}`);
16180
16329
  }, [basePath, item.id, embedded]);
16181
- const headerNode = React63__default.useMemo(
16330
+ const headerNode = React65__default.useMemo(
16182
16331
  () => embedded ? null : /* @__PURE__ */ jsx(SubpageHeader, { title: displayValue, parentLabel: namePlural, onBack }),
16183
16332
  [embedded, displayValue, namePlural, onBack]
16184
16333
  );
@@ -16204,7 +16353,7 @@ function CrudDetailPage({
16204
16353
  ] }),
16205
16354
  subtitleValue && /* @__PURE__ */ jsx("p", { className: `text-muted-foreground mt-0.5 ${embedded ? "text-xs" : ""}`, children: subtitleValue })
16206
16355
  ] }),
16207
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 shrink-0", children: [
16356
+ /* @__PURE__ */ jsxs(ActionSlot, { embedded, children: [
16208
16357
  /* @__PURE__ */ jsx(WidgetSlot, { zone: headerActionsZone, item, entityId, embedded }),
16209
16358
  onEdit && /* @__PURE__ */ jsxs(Button, { variant: "outline", size: embedded ? "xs" : "sm", onClick: onEdit, className: embedded ? "h-7 px-2 text-xs gap-1" : "", children: [
16210
16359
  /* @__PURE__ */ jsx(Edit, { className: embedded ? "h-3 w-3" : "h-4 w-4 mr-1.5" }),
@@ -16231,7 +16380,7 @@ function CrudDetailPage({
16231
16380
  })
16232
16381
  ] }),
16233
16382
  /* @__PURE__ */ jsx(TabsContent, { value: "overview", className: embedded ? "mt-2" : "mt-4", children: /* @__PURE__ */ jsx(OverviewTab, { entityDef, item, compact: embedded, onFieldSave }) }),
16234
- customTabs.map((tab) => /* @__PURE__ */ jsx(TabsContent, { value: tab.id, className: "mt-4", children: tab.component ? React63__default.createElement(tab.component, { item, entityDef, ...tab.props ?? {} }) : /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(CardContent, { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: t("common.noContent") }) }) }) }, tab.id))
16383
+ customTabs.map((tab) => /* @__PURE__ */ jsx(TabsContent, { value: tab.id, className: "mt-4", children: tab.component ? React65__default.createElement(tab.component, { item, entityDef, ...tab.props ?? {} }) : /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(CardContent, { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: t("common.noContent") }) }) }) }, tab.id))
16235
16384
  ] }),
16236
16385
  /* @__PURE__ */ jsx(WidgetSlot, { zone: widgetZone }),
16237
16386
  legacyWidgetZone !== widgetZone && /* @__PURE__ */ jsx(WidgetSlot, { zone: legacyWidgetZone }),
@@ -16283,7 +16432,7 @@ function useFieldRules(entityKey) {
16283
16432
  };
16284
16433
  }, [entityKey, fieldRules]);
16285
16434
  }
16286
- var ImportWizard2 = React63__default.lazy(
16435
+ var ImportWizard2 = React65__default.lazy(
16287
16436
  () => import('./ImportWizard-CISHGNQC.js').then((m) => ({ default: m.ImportWizard }))
16288
16437
  );
16289
16438
  var PAGE_SIZE = 50;
@@ -16395,7 +16544,7 @@ function useCrudColumns(entityDef, options) {
16395
16544
  return tanCols;
16396
16545
  }, [cols, displayField, options?.basePath, options?.onDelete, options?.feature, options?.readOnly]);
16397
16546
  }
16398
- function CrudPage({ entityDef: rawEntityDef, useStore, basePath, display, feature, readOnly, navTabs, activeNavTab, stats }) {
16547
+ function CrudPage({ entityDef: rawEntityDef, useStore, basePath, display, feature, readOnly, navTabs, activeNavTab, stats, embedded }) {
16399
16548
  const store = useStore();
16400
16549
  const t = useTranslation();
16401
16550
  const normalizedBasePath = normalizeCrudBasePath(basePath);
@@ -16672,6 +16821,7 @@ function CrudPage({ entityDef: rawEntityDef, useStore, basePath, display, featur
16672
16821
  onExport: handleExport,
16673
16822
  feature,
16674
16823
  readOnly,
16824
+ embedded,
16675
16825
  navTabs,
16676
16826
  activeNavTab,
16677
16827
  stats: stats?.(store.items, store.total),
@@ -16744,7 +16894,7 @@ function CrudPage({ entityDef: rawEntityDef, useStore, basePath, display, featur
16744
16894
  displayValue: deleteItem ? deleteItem[displayField] : void 0
16745
16895
  }
16746
16896
  ),
16747
- /* @__PURE__ */ jsx(React63__default.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
16897
+ /* @__PURE__ */ jsx(React65__default.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
16748
16898
  ImportWizard2,
16749
16899
  {
16750
16900
  open: importOpen,
@@ -17236,7 +17386,7 @@ function FieldRulesSettings({ entities, rules: initialRules, onSave }) {
17236
17386
  const [saving, setSaving] = useState(false);
17237
17387
  const [search, setSearch] = useState("");
17238
17388
  const [showMore, setShowMore] = useState(false);
17239
- React63.useEffect(() => {
17389
+ React65.useEffect(() => {
17240
17390
  setDraft(initialRules);
17241
17391
  }, [initialRules]);
17242
17392
  const isDirty = useMemo(
@@ -17357,16 +17507,10 @@ function FieldRulesSettings({ entities, rules: initialRules, onSave }) {
17357
17507
  entity.entityKey
17358
17508
  ));
17359
17509
  return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
17360
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
17361
- /* @__PURE__ */ jsxs("div", { children: [
17362
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: t("settings.fieldRules") }),
17363
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-0.5", children: t("settings.fieldRules.subtitle") })
17364
- ] }),
17365
- /* @__PURE__ */ jsxs(Button, { onClick: handleSave, disabled: !isDirty || saving, className: "shrink-0", children: [
17366
- saving && /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
17367
- t("common.save")
17368
- ] })
17369
- ] }),
17510
+ /* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsxs(Button, { onClick: handleSave, disabled: !isDirty || saving, className: "shrink-0", children: [
17511
+ saving && /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
17512
+ t("common.save")
17513
+ ] }) }),
17370
17514
  entities.length > 4 && /* @__PURE__ */ jsxs("div", { className: "relative max-w-sm", children: [
17371
17515
  /* @__PURE__ */ jsx(Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" }),
17372
17516
  /* @__PURE__ */ jsx(
@@ -17513,7 +17657,7 @@ function UpgradeModal() {
17513
17657
  }
17514
17658
  function LimitProbe({ limitKey, onReport }) {
17515
17659
  const info = useLimit(limitKey);
17516
- React63.useEffect(() => {
17660
+ React65.useEffect(() => {
17517
17661
  onReport(limitKey, info);
17518
17662
  }, [limitKey, info, onReport]);
17519
17663
  return null;
@@ -17526,16 +17670,16 @@ function SoftLimitBanner({ keys }) {
17526
17670
  if (params) for (const [k, val] of Object.entries(params)) v = v.replace(`{${k}}`, String(val)).replace(`{{${k}}}`, String(val));
17527
17671
  return v;
17528
17672
  };
17529
- const [over, setOver] = React63.useState({});
17530
- const [dismissed, setDismissed] = React63.useState({});
17531
- const report = React63.useCallback((key, info) => {
17673
+ const [over, setOver] = React65.useState({});
17674
+ const [dismissed, setDismissed] = React65.useState({});
17675
+ const report = React65.useCallback((key, info) => {
17532
17676
  const isOver = !info.unlimited && !info.loading && info.used > info.max;
17533
17677
  setOver((prev) => {
17534
17678
  if (isOver === Boolean(prev[key])) return prev;
17535
17679
  return { ...prev, [key]: isOver };
17536
17680
  });
17537
17681
  }, []);
17538
- const monitored = React63.useMemo(() => Array.from(new Set(keys)), [keys]);
17682
+ const monitored = React65.useMemo(() => Array.from(new Set(keys)), [keys]);
17539
17683
  const activeKey = monitored.find((k) => over[k] && !dismissed[k]);
17540
17684
  return /* @__PURE__ */ jsxs(Fragment, { children: [
17541
17685
  monitored.map((k) => /* @__PURE__ */ jsx(LimitProbe, { limitKey: k, onReport: report }, k)),
@@ -17558,11 +17702,11 @@ function SoftLimitBanner({ keys }) {
17558
17702
  ] })
17559
17703
  ] });
17560
17704
  }
17561
- var CommandPalette = React63.lazy(
17705
+ var CommandPalette = React65.lazy(
17562
17706
  () => import('./CommandPalette-U7MMA2WH.js').then((m) => ({ default: m.CommandPalette }))
17563
17707
  );
17564
- var SubscriptionPage = React63.lazy(
17565
- () => import('./SubscriptionPage-NLZAZO4P.js').then((m) => ({ default: m.SubscriptionPage }))
17708
+ var SubscriptionPage = React65.lazy(
17709
+ () => import('./SubscriptionPage-4KP7DKA2.js').then((m) => ({ default: m.SubscriptionPage }))
17566
17710
  );
17567
17711
  function orgInitials(name) {
17568
17712
  const words = name.trim().split(/\s+/).filter(Boolean);
@@ -17791,9 +17935,9 @@ function AccessDenied({ tr }) {
17791
17935
  }
17792
17936
  function AdminNotifications() {
17793
17937
  const { notifications, unreadCount, fetchNotifications, markAsRead, markAllAsRead } = useNotifications();
17794
- const [open, setOpen] = React63.useState(false);
17795
- const fetchedRef = React63.useRef(false);
17796
- React63.useEffect(() => {
17938
+ const [open, setOpen] = React65.useState(false);
17939
+ const fetchedRef = React65.useRef(false);
17940
+ React65.useEffect(() => {
17797
17941
  if (fetchedRef.current) return;
17798
17942
  fetchedRef.current = true;
17799
17943
  void fetchNotifications();
@@ -17910,7 +18054,7 @@ function buildSettingsTabs(pluginTabs, can, hasSystem, t, showOrgSettings, hasBi
17910
18054
  // sidebar ICON_MAP, which made the settings rail fall back to Home.
17911
18055
  icon: /* @__PURE__ */ jsx(CreditCard, { className: "h-4 w-4" }),
17912
18056
  iconName: "CreditCard",
17913
- component: /* @__PURE__ */ jsx(React63.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(SubscriptionPage, {}) })
18057
+ component: /* @__PURE__ */ jsx(React65.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(SubscriptionPage, {}) })
17914
18058
  });
17915
18059
  }
17916
18060
  if (showOrgSettings) {
@@ -17934,9 +18078,9 @@ function buildSettingsTabs(pluginTabs, can, hasSystem, t, showOrgSettings, hasBi
17934
18078
  settingsTabs.push({
17935
18079
  id: tab.id,
17936
18080
  label: translated === labelKey ? tab.label : translated,
17937
- icon: React63.createElement(IconComp, { className: "h-4 w-4" }),
18081
+ icon: React65.createElement(IconComp, { className: "h-4 w-4" }),
17938
18082
  iconName: tab.icon ?? "Puzzle",
17939
- component: React63.createElement(tab.component),
18083
+ component: React65.createElement(tab.component),
17940
18084
  // Flag plugin-contributed tabs so SettingsPage draws the core/plugins divider.
17941
18085
  isPlugin: true,
17942
18086
  group: tab.group
@@ -17950,7 +18094,7 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
17950
18094
  const can = usePermissionOptional();
17951
18095
  const access = useAccessOptional();
17952
18096
  const currentProfile = usePermissionsStore((s) => s.currentProfile);
17953
- const hasSystem = React63.useCallback(
18097
+ const hasSystem = React65.useCallback(
17954
18098
  (perm) => {
17955
18099
  if (!currentProfile) return true;
17956
18100
  if (currentProfile.id === "owner" || currentProfile.name?.toLowerCase() === "owner") return true;
@@ -17964,20 +18108,20 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
17964
18108
  };
17965
18109
  const path = useAdminPath();
17966
18110
  const { user, signOut } = useAuth();
17967
- React63.useEffect(() => installGlobalErrorHandlers(), []);
18111
+ React65.useEffect(() => installGlobalErrorHandlers(), []);
17968
18112
  const railOpen = useRightRailStore((s) => s.open);
17969
18113
  const railHasPanels = useRightRailStore((s) => s.panels.length > 0);
17970
18114
  const rightRail = railHasPanels ? /* @__PURE__ */ jsx(RightRail, { frame: contentFrame }) : null;
17971
18115
  const setRailMounted = useRightRailStore((s) => s.setMounted);
17972
- React63.useEffect(() => {
18116
+ React65.useEffect(() => {
17973
18117
  setRailMounted(true);
17974
18118
  return () => setRailMounted(false);
17975
18119
  }, [setRailMounted]);
17976
18120
  useConnectorOAuthReturn();
17977
18121
  const railWidthLive = useRightRailStore((s) => s.width);
17978
18122
  const setSidebarCollapsed = useLayoutStore((s) => s.setSidebarCollapsed);
17979
- const railAutoCollapsedRef = React63.useRef(false);
17980
- React63.useEffect(() => {
18123
+ const railAutoCollapsedRef = React65.useRef(false);
18124
+ React65.useEffect(() => {
17981
18125
  if (layout !== "sidebar") return;
17982
18126
  const SIDEBAR_EXPANDED = 224;
17983
18127
  const MIN_CONTENT = 620;
@@ -17999,20 +18143,20 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
17999
18143
  window.addEventListener("resize", apply);
18000
18144
  return () => window.removeEventListener("resize", apply);
18001
18145
  }, [railOpen, railWidthLive, layout, setSidebarCollapsed]);
18002
- const [railWidth] = React63.useState(() => readRightRailWidth());
18146
+ const [railWidth] = React65.useState(() => readRightRailWidth());
18003
18147
  const billingPlans = useBillingStore((s) => s.plans);
18004
18148
  const hasBilling = billingPlans.length > 0;
18005
18149
  const orgPlan = useTenantOptional()?.org?.plan;
18006
- const planBadge = React63.useMemo(
18150
+ const planBadge = React65.useMemo(
18007
18151
  () => hasBilling ? resolvePlanBadge(orgPlan, billingPlans) : null,
18008
18152
  [hasBilling, orgPlan, billingPlans]
18009
18153
  );
18010
- const softLimitKeys = React63.useMemo(() => {
18154
+ const softLimitKeys = React65.useMemo(() => {
18011
18155
  const plan = billingPlans.find((p) => p.id === (orgPlan || "free"));
18012
18156
  return Object.keys(getPlanEntitlements(plan)?.limits ?? {});
18013
18157
  }, [billingPlans, orgPlan]);
18014
18158
  const navContributions = useNavContributionsStore((s) => s.contributions);
18015
- const navigation = React63.useMemo(() => {
18159
+ const navigation = React65.useMemo(() => {
18016
18160
  const contributed = Object.values(navContributions).flat();
18017
18161
  const flat = [...runtime.navigation, ...contributed].map((entry) => ({ ...navEntryToItem(entry), position: entry.position, indexChild: entry.indexChild })).sort(compareNavigation);
18018
18162
  const items = [];
@@ -18059,7 +18203,7 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
18059
18203
  }, [runtime.navigation, navContributions, pages, access]);
18060
18204
  const commandPaletteOpen = useLayoutStore((s) => s.commandPaletteOpen);
18061
18205
  const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
18062
- const commandItems = React63.useMemo(() => {
18206
+ const commandItems = React65.useMemo(() => {
18063
18207
  const navGroup = tr("layout.commandPalette.navigation", "Navigation");
18064
18208
  const items = [];
18065
18209
  for (const nav of navigation) {
@@ -18071,7 +18215,7 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
18071
18215
  return items;
18072
18216
  }, [navigation]);
18073
18217
  const globalSearch = useGlobalSearch();
18074
- const routes = React63.useMemo(() => {
18218
+ const routes = React65.useMemo(() => {
18075
18219
  const list = [];
18076
18220
  const entityRouteMap = /* @__PURE__ */ new Map();
18077
18221
  for (const r of runtime.routes) {
@@ -18093,25 +18237,25 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
18093
18237
  setEntityRouteMap(entityRouteMap);
18094
18238
  return list.sort((a, b) => routeScore(b.path) - routeScore(a.path));
18095
18239
  }, [runtime.routes, pages, showSettings]);
18096
- const match = React63.useMemo(() => {
18240
+ const match = React65.useMemo(() => {
18097
18241
  for (const r of routes) {
18098
18242
  const params = matchRoute(r.path, path);
18099
18243
  if (params) return { route: r, params };
18100
18244
  }
18101
18245
  return null;
18102
18246
  }, [routes, path]);
18103
- React63.useEffect(() => {
18247
+ React65.useEffect(() => {
18104
18248
  if (!match && (path === "/" || path === "") && navigation.length > 0) {
18105
18249
  navigateTo(navigation[0].route);
18106
18250
  }
18107
18251
  }, [match, path, navigation]);
18108
18252
  const ActiveComponent = match?.route.Component;
18109
18253
  const activeParams = match?.params ?? {};
18110
- const settingsTabs = React63.useMemo(
18254
+ const settingsTabs = React65.useMemo(
18111
18255
  () => buildSettingsTabs(runtime.settingsTabs, can, hasSystem, t, showOrgSettings, hasBilling),
18112
18256
  [runtime.settingsTabs, can, hasSystem, t, showOrgSettings, hasBilling]
18113
18257
  );
18114
- const profileRoute = React63.useMemo(() => {
18258
+ const profileRoute = React65.useMemo(() => {
18115
18259
  const explicit = routes.find((r) => r.path === "/perfil" || r.path === "/profile");
18116
18260
  if (explicit) return explicit.path;
18117
18261
  return showSettings ? "/settings/profile" : null;
@@ -18119,7 +18263,7 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
18119
18263
  const onProfile = profileRoute ? () => navigateTo(profileRoute) : void 0;
18120
18264
  const onBilling = hasBilling && showSettings ? () => navigateTo("/settings/subscription") : void 0;
18121
18265
  const coreSettingsTabs = useCoreSettingsTabs({ showCompany: showBranding, showBranding });
18122
- const allSettingsTabs = React63.useMemo(
18266
+ const allSettingsTabs = React65.useMemo(
18123
18267
  () => {
18124
18268
  const hidden = new Set(hiddenSettingsTabs ?? []);
18125
18269
  return [...coreSettingsTabs, ...settingsTabs].filter((tab) => !hidden.has(tab.id));
@@ -18131,12 +18275,12 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
18131
18275
  const contextualNav = useContextualNavStore((s) => s.nav);
18132
18276
  const moduleRail = !inSettings && layout === "sidebar" && contextualNav && (path === contextualNav.base || path.startsWith(contextualNav.base + "/")) ? contextualNav : null;
18133
18277
  const activeSettingsTab = inSettings ? path === "/settings" ? null : path.slice("/settings/".length).split("/")[0] : void 0;
18134
- const settingsTabDef = React63.useMemo(() => {
18278
+ const settingsTabDef = React65.useMemo(() => {
18135
18279
  if (!showSettings || !path.startsWith("/settings/")) return void 0;
18136
18280
  const id = path.slice("/settings/".length).split("/")[0];
18137
18281
  return allSettingsTabs.find((tab) => tab.id === id);
18138
18282
  }, [showSettings, path, allSettingsTabs]);
18139
- const settingsNavigation = React63.useMemo(
18283
+ const settingsNavigation = React65.useMemo(
18140
18284
  () => allSettingsTabs.map((tab) => ({
18141
18285
  id: `settings:${tab.id}`,
18142
18286
  label: tab.label,
@@ -18154,10 +18298,10 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
18154
18298
  const shellUser = user ? { fullName: user.fullName ?? user.email, email: user.email, avatarUrl: user.avatarUrl } : void 0;
18155
18299
  const moduleVariant = moduleNav ?? (layout === "sidebar" ? "tabs" : "rail");
18156
18300
  const setRailAvailable = useContextualNavStore((s) => s.setRailAvailable);
18157
- React63.useEffect(() => {
18301
+ React65.useEffect(() => {
18158
18302
  setRailAvailable(layout === "sidebar" && moduleVariant !== "rail");
18159
18303
  }, [layout, moduleVariant, setRailAvailable]);
18160
- const activePageTitle = React63.useMemo(() => {
18304
+ const activePageTitle = React65.useMemo(() => {
18161
18305
  if (settingsTabDef) return settingsTabDef.label;
18162
18306
  if (path === "/settings" || path.startsWith("/settings/")) return tr("common.settings", "Settings");
18163
18307
  if (match?.route.title) return match.route.title;
@@ -18167,7 +18311,7 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
18167
18311
  );
18168
18312
  return hit?.label ?? candidates.find((n) => n.route === "/")?.label ?? "";
18169
18313
  }, [navigation, path, tr, match, settingsTabDef]);
18170
- const parentBack = React63.useMemo(() => {
18314
+ const parentBack = React65.useMemo(() => {
18171
18315
  if (settingsTabDef) {
18172
18316
  return { onBack: () => navigateTo("/settings"), label: tr("common.settings", "Settings") };
18173
18317
  }
@@ -18246,11 +18390,15 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
18246
18390
  onEdit: site?.editRoute ? () => navigateTo(site.editRoute) : void 0
18247
18391
  }
18248
18392
  ),
18393
+ /* @__PURE__ */ jsx(WidgetSlot, { zone: "shell.sidebar.footer" }),
18249
18394
  sidebarFooter
18250
18395
  ] }),
18251
18396
  orgSwitcher: layout === "topbar" && showOrgSwitcher ? /* @__PURE__ */ jsx(WorkspaceSwitcher, { variant: "topbar" }) : void 0,
18252
- topbarStart: /* @__PURE__ */ jsx(WidgetSlot, { zone: "shell.topbar.start" }),
18253
- topbarEnd: /* @__PURE__ */ jsx(WidgetSlot, { zone: "shell.topbar.end" }),
18397
+ topbarStart: /* @__PURE__ */ jsx(WidgetSlot, { zone: "shell.topbar.start", surface: "topbar" }),
18398
+ topbarEnd: /* @__PURE__ */ jsxs(Fragment, { children: [
18399
+ /* @__PURE__ */ jsx(WidgetSlot, { zone: "shell.topbar.end", surface: "topbar" }),
18400
+ layout !== "sidebar" && /* @__PURE__ */ jsx(WidgetSlot, { zone: "shell.sidebar.footer", surface: "topbar" })
18401
+ ] }),
18254
18402
  rightRail,
18255
18403
  rightRailOpen: railOpen,
18256
18404
  defaultRightRailWidth: railWidth,
@@ -18297,10 +18445,15 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
18297
18445
  userId: user?.id,
18298
18446
  backLabel: parentBack?.label,
18299
18447
  onBack: parentBack ? parentBack.onBack : () => navigateTo(homeRoute),
18300
- children: match?.route.fullBleed ? /* @__PURE__ */ jsx("div", { className: "h-full min-h-0 overflow-hidden", children: activeContent }) : /* @__PURE__ */ jsxs("div", { className: "space-y-4 p-3 md:space-y-6 md:p-6", children: [
18301
- softLimitKeys.length > 0 && /* @__PURE__ */ jsx(SoftLimitBanner, { keys: softLimitKeys }),
18302
- activeContent
18303
- ] })
18448
+ children: match?.route.fullBleed ? /* @__PURE__ */ jsx("div", { className: "h-full min-h-0 overflow-hidden", children: activeContent }) : (
18449
+ // Less air at the top than at the sides: the bar above already
18450
+ // ends in a hairline, so a full 24px under it read as a gap
18451
+ // before the page started rather than as the page's margin.
18452
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4 p-3 md:space-y-6 md:px-6 md:pb-6 md:pt-4", children: [
18453
+ softLimitKeys.length > 0 && /* @__PURE__ */ jsx(SoftLimitBanner, { keys: softLimitKeys }),
18454
+ activeContent
18455
+ ] })
18456
+ )
18304
18457
  },
18305
18458
  match?.route.path ?? path
18306
18459
  )
@@ -18319,7 +18472,7 @@ function AdminShellInner({ appName, layout = "sidebar", logo, pages = [], showSe
18319
18472
  ]
18320
18473
  }
18321
18474
  ),
18322
- /* @__PURE__ */ jsx(React63.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
18475
+ /* @__PURE__ */ jsx(React65.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
18323
18476
  CommandPalette,
18324
18477
  {
18325
18478
  commands: commandItems,
@@ -18487,7 +18640,7 @@ function buildI18nConfig(config) {
18487
18640
  function BillingInitializer({ config }) {
18488
18641
  const setPlans = useBillingStore((s) => s.setPlans);
18489
18642
  const setCheckout = useBillingStore((s) => s.setCheckout);
18490
- React63.useEffect(() => {
18643
+ React65.useEffect(() => {
18491
18644
  if (config.billing?.plans) setPlans(config.billing.plans.map(normalizeBillingPlan));
18492
18645
  setCheckout(config.billing?.onCheckout ?? null);
18493
18646
  }, [config.billing, setPlans, setCheckout]);
@@ -18514,7 +18667,7 @@ function ThemeInitializer({ config }) {
18514
18667
  const initialize = useThemeStore((s) => s.initialize);
18515
18668
  const setOverrides = useThemeStore((s) => s.setOverrides);
18516
18669
  const setMode = useThemeStore((s) => s.setMode);
18517
- React63.useEffect(() => {
18670
+ React65.useEffect(() => {
18518
18671
  if (config.theme) {
18519
18672
  const resolved = isSaasTheme(config.theme) ? resolveTheme(config.theme) : config.theme;
18520
18673
  setOverrides(resolved);
@@ -18527,20 +18680,20 @@ function ThemeInitializer({ config }) {
18527
18680
  return null;
18528
18681
  }
18529
18682
  function PersistentCacheInitializer() {
18530
- React63.useEffect(() => {
18683
+ React65.useEffect(() => {
18531
18684
  attachPersistentCache();
18532
18685
  void getPersistentCache()?.hydrate();
18533
18686
  }, []);
18534
18687
  return null;
18535
18688
  }
18536
18689
  function FayzEventBridgeInitializer({ config }) {
18537
- React63.useEffect(() => startFayzEventBridge(config.chat?.agent), [config.chat?.agent]);
18690
+ React65.useEffect(() => startFayzEventBridge(config.chat?.agent), [config.chat?.agent]);
18538
18691
  return null;
18539
18692
  }
18540
18693
  function TeamInitializer({ config }) {
18541
18694
  const setTeamPersonKinds = useOrganizationStore((s) => s.setTeamPersonKinds);
18542
18695
  const kinds = config.team?.personKinds;
18543
- React63.useEffect(() => {
18696
+ React65.useEffect(() => {
18544
18697
  setTeamPersonKinds(kinds ?? []);
18545
18698
  }, [setTeamPersonKinds, kinds]);
18546
18699
  return null;
@@ -18556,7 +18709,7 @@ function ChatRailPanel({ config }) {
18556
18709
  const agent = config.chat?.agent;
18557
18710
  const voice = config.chat?.voice;
18558
18711
  const whatsapp = config.chat?.whatsapp;
18559
- const Component2 = React63.useMemo(() => {
18712
+ const Component2 = React65.useMemo(() => {
18560
18713
  const Panel = () => /* @__PURE__ */ jsx(
18561
18714
  ChatConversation,
18562
18715
  {
@@ -18573,15 +18726,15 @@ function ChatRailPanel({ config }) {
18573
18726
  const conversations = useChatStore((s) => s.conversations);
18574
18727
  const setConversations = useChatStore((s) => s.setConversations);
18575
18728
  const user = useAuthStore((s) => s.user);
18576
- const connection = React63.useMemo(() => resolveFayzAgentConnection(agent), [agent]);
18577
- React63.useEffect(() => {
18729
+ const connection = React65.useMemo(() => resolveFayzAgentConnection(agent), [agent]);
18730
+ React65.useEffect(() => {
18578
18731
  if (!connection) return;
18579
18732
  getFayzAgentClient(connection).listConversations(user?.id).then(setConversations).catch(() => {
18580
18733
  });
18581
18734
  }, [connection, user?.id, setConversations]);
18582
18735
  const persona = useAssistantInviteStore((s) => s.invite?.persona);
18583
18736
  useRightRailPanel(
18584
- React63.useMemo(
18737
+ React65.useMemo(
18585
18738
  () => ({
18586
18739
  id: "chat",
18587
18740
  label: persona ?? "Chat",
@@ -18593,17 +18746,17 @@ function ChatRailPanel({ config }) {
18593
18746
  [Component2, conversations.length, persona]
18594
18747
  )
18595
18748
  );
18596
- React63.useEffect(() => {
18749
+ React65.useEffect(() => {
18597
18750
  if (chatOpen) openPanel("chat");
18598
18751
  }, [chatOpen, openPanel]);
18599
- React63.useEffect(() => {
18752
+ React65.useEffect(() => {
18600
18753
  if (!(railOpen && railActive === "chat")) setChatOpen(false);
18601
18754
  }, [railOpen, railActive, setChatOpen]);
18602
18755
  return null;
18603
18756
  }
18604
18757
  function AdminProviders({ config, children }) {
18605
18758
  const currentOrg = useOrganizationStore((s) => s.currentOrg);
18606
- const hasFayzAgent = React63.useMemo(
18759
+ const hasFayzAgent = React65.useMemo(
18607
18760
  () => !!resolveFayzAgentConnection(config.chat?.agent),
18608
18761
  [config.chat?.agent]
18609
18762
  );
@@ -18611,7 +18764,7 @@ function AdminProviders({ config, children }) {
18611
18764
  const surface = config.chat?.surface ?? "dock";
18612
18765
  const onConsentScreen = typeof window !== "undefined" && window.location.pathname.replace(/\/+$/, "").endsWith("/connect");
18613
18766
  const showFab = assistantEnabled && surface === "dock" && !onConsentScreen;
18614
- const resolved = React63.useMemo(() => {
18767
+ const resolved = React65.useMemo(() => {
18615
18768
  if (config.supabaseUrl && config.supabaseAnonKey) {
18616
18769
  createFayzSupabaseClient(config.supabaseUrl, config.supabaseAnonKey);
18617
18770
  }
@@ -18627,7 +18780,7 @@ function AdminProviders({ config, children }) {
18627
18780
  };
18628
18781
  }, [config]);
18629
18782
  const path = useAdminPath();
18630
- const runtime = React63.useMemo(
18783
+ const runtime = React65.useMemo(
18631
18784
  () => resolvePluginRuntime({
18632
18785
  plugins: resolved.plugins,
18633
18786
  context: {
@@ -18939,8 +19092,8 @@ function manifestToFayzConfig(manifest, surfaceName) {
18939
19092
  };
18940
19093
  }
18941
19094
  function AdminScaffold({ manifest, surface }) {
18942
- const config = React63.useMemo(() => manifestToFayzConfig(manifest, surface), [manifest, surface]);
18943
- const authShellProps = React63.useMemo(() => getAuthShellProps(config.auth), [config.auth]);
19095
+ const config = React65.useMemo(() => manifestToFayzConfig(manifest, surface), [manifest, surface]);
19096
+ const authShellProps = React65.useMemo(() => getAuthShellProps(config.auth), [config.auth]);
18944
19097
  return /* @__PURE__ */ jsx(AdminProviders, { config, children: /* @__PURE__ */ jsx(
18945
19098
  AdminShell,
18946
19099
  {
@@ -19219,10 +19372,10 @@ function OrderDetailView(props) {
19219
19372
  // três colunas viravam uma tira de 280px que quebrava todo rótulo.
19220
19373
  /* @__PURE__ */ jsxs("div", { className: "fz-container space-y-4", children: [
19221
19374
  /* @__PURE__ */ jsx(PageHeader, { title, parentLabel: backLabel, onBack }),
19222
- (badges.length > 0 || props.badgesNode || subtitle || actions) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
19375
+ actions && /* @__PURE__ */ jsx(PageHeaderActions, { children: actions }),
19376
+ (badges.length > 0 || props.badgesNode || subtitle) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
19223
19377
  props.badgesNode ?? badges.map((b, i) => /* @__PURE__ */ jsx(Badge15, { badge: b }, i)),
19224
- subtitle && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: subtitle }),
19225
- actions && /* @__PURE__ */ jsx("div", { className: "ml-auto flex flex-wrap items-center gap-2", children: actions })
19378
+ subtitle && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: subtitle })
19226
19379
  ] }),
19227
19380
  stats.length > 0 && /* @__PURE__ */ jsx("div", { className: "fz-fields fz-fields-4 gap-3", children: stats.map((tile, i) => /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-3", children: [
19228
19381
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
@@ -19310,7 +19463,9 @@ var ITEM_LABELS = {
19310
19463
  adjustments: "Desconto / acr\xE9scimo",
19311
19464
  removeAdjustments: "Remover ajustes",
19312
19465
  remove: "Remover item",
19313
- done: "Conclu\xEDdo"
19466
+ done: "Conclu\xEDdo",
19467
+ create: "Cadastrar",
19468
+ clear: "Limpar"
19314
19469
  };
19315
19470
  function OrderFormItemRow({
19316
19471
  index,
@@ -19337,7 +19492,7 @@ function OrderFormItemRow({
19337
19492
  const total = quantity * unitPrice - (discount ?? 0) + (surcharge ?? 0);
19338
19493
  const kindLabel = itemTypes.find((tp) => tp.value === itemKind)?.label ?? itemKind;
19339
19494
  const hasAdjustments = (discount ?? 0) > 0 || (surcharge ?? 0) > 0;
19340
- const [showAdjustments, setShowAdjustments] = React63.useState(hasAdjustments);
19495
+ const [showAdjustments, setShowAdjustments] = React65.useState(hasAdjustments);
19341
19496
  const lookup2 = entityLookups[itemKind];
19342
19497
  function handleFieldKeyDown(e) {
19343
19498
  if (e.key === "Enter" && !e.shiftKey) {
@@ -19412,6 +19567,12 @@ function OrderFormItemRow({
19412
19567
  const results = await lookup2.search(q);
19413
19568
  return results.map((r) => ({ id: r.id, label: r.label, subtitle: r.subtitle, group: r.group, data: r }));
19414
19569
  },
19570
+ createLabel: l.create,
19571
+ clearLabel: l.clear,
19572
+ onCreate: lookup2.create ? async (name) => {
19573
+ const created = await lookup2.create(name);
19574
+ onChange({ referenceId: created.id, description: created.label });
19575
+ } : void 0,
19415
19576
  placeholder: `${l.item}\u2026`,
19416
19577
  renderOption: (opt) => /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
19417
19578
  /* @__PURE__ */ jsx("p", { className: "truncate text-sm", children: opt.label }),
@@ -19607,7 +19768,7 @@ function OrderFormView({
19607
19768
  parentLabel,
19608
19769
  onBack,
19609
19770
  badges,
19610
- subtitle,
19771
+ subtitle: _subtitle,
19611
19772
  actions,
19612
19773
  banner,
19613
19774
  children,
@@ -19618,11 +19779,8 @@ function OrderFormView({
19618
19779
  // se cabem duas colunas é a LARGURA DESTA COLUNA, não a da janela.
19619
19780
  /* @__PURE__ */ jsxs("div", { className: "fz-container space-y-4", children: [
19620
19781
  /* @__PURE__ */ jsx(PageHeader, { title, parentLabel, onBack }),
19621
- (badges || subtitle || actions) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
19622
- badges,
19623
- subtitle && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: subtitle }),
19624
- actions && /* @__PURE__ */ jsx("div", { className: "ml-auto flex flex-wrap items-center gap-2", children: actions })
19625
- ] }),
19782
+ actions && /* @__PURE__ */ jsx(PageHeaderActions, { children: actions }),
19783
+ badges && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2", children: badges }),
19626
19784
  banner,
19627
19785
  /* @__PURE__ */ jsxs("div", { className: "fz-split", children: [
19628
19786
  /* @__PURE__ */ jsx("div", { className: "fz-container space-y-4", children }),
@@ -19633,13 +19791,12 @@ function OrderFormView({
19633
19791
  }
19634
19792
  OrderFormView.displayName = "OrderFormView";
19635
19793
  function OrderFormSkeleton() {
19636
- return /* @__PURE__ */ jsxs("div", { className: "fz-container space-y-4", children: [
19637
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-20" }),
19638
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
19639
- /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-20 rounded-full" }),
19640
- /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-20 rounded-full" })
19641
- ] }),
19642
- /* @__PURE__ */ jsxs("div", { className: "fz-split", children: [
19794
+ return (
19795
+ // Sem a linha da migalha nem a fileira de pastilhas: a migalha mora na barra
19796
+ // da shell (que já está desenhada quando isto aparece) e o formulário não
19797
+ // tem badges. Eram duas faixas cinzas prometendo conteúdo que nunca chega —
19798
+ // o "pulo" que um esqueleto existe para evitar, causado pelo esqueleto.
19799
+ /* @__PURE__ */ jsx("div", { className: "fz-container space-y-4", children: /* @__PURE__ */ jsxs("div", { className: "fz-split", children: [
19643
19800
  /* @__PURE__ */ jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card", children: [
19644
19801
  /* @__PURE__ */ jsx("div", { className: "border-b px-4 py-3", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-24" }) }),
19645
19802
  /* @__PURE__ */ jsx("div", { className: "space-y-3 p-4", children: [1, 2].map((i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
@@ -19652,11 +19809,13 @@ function OrderFormSkeleton() {
19652
19809
  /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-20" }),
19653
19810
  /* @__PURE__ */ jsx("div", { className: "mt-3 space-y-2", children: Array.from({ length: rows }).map((_, j) => /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" }, j)) })
19654
19811
  ] }, i)) })
19655
- ] })
19656
- ] });
19812
+ ] }) })
19813
+ );
19657
19814
  }
19658
19815
  function OrderListView({
19659
- title,
19816
+ // `title` continua na API (é o que o chamador declara), mas quem escreve o
19817
+ // nome da tela é a barra da shell — ver o corpo.
19818
+ title: _title,
19660
19819
  subtitle,
19661
19820
  actions,
19662
19821
  stats,
@@ -19674,10 +19833,10 @@ function OrderListView({
19674
19833
  bulkActions,
19675
19834
  rowId
19676
19835
  }) {
19677
- const [search, setSearch] = React63.useState("");
19678
- const [page, setPage] = React63.useState(1);
19679
- const [rawSelection, setRawSelection] = React63.useState([]);
19680
- const cols = React63.useMemo(
19836
+ const [search, setSearch] = React65.useState("");
19837
+ const [page, setPage] = React65.useState(1);
19838
+ const [rawSelection, setRawSelection] = React65.useState([]);
19839
+ const cols = React65.useMemo(
19681
19840
  () => columns.map((c) => ({
19682
19841
  id: c.key,
19683
19842
  header: () => /* @__PURE__ */ jsx("div", { className: c.align === "right" ? "text-right" : "", children: c.header }),
@@ -19685,29 +19844,30 @@ function OrderListView({
19685
19844
  })),
19686
19845
  [columns]
19687
19846
  );
19688
- const filtered = React63.useMemo(() => {
19847
+ const filtered = React65.useMemo(() => {
19689
19848
  const term = search.trim().toLowerCase();
19690
19849
  if (!term || !searchText) return rows;
19691
19850
  return rows.filter((row) => searchText(row).toLowerCase().includes(term));
19692
19851
  }, [rows, search, searchText]);
19693
- React63.useEffect(() => {
19852
+ React65.useEffect(() => {
19694
19853
  setPage(1);
19695
19854
  }, [search]);
19696
19855
  const paged = pageSize > 0 ? filtered.slice((page - 1) * pageSize, page * pageSize) : filtered;
19697
- const getId = React63.useCallback(
19856
+ const getId = React65.useCallback(
19698
19857
  (row) => rowId ? rowId(row) : String(row.id ?? ""),
19699
19858
  [rowId]
19700
19859
  );
19701
- const pageIds = React63.useMemo(() => paged.map(getId), [paged, getId]);
19702
- const selectedIds = React63.useMemo(
19860
+ const pageIds = React65.useMemo(() => paged.map(getId), [paged, getId]);
19861
+ const selectedIds = React65.useMemo(
19703
19862
  () => rawSelection.filter((id) => pageIds.includes(id)),
19704
19863
  [rawSelection, pageIds]
19705
19864
  );
19706
- const selectedRows = React63.useMemo(
19865
+ const selectedRows = React65.useMemo(
19707
19866
  () => paged.filter((row) => selectedIds.includes(getId(row))),
19708
19867
  [paged, selectedIds, getId]
19709
19868
  );
19710
19869
  const selectable = (bulkActions?.length ?? 0) > 0;
19870
+ const hasSelection = selectable && selectedIds.length > 0;
19711
19871
  const barActions = (bulkActions ?? []).map((action) => ({
19712
19872
  id: action.id,
19713
19873
  label: action.label,
@@ -19729,38 +19889,31 @@ function OrderListView({
19729
19889
  // `p-3 md:p-6` (AdminShell). Reaplicar `p-6 md:p-8` aqui empurrava a lista
19730
19890
  // 32px à direita do título na barra de topo e de todas as outras telas.
19731
19891
  /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
19732
- navTabs && navTabs.length > 0 && // Mesma linha de CrudListView: abas à esquerda, ações à direita.
19733
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
19734
- /* @__PURE__ */ jsx(
19735
- HeaderTabs,
19736
- {
19737
- tabs: navTabs,
19738
- value: activeNavTab ?? navTabs[0].value,
19739
- onChange: (v) => onNavTabChange?.(v)
19740
- }
19741
- ),
19742
- actions
19743
- ] }),
19744
- !navTabs?.length && (title || subtitle || actions) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
19745
- title || subtitle ? /* @__PURE__ */ jsxs("div", { children: [
19746
- title && /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: title }),
19747
- subtitle && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: subtitle })
19748
- ] }) : /* @__PURE__ */ jsx("span", {}),
19749
- actions
19750
- ] }),
19751
- tiles.length > 0 && /* @__PURE__ */ jsx(StatTiles, { tiles, loading }),
19752
- selectable && /* @__PURE__ */ jsx(
19753
- BulkActionBar,
19892
+ actions && /* @__PURE__ */ jsx(PageHeaderActions, { children: actions }),
19893
+ navTabs && navTabs.length > 0 && // Mesma faixa de CrudListView e da sub-nav de módulo: abas à esquerda,
19894
+ // fechada pelo filete que atravessa a página.
19895
+ /* @__PURE__ */ jsx(
19896
+ PageTabs,
19754
19897
  {
19755
- count: selectedIds.length,
19756
- total: paged.length,
19757
- onSelectAll: () => setRawSelection(pageIds),
19758
- onClear: () => setRawSelection([]),
19759
- actions: barActions
19898
+ className: "mb-0",
19899
+ tabs: navTabs,
19900
+ value: activeNavTab ?? navTabs[0].value,
19901
+ onChange: (v) => onNavTabChange?.(v)
19760
19902
  }
19761
19903
  ),
19904
+ tiles.length > 0 && /* @__PURE__ */ jsx(StatTiles, { tiles, loading }),
19762
19905
  /* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
19763
- searchText && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-2", children: /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: /* @__PURE__ */ jsx(
19906
+ (searchText || hasSelection) && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-2", children: hasSelection ? /* @__PURE__ */ jsx(
19907
+ BulkActionBar,
19908
+ {
19909
+ variant: "inline",
19910
+ count: selectedIds.length,
19911
+ total: paged.length,
19912
+ onSelectAll: () => setRawSelection(pageIds),
19913
+ onClear: () => setRawSelection([]),
19914
+ actions: barActions
19915
+ }
19916
+ ) : /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: /* @__PURE__ */ jsx(
19764
19917
  SearchField,
19765
19918
  {
19766
19919
  value: search,
@@ -19958,6 +20111,21 @@ function createArchetypeLookup(config) {
19958
20111
  (row) => toResult(row, display, config.kindLabels)
19959
20112
  );
19960
20113
  },
20114
+ // Cadastro na hora: só o nome (e o `kind`, quando a busca já está presa a
20115
+ // um). Um registro nascido aqui é um esboço de propósito — o campo que o
20116
+ // pediu precisa continuar, não abrir um formulário inteiro.
20117
+ async create(name) {
20118
+ const supabase = getSupabaseClientOptional();
20119
+ if (!supabase) throw new Error("No database connection");
20120
+ const row = {
20121
+ [display.labelField]: name,
20122
+ is_active: true
20123
+ };
20124
+ if (kinds && kinds.length === 1) row.kind = kinds[0];
20125
+ const { data, error } = await supabase.from(display.table).insert(row).select("*").single();
20126
+ if (error) throw new Error(error.message);
20127
+ return toResult(data, display, config.kindLabels);
20128
+ },
19961
20129
  async getById(id) {
19962
20130
  const supabase = getSupabaseClientOptional();
19963
20131
  if (!supabase) return null;
@@ -20141,11 +20309,11 @@ function PersonTimeline({
20141
20309
  pageSize,
20142
20310
  activeSourceIds
20143
20311
  });
20144
- const toneBySource = React63__default.useMemo(
20312
+ const toneBySource = React65__default.useMemo(
20145
20313
  () => new Map(sources2.map((s) => [s.id, s.tone ?? "neutral"])),
20146
20314
  [sources2]
20147
20315
  );
20148
- const hrefFor = React63__default.useCallback(
20316
+ const hrefFor = React65__default.useCallback(
20149
20317
  (item) => {
20150
20318
  if (item.href) return item.href;
20151
20319
  if (!recordPath || !item.targetTab) return void 0;
@@ -20188,19 +20356,19 @@ function PersonTimeline({
20188
20356
  }
20189
20357
  function createPlaceholder(title, description) {
20190
20358
  return function PlaceholderPage() {
20191
- return React63__default.createElement(
20359
+ return React65__default.createElement(
20192
20360
  "div",
20193
20361
  { className: "mx-auto max-w-4xl" },
20194
- React63__default.createElement("h1", { className: "text-3xl font-bold text-foreground" }, title),
20195
- description ? React63__default.createElement("p", { className: "mt-1 text-muted-foreground" }, description) : null,
20196
- React63__default.createElement(
20362
+ React65__default.createElement("h1", { className: "text-3xl font-bold text-foreground" }, title),
20363
+ description ? React65__default.createElement("p", { className: "mt-1 text-muted-foreground" }, description) : null,
20364
+ React65__default.createElement(
20197
20365
  "div",
20198
20366
  { className: "mt-8 flex items-center justify-center rounded-card border border-dashed border-border bg-card p-16" },
20199
- React63__default.createElement(
20367
+ React65__default.createElement(
20200
20368
  "div",
20201
20369
  { className: "text-center" },
20202
- React63__default.createElement("p", { className: "text-lg font-medium text-muted-foreground" }, "Coming Soon"),
20203
- React63__default.createElement(
20370
+ React65__default.createElement("p", { className: "text-lg font-medium text-muted-foreground" }, "Coming Soon"),
20371
+ React65__default.createElement(
20204
20372
  "p",
20205
20373
  { className: "mt-1 text-sm text-muted-foreground/70" },
20206
20374
  "This module is being built as a plugin."
@@ -20210,55 +20378,6 @@ function createPlaceholder(title, description) {
20210
20378
  );
20211
20379
  };
20212
20380
  }
20213
- function QuickActionsButton({ actions, className }) {
20214
- const [open, setOpen] = useState(false);
20215
- const ref = useRef(null);
20216
- const variant = useModuleLayout() === "tabs" ? "default" : "outline";
20217
- useEffect(() => {
20218
- function handler(e) {
20219
- if (ref.current && !ref.current.contains(e.target)) setOpen(false);
20220
- }
20221
- document.addEventListener("mousedown", handler);
20222
- return () => document.removeEventListener("mousedown", handler);
20223
- }, []);
20224
- if (actions.length === 0) return null;
20225
- return /* @__PURE__ */ jsxs("div", { ref, className: cn("relative", className), children: [
20226
- /* @__PURE__ */ jsxs(
20227
- Button,
20228
- {
20229
- variant,
20230
- size: "sm",
20231
- onClick: () => setOpen(!open),
20232
- className: cn(open && variant === "outline" && "bg-muted"),
20233
- children: [
20234
- /* @__PURE__ */ jsx(Plus, { className: cn("h-3.5 w-3.5 transition-transform duration-200", open && "rotate-45") }),
20235
- /* @__PURE__ */ jsx("span", { children: "New" })
20236
- ]
20237
- }
20238
- ),
20239
- open && /* @__PURE__ */ jsx("div", { className: "fayz-glass-surface absolute top-full right-0 z-50 mt-2 w-64 rounded-xl border bg-popover shadow-lg overflow-hidden animate-in fade-in-0 zoom-in-95 origin-top-right", children: /* @__PURE__ */ jsx("div", { className: "p-1.5", children: actions.map((action) => {
20240
- const Icon = action.icon ? ICON_MAP[action.icon] ?? Plus : Plus;
20241
- return /* @__PURE__ */ jsxs(
20242
- "button",
20243
- {
20244
- onClick: () => {
20245
- action.action();
20246
- setOpen(false);
20247
- },
20248
- className: "w-full flex items-center gap-3 rounded-lg px-3 py-2.5 text-left hover:bg-muted/50 transition-colors group",
20249
- children: [
20250
- /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-muted group-hover:bg-primary/10 transition-colors shrink-0", children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" }) }),
20251
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
20252
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: action.label }),
20253
- action.description && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground leading-tight", children: action.description })
20254
- ] })
20255
- ]
20256
- },
20257
- action.id
20258
- );
20259
- }) }) })
20260
- ] });
20261
- }
20262
20381
  function ModuleActionBar({
20263
20382
  quickActions,
20264
20383
  settingsPath,
@@ -20287,9 +20406,9 @@ function ModuleActionBar({
20287
20406
  ] });
20288
20407
  }
20289
20408
  function createPluginContext(displayName) {
20290
- const ConfigContext = React63__default.createContext(null);
20291
- const ProviderContext = React63__default.createContext(null);
20292
- const StoreContext = React63__default.createContext(null);
20409
+ const ConfigContext = React65__default.createContext(null);
20410
+ const ProviderContext = React65__default.createContext(null);
20411
+ const StoreContext = React65__default.createContext(null);
20293
20412
  const ContextProvider = ({
20294
20413
  config,
20295
20414
  provider,
@@ -20298,17 +20417,17 @@ function createPluginContext(displayName) {
20298
20417
  }) => /* @__PURE__ */ jsx(ConfigContext.Provider, { value: config, children: /* @__PURE__ */ jsx(ProviderContext.Provider, { value: provider, children: /* @__PURE__ */ jsx(StoreContext.Provider, { value: store, children }) }) });
20299
20418
  ContextProvider.displayName = `${displayName}ContextProvider`;
20300
20419
  function useConfig() {
20301
- const ctx = React63__default.useContext(ConfigContext);
20420
+ const ctx = React65__default.useContext(ConfigContext);
20302
20421
  if (!ctx) throw new Error(`useConfig must be used within ${displayName}`);
20303
20422
  return ctx;
20304
20423
  }
20305
20424
  function useProvider() {
20306
- const ctx = React63__default.useContext(ProviderContext);
20425
+ const ctx = React65__default.useContext(ProviderContext);
20307
20426
  if (!ctx) throw new Error(`useProvider must be used within ${displayName}`);
20308
20427
  return ctx;
20309
20428
  }
20310
20429
  function useStore$1(selector) {
20311
- const store = React63__default.useContext(StoreContext);
20430
+ const store = React65__default.useContext(StoreContext);
20312
20431
  if (!store) throw new Error(`useStore must be used within ${displayName}`);
20313
20432
  return useStore(store, selector);
20314
20433
  }
@@ -20365,7 +20484,7 @@ function PluginRegistryManager({ registries, routeBase, className }) {
20365
20484
  return registries[0]?.id ?? "";
20366
20485
  };
20367
20486
  const [activeTab, setActiveTab] = useState(getTabFromHash);
20368
- React63__default.useEffect(() => {
20487
+ React65__default.useEffect(() => {
20369
20488
  if (!routeBase) return;
20370
20489
  const handler = () => setActiveTab(getTabFromHash());
20371
20490
  window.addEventListener("hashchange", handler);
@@ -20423,6 +20542,14 @@ function useModuleNavigation(hashBase, depthMap, homeView = "summary") {
20423
20542
  const rest = hash.slice(hashBase.length + 1);
20424
20543
  const segments = rest.split("/");
20425
20544
  if (segments.length === 1 && segments[0] === homeView) return homeView;
20545
+ const UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
20546
+ const last = segments[segments.length - 1];
20547
+ if (segments.length >= 3 && !UUID_RE2.test(last) && UUID_RE2.test(segments[segments.length - 2])) {
20548
+ return segments.slice(0, -2).join("-") + "-" + last + ":" + segments[segments.length - 2];
20549
+ }
20550
+ if (segments.length === 2 && UUID_RE2.test(last)) {
20551
+ return segments[0] + "-detail:" + last;
20552
+ }
20426
20553
  const ACTION_KEYWORDS = ["edit", "detail", "view", "post"];
20427
20554
  if (segments.length >= 3) {
20428
20555
  const maybeAction = segments[segments.length - 2];
@@ -20430,9 +20557,8 @@ function useModuleNavigation(hashBase, depthMap, homeView = "summary") {
20430
20557
  return segments.slice(0, -2).join("-") + "-" + maybeAction + ":" + segments[segments.length - 1];
20431
20558
  }
20432
20559
  }
20433
- const UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
20434
- if (segments.length >= 2 && UUID_RE2.test(segments[segments.length - 1])) {
20435
- return segments.slice(0, -1).join("-") + ":" + segments[segments.length - 1];
20560
+ if (segments.length >= 2 && UUID_RE2.test(last)) {
20561
+ return segments.slice(0, -1).join("-") + ":" + last;
20436
20562
  }
20437
20563
  return segments.join("-");
20438
20564
  }
@@ -20487,9 +20613,17 @@ function useModuleNavigation(hashBase, depthMap, homeView = "summary") {
20487
20613
  } else {
20488
20614
  const colonIdx = nextView.indexOf(":");
20489
20615
  if (colonIdx !== -1) {
20490
- const prefix = nextView.slice(0, colonIdx).replace(/-/g, "/");
20616
+ const rawPrefix = nextView.slice(0, colonIdx);
20491
20617
  const id = nextView.slice(colonIdx + 1);
20492
- window.location.hash = `${hashBase}/${prefix}/${id}`;
20618
+ const parts = rawPrefix.split("-");
20619
+ const verb = parts.length > 1 ? parts[parts.length - 1] : void 0;
20620
+ if (verb === "detail") {
20621
+ window.location.hash = `${hashBase}/${parts.slice(0, -1).join("/")}/${id}`;
20622
+ } else if (verb === "edit") {
20623
+ window.location.hash = `${hashBase}/${parts.slice(0, -1).join("/")}/${id}/edit`;
20624
+ } else {
20625
+ window.location.hash = `${hashBase}/${rawPrefix.replace(/-/g, "/")}/${id}`;
20626
+ }
20493
20627
  } else {
20494
20628
  const path = nextView.replace(/-/g, "/");
20495
20629
  window.location.hash = `${hashBase}/${path}`;
@@ -20668,12 +20802,12 @@ function CrudRecordModal({
20668
20802
  description,
20669
20803
  emptyLabel
20670
20804
  }) {
20671
- const [record, setRecord] = React63.useState(null);
20672
- const [loading, setLoading] = React63.useState(false);
20673
- const [saving, setSaving] = React63.useState(false);
20674
- const [error, setError] = React63.useState(null);
20675
- const formId = React63.useId();
20676
- React63.useEffect(() => {
20805
+ const [record, setRecord] = React65.useState(null);
20806
+ const [loading, setLoading] = React65.useState(false);
20807
+ const [saving, setSaving] = React65.useState(false);
20808
+ const [error, setError] = React65.useState(null);
20809
+ const formId = React65.useId();
20810
+ React65.useEffect(() => {
20677
20811
  if (!open) return;
20678
20812
  let cancelled = false;
20679
20813
  setLoading(true);
@@ -21311,10 +21445,10 @@ function useTenantPluginSettings(pluginId, defaults) {
21311
21445
  );
21312
21446
  }
21313
21447
  function useAgentSurface(contribution) {
21314
- const ref = React63.useRef(contribution);
21448
+ const ref = React65.useRef(contribution);
21315
21449
  ref.current = contribution;
21316
21450
  const id = contribution.id;
21317
- React63.useEffect(() => {
21451
+ React65.useEffect(() => {
21318
21452
  registerSurface({ id, get: () => ref.current });
21319
21453
  const names = (ref.current.tools ?? []).map((t) => t.tool.name);
21320
21454
  for (const name of names) {
@@ -21334,21 +21468,21 @@ function ConnectorsHub({ hostPluginId }) {
21334
21468
  const { t } = useTranslation$1();
21335
21469
  const { connectors, reload } = useConnectors({ includeGrants: false });
21336
21470
  const assistantAvailable = useConnectorsPanelAvailable();
21337
- const [selected, setSelected] = React63__default.useState(null);
21338
- const [adding, setAdding] = React63__default.useState(false);
21339
- const hosted = React63__default.useMemo(
21471
+ const [selected, setSelected] = React65__default.useState(null);
21472
+ const [adding, setAdding] = React65__default.useState(false);
21473
+ const hosted = React65__default.useMemo(
21340
21474
  () => (connectors ?? []).filter((c) => c.hostPluginId === hostPluginId),
21341
21475
  [connectors, hostPluginId]
21342
21476
  );
21343
- const categories = React63__default.useMemo(
21477
+ const categories = React65__default.useMemo(
21344
21478
  () => [...new Set(hosted.map((c) => c.category).filter((c) => !!c))],
21345
21479
  [hosted]
21346
21480
  );
21347
- const scoped = React63__default.useMemo(() => {
21481
+ const scoped = React65__default.useMemo(() => {
21348
21482
  const siblings = inCategories(connectors ?? [], categories).filter((c) => c.hostPluginId !== hostPluginId);
21349
21483
  return [...hosted, ...siblings];
21350
21484
  }, [connectors, hosted, categories, hostPluginId]);
21351
- React63__default.useEffect(() => {
21485
+ React65__default.useEffect(() => {
21352
21486
  if (!selected || !connectors) return;
21353
21487
  const fresh = connectors.find((c) => c.id === selected.id);
21354
21488
  if (fresh && fresh !== selected) setSelected(fresh);
@@ -21360,7 +21494,7 @@ function ConnectorsHub({ hostPluginId }) {
21360
21494
  const only = categories.length === 1 ? categoryLabel(categories[0]) : void 0;
21361
21495
  const moreLabel = only ? t("connectors.viewCategory", { category: only }) : t("connectors.viewSimilar");
21362
21496
  return /* @__PURE__ */ jsxs("div", { className: "max-w-3xl space-y-3", children: [
21363
- /* @__PURE__ */ jsx("ul", { className: "divide-y divide-border overflow-hidden rounded-xl border border-border", children: scoped.map((c) => /* @__PURE__ */ jsx(
21497
+ /* @__PURE__ */ jsx("ul", { className: "fayz-glass-surface divide-y divide-border overflow-hidden rounded-card border bg-card text-card-foreground shadow-sm", children: scoped.map((c) => /* @__PURE__ */ jsx(
21364
21498
  ConnectorRow,
21365
21499
  {
21366
21500
  connector: c,
@@ -21420,7 +21554,7 @@ function ConnectorsHub({ hostPluginId }) {
21420
21554
  ] });
21421
21555
  }
21422
21556
  function HubSkeleton() {
21423
- return /* @__PURE__ */ jsx("div", { className: "max-w-3xl", "aria-hidden": true, children: /* @__PURE__ */ jsx("ul", { className: "divide-y divide-border overflow-hidden rounded-xl border border-border", children: [0, 1].map((i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-4 p-4", children: [
21557
+ return /* @__PURE__ */ jsx("div", { className: "max-w-3xl", "aria-hidden": true, children: /* @__PURE__ */ jsx("ul", { className: "fayz-glass-surface divide-y divide-border overflow-hidden rounded-card border bg-card text-card-foreground shadow-sm", children: [0, 1].map((i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-4 p-4", children: [
21424
21558
  /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-10 shrink-0 rounded-lg" }),
21425
21559
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-2 py-0.5", children: [
21426
21560
  /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-44" }),
@@ -21429,7 +21563,7 @@ function HubSkeleton() {
21429
21563
  /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-24 shrink-0" })
21430
21564
  ] }, i)) }) });
21431
21565
  }
21432
- function RegistryCrudView2({ registry: registry3, basePath }) {
21566
+ function RegistryCrudView2({ registry: registry3, basePath, embedded }) {
21433
21567
  const useStore = useMemo(() => {
21434
21568
  const mockData = registry3.mockData ?? registry3.seedData ?? [];
21435
21569
  const provider = registry3.dataProvider ?? resolveDataProvider(registry3.entity, mockData);
@@ -21442,7 +21576,8 @@ function RegistryCrudView2({ registry: registry3, basePath }) {
21442
21576
  useStore,
21443
21577
  basePath,
21444
21578
  display: registry3.display === "cards" ? "cards" : "table",
21445
- readOnly: registry3.readOnly
21579
+ readOnly: registry3.readOnly,
21580
+ embedded
21446
21581
  }
21447
21582
  );
21448
21583
  }
@@ -21462,7 +21597,7 @@ function PropertiesTab({ registries, routeBase, regLabel }) {
21462
21597
  return registries[0]?.id ?? "";
21463
21598
  }
21464
21599
  const [active2, setActive] = useState(getActive);
21465
- React63__default.useEffect(() => {
21600
+ React65__default.useEffect(() => {
21466
21601
  const handler = () => setActive(getActive());
21467
21602
  window.addEventListener("hashchange", handler);
21468
21603
  return () => window.removeEventListener("hashchange", handler);
@@ -21537,7 +21672,7 @@ function PluginSettingsPanel({ title, subtitle, generalSettings, registries, cus
21537
21672
  return tabs[0]?.id ?? "";
21538
21673
  }
21539
21674
  const [activeTab, setActiveTab] = useState(getActiveFromHash);
21540
- React63__default.useEffect(() => {
21675
+ React65__default.useEffect(() => {
21541
21676
  const handler = () => setActiveTab(getActiveFromHash());
21542
21677
  window.addEventListener("hashchange", handler);
21543
21678
  return () => window.removeEventListener("hashchange", handler);
@@ -21585,6 +21720,6 @@ var renderApp = (...args) => {
21585
21720
  return renderApp$1(...args);
21586
21721
  };
21587
21722
 
21588
- export { AddConnectorButton, AddConnectorPanel, AdminProviders, AdminScaffold, AdminShell, AssistantInvite, ChatConversation, ClientOrdersTab, ConnectConsentPage, ConnectorDeliveries, ConnectorDetail, ConnectorMark, ConnectorRow, ConnectorSyncActions, ConnectorsHub, ConnectorsTab, ContactPicker, CredentialSinkMissingError, CrudCardGrid, CrudDetailPage, CrudDetailSkeleton, CrudFormPage, CrudFormSkeleton, CrudListView, CrudPage, CrudRecordModal, DeleteConfirmDialog, EntitlementGate, EntityLink, LimitGate, ModuleActionBar, MultiSelectRow, NOTE_LABEL_PREFIX, OrderDetailBlock, OrderDetailRow, OrderDetailSkeleton, OrderDetailView, OrderFormAddItemStep, OrderDetailBlock as OrderFormBlock, OrderFormItemRow, OrderFormItemsCard, OrderFormSkeleton, OrderFormView, OrderListView, PermissionGate, PersonLink2 as PersonLink, PersonTimeline, PluginRegistryManager, PluginSettingsPanel, ProjectsSettings, QuickActionsButton, RecordPickerModal, RegistryCrudView2 as RegistryCrudView, RouteErrorBoundary, RouteErrorScreen, SelectRow, SettingsGroup, SeuSiteWidget, StateChip, TextRow, ToggleRow, UpgradePrompt, WidgetSlot, navigateTo as adminNavigateTo, categoryLabel, connectorRoute, createArchetypeLookup, createClientOrdersProvider, createCrudPage, createFayzApp, createFayzProject, createCrudPage as createNativeCrudPage, createPerson, createPlaceholder, createPluginContext, createViewRouter, dedup, defaultProjectOf, defineSaas, deleteFayzProject, deriveAgentContract, exportToCSV, filterConnectors, formatActivityElapsed, formatCurrency4 as formatCurrency, getDefaultFayzProject, getFayzAgentClient, getPersonLookup, getPersonPath, getTimelineSources, listFayzProjects, needsCredentialSink, openAssistant, openConnectorsPanel, openEntity, parseViewId, publishAssistantActivity, registerAdminScaffold, registerAssistantLauncher, registerEntityPath, registerNotesTasksAdapter, registerPersonLookup, registerTimelineSource, renderApp, resolveEntityAnchor, resolveEntityHref, resolveFayzAgentConnection, splitConnectorValues, submitConnection, unregisterAssistantLauncher, unregisterTimelineSource, updateFayzProject, useAdminPath, useAgentSurface, useAssistantActivity, useAssistantInviteStore, useAssistantLaunchers, useChatStore, useConnectors, useConnectorsPanelAvailable, useContextualNav, useContextualNavStore, useDelegateToAssistant, useFayzProjectsStore, useFieldRules, useHasRightRail, useModuleNavigation, useNavContribution, useNavContributionsStore, useNotesTasksBridge, usePersonTimeline, usePluginPrefs, usePublishAssistantActivity, useRegisterAssistantLauncher, useRightRailPanel, useRightRailStore, useShellRailAvailable, useTenantPluginSettings, withdrawAssistantActivity };
21723
+ export { AddConnectorButton, AddConnectorPanel, AdminProviders, AdminScaffold, AdminShell, AssistantInvite, ChatConversation, ClientOrdersTab, ConnectConsentPage, ConnectorDeliveries, ConnectorDetail, ConnectorMark, ConnectorRow, ConnectorSyncActions, ConnectorsHub, ConnectorsTab, ContactPicker, CredentialSinkMissingError, CrudCardGrid, CrudDetailPage, CrudDetailSkeleton, CrudFormPage, CrudFormSkeleton, CrudListView, CrudPage, CrudRecordModal, DeleteConfirmDialog, EntitlementGate, EntityLink, LimitGate, ModuleActionBar, MultiSelectRow, NOTE_LABEL_PREFIX, OrderDetailBlock, OrderDetailRow, OrderDetailSkeleton, OrderDetailView, OrderFormAddItemStep, OrderDetailBlock as OrderFormBlock, OrderFormItemRow, OrderFormItemsCard, OrderFormSkeleton, OrderFormView, OrderListView, PermissionGate, PersonLink2 as PersonLink, PersonTimeline, PluginRegistryManager, PluginSettingsPanel, ProjectsSettings, QuickActionsButton, RecordPickerModal, RegistryCrudView2 as RegistryCrudView, RouteErrorBoundary, RouteErrorScreen, SelectRow, SettingsGroup, SeuSiteWidget, StateChip, TextRow, ToggleRow, UpgradePrompt, WidgetSlot, navigateTo as adminNavigateTo, categoryLabel, connectorRoute, createArchetypeLookup, createClientOrdersProvider, createCrudPage, createFayzApp, createFayzProject, createCrudPage as createNativeCrudPage, createPerson, createPlaceholder, createPluginContext, createViewRouter, dedup, defaultProjectOf, defineSaas, deleteFayzProject, deriveAgentContract, exportToCSV, filterConnectors, formatActivityElapsed, formatCurrency4 as formatCurrency, getDefaultFayzProject, getFayzAgentClient, getPersonLookup, getPersonPath, getTimelineSources, listFayzProjects, needsCredentialSink, openAssistant, openConnectorsPanel, openEntity, parseViewId, publishAssistantActivity, registerAdminScaffold, registerAssistantLauncher, registerEntityPath, registerNotesTasksAdapter, registerPersonLookup, registerTimelineSource, renderApp, resolveEntityAnchor, resolveEntityHref, resolveFayzAgentConnection, splitConnectorValues, submitConnection, unregisterAssistantLauncher, unregisterTimelineSource, updateFayzProject, useAdminPath, useAgentSurface, useAssistantActivity, useAssistantInviteStore, useAssistantLaunchers, useChatStore, useConnectors, useConnectorsPanelAvailable, useContextualNav, useContextualNavStore, useDelegateToAssistant, useFayzProjectsStore, useFieldRules, useHasRightRail, useModuleNavigation, useNavContribution, useNavContributionsStore, useNotesTasksBridge, usePersonTimeline, usePluginPrefs, usePublishAssistantActivity, useRegisterAssistantLauncher, useRightRailPanel, useRightRailStore, useShellRailAvailable, useTenantPluginSettings, useWidgetSurface, withdrawAssistantActivity };
21589
21724
  //# sourceMappingURL=index.js.map
21590
21725
  //# sourceMappingURL=index.js.map