@lindaui/blocks 0.4.2 → 0.5.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 (255) hide show
  1. package/README.md +67 -0
  2. package/dist/ai-cost-card-f403ypsg.js +99 -0
  3. package/dist/ai-performance-card-cggm09nc.js +191 -0
  4. package/dist/analytics/ai-cost-card.d.ts +3 -0
  5. package/dist/analytics/ai-cost-card.d.ts.map +1 -0
  6. package/dist/analytics/ai-performance-card.d.ts +3 -0
  7. package/dist/analytics/ai-performance-card.d.ts.map +1 -0
  8. package/dist/analytics/analytics-card.d.ts +3 -0
  9. package/dist/analytics/analytics-card.d.ts.map +1 -0
  10. package/dist/analytics/analytics-skeleton.d.ts +5 -0
  11. package/dist/analytics/analytics-skeleton.d.ts.map +1 -0
  12. package/dist/analytics/entity-health-card.d.ts +3 -0
  13. package/dist/analytics/entity-health-card.d.ts.map +1 -0
  14. package/dist/analytics/status-distribution-chart.d.ts +3 -0
  15. package/dist/analytics/status-distribution-chart.d.ts.map +1 -0
  16. package/dist/analytics/time-range-picker.d.ts +3 -0
  17. package/dist/analytics/time-range-picker.d.ts.map +1 -0
  18. package/dist/analytics/top-entities-table.d.ts +3 -0
  19. package/dist/analytics/top-entities-table.d.ts.map +1 -0
  20. package/dist/analytics/types.d.ts +104 -0
  21. package/dist/analytics/types.d.ts.map +1 -0
  22. package/dist/analytics-card-bcmijpt6.js +38 -0
  23. package/dist/analytics-skeleton-imve37du.js +164 -0
  24. package/dist/analytics.d.ts +11 -0
  25. package/dist/analytics.d.ts.map +1 -0
  26. package/dist/analytics.js +8 -0
  27. package/dist/app-shell/drawer-focus.d.ts +8 -0
  28. package/dist/app-shell/drawer-focus.d.ts.map +1 -0
  29. package/dist/app-shell/footer.d.ts +39 -0
  30. package/dist/app-shell/footer.d.ts.map +1 -0
  31. package/dist/app-shell/logout-dialog.d.ts +6 -0
  32. package/dist/app-shell/logout-dialog.d.ts.map +1 -0
  33. package/dist/app-shell/navigation.d.ts +15 -0
  34. package/dist/app-shell/navigation.d.ts.map +1 -0
  35. package/dist/app-shell/types.d.ts +55 -0
  36. package/dist/app-shell/types.d.ts.map +1 -0
  37. package/dist/app-shell.d.ts +7 -0
  38. package/dist/app-shell.d.ts.map +1 -0
  39. package/dist/app-shell.js +254 -0
  40. package/dist/channel-settings.d.ts +24 -0
  41. package/dist/channel-settings.d.ts.map +1 -0
  42. package/dist/channel-settings.js +60 -0
  43. package/dist/chat-avatar-jdmeyf2o.js +30 -0
  44. package/dist/chat-layout-fwx3x26g.js +25 -0
  45. package/dist/chat.d.ts +22 -0
  46. package/dist/chat.d.ts.map +1 -0
  47. package/dist/chat.js +66 -0
  48. package/dist/command-palette.d.ts +22 -0
  49. package/dist/command-palette.d.ts.map +1 -0
  50. package/dist/command-palette.js +141 -0
  51. package/dist/compat-chat/chat-avatar.d.ts +16 -0
  52. package/dist/compat-chat/chat-avatar.d.ts.map +1 -0
  53. package/dist/compat-chat/chat-header.d.ts +9 -0
  54. package/dist/compat-chat/chat-header.d.ts.map +1 -0
  55. package/dist/compat-chat/chat-layout.d.ts +10 -0
  56. package/dist/compat-chat/chat-layout.d.ts.map +1 -0
  57. package/dist/compat-chat/conversation-list-item.d.ts +10 -0
  58. package/dist/compat-chat/conversation-list-item.d.ts.map +1 -0
  59. package/dist/compat-chat/conversation-list.d.ts +24 -0
  60. package/dist/compat-chat/conversation-list.d.ts.map +1 -0
  61. package/dist/compat-chat/conversation-thread.d.ts +18 -0
  62. package/dist/compat-chat/conversation-thread.d.ts.map +1 -0
  63. package/dist/compat-chat/date-divider.d.ts +5 -0
  64. package/dist/compat-chat/date-divider.d.ts.map +1 -0
  65. package/dist/compat-chat/empty-chat-view.d.ts +6 -0
  66. package/dist/compat-chat/empty-chat-view.d.ts.map +1 -0
  67. package/dist/compat-chat/image-lightbox.d.ts +7 -0
  68. package/dist/compat-chat/image-lightbox.d.ts.map +1 -0
  69. package/dist/compat-chat/message-bubble.d.ts +6 -0
  70. package/dist/compat-chat/message-bubble.d.ts.map +1 -0
  71. package/dist/compat-chat/message-composer.d.ts +11 -0
  72. package/dist/compat-chat/message-composer.d.ts.map +1 -0
  73. package/dist/compat-chat/time-divider.d.ts +5 -0
  74. package/dist/compat-chat/time-divider.d.ts.map +1 -0
  75. package/dist/compat-chat/time-grouping.d.ts +5 -0
  76. package/dist/compat-chat/time-grouping.d.ts.map +1 -0
  77. package/dist/compat-chat/types.d.ts +35 -0
  78. package/dist/compat-chat/types.d.ts.map +1 -0
  79. package/dist/compat-chat/whatsapp-audio-player.d.ts +7 -0
  80. package/dist/compat-chat/whatsapp-audio-player.d.ts.map +1 -0
  81. package/dist/compat.d.ts +9 -0
  82. package/dist/compat.d.ts.map +1 -0
  83. package/dist/compat.js +4 -0
  84. package/dist/connected-panel-lhwy25yk.js +132 -0
  85. package/dist/connection-panel/connected-panel.d.ts +26 -0
  86. package/dist/connection-panel/connected-panel.d.ts.map +1 -0
  87. package/dist/connection-panel/disconnected-panel.d.ts +12 -0
  88. package/dist/connection-panel/disconnected-panel.d.ts.map +1 -0
  89. package/dist/connection-panel/instructions.d.ts +5 -0
  90. package/dist/connection-panel/instructions.d.ts.map +1 -0
  91. package/dist/connection-panel/qr-panel.d.ts +14 -0
  92. package/dist/connection-panel/qr-panel.d.ts.map +1 -0
  93. package/dist/connection-panel/use-qr-refresh.d.ts +18 -0
  94. package/dist/connection-panel/use-qr-refresh.d.ts.map +1 -0
  95. package/dist/connection-panel.d.ts +39 -0
  96. package/dist/connection-panel.d.ts.map +1 -0
  97. package/dist/connection-panel.js +328 -0
  98. package/dist/conversation-list-ekq2dzca.js +133 -0
  99. package/dist/conversation-list-item-fy6t5af2.js +55 -0
  100. package/dist/conversation-thread-c60431oa.js +205 -0
  101. package/dist/entity-card.d.ts +17 -0
  102. package/dist/entity-card.d.ts.map +1 -0
  103. package/dist/entity-card.js +69 -0
  104. package/dist/entity-health-card-ggnmrtrq.js +192 -0
  105. package/dist/entity-switcher.d.ts +33 -0
  106. package/dist/entity-switcher.d.ts.map +1 -0
  107. package/dist/entity-switcher.js +137 -0
  108. package/dist/filter-bar.d.ts +41 -0
  109. package/dist/filter-bar.d.ts.map +1 -0
  110. package/dist/filter-bar.js +155 -0
  111. package/dist/footer-f7r5e42b.js +192 -0
  112. package/dist/image-lightbox-ci3arb6z.js +62 -0
  113. package/dist/kanban/drop-utils.d.ts +18 -0
  114. package/dist/kanban/drop-utils.d.ts.map +1 -0
  115. package/dist/kanban/navigation-buttons.d.ts +9 -0
  116. package/dist/kanban/navigation-buttons.d.ts.map +1 -0
  117. package/dist/kanban/scroll-indicators.d.ts +6 -0
  118. package/dist/kanban/scroll-indicators.d.ts.map +1 -0
  119. package/dist/kanban/use-keyboard-navigation.d.ts +4 -0
  120. package/dist/kanban/use-keyboard-navigation.d.ts.map +1 -0
  121. package/dist/kanban-board.d.ts +31 -0
  122. package/dist/kanban-board.d.ts.map +1 -0
  123. package/dist/kanban-board.js +128 -0
  124. package/dist/kanban-column.d.ts +13 -0
  125. package/dist/kanban-column.d.ts.map +1 -0
  126. package/dist/kanban-column.js +58 -0
  127. package/dist/legacy-kpi-card.d.ts +16 -0
  128. package/dist/legacy-kpi-card.d.ts.map +1 -0
  129. package/dist/legacy-kpi-card.js +4 -0
  130. package/dist/logout-dialog-bbv59tbi.js +93 -0
  131. package/dist/message-bubble-odjvhroq.js +110 -0
  132. package/dist/message-composer-m2n6soo7.js +59 -0
  133. package/dist/navigation-buttons-e77mshh0.js +65 -0
  134. package/dist/navigation-hotcrqoq.js +115 -0
  135. package/dist/save-bar.d.ts +15 -0
  136. package/dist/save-bar.d.ts.map +1 -0
  137. package/dist/save-bar.js +38 -0
  138. package/dist/scroll-indicators-gvxapogd.js +39 -0
  139. package/dist/settings-layout.d.ts +20 -0
  140. package/dist/settings-layout.d.ts.map +1 -0
  141. package/dist/settings-layout.js +56 -0
  142. package/dist/source-selector.d.ts +18 -0
  143. package/dist/source-selector.d.ts.map +1 -0
  144. package/dist/source-selector.js +59 -0
  145. package/dist/status-distribution-chart-oucedzv7.js +87 -0
  146. package/dist/status-filters.d.ts +12 -0
  147. package/dist/status-filters.d.ts.map +1 -0
  148. package/dist/status-filters.js +31 -0
  149. package/dist/stepper.d.ts +15 -0
  150. package/dist/stepper.d.ts.map +1 -0
  151. package/dist/stepper.js +42 -0
  152. package/dist/time-range-picker-mu38hul4.js +123 -0
  153. package/dist/top-entities-table-o7xzpq96.js +78 -0
  154. package/dist/use-keyboard-navigation-he1xmriz.js +52 -0
  155. package/dist/whatsapp-audio-player-nooty6jb.js +277 -0
  156. package/llms.txt +98 -4
  157. package/package.json +191 -46
  158. package/src/analytics/ai-cost-card.tsx +31 -0
  159. package/src/analytics/ai-performance-card.tsx +48 -0
  160. package/src/analytics/analytics-card.tsx +14 -0
  161. package/src/analytics/analytics-skeleton.tsx +15 -0
  162. package/src/analytics/entity-health-card.tsx +50 -0
  163. package/src/analytics/status-distribution-chart.tsx +20 -0
  164. package/src/analytics/time-range-picker.tsx +43 -0
  165. package/src/analytics/top-entities-table.tsx +24 -0
  166. package/src/analytics/types.ts +43 -0
  167. package/src/analytics.ts +10 -0
  168. package/src/app-shell/drawer-focus.ts +42 -0
  169. package/src/app-shell/footer.tsx +160 -0
  170. package/src/app-shell/logout-dialog.tsx +68 -0
  171. package/src/app-shell/navigation.tsx +147 -0
  172. package/src/app-shell/types.ts +57 -0
  173. package/src/app-shell.tsx +166 -0
  174. package/src/area-chart.tsx +85 -0
  175. package/src/audio-player.tsx +74 -0
  176. package/src/auth-layout.tsx +132 -0
  177. package/src/auth-provider.tsx +29 -0
  178. package/src/bar-chart.tsx +78 -0
  179. package/src/channel-settings.tsx +76 -0
  180. package/src/chart-card.tsx +45 -0
  181. package/src/chat-avatar.tsx +57 -0
  182. package/src/chat-date-divider.tsx +18 -0
  183. package/src/chat-header.tsx +24 -0
  184. package/src/chat-layout.tsx +41 -0
  185. package/src/chat-time-divider.tsx +20 -0
  186. package/src/chat-types.ts +32 -0
  187. package/src/chat.ts +21 -0
  188. package/src/command-palette.tsx +110 -0
  189. package/src/compat-chat/chat-avatar.tsx +23 -0
  190. package/src/compat-chat/chat-header.tsx +12 -0
  191. package/src/compat-chat/chat-layout.tsx +14 -0
  192. package/src/compat-chat/conversation-list-item.tsx +27 -0
  193. package/src/compat-chat/conversation-list.tsx +49 -0
  194. package/src/compat-chat/conversation-thread.tsx +92 -0
  195. package/src/compat-chat/date-divider.tsx +7 -0
  196. package/src/compat-chat/empty-chat-view.tsx +9 -0
  197. package/src/compat-chat/image-lightbox.tsx +22 -0
  198. package/src/compat-chat/message-bubble.tsx +28 -0
  199. package/src/compat-chat/message-composer.tsx +26 -0
  200. package/src/compat-chat/time-divider.tsx +5 -0
  201. package/src/compat-chat/time-grouping.ts +19 -0
  202. package/src/compat-chat/types.ts +31 -0
  203. package/src/compat-chat/whatsapp-audio-player.tsx +100 -0
  204. package/src/compat.ts +8 -0
  205. package/src/confirm-dialog.tsx +85 -0
  206. package/src/connection-panel/connected-panel.tsx +106 -0
  207. package/src/connection-panel/disconnected-panel.tsx +48 -0
  208. package/src/connection-panel/instructions.tsx +9 -0
  209. package/src/connection-panel/qr-panel.tsx +62 -0
  210. package/src/connection-panel/use-qr-refresh.ts +52 -0
  211. package/src/connection-panel.tsx +141 -0
  212. package/src/conversation-list-item.tsx +53 -0
  213. package/src/conversation-list.tsx +67 -0
  214. package/src/conversation-thread.tsx +64 -0
  215. package/src/detail-panel.tsx +123 -0
  216. package/src/document-panel.tsx +109 -0
  217. package/src/document-reader.tsx +29 -0
  218. package/src/empty-chat-view.tsx +25 -0
  219. package/src/entity-card.tsx +74 -0
  220. package/src/entity-health-card.tsx +53 -0
  221. package/src/entity-switcher.tsx +126 -0
  222. package/src/fetching-indicator.tsx +16 -0
  223. package/src/field-array-form.tsx +166 -0
  224. package/src/filter-bar.tsx +203 -0
  225. package/src/image-viewer.tsx +129 -0
  226. package/src/kanban/drop-utils.ts +31 -0
  227. package/src/kanban/navigation-buttons.tsx +80 -0
  228. package/src/kanban/scroll-indicators.tsx +47 -0
  229. package/src/kanban/use-keyboard-navigation.ts +43 -0
  230. package/src/kanban-board.tsx +160 -0
  231. package/src/kanban-column.tsx +62 -0
  232. package/src/legacy-kpi-card.tsx +38 -0
  233. package/src/line-chart.tsx +58 -0
  234. package/src/list-item.tsx +63 -0
  235. package/src/list-pane.tsx +143 -0
  236. package/src/login-form.tsx +128 -0
  237. package/src/message-bubble.tsx +70 -0
  238. package/src/message-composer.tsx +52 -0
  239. package/src/pie-chart.tsx +70 -0
  240. package/src/radar-chart.tsx +55 -0
  241. package/src/radial-chart.tsx +103 -0
  242. package/src/recording-overlay.tsx +159 -0
  243. package/src/save-bar.tsx +35 -0
  244. package/src/settings-layout.tsx +79 -0
  245. package/src/source-selector.tsx +71 -0
  246. package/src/split-workspace.tsx +74 -0
  247. package/src/stat-card.tsx +166 -0
  248. package/src/stats-grid.tsx +23 -0
  249. package/src/status-filters.tsx +28 -0
  250. package/src/stepper.tsx +47 -0
  251. package/src/table-pane.tsx +194 -0
  252. package/src/time-range-picker.tsx +89 -0
  253. package/src/workspace-back-button.tsx +32 -0
  254. package/dist/chat-types.test.d.ts +0 -2
  255. package/dist/chat-types.test.d.ts.map +0 -1
@@ -0,0 +1,164 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { Card, Skeleton } from '@lindaui/ui/compound';
4
+ import { Building2, Wifi, Loader2 } from 'lucide-react';
5
+ import { cn } from '@lindaui/ui/cn';
6
+
7
+ const COLOR_CONFIG = {
8
+ default: {
9
+ icon: "bg-surface-secondary text-muted",
10
+ value: "text-foreground"
11
+ },
12
+ primary: {
13
+ icon: "bg-accent/10 text-accent",
14
+ value: "text-accent"
15
+ },
16
+ success: {
17
+ icon: "bg-success/10 text-success",
18
+ value: "text-success"
19
+ },
20
+ warning: {
21
+ icon: "bg-warning/10 text-warning",
22
+ value: "text-warning"
23
+ }
24
+ };
25
+ /** Exact legacy KPI anatomy; StatCard and its featured variant remain unchanged. */ function KPICard({ title, value, icon: Icon, trend, color = "default", isLoading = false }) {
26
+ const colorConfig = COLOR_CONFIG[color];
27
+ if (isLoading) return /*#__PURE__*/ jsx(Card, {
28
+ className: "border-none bg-surface",
29
+ children: /*#__PURE__*/ jsxs(Card.Content, {
30
+ className: "p-4",
31
+ children: [
32
+ /*#__PURE__*/ jsxs("div", {
33
+ className: "flex items-start justify-between",
34
+ children: [
35
+ /*#__PURE__*/ jsx(Skeleton, {
36
+ className: "h-10 w-10 rounded-xl"
37
+ }),
38
+ /*#__PURE__*/ jsx(Skeleton, {
39
+ className: "h-4 w-16 rounded"
40
+ })
41
+ ]
42
+ }),
43
+ /*#__PURE__*/ jsx(Skeleton, {
44
+ className: "mt-4 h-8 w-24 rounded"
45
+ }),
46
+ /*#__PURE__*/ jsx(Skeleton, {
47
+ className: "mt-2 h-4 w-20 rounded"
48
+ })
49
+ ]
50
+ })
51
+ });
52
+ return /*#__PURE__*/ jsx(Card, {
53
+ className: "border-none bg-surface transition-colors hover:bg-surface-secondary",
54
+ children: /*#__PURE__*/ jsxs(Card.Content, {
55
+ className: "p-4",
56
+ children: [
57
+ /*#__PURE__*/ jsxs("div", {
58
+ className: "flex items-start justify-between",
59
+ children: [
60
+ /*#__PURE__*/ jsx("div", {
61
+ className: cn("rounded-xl p-2.5", colorConfig.icon),
62
+ children: /*#__PURE__*/ jsx(Icon, {
63
+ size: 20
64
+ })
65
+ }),
66
+ !!trend && /*#__PURE__*/ jsxs("span", {
67
+ className: cn("rounded-full px-2 py-1 font-medium text-xs", trend.isPositive ? "bg-success/10 text-success" : "bg-danger/10 text-danger"),
68
+ children: [
69
+ trend.isPositive ? "+" : "-",
70
+ Math.abs(trend.value),
71
+ "%"
72
+ ]
73
+ })
74
+ ]
75
+ }),
76
+ /*#__PURE__*/ jsxs("div", {
77
+ className: "mt-4",
78
+ children: [
79
+ /*#__PURE__*/ jsx("p", {
80
+ className: cn("font-bold text-2xl", colorConfig.value),
81
+ children: value
82
+ }),
83
+ /*#__PURE__*/ jsx("p", {
84
+ className: "mt-1 text-muted text-sm",
85
+ children: title
86
+ })
87
+ ]
88
+ })
89
+ ]
90
+ })
91
+ });
92
+ }
93
+
94
+ function AnalyticsSkeleton() {
95
+ return /*#__PURE__*/ jsxs("div", {
96
+ className: "space-y-6",
97
+ children: [
98
+ /*#__PURE__*/ jsx("div", {
99
+ className: "grid grid-cols-2 gap-4 lg:grid-cols-4",
100
+ children: [
101
+ "a",
102
+ "b",
103
+ "c",
104
+ "d"
105
+ ].map((k)=>/*#__PURE__*/ jsx(KPICard, {
106
+ icon: Building2,
107
+ isLoading: true,
108
+ title: "",
109
+ value: ""
110
+ }, k))
111
+ }),
112
+ /*#__PURE__*/ jsx("div", {
113
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
114
+ children: [
115
+ "e",
116
+ "f",
117
+ "g"
118
+ ].map((k)=>/*#__PURE__*/ jsx(KPICard, {
119
+ icon: Wifi,
120
+ isLoading: true,
121
+ title: "",
122
+ value: ""
123
+ }, k))
124
+ }),
125
+ /*#__PURE__*/ jsxs("div", {
126
+ className: "grid gap-6 lg:grid-cols-2",
127
+ children: [
128
+ /*#__PURE__*/ jsx(Skeleton, {
129
+ className: "h-72 w-full rounded-xl"
130
+ }),
131
+ /*#__PURE__*/ jsx(Skeleton, {
132
+ className: "h-72 w-full rounded-xl"
133
+ })
134
+ ]
135
+ }),
136
+ /*#__PURE__*/ jsxs("div", {
137
+ className: "grid gap-6 lg:grid-cols-2",
138
+ children: [
139
+ /*#__PURE__*/ jsx(Skeleton, {
140
+ className: "h-64 w-full rounded-xl"
141
+ }),
142
+ /*#__PURE__*/ jsx(Skeleton, {
143
+ className: "h-64 w-full rounded-xl"
144
+ })
145
+ ]
146
+ })
147
+ ]
148
+ });
149
+ }
150
+ function FetchingIndicator({ label }) {
151
+ return /*#__PURE__*/ jsxs("div", {
152
+ className: "flex items-center gap-1.5 text-muted text-xs",
153
+ children: [
154
+ /*#__PURE__*/ jsx(Loader2, {
155
+ className: "h-3 w-3 animate-spin"
156
+ }),
157
+ /*#__PURE__*/ jsx("span", {
158
+ children: label
159
+ })
160
+ ]
161
+ });
162
+ }
163
+
164
+ export { AnalyticsSkeleton as A, FetchingIndicator as F, KPICard as K };
@@ -0,0 +1,11 @@
1
+ /** Generic analytics migration API; the existing individual blocks remain unchanged. */
2
+ export { AiCostCard } from "./analytics/ai-cost-card.js";
3
+ export { AiPerformanceCard } from "./analytics/ai-performance-card.js";
4
+ export { AnalyticsCard } from "./analytics/analytics-card.js";
5
+ export { AnalyticsSkeleton, FetchingIndicator } from "./analytics/analytics-skeleton.js";
6
+ export { EntityHealthCard } from "./analytics/entity-health-card.js";
7
+ export { StatusDistributionChart } from "./analytics/status-distribution-chart.js";
8
+ export { TimeRangePicker } from "./analytics/time-range-picker.js";
9
+ export { TopEntitiesTable } from "./analytics/top-entities-table.js";
10
+ export type { AiCostCardProps, AiCostData, AiPerformanceCardProps, AiVsHumanData, AnalyticsCardProps, EntityCell, EntityHealthCardProps, HealthCardLabels, HealthEntity, HealthStatus, Preset, StatusDatum, StatusDistributionChartProps, TimeRangePickerProps, TopEntitiesColumn, TopEntitiesTableProps, TopEntityRow } from "./analytics/types.js";
11
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA0B,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAiC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA4B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mCAAgC,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAgC,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAAuC,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,kCAA+B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAgC,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,sBAAsB,EAAE,aAAa,EAAE,kBAAkB,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,4BAA4B,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,sBAAmB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { A as AiCostCard } from './ai-cost-card-f403ypsg.js';
2
+ export { A as AiPerformanceCard } from './ai-performance-card-cggm09nc.js';
3
+ export { A as AnalyticsCard } from './analytics-card-bcmijpt6.js';
4
+ export { A as AnalyticsSkeleton, F as FetchingIndicator } from './analytics-skeleton-imve37du.js';
5
+ export { E as EntityHealthCard } from './entity-health-card-ggnmrtrq.js';
6
+ export { S as StatusDistributionChart } from './status-distribution-chart-oucedzv7.js';
7
+ export { T as TimeRangePicker } from './time-range-picker-mu38hul4.js';
8
+ export { T as TopEntitiesTable } from './top-entities-table-o7xzpq96.js';
@@ -0,0 +1,8 @@
1
+ import type { KeyboardEvent } from "react";
2
+ /** Add keyboard focus management without changing the original drawer DOM or animations. */
3
+ export declare function useDrawerFocus(isOpen: boolean, onClose: () => void): {
4
+ drawerRef: import("react").RefObject<HTMLElement | null>;
5
+ triggerRef: import("react").RefObject<HTMLButtonElement | null>;
6
+ onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
7
+ };
8
+ //# sourceMappingURL=drawer-focus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drawer-focus.d.ts","sourceRoot":"","sources":["../../src/app-shell/drawer-focus.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,4FAA4F;AAC5F,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI;;;uBAcvC,aAAa,CAAC,WAAW,CAAC;EAuBrD"}
@@ -0,0 +1,39 @@
1
+ export interface AppShellUser {
2
+ displayName?: string;
3
+ avatarSrc?: string;
4
+ avatarAlt?: string;
5
+ initials?: string;
6
+ }
7
+ export interface AppShellFooterLabels {
8
+ connected: string;
9
+ disconnected: string;
10
+ installApp: string;
11
+ lightTheme: string;
12
+ darkTheme: string;
13
+ lightThemeTooltip: string;
14
+ darkThemeTooltip: string;
15
+ logoutTrigger: string;
16
+ logoutTitle: string;
17
+ logoutDescription: string;
18
+ logoutCancel: string;
19
+ logoutConfirm: string;
20
+ logoutPending: string;
21
+ logoutError: string;
22
+ }
23
+ export interface AppShellFooterProps {
24
+ className?: string;
25
+ isCollapsed?: boolean;
26
+ isConnected?: boolean;
27
+ showConnectionStatus?: boolean;
28
+ isInstallable?: boolean;
29
+ onInstall?: () => void;
30
+ mounted?: boolean;
31
+ theme?: string;
32
+ onToggleTheme?: () => void;
33
+ user?: AppShellUser | null;
34
+ onSignOut: () => void | Promise<void>;
35
+ labels?: Partial<AppShellFooterLabels>;
36
+ }
37
+ /** Connection, installation, theme and account actions; all business effects are injected. */
38
+ export declare function AppShellFooter({ className, isCollapsed, isConnected, showConnectionStatus, isInstallable, onInstall, mounted, theme, onToggleTheme, user, onSignOut, labels: labelOverrides, }: AppShellFooterProps): import("react").JSX.Element;
39
+ //# sourceMappingURL=footer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../src/app-shell/footer.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;CACxC;AAmBD,8FAA8F;AAC9F,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EAAE,WAAmB,EAAE,WAAmB,EAAE,oBAA2B,EAChF,aAAqB,EAAE,SAAS,EAAE,OAAe,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAC7E,SAAS,EAAE,MAAM,EAAE,cAAc,GAClC,EAAE,mBAAmB,+BA2FrB"}
@@ -0,0 +1,6 @@
1
+ import type { AppShellFooterLabels } from "./footer.js";
2
+ export declare function useLogoutDialog(onSignOut: () => void | Promise<void>, labels: AppShellFooterLabels): {
3
+ open: () => void;
4
+ dialog: import("react").JSX.Element;
5
+ };
6
+ //# sourceMappingURL=logout-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout-dialog.d.ts","sourceRoot":"","sources":["../../src/app-shell/logout-dialog.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAU,CAAC;AAErD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,oBAAoB;IA4B/F,IAAI;IACJ,MAAM;EAgCT"}
@@ -0,0 +1,15 @@
1
+ import type { AppShellLinkProps, AppShellNavItem, AppShellProps } from "./types.js";
2
+ export declare function ShellLink({ renderLink, ...props }: AppShellLinkProps & Pick<AppShellProps, "renderLink">): string | number | bigint | boolean | import("react").JSX.Element | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | Iterable<import("react").ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null | undefined;
3
+ export declare function SidebarNavLink({ item, collapsed, onClick, renderLink, }: {
4
+ item: AppShellNavItem;
5
+ collapsed?: boolean;
6
+ onClick?: () => void;
7
+ renderLink?: AppShellProps["renderLink"];
8
+ }): import("react").JSX.Element;
9
+ export declare function MobileBottomNavigation({ navItems, isVisiting, label, renderLink }: {
10
+ navItems: AppShellNavItem[];
11
+ isVisiting: boolean;
12
+ label: string;
13
+ renderLink?: AppShellProps["renderLink"];
14
+ }): import("react").JSX.Element;
15
+ //# sourceMappingURL=navigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/app-shell/navigation.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAS,CAAC;AAEjF,wBAAgB,SAAS,CAAC,EAAE,UAAU,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,GAAG,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,+VAExG;AAED,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,SAAS,EACT,OAAO,EACP,UAAU,GACX,EAAE;IACD,IAAI,EAAE,eAAe,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CAC1C,+BAyCA;AAiDD,wBAAgB,sBAAsB,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;IAClF,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CAC1C,+BA+BA"}
@@ -0,0 +1,55 @@
1
+ import type { AnchorHTMLAttributes, ComponentType, ReactNode } from "react";
2
+ export interface AppShellNavItem {
3
+ key: string;
4
+ label: string;
5
+ href: string;
6
+ icon: ComponentType<{
7
+ className?: string;
8
+ size?: number;
9
+ }>;
10
+ isActive?: boolean;
11
+ hideOnMobile?: boolean;
12
+ isCenterButton?: boolean;
13
+ /** Intercept sidebar/drawer navigation, for example to open a settings dialog. */
14
+ onAction?: () => void;
15
+ }
16
+ export interface AppShellBrand {
17
+ label: string;
18
+ href: string;
19
+ logoSrc?: string;
20
+ }
21
+ export type AppShellLinkProps = AnchorHTMLAttributes<HTMLAnchorElement> & {
22
+ href: string;
23
+ children: ReactNode;
24
+ };
25
+ export interface AppShellImageProps {
26
+ alt: string;
27
+ className: string;
28
+ height: number;
29
+ src: string;
30
+ width: number;
31
+ }
32
+ export interface AppShellLabels {
33
+ collapseSidebar: string;
34
+ expandSidebar: string;
35
+ openMenu: string;
36
+ closeMenu: string;
37
+ mainNavigation: string;
38
+ bottomNavigation: string;
39
+ }
40
+ export interface AppShellProps {
41
+ brand: AppShellBrand;
42
+ children: ReactNode;
43
+ navItems: AppShellNavItem[];
44
+ contentTopSlot?: ReactNode;
45
+ headerRightSlot?: ReactNode;
46
+ sidebarTopSlot?: ReactNode | ((isCollapsed: boolean) => ReactNode);
47
+ sidebarFooterSlot?: ReactNode | ((isCollapsed: boolean) => ReactNode);
48
+ isVisiting?: boolean;
49
+ defaultCollapsed?: boolean;
50
+ labels?: Partial<AppShellLabels>;
51
+ /** Inject a router link without coupling the block to any framework. */
52
+ renderLink?: (props: AppShellLinkProps) => ReactNode;
53
+ renderImage?: (props: AppShellImageProps) => ReactNode;
54
+ }
55
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/app-shell/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5E,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,cAAc,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,WAAW,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC;IACnE,iBAAiB,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,WAAW,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACjC,wEAAwE;IACxE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC;IACrD,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,SAAS,CAAC;CACxD"}
@@ -0,0 +1,7 @@
1
+ import type { AppShellProps } from "./app-shell/types.js";
2
+ export type { AppShellBrand, AppShellImageProps, AppShellLabels, AppShellLinkProps, AppShellNavItem, AppShellProps, } from "./app-shell/types.js";
3
+ export { AppShellFooter } from "./app-shell/footer.js";
4
+ export type { AppShellFooterLabels, AppShellFooterProps, AppShellUser } from "./app-shell/footer.js";
5
+ /** The original collapsible desktop sidebar, mobile drawer and floating bottom navigation. */
6
+ export declare function AppShell({ children, navItems, sidebarTopSlot, sidebarFooterSlot, contentTopSlot, headerRightSlot, brand, isVisiting, defaultCollapsed, labels: labelOverrides, renderLink, renderImage, }: AppShellProps): import("react").JSX.Element;
7
+ //# sourceMappingURL=app-shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../src/app-shell.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,sBAAmB,CAAC;AAEvE,YAAY,EACV,aAAa,EAAE,kBAAkB,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,aAAa,GACrG,MAAM,sBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAoB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,uBAAoB,CAAC;AAWlG,8FAA8F;AAC9F,wBAAgB,QAAQ,CAAC,EACvB,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EACtF,KAAK,EAAE,UAAkB,EAAE,gBAAwB,EAAE,MAAM,EAAE,cAAc,EAC3E,UAAU,EAAE,WAAW,GACxB,EAAE,aAAa,+BAuIf"}
@@ -0,0 +1,254 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { Button } from '@lindaui/ui/compound';
4
+ import { cn } from '@lindaui/ui/cn';
5
+ import { PanelLeftClose, PanelLeft, X, Menu } from 'lucide-react';
6
+ import { useRef, useEffect, useState, useId } from 'react';
7
+ import { S as ShellLink, a as SidebarNavLink, M as MobileBottomNavigation } from './navigation-hotcrqoq.js';
8
+ export { A as AppShellFooter } from './footer-f7r5e42b.js';
9
+
10
+ /** Add keyboard focus management without changing the original drawer DOM or animations. */ function useDrawerFocus(isOpen, onClose) {
11
+ const drawerRef = useRef(null);
12
+ const triggerRef = useRef(null);
13
+ const wasOpen = useRef(false);
14
+ useEffect(()=>{
15
+ if (isOpen) {
16
+ drawerRef.current?.querySelector("button")?.focus();
17
+ } else if (wasOpen.current) {
18
+ triggerRef.current?.focus();
19
+ }
20
+ wasOpen.current = isOpen;
21
+ }, [
22
+ isOpen
23
+ ]);
24
+ const onKeyDown = (event)=>{
25
+ // React portals bubble through their owner: do not dismiss a drawer behind a menu/modal.
26
+ if (!isOpen || !event.currentTarget.contains(event.target)) return;
27
+ if (event.key === "Escape") {
28
+ event.preventDefault();
29
+ onClose();
30
+ return;
31
+ }
32
+ if (event.key !== "Tab") return;
33
+ const focusable = Array.from(event.currentTarget.querySelectorAll('a[href], button:not(:disabled), input:not(:disabled), [tabindex="0"]')).filter((element)=>!element.closest('[inert], [aria-hidden="true"]') && element.getAttribute("aria-disabled") !== "true");
34
+ const first = focusable[0];
35
+ const last = focusable[focusable.length - 1];
36
+ const activeElement = event.currentTarget.ownerDocument.activeElement;
37
+ if (event.shiftKey && activeElement === first || !event.shiftKey && activeElement === last) {
38
+ event.preventDefault();
39
+ (event.shiftKey ? last : first)?.focus();
40
+ }
41
+ };
42
+ return {
43
+ drawerRef,
44
+ triggerRef,
45
+ onKeyDown
46
+ };
47
+ }
48
+
49
+ const defaultLabels = {
50
+ collapseSidebar: "Collapse sidebar",
51
+ expandSidebar: "Expand sidebar",
52
+ openMenu: "Open menu",
53
+ closeMenu: "Close menu",
54
+ mainNavigation: "Main navigation",
55
+ bottomNavigation: "Bottom navigation"
56
+ };
57
+ /** The original collapsible desktop sidebar, mobile drawer and floating bottom navigation. */ function AppShell({ children, navItems, sidebarTopSlot, sidebarFooterSlot, contentTopSlot, headerRightSlot, brand, isVisiting = false, defaultCollapsed = false, labels: labelOverrides, renderLink, renderImage }) {
58
+ const [sidebarOpen, setSidebarOpen] = useState(false);
59
+ const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);
60
+ const drawerFocus = useDrawerFocus(sidebarOpen, ()=>setSidebarOpen(false));
61
+ const drawerId = useId();
62
+ const labels = {
63
+ ...defaultLabels,
64
+ ...labelOverrides
65
+ };
66
+ // Preserve the existing slot API: the top slot follows desktop collapse state in both sidebars.
67
+ const topSlot = typeof sidebarTopSlot === "function" ? sidebarTopSlot(isCollapsed) : sidebarTopSlot;
68
+ const footer = (collapsed)=>typeof sidebarFooterSlot === "function" ? sidebarFooterSlot(collapsed) : sidebarFooterSlot;
69
+ const logo = (size, className)=>{
70
+ if (!brand.logoSrc) return null;
71
+ const props = {
72
+ alt: brand.label,
73
+ className,
74
+ height: size,
75
+ src: brand.logoSrc,
76
+ width: size
77
+ };
78
+ return renderImage ? renderImage(props) : /*#__PURE__*/ jsx("img", {
79
+ ...props
80
+ });
81
+ };
82
+ const mobileBrand = /*#__PURE__*/ jsxs(ShellLink, {
83
+ className: "flex items-center gap-2",
84
+ href: brand.href,
85
+ renderLink: renderLink,
86
+ children: [
87
+ logo(28, "h-7 w-7 rounded-lg"),
88
+ /*#__PURE__*/ jsx("span", {
89
+ className: "font-extrabold text-sm uppercase",
90
+ children: brand.label
91
+ })
92
+ ]
93
+ });
94
+ return /*#__PURE__*/ jsxs("div", {
95
+ className: "flex min-h-screen bg-background",
96
+ children: [
97
+ /*#__PURE__*/ jsxs("aside", {
98
+ className: cn("fixed z-40 hidden h-full flex-col lg:flex", "border-border border-r", "transition-all duration-300 ease-in-out", isVisiting ? "bg-warning-soft dark:bg-warning/20" : "bg-background", isCollapsed ? "w-16" : "w-48"),
99
+ children: [
100
+ /*#__PURE__*/ jsxs("div", {
101
+ className: cn("flex h-14 items-center border-border border-b", isCollapsed ? "flex-col justify-center gap-0 px-2" : "justify-between px-4"),
102
+ children: [
103
+ /*#__PURE__*/ jsxs(ShellLink, {
104
+ "aria-label": brand.label,
105
+ className: cn("flex items-center gap-2", isCollapsed ? "mb-0" : ""),
106
+ href: brand.href,
107
+ renderLink: renderLink,
108
+ children: [
109
+ logo(32, cn("rounded-lg", isCollapsed ? "h-7 w-7" : "h-8 w-8") ?? ""),
110
+ isCollapsed ? null : /*#__PURE__*/ jsx("span", {
111
+ className: "font-extrabold text-sm uppercase",
112
+ children: brand.label
113
+ })
114
+ ]
115
+ }),
116
+ isCollapsed ? null : /*#__PURE__*/ jsx(Button, {
117
+ "aria-label": labels.collapseSidebar,
118
+ className: "text-muted hover:text-foreground",
119
+ isIconOnly: true,
120
+ onPress: ()=>setIsCollapsed(true),
121
+ size: "sm",
122
+ variant: "ghost",
123
+ children: /*#__PURE__*/ jsx(PanelLeftClose, {
124
+ size: 18
125
+ })
126
+ })
127
+ ]
128
+ }),
129
+ isCollapsed ? /*#__PURE__*/ jsx("div", {
130
+ className: "flex justify-center border-border border-b py-2",
131
+ children: /*#__PURE__*/ jsx(Button, {
132
+ "aria-label": labels.expandSidebar,
133
+ className: "text-muted hover:text-foreground",
134
+ isIconOnly: true,
135
+ onPress: ()=>setIsCollapsed(false),
136
+ size: "sm",
137
+ variant: "ghost",
138
+ children: /*#__PURE__*/ jsx(PanelLeft, {
139
+ size: 18
140
+ })
141
+ })
142
+ }) : null,
143
+ topSlot ?? null,
144
+ /*#__PURE__*/ jsx("nav", {
145
+ "aria-label": labels.mainNavigation,
146
+ className: "flex-1 space-y-1 px-2 py-4",
147
+ children: navItems.map((item)=>/*#__PURE__*/ jsx(SidebarNavLink, {
148
+ collapsed: isCollapsed,
149
+ item: item,
150
+ renderLink: renderLink
151
+ }, item.key))
152
+ }),
153
+ footer(isCollapsed)
154
+ ]
155
+ }),
156
+ /*#__PURE__*/ jsx("header", {
157
+ className: "!bg-transparent fixed top-0 right-0 left-0 z-50 border-border border-b backdrop-blur backdrop-saturate-200 lg:hidden dark:border-white/10",
158
+ children: /*#__PURE__*/ jsxs("div", {
159
+ className: "flex h-14 items-center justify-between px-4",
160
+ children: [
161
+ /*#__PURE__*/ jsx(Button, {
162
+ ref: drawerFocus.triggerRef,
163
+ "aria-label": sidebarOpen ? labels.closeMenu : labels.openMenu,
164
+ "aria-controls": drawerId,
165
+ "aria-expanded": sidebarOpen,
166
+ isIconOnly: true,
167
+ onPress: ()=>setSidebarOpen(!sidebarOpen),
168
+ size: "sm",
169
+ variant: "ghost",
170
+ children: sidebarOpen ? /*#__PURE__*/ jsx(X, {
171
+ size: 20
172
+ }) : /*#__PURE__*/ jsx(Menu, {
173
+ size: 20
174
+ })
175
+ }),
176
+ mobileBrand,
177
+ headerRightSlot
178
+ ]
179
+ })
180
+ }),
181
+ sidebarOpen ? /*#__PURE__*/ jsx("div", {
182
+ "aria-label": labels.closeMenu,
183
+ className: "fixed inset-0 z-[60] bg-black/50 backdrop-blur-sm lg:hidden",
184
+ onClick: ()=>setSidebarOpen(false),
185
+ onKeyDown: (event)=>{
186
+ if ([
187
+ "Enter",
188
+ " ",
189
+ "Escape"
190
+ ].includes(event.key)) {
191
+ event.preventDefault();
192
+ setSidebarOpen(false);
193
+ }
194
+ },
195
+ role: "button",
196
+ tabIndex: 0
197
+ }) : null,
198
+ /*#__PURE__*/ jsxs("aside", {
199
+ ref: drawerFocus.drawerRef,
200
+ id: drawerId,
201
+ inert: !sidebarOpen,
202
+ onKeyDown: drawerFocus.onKeyDown,
203
+ className: cn("fixed inset-y-0 left-0 z-[60] flex w-64 flex-col border-border border-r lg:hidden", "transform transition-transform duration-300 ease-in-out", isVisiting ? "bg-warning-soft dark:bg-warning/20" : "bg-background", sidebarOpen ? "translate-x-0" : "-translate-x-full"),
204
+ children: [
205
+ /*#__PURE__*/ jsxs("div", {
206
+ className: "flex h-14 items-center justify-between border-border border-b px-4",
207
+ children: [
208
+ mobileBrand,
209
+ /*#__PURE__*/ jsx(Button, {
210
+ "aria-label": labels.closeMenu,
211
+ isIconOnly: true,
212
+ onPress: ()=>setSidebarOpen(false),
213
+ size: "sm",
214
+ variant: "ghost",
215
+ children: /*#__PURE__*/ jsx(X, {
216
+ size: 20
217
+ })
218
+ })
219
+ ]
220
+ }),
221
+ topSlot ?? null,
222
+ /*#__PURE__*/ jsx("nav", {
223
+ "aria-label": labels.mainNavigation,
224
+ className: "flex-1 space-y-1 p-3",
225
+ children: navItems.map((item)=>/*#__PURE__*/ jsx(SidebarNavLink, {
226
+ item: item,
227
+ onClick: ()=>setSidebarOpen(false),
228
+ renderLink: renderLink
229
+ }, item.key))
230
+ }),
231
+ footer(false)
232
+ ]
233
+ }),
234
+ /*#__PURE__*/ jsxs("main", {
235
+ className: cn("flex h-screen min-w-0 flex-1 flex-col overflow-x-hidden pt-14 transition-all duration-300 lg:pt-0", isCollapsed ? "lg:ml-16" : "lg:ml-48"),
236
+ children: [
237
+ contentTopSlot,
238
+ /*#__PURE__*/ jsx("div", {
239
+ className: "min-h-0 flex-1 overflow-auto pb-20 lg:pb-0",
240
+ children: children
241
+ })
242
+ ]
243
+ }),
244
+ /*#__PURE__*/ jsx(MobileBottomNavigation, {
245
+ navItems: navItems,
246
+ isVisiting: isVisiting,
247
+ label: labels.bottomNavigation,
248
+ renderLink: renderLink
249
+ })
250
+ ]
251
+ });
252
+ }
253
+
254
+ export { AppShell };
@@ -0,0 +1,24 @@
1
+ import { type ReactNode } from "react";
2
+ export interface SettingsChannel {
3
+ id: string;
4
+ label: ReactNode;
5
+ status: ReactNode;
6
+ icon?: ReactNode;
7
+ isDisabled?: boolean;
8
+ panel: ReactNode | ((isSelected: boolean) => ReactNode);
9
+ /** Optional mounting order, independent of the tab order. */
10
+ panelOrder?: number;
11
+ }
12
+ export interface ChannelSettingsProps {
13
+ channels: readonly SettingsChannel[];
14
+ navigationLabel: string;
15
+ selected?: string;
16
+ defaultSelected?: string;
17
+ onSelect?: (id: string) => void;
18
+ className?: string;
19
+ /** Two channels retain the original two-column layout; other counts adapt automatically. */
20
+ listClassName?: string;
21
+ }
22
+ /** Every panel stays mounted so switching channels preserves form and challenge state. */
23
+ export declare function ChannelSettings({ channels, navigationLabel, selected, defaultSelected, onSelect, className, listClassName, }: ChannelSettingsProps): import("react").JSX.Element;
24
+ //# sourceMappingURL=channel-settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-settings.d.ts","sourceRoot":"","sources":["../src/channel-settings.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,SAAS,GAAG,CAAC,CAAC,UAAU,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC;IACxD,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,SAA0B,EAC1B,aAAa,GACd,EAAE,oBAAoB,+BAuCtB"}