@fayz-ai/ui 0.9.0 → 0.10.1

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 (156) hide show
  1. package/README.md +2 -2
  2. package/dist/analytics/AnalyticsCard.d.ts +10 -0
  3. package/dist/analytics/AnalyticsCard.d.ts.map +1 -0
  4. package/dist/analytics/AnalyticsControls.d.ts +18 -0
  5. package/dist/analytics/AnalyticsControls.d.ts.map +1 -0
  6. package/dist/analytics/AnalyticsGrid.d.ts +16 -0
  7. package/dist/analytics/AnalyticsGrid.d.ts.map +1 -0
  8. package/dist/analytics/context.d.ts +58 -0
  9. package/dist/analytics/context.d.ts.map +1 -0
  10. package/dist/analytics/derive.d.ts +81 -0
  11. package/dist/analytics/derive.d.ts.map +1 -0
  12. package/dist/analytics/index.d.ts +13 -0
  13. package/dist/analytics/index.d.ts.map +1 -0
  14. package/dist/analytics/range.d.ts +22 -0
  15. package/dist/analytics/range.d.ts.map +1 -0
  16. package/dist/{chunk-PVIB724L.js → chunk-22EVFMS3.js} +5 -3
  17. package/dist/chunk-22EVFMS3.js.map +1 -0
  18. package/dist/{chunk-G6OKZ7WL.js → chunk-6V5MGYXH.js} +13 -9
  19. package/dist/chunk-6V5MGYXH.js.map +1 -0
  20. package/dist/{chunk-KV3MHB6N.js → chunk-H63TOSQ7.js} +196 -53
  21. package/dist/chunk-H63TOSQ7.js.map +1 -0
  22. package/dist/{chunk-OUPJDGKE.js → chunk-I6CPKAOD.js} +134 -37
  23. package/dist/chunk-I6CPKAOD.js.map +1 -0
  24. package/dist/{chunk-YRVE4FOD.js → chunk-OKZ6WQB3.js} +3 -3
  25. package/dist/chunk-OKZ6WQB3.js.map +1 -0
  26. package/dist/{chunk-S5KNM4D2.js → chunk-SEIY2F5F.js} +235 -107
  27. package/dist/chunk-SEIY2F5F.js.map +1 -0
  28. package/dist/{chunk-75EFDLST.js → chunk-VAKWUUVC.js} +157 -6
  29. package/dist/chunk-VAKWUUVC.js.map +1 -0
  30. package/dist/dashboard/OnboardingWidget.d.ts +2 -14
  31. package/dist/dashboard/OnboardingWidget.d.ts.map +1 -1
  32. package/dist/dashboard/SidebarOnboarding.d.ts +28 -0
  33. package/dist/dashboard/SidebarOnboarding.d.ts.map +1 -0
  34. package/dist/dashboard/index.d.ts +2 -0
  35. package/dist/dashboard/index.d.ts.map +1 -1
  36. package/dist/dashboard/index.js +4 -4
  37. package/dist/dashboard/types.d.ts +18 -0
  38. package/dist/dashboard/types.d.ts.map +1 -1
  39. package/dist/dashboard/useOnboardingProgress.d.ts +28 -0
  40. package/dist/dashboard/useOnboardingProgress.d.ts.map +1 -0
  41. package/dist/icons.js +1 -1
  42. package/dist/index.d.ts +5 -4
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +960 -14
  45. package/dist/index.js.map +1 -1
  46. package/dist/layout/AppShell.d.ts +14 -1
  47. package/dist/layout/AppShell.d.ts.map +1 -1
  48. package/dist/layout/ModulePage.d.ts +11 -2
  49. package/dist/layout/ModulePage.d.ts.map +1 -1
  50. package/dist/layout/Sidebar.d.ts +8 -1
  51. package/dist/layout/Sidebar.d.ts.map +1 -1
  52. package/dist/layout/index.js +4 -4
  53. package/dist/lib/cn.d.ts.map +1 -0
  54. package/dist/preset.d.ts +3 -0
  55. package/dist/preset.d.ts.map +1 -0
  56. package/dist/primitives/data-table.d.ts +19 -4
  57. package/dist/primitives/data-table.d.ts.map +1 -1
  58. package/dist/primitives/date-picker.d.ts +4 -2
  59. package/dist/primitives/date-picker.d.ts.map +1 -1
  60. package/dist/primitives/filter-chip.d.ts +26 -0
  61. package/dist/primitives/filter-chip.d.ts.map +1 -0
  62. package/dist/primitives/header-tabs.d.ts +32 -0
  63. package/dist/primitives/header-tabs.d.ts.map +1 -0
  64. package/dist/primitives/hint.d.ts +25 -0
  65. package/dist/primitives/hint.d.ts.map +1 -0
  66. package/dist/primitives/index.d.ts +7 -0
  67. package/dist/primitives/index.d.ts.map +1 -1
  68. package/dist/primitives/index.js +4 -4
  69. package/dist/primitives/list-view.d.ts +14 -1
  70. package/dist/primitives/list-view.d.ts.map +1 -1
  71. package/dist/primitives/page-header.d.ts +23 -0
  72. package/dist/primitives/page-header.d.ts.map +1 -0
  73. package/dist/primitives/stat-tiles.d.ts +30 -0
  74. package/dist/primitives/stat-tiles.d.ts.map +1 -0
  75. package/dist/primitives/switch.d.ts +11 -0
  76. package/dist/primitives/switch.d.ts.map +1 -0
  77. package/dist/stores/index.d.ts +1 -0
  78. package/dist/stores/index.d.ts.map +1 -1
  79. package/dist/stores/page-header.store.d.ts +69 -0
  80. package/dist/stores/page-header.store.d.ts.map +1 -0
  81. package/package.json +6 -15
  82. package/dist/chunk-75EFDLST.js.map +0 -1
  83. package/dist/chunk-G6OKZ7WL.js.map +0 -1
  84. package/dist/chunk-KV3MHB6N.js.map +0 -1
  85. package/dist/chunk-OUPJDGKE.js.map +0 -1
  86. package/dist/chunk-PVIB724L.js.map +0 -1
  87. package/dist/chunk-S5KNM4D2.js.map +0 -1
  88. package/dist/chunk-YRVE4FOD.js.map +0 -1
  89. package/dist/utils/cn.d.ts.map +0 -1
  90. package/src/dashboard/ChartWidget.tsx +0 -50
  91. package/src/dashboard/ChartWidgetInner.tsx +0 -83
  92. package/src/dashboard/DashboardCanvas.tsx +0 -210
  93. package/src/dashboard/DashboardCustomizeMenu.tsx +0 -53
  94. package/src/dashboard/DashboardGrid.tsx +0 -35
  95. package/src/dashboard/DashboardRange.tsx +0 -62
  96. package/src/dashboard/GoldCard.tsx +0 -38
  97. package/src/dashboard/KpiCard.tsx +0 -238
  98. package/src/dashboard/OnboardingWidget.tsx +0 -140
  99. package/src/dashboard/TableWidget.tsx +0 -51
  100. package/src/dashboard/define.ts +0 -53
  101. package/src/dashboard/icon.ts +0 -13
  102. package/src/dashboard/index.ts +0 -38
  103. package/src/dashboard/layout.ts +0 -50
  104. package/src/dashboard/preferences.ts +0 -71
  105. package/src/dashboard/types.ts +0 -41
  106. package/src/icons.ts +0 -66
  107. package/src/index.ts +0 -238
  108. package/src/layout/AppShell.tsx +0 -987
  109. package/src/layout/ContentSplit.tsx +0 -153
  110. package/src/layout/ModulePage.tsx +0 -466
  111. package/src/layout/PageTransition.tsx +0 -57
  112. package/src/layout/SaveBar.tsx +0 -247
  113. package/src/layout/Sidebar.tsx +0 -535
  114. package/src/layout/Topbar.tsx +0 -462
  115. package/src/layout/index.ts +0 -39
  116. package/src/layout/useCrossModuleBack.ts +0 -30
  117. package/src/primitives/Avatar.tsx +0 -48
  118. package/src/primitives/SearchCombobox.tsx +0 -216
  119. package/src/primitives/badge.tsx +0 -68
  120. package/src/primitives/breadcrumb.tsx +0 -43
  121. package/src/primitives/button.tsx +0 -60
  122. package/src/primitives/card.tsx +0 -79
  123. package/src/primitives/checkbox.tsx +0 -53
  124. package/src/primitives/confirm-dialog.tsx +0 -125
  125. package/src/primitives/currency-input.tsx +0 -121
  126. package/src/primitives/data-table.tsx +0 -160
  127. package/src/primitives/date-picker.tsx +0 -225
  128. package/src/primitives/dropdown.tsx +0 -196
  129. package/src/primitives/index.ts +0 -87
  130. package/src/primitives/input.tsx +0 -50
  131. package/src/primitives/list-view.tsx +0 -252
  132. package/src/primitives/markdown-editor.tsx +0 -75
  133. package/src/primitives/markdown.tsx +0 -169
  134. package/src/primitives/modal.tsx +0 -156
  135. package/src/primitives/phone-link.tsx +0 -138
  136. package/src/primitives/popover.tsx +0 -30
  137. package/src/primitives/search-select.tsx +0 -314
  138. package/src/primitives/segmented-control.tsx +0 -66
  139. package/src/primitives/select.tsx +0 -157
  140. package/src/primitives/separator.tsx +0 -29
  141. package/src/primitives/sheet.tsx +0 -181
  142. package/src/primitives/skeleton.tsx +0 -46
  143. package/src/primitives/tabs.tsx +0 -53
  144. package/src/primitives/time-picker.tsx +0 -148
  145. package/src/primitives/toast.tsx +0 -46
  146. package/src/primitives/tooltip.tsx +0 -28
  147. package/src/stores/index.ts +0 -10
  148. package/src/stores/layout.store.ts +0 -31
  149. package/src/stores/theme.store.ts +0 -457
  150. package/src/tailwind.ts +0 -43
  151. package/src/theme/index.ts +0 -94
  152. package/src/theme/preset.ts +0 -209
  153. package/src/theme/presets.ts +0 -106
  154. package/src/utils/cn.ts +0 -6
  155. /package/dist/{utils → lib}/cn.d.ts +0 -0
  156. /package/{src → dist}/styles.css +0 -0
@@ -1,8 +1,8 @@
1
- import { useCrossModuleBack, useBackHandler, Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody, SaveBarProvider, SaveBar } from './chunk-75EFDLST.js';
2
- import { cn, Button } from './chunk-YRVE4FOD.js';
3
- import { ICON_MAP } from './chunk-PVIB724L.js';
1
+ import { useHasPageHeaderHost, useCrossModuleBack, useBackHandler, usePageHeader, PageHeaderCrumb, PageHeaderOutlet, Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody, HeaderTabs, usePageHeaderSlot, useHasPageHeaderOutlet, usePageHeaderHost, SaveBarProvider, SaveBar } from './chunk-VAKWUUVC.js';
2
+ import { cn, Button } from './chunk-OKZ6WQB3.js';
3
+ import { ICON_MAP } from './chunk-22EVFMS3.js';
4
4
  import * as React3 from 'react';
5
- import { PanelLeftClose, PanelLeft, Search, Bell, Menu, Crown, ChevronRight, ChevronLeft, PanelRightOpen, PanelRightClose, PanelRight, Repeat, GraduationCap, Newspaper, Clapperboard, Zap, Star, UserCheck, Inbox, Clock3, Ban, Map, ListPlus, CalendarX, CalendarCheck2, Mic, UsersRound, Disc3, ListMusic, Eye, Music, Layers, Banknote, BadgeDollarSign, CalendarDays, Radio, PartyPopper, FileCheck2, Box, Boxes, TreePalm, UserX, UserPlus, ArrowDownRight, ArrowUpRight, Ruler, Warehouse, Wallet, Sparkles, AlertTriangle, Clock, CircleDollarSign, TrendingUp, Receipt, Landmark, TableProperties, SlidersHorizontal, Plug, ArrowLeftRight, ArrowUpCircle, ArrowDownCircle, Wheat, Egg, Apple, LeafyGreen, LayoutTemplate, Heart, PawPrint, Cat, Dog, FolderOpen, ListChecks, List, Shield, Plus, Filter, ChevronDown, Building2, Contact, Handshake, MapPin, UtensilsCrossed, Camera, Tags, Tag, Percent, BookOpenCheck, Globe, MessageCircle, BookOpen, UserCog, Briefcase, ClipboardCheck, ClipboardList, Wrench, Target, ShoppingBag, ShoppingCart, Megaphone, DollarSign, Mail, FileText, BarChart3, Activity, Package, CalendarClock, Calendar, CreditCard, Settings, Users, Home, ExternalLink, PiggyBank, LogOut } from 'lucide-react';
5
+ import { PanelLeftClose, PanelLeft, Search, Bell, Menu, Crown, Repeat, GraduationCap, Newspaper, Clapperboard, Zap, Star, UserCheck, Inbox, Clock3, Ban, Map, ListPlus, CalendarX, CalendarCheck2, Mic, UsersRound, Disc3, ListMusic, Eye, Music, Layers, Banknote, BadgeDollarSign, CalendarDays, Radio, PartyPopper, FileCheck2, Box, Boxes, TreePalm, UserX, UserPlus, ArrowDownRight, ArrowUpRight, Ruler, Warehouse, Wallet, Sparkles, AlertTriangle, Clock, CircleDollarSign, TrendingUp, Receipt, Landmark, TableProperties, SlidersHorizontal, Plug, ArrowLeftRight, ArrowUpCircle, ArrowDownCircle, Wheat, Egg, Apple, LeafyGreen, LayoutTemplate, Heart, PawPrint, Cat, Dog, FolderOpen, ListChecks, List, Shield, Plus, Filter, ChevronDown, Building2, Contact, Handshake, MapPin, UtensilsCrossed, Camera, Tags, Tag, Percent, BookOpenCheck, Globe, MessageCircle, BookOpen, UserCog, Briefcase, ClipboardCheck, ClipboardList, Wrench, Target, ShoppingBag, ShoppingCart, Megaphone, DollarSign, Mail, FileText, BarChart3, Activity, Package, CalendarClock, Calendar, CreditCard, Settings, Users, Home, ChevronRight, ChevronLeft, PanelRightOpen, PanelRightClose, PanelRight, ExternalLink, PiggyBank, LogOut } from 'lucide-react';
6
6
  import * as Tooltip from '@radix-ui/react-tooltip';
7
7
  import { create } from 'zustand';
8
8
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
@@ -34,7 +34,7 @@ function NavItem({
34
34
  const Icon = getIcon(item.icon);
35
35
  const isExternal = !!item.href;
36
36
  const className = cn(
37
- "flex w-full items-center gap-3 rounded-md px-2.5 py-1.5 text-[13px] font-medium transition-colors",
37
+ "flex w-full items-center gap-3 rounded-button px-2.5 py-1.5 text-[13px] font-medium transition-colors",
38
38
  "hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground",
39
39
  isActive ? "bg-sidebar-accent font-semibold text-sidebar-accent-foreground shadow-sm" : "text-sidebar-foreground/80",
40
40
  collapsed && "justify-center px-2"
@@ -96,7 +96,8 @@ function NavGroup({
96
96
  item,
97
97
  collapsed,
98
98
  activeRoute,
99
- onNavigate
99
+ onNavigate,
100
+ childConnector
100
101
  }) {
101
102
  const isChildActive = item.children?.some((c) => c.route === activeRoute);
102
103
  const [open, setOpen] = React3.useState(() => isChildActive ?? false);
@@ -108,7 +109,7 @@ function NavGroup({
108
109
  {
109
110
  onClick: () => onNavigate(item.route),
110
111
  className: cn(
111
- "flex w-full items-center justify-center rounded-md px-2 py-2 text-sm font-medium transition-colors",
112
+ "flex w-full items-center justify-center rounded-button px-2 py-2 text-sm font-medium transition-colors",
112
113
  "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
113
114
  isChildActive ? "bg-sidebar-accent text-sidebar-accent-foreground" : "text-sidebar-muted"
114
115
  ),
@@ -127,9 +128,9 @@ function NavGroup({
127
128
  {
128
129
  onClick: () => setOpen(!open),
129
130
  className: cn(
130
- "flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors",
131
- "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
132
- isChildActive ? "text-sidebar-accent-foreground" : "text-sidebar-muted"
131
+ "flex w-full items-center gap-3 rounded-button px-2.5 py-1.5 text-[13px] font-medium transition-colors",
132
+ "hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground",
133
+ isChildActive ? "text-sidebar-accent-foreground" : "text-sidebar-foreground/80"
133
134
  ),
134
135
  children: [
135
136
  /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 shrink-0" }),
@@ -138,21 +139,98 @@ function NavGroup({
138
139
  ]
139
140
  }
140
141
  ),
141
- open && /* @__PURE__ */ jsx("div", { className: "ml-4 mt-0.5 space-y-0.5 border-l border-sidebar-border/50 pl-3", children: item.children?.map((child) => {
142
+ open && /* @__PURE__ */ jsx("div", { className: cn(
143
+ "mt-0.5",
144
+ // Connector mode has no per-child icon and no running rule: the line
145
+ // is DRAWN, from the parent down to the active child and curving into
146
+ // it. Extra left padding reserves the column that line lives in.
147
+ //
148
+ // No row gap (space-y-*) here: the line is assembled from one segment
149
+ // per row, so any gap between rows shows up as a break in what has to
150
+ // read as a single continuous stroke. Rows carry a fixed h-8 instead,
151
+ // which is also what makes the elbow's y=16 land on their centre.
152
+ //
153
+ // The indent lives on the ROWS, not here: the connector is positioned
154
+ // from this box's left edge, so padding it would push the line right
155
+ // along with the labels and land the arrowhead on top of the text.
156
+ childConnector ? "relative" : "ml-4 space-y-0.5 border-l border-sidebar-border/50 pl-3"
157
+ ), children: item.children?.map((child, childIndex) => {
142
158
  const ChildIcon = getIcon(child.icon);
143
159
  const isActive = child.route === activeRoute;
144
160
  const childExternal = !!child.href;
145
161
  const childClass = cn(
146
- "flex w-full items-center gap-2.5 rounded-md px-2 py-1.5 text-sm transition-colors",
147
- isActive ? "font-medium text-sidebar-accent-foreground" : "text-sidebar-muted hover:text-sidebar-accent-foreground"
162
+ "flex w-full items-center rounded-button text-sm transition-colors",
163
+ // pl-11 clears the connector (whose arrowhead ends at ~24px) with
164
+ // room to spare, so the children read as one clearly indented
165
+ // column rather than crowding the line that points at them.
166
+ childConnector ? "h-8 gap-0 pl-11 pr-1" : "gap-2.5 px-2 py-1.5",
167
+ isActive ? "font-medium text-sidebar-accent-foreground" : "text-sidebar-foreground/70 hover:text-sidebar-accent-foreground"
148
168
  );
149
169
  const childInner = /* @__PURE__ */ jsxs(Fragment, { children: [
150
- /* @__PURE__ */ jsx(ChildIcon, { className: "h-3.5 w-3.5 shrink-0" }),
170
+ childConnector ? null : /* @__PURE__ */ jsx(ChildIcon, { className: "mr-2.5 h-3.5 w-3.5 shrink-0" }),
151
171
  /* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-left", children: child.label }),
152
172
  childExternal && /* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3 shrink-0 opacity-50", "aria-hidden": true }),
153
173
  child.premium && /* @__PURE__ */ jsx(Crown, { className: "h-3 w-3 shrink-0 text-amber-500", "aria-hidden": true })
154
174
  ] });
155
- return childExternal ? /* @__PURE__ */ jsx("a", { href: child.href, target: "_blank", rel: "noopener noreferrer", className: childClass, children: childInner }, child.id) : /* @__PURE__ */ jsx("button", { onClick: () => onNavigate(child.route), className: childClass, children: childInner }, child.id);
175
+ const row = childExternal ? /* @__PURE__ */ jsx("a", { href: child.href, target: "_blank", rel: "noopener noreferrer", className: childClass, children: childInner }) : /* @__PURE__ */ jsx("button", { onClick: () => onNavigate(child.route), className: childClass, children: childInner });
176
+ if (!childConnector) return /* @__PURE__ */ jsx(React3.Fragment, { children: row }, child.id);
177
+ const activeIndex = item.children.findIndex((c) => c.route === activeRoute);
178
+ const onPath = activeIndex >= 0 && childIndex < activeIndex;
179
+ return (
180
+ // The connector's colour is set HERE, on the wrapper, and BOTH
181
+ // halves inherit it: the straight segments and the elbow are one
182
+ // line, so a different opacity on either makes the stroke change
183
+ // shade halfway down. Weight matches too — the span is 1.5px wide
184
+ // and the path is stroke-width 1.5 on the same 13.75px centre.
185
+ //
186
+ // Set on the wrapper rather than inherited from the row: rows dim
187
+ // to /70 when inactive, and a line fading along with the label it
188
+ // points AT was nearly invisible on a dark rail.
189
+ /* @__PURE__ */ jsxs("div", { className: "relative h-8 text-sidebar-foreground/45", children: [
190
+ onPath && /* @__PURE__ */ jsx(
191
+ "span",
192
+ {
193
+ "aria-hidden": true,
194
+ className: "pointer-events-none absolute bottom-0 left-[13px] top-0 w-[1.5px] bg-current"
195
+ }
196
+ ),
197
+ isActive && /* @__PURE__ */ jsxs(
198
+ "svg",
199
+ {
200
+ "aria-hidden": true,
201
+ className: "pointer-events-none absolute left-1 top-0",
202
+ width: "21",
203
+ height: "32",
204
+ viewBox: "0 0 21 32",
205
+ fill: "none",
206
+ children: [
207
+ /* @__PURE__ */ jsx(
208
+ "path",
209
+ {
210
+ d: "M9.75 0 V11 Q9.75 16 14.75 16 H20",
211
+ stroke: "currentColor",
212
+ strokeWidth: "1.5",
213
+ strokeLinecap: "round",
214
+ fill: "none"
215
+ }
216
+ ),
217
+ /* @__PURE__ */ jsx(
218
+ "path",
219
+ {
220
+ d: "M17 13 L20 16 L17 19",
221
+ stroke: "currentColor",
222
+ strokeWidth: "1.5",
223
+ strokeLinecap: "round",
224
+ strokeLinejoin: "round",
225
+ fill: "none"
226
+ }
227
+ )
228
+ ]
229
+ }
230
+ ),
231
+ row
232
+ ] }, child.id)
233
+ );
156
234
  }) })
157
235
  ] });
158
236
  }
@@ -173,7 +251,8 @@ function Sidebar({
173
251
  unreadCount = 0,
174
252
  sectionLabels,
175
253
  navKey,
176
- navDirection = "forward"
254
+ navDirection = "forward",
255
+ navChildConnector
177
256
  }) {
178
257
  const currentPath = currentPathProp;
179
258
  const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
@@ -185,7 +264,7 @@ function Sidebar({
185
264
  onNavigate?.(route);
186
265
  };
187
266
  const sectionHeading = (label) => label && !collapsed ? /* @__PURE__ */ jsx("p", { className: "px-2.5 pb-1 pt-1 text-[10px] font-semibold uppercase tracking-wider text-sidebar-muted", children: label }) : null;
188
- const renderItem = (item) => item.children && item.children.length > 0 ? /* @__PURE__ */ jsx(NavGroup, { item, collapsed, activeRoute, onNavigate: handleNavigate }, item.id) : /* @__PURE__ */ jsx(
267
+ const renderItem = (item) => item.children && item.children.length > 0 ? /* @__PURE__ */ jsx(NavGroup, { item, collapsed, activeRoute, onNavigate: handleNavigate, childConnector: navChildConnector }, item.id) : /* @__PURE__ */ jsx(
189
268
  NavItem,
190
269
  {
191
270
  item,
@@ -250,7 +329,7 @@ function Sidebar({
250
329
  "button",
251
330
  {
252
331
  onClick: onToggle,
253
- className: "ml-auto rounded-md p-1.5 text-sidebar-muted transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
332
+ className: "ml-auto rounded-button p-1.5 text-sidebar-muted transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
254
333
  "aria-label": "Collapse sidebar",
255
334
  children: /* @__PURE__ */ jsx(PanelLeftClose, { className: "h-4 w-4" })
256
335
  }
@@ -260,7 +339,7 @@ function Sidebar({
260
339
  "button",
261
340
  {
262
341
  onClick: onToggle,
263
- className: "rounded-md p-1.5 text-sidebar-muted transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
342
+ className: "rounded-button p-1.5 text-sidebar-muted transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
264
343
  "aria-label": "Expand sidebar",
265
344
  children: /* @__PURE__ */ jsx(PanelLeft, { className: "h-4 w-4" })
266
345
  }
@@ -313,10 +392,13 @@ function Sidebar({
313
392
  },
314
393
  item.id
315
394
  )) }),
316
- footerContent && /* @__PURE__ */ jsx("div", { className: cn("p-2", !borderless && "border-t border-sidebar-border"), children: /* @__PURE__ */ jsx("div", { className: "space-y-2", children: footerContent }) }),
395
+ footerContent && // `empty:hidden` slot children may all render null (e.g. the
396
+ // SeuSiteWidget self-hides when the tenant has no project); without
397
+ // it the padded/bordered wrapper shows as a blank block.
398
+ /* @__PURE__ */ jsx("div", { className: cn("space-y-2 p-2 empty:hidden", !borderless && "border-t border-sidebar-border"), children: footerContent }),
317
399
  orgSwitcher && React3.isValidElement(orgSwitcher) ? React3.cloneElement(orgSwitcher, { collapsed }) : orgSwitcher,
318
400
  /* @__PURE__ */ jsx("div", { className: cn("p-2", !borderless && "border-t border-sidebar-border"), children: /* @__PURE__ */ jsxs("div", { className: cn(
319
- "flex items-center rounded-md",
401
+ "flex items-center rounded-button",
320
402
  collapsed ? "flex-col gap-1" : "gap-1 px-1"
321
403
  ), children: [
322
404
  userMenuSlot,
@@ -325,7 +407,7 @@ function Sidebar({
325
407
  "button",
326
408
  {
327
409
  onClick: () => setCommandPaletteOpen(true),
328
- className: "inline-flex shrink-0 items-center justify-center rounded-md p-2 text-sidebar-muted transition-colors hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
410
+ className: "inline-flex shrink-0 items-center justify-center rounded-button p-2 text-sidebar-muted transition-colors hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
329
411
  "aria-label": "Search",
330
412
  children: /* @__PURE__ */ jsx(Search, { className: "h-4 w-4" })
331
413
  }
@@ -333,7 +415,7 @@ function Sidebar({
333
415
  notificationSlot ?? /* @__PURE__ */ jsxs(
334
416
  "button",
335
417
  {
336
- className: "relative inline-flex shrink-0 items-center justify-center rounded-md p-2 text-sidebar-muted transition-colors hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
418
+ className: "relative inline-flex shrink-0 items-center justify-center rounded-button p-2 text-sidebar-muted transition-colors hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
337
419
  "aria-label": unreadCount > 0 ? `${unreadCount} unread notifications` : "Notifications",
338
420
  children: [
339
421
  /* @__PURE__ */ jsx(Bell, { className: "h-4 w-4" }),
@@ -718,6 +800,13 @@ var ModuleHeaderActionsSlotContext = React3.createContext(null);
718
800
  function useModuleHeaderActionsSlot() {
719
801
  return React3.useContext(ModuleHeaderActionsSlotContext);
720
802
  }
803
+ function ShellPageTitle({
804
+ title,
805
+ back
806
+ }) {
807
+ if (!title && !back) return null;
808
+ return /* @__PURE__ */ jsx(PageHeaderCrumb, { title, parentLabel: back?.label, onBack: back?.onBack });
809
+ }
721
810
  function SidebarLayout({
722
811
  navigation = [],
723
812
  logo,
@@ -735,6 +824,7 @@ function SidebarLayout({
735
824
  frame,
736
825
  currentPath,
737
826
  pageTitle,
827
+ pageBack,
738
828
  topbarStart,
739
829
  topbarEnd,
740
830
  userMenuSlot,
@@ -744,9 +834,12 @@ function SidebarLayout({
744
834
  mobileHeader = "minimal",
745
835
  sidebarSectionLabels,
746
836
  sidebarNavKey,
747
- sidebarNavDirection
837
+ sidebarNavDirection,
838
+ sidebarNavChildConnector
748
839
  }) {
749
840
  const sidebarCollapsed = useLayoutStore((s) => s.sidebarCollapsed);
841
+ const pageHeaderSlot = usePageHeaderSlot();
842
+ usePageHeaderHost();
750
843
  const setSidebarCollapsed = useLayoutStore((s) => s.setSidebarCollapsed);
751
844
  const [mobileMenuOpen, setMobileMenuOpen] = React3.useState(false);
752
845
  const [headerSlot, setHeaderSlot] = React3.useState(null);
@@ -781,7 +874,8 @@ function SidebarLayout({
781
874
  unreadCount,
782
875
  sectionLabels: sidebarSectionLabels,
783
876
  navKey: sidebarNavKey,
784
- navDirection: sidebarNavDirection
877
+ navDirection: sidebarNavDirection,
878
+ navChildConnector: sidebarNavChildConnector
785
879
  }
786
880
  ) }),
787
881
  /* @__PURE__ */ jsxs("div", { className: cn(
@@ -802,7 +896,7 @@ function SidebarLayout({
802
896
  children: /* @__PURE__ */ jsx(Menu, { className: "h-5 w-5" })
803
897
  }
804
898
  ),
805
- pageTitle && /* @__PURE__ */ jsx("h2", { className: "font-semibold text-lg", children: pageTitle }),
899
+ pageHeaderSlot ?? /* @__PURE__ */ jsx(ShellPageTitle, { title: pageTitle, back: pageBack }),
806
900
  topbarStart,
807
901
  /* @__PURE__ */ jsx("div", { ref: setHeaderSlot, className: "flex min-w-0 flex-1 items-center" })
808
902
  ] }),
@@ -855,10 +949,17 @@ function TopbarLayout({
855
949
  currentPath,
856
950
  topbarStart,
857
951
  topbarEnd,
952
+ pageTitle,
953
+ pageBack,
858
954
  notificationSlot,
859
955
  hasBottomNav = false
860
956
  }) {
861
957
  const [mobileMenuOpen, setMobileMenuOpen] = React3.useState(false);
958
+ const rawSlot = usePageHeaderSlot();
959
+ const hasOutlet = useHasPageHeaderOutlet();
960
+ usePageHeaderHost();
961
+ const pageHeaderSlot = hasOutlet ? null : rawSlot;
962
+ const showTitle = !hasOutlet && !!pageTitle;
862
963
  return /* @__PURE__ */ jsx(SaveBarProvider, { children: /* @__PURE__ */ jsxs("div", { className: "relative flex h-screen flex-col overflow-hidden bg-background", children: [
863
964
  /* @__PURE__ */ jsx(
864
965
  Topbar,
@@ -884,7 +985,10 @@ function TopbarLayout({
884
985
  onMenuClick: hasBottomNav ? void 0 : () => setMobileMenuOpen(true)
885
986
  }
886
987
  ),
887
- /* @__PURE__ */ jsx("main", { className: cn("flex min-w-0 min-h-0 flex-1 flex-col overflow-hidden", frame && "md:bg-sidebar md:p-2"), children: /* @__PURE__ */ jsx("div", { className: cn("flex min-w-0 min-h-0 flex-1 flex-col overflow-hidden", frame && "md:rounded-xl md:border md:border-border md:bg-card"), children: /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto pb-16 md:pb-0", children }) }) }),
988
+ /* @__PURE__ */ jsx("main", { className: cn("flex min-w-0 min-h-0 flex-1 flex-col overflow-hidden", frame && "md:bg-sidebar md:p-2"), children: /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 min-h-0 flex-1 flex-col overflow-hidden", frame && "md:rounded-xl md:border md:border-border md:bg-card"), children: [
989
+ (pageHeaderSlot || pageBack || showTitle) && /* @__PURE__ */ jsx("div", { className: "flex min-h-12 shrink-0 items-center gap-3 border-b border-border px-4 py-2", children: pageHeaderSlot ?? /* @__PURE__ */ jsx(ShellPageTitle, { title: showTitle ? pageTitle : void 0, back: pageBack }) }),
990
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto pb-16 md:pb-0", children })
991
+ ] }) }),
888
992
  /* @__PURE__ */ jsx(SaveBar, {}),
889
993
  mobileMenuOpen && /* @__PURE__ */ jsx(
890
994
  MobileOverlay,
@@ -1076,6 +1180,7 @@ function AppShell({
1076
1180
  userPlan,
1077
1181
  billingLabel,
1078
1182
  pageTitle,
1183
+ pageBack,
1079
1184
  currentPath,
1080
1185
  userMenuExtras,
1081
1186
  orgSwitcher,
@@ -1092,6 +1197,7 @@ function AppShell({
1092
1197
  sidebarSectionLabels,
1093
1198
  sidebarNavKey,
1094
1199
  sidebarNavDirection,
1200
+ sidebarNavChildConnector,
1095
1201
  rightRail,
1096
1202
  rightRailOpen = true,
1097
1203
  defaultRightRailWidth,
@@ -1132,6 +1238,7 @@ function AppShell({
1132
1238
  frame: contentFrame,
1133
1239
  currentPath,
1134
1240
  pageTitle,
1241
+ pageBack,
1135
1242
  topbarStart,
1136
1243
  topbarEnd,
1137
1244
  userMenuSlot,
@@ -1142,6 +1249,7 @@ function AppShell({
1142
1249
  sidebarSectionLabels,
1143
1250
  sidebarNavKey,
1144
1251
  sidebarNavDirection,
1252
+ sidebarNavChildConnector,
1145
1253
  children
1146
1254
  }
1147
1255
  );
@@ -1166,6 +1274,8 @@ function AppShell({
1166
1274
  currentPath,
1167
1275
  topbarStart,
1168
1276
  topbarEnd,
1277
+ pageTitle,
1278
+ pageBack,
1169
1279
  notificationSlot,
1170
1280
  hasBottomNav,
1171
1281
  children
@@ -1479,9 +1589,23 @@ function useBackStyle() {
1479
1589
  function SubpageHeader({ title, subtitle, icon, onBack, parentLabel, actions, backStyle }) {
1480
1590
  const t = useTranslation();
1481
1591
  const appStyle = useBackStyle();
1592
+ const hasShellBar = useHasPageHeaderHost();
1482
1593
  const { onBack: effectiveOnBack, parentLabel: effectiveParentLabel } = useCrossModuleBack(onBack, parentLabel);
1483
1594
  useBackHandler(effectiveOnBack);
1484
1595
  const Icon = icon ? ICON_MAP2[icon] ?? null : null;
1596
+ if (hasShellBar) {
1597
+ return /* @__PURE__ */ jsx(
1598
+ ShellSubpageHeader,
1599
+ {
1600
+ title,
1601
+ subtitle,
1602
+ icon: Icon,
1603
+ onBack: effectiveOnBack,
1604
+ parentLabel: effectiveParentLabel,
1605
+ actions
1606
+ }
1607
+ );
1608
+ }
1485
1609
  const style = !effectiveOnBack ? "icon" : backStyle ?? appStyle;
1486
1610
  const effectiveStyle = style !== "icon" && !effectiveParentLabel ? "icon" : style;
1487
1611
  const titleBlock = /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
@@ -1533,41 +1657,59 @@ function SubpageHeader({ title, subtitle, icon, onBack, parentLabel, actions, ba
1533
1657
  }
1534
1658
  return /* @__PURE__ */ jsx("div", { className: "space-y-4 mb-6", children: titleBlock });
1535
1659
  }
1660
+ function ShellSubpageHeader({
1661
+ title,
1662
+ subtitle,
1663
+ icon: Icon,
1664
+ onBack,
1665
+ parentLabel,
1666
+ actions
1667
+ }) {
1668
+ usePageHeader(
1669
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
1670
+ Icon && !onBack && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
1671
+ /* @__PURE__ */ jsx(PageHeaderCrumb, { title, parentLabel, onBack })
1672
+ ] })
1673
+ );
1674
+ if (!subtitle && !actions) return null;
1675
+ return /* @__PURE__ */ jsxs("div", { className: "mb-5 flex flex-wrap items-start justify-between gap-3", children: [
1676
+ subtitle ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: subtitle }) : /* @__PURE__ */ jsx("span", {}),
1677
+ actions && /* @__PURE__ */ jsx("div", { className: "no-print flex shrink-0 items-center gap-2", children: actions })
1678
+ ] });
1679
+ }
1536
1680
  function ModuleHeader({ nav }) {
1537
- const slot = useModuleHeaderSlot();
1538
1681
  function defaultChild(item) {
1539
1682
  const kids = item.children ?? [];
1540
1683
  return kids.find((c) => /list/i.test(c.id) || /^list$/i.test(c.label)) ?? kids[kids.length - 1];
1541
1684
  }
1542
- const content = /* @__PURE__ */ jsx("div", { className: "flex w-full min-w-0 items-center gap-4", children: /* @__PURE__ */ jsx("div", { className: "flex min-w-0 items-center gap-0.5 overflow-x-auto scrollbar-none", children: nav.map((item) => {
1543
- const Icon = item.icon ? ICON_MAP2[item.icon] ?? null : null;
1685
+ const activeItem = nav.find((item) => item.active || item.children?.some((c) => c.active));
1686
+ const tabs = nav.map((item) => ({
1687
+ value: item.id,
1688
+ label: item.label,
1689
+ icon: item.icon ? ICON_MAP2[item.icon] ?? void 0 : void 0,
1690
+ // Plan-gated views keep their upgrade marker — dropping it would hide the
1691
+ // only signal that the tab costs an upgrade.
1692
+ badge: item.premium ? /* @__PURE__ */ jsx(PremiumBadge, {}) : void 0
1693
+ }));
1694
+ const onChange = (id) => {
1695
+ const item = nav.find((n) => n.id === id);
1696
+ if (!item) return;
1544
1697
  const hasChildren = item.children && item.children.length > 0;
1545
- const isActive = item.active || item.children?.some((c) => c.active);
1546
- return /* @__PURE__ */ jsxs(
1547
- "button",
1548
- {
1549
- type: "button",
1550
- onClick: () => hasChildren ? defaultChild(item)?.onClick?.() : item.onClick?.(),
1551
- className: cn(
1552
- "flex shrink-0 items-center gap-1.5 whitespace-nowrap border-b-2 px-2.5 py-1.5 text-sm font-medium transition-colors",
1553
- isActive ? "border-primary text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
1554
- ),
1555
- children: [
1556
- Icon && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
1557
- item.label,
1558
- item.premium && /* @__PURE__ */ jsx(PremiumBadge, {})
1559
- ]
1560
- },
1561
- item.id
1562
- );
1563
- }) }) });
1564
- if (slot) return createPortal(content, slot);
1565
- return /* @__PURE__ */ jsx("div", { className: "mb-5 border-b border-border pb-2", children: content });
1698
+ if (hasChildren) defaultChild(item)?.onClick?.();
1699
+ else item.onClick?.();
1700
+ };
1701
+ return /* @__PURE__ */ jsx("div", { className: "mb-6 flex flex-wrap items-center justify-between gap-3", children: /* @__PURE__ */ jsx(HeaderTabs, { tabs, value: activeItem?.id ?? nav[0]?.id ?? "", onChange }) });
1566
1702
  }
1567
1703
  function ModulePage({ title, subtitle, nav, children, className, headerAction, showHeader = true, sidebarFooter, navVariant, viewKey, direction }) {
1568
1704
  const ctxVariant = useModuleLayout();
1569
1705
  const variant = navVariant ?? ctxVariant;
1570
1706
  const transitionKey = viewKey ?? "view";
1707
+ if (variant === "sidebar") {
1708
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1709
+ showHeader && headerAction && /* @__PURE__ */ jsx(PageHeaderActions, { children: headerAction }),
1710
+ /* @__PURE__ */ jsx(PageTransition, { transitionKey, direction, className: cn("min-w-0", className), children })
1711
+ ] });
1712
+ }
1571
1713
  if (variant === "tabs") {
1572
1714
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1573
1715
  /* @__PURE__ */ jsx(ModuleHeader, { nav }),
@@ -1584,6 +1726,7 @@ function ModulePage({ title, subtitle, nav, children, className, headerAction, s
1584
1726
  sidebarFooter && /* @__PURE__ */ jsx("div", { className: "mt-auto", children: sidebarFooter })
1585
1727
  ] }) }),
1586
1728
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1729
+ /* @__PURE__ */ jsx(PageHeaderOutlet, {}),
1587
1730
  showHeader && /* @__PURE__ */ jsxs("div", { className: "mb-6 flex items-start justify-between gap-3", children: [
1588
1731
  /* @__PURE__ */ jsxs("div", { children: [
1589
1732
  /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold", children: title }),
@@ -1683,5 +1826,5 @@ function ContentSplitTrigger({ label, iconOnly, className }) {
1683
1826
  }
1684
1827
 
1685
1828
  export { AppShell, BackStyleProvider, ContentSplit, ContentSplitTrigger, ModuleLayoutProvider, ModulePage, NavTransitionProvider, PageHeaderActions, PageTransition, Sidebar, SubpageHeader, Topbar, useBackStyle, useLayoutStore, useModuleHeaderActionsSlot, useModuleHeaderSlot, useModuleLayout, useNavTransition };
1686
- //# sourceMappingURL=chunk-KV3MHB6N.js.map
1687
- //# sourceMappingURL=chunk-KV3MHB6N.js.map
1829
+ //# sourceMappingURL=chunk-H63TOSQ7.js.map
1830
+ //# sourceMappingURL=chunk-H63TOSQ7.js.map