@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,9 @@
1
+ import { type RefObject } from "react";
2
+ export interface NavigationButtonsProps {
3
+ scrollRef: RefObject<HTMLElement | null>;
4
+ columnWidth?: number;
5
+ leftLabel?: string;
6
+ rightLabel?: string;
7
+ }
8
+ export declare function NavigationButtons({ scrollRef, columnWidth, leftLabel, rightLabel, }: NavigationButtonsProps): import("react").JSX.Element;
9
+ //# sourceMappingURL=navigation-buttons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-buttons.d.ts","sourceRoot":"","sources":["../../src/kanban/navigation-buttons.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5D,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,WAAiB,EACjB,SAAyB,EACzB,UAA2B,GAC5B,EAAE,sBAAsB,+BA4DxB"}
@@ -0,0 +1,6 @@
1
+ import { type RefObject } from "react";
2
+ export interface ScrollIndicatorsProps {
3
+ scrollRef: RefObject<HTMLElement | null>;
4
+ }
5
+ export declare function ScrollIndicators({ scrollRef }: ScrollIndicatorsProps): import("react").JSX.Element;
6
+ //# sourceMappingURL=scroll-indicators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-indicators.d.ts","sourceRoot":"","sources":["../../src/kanban/scroll-indicators.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5D,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAC1C;AAED,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,EAAE,qBAAqB,+BAqCpE"}
@@ -0,0 +1,4 @@
1
+ import { type RefObject } from "react";
2
+ /** Preserve horizontal board navigation, without intercepting text editing. */
3
+ export declare function useKeyboardNavigation<T extends HTMLElement>(scrollRef: RefObject<T | null>, columnWidth?: number): void;
4
+ //# sourceMappingURL=use-keyboard-navigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-keyboard-navigation.d.ts","sourceRoot":"","sources":["../../src/kanban/use-keyboard-navigation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,WAAW,EACzD,SAAS,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,EAC9B,WAAW,SAAM,QAmClB"}
@@ -0,0 +1,31 @@
1
+ import { type UniqueIdentifier } from "@dnd-kit/core";
2
+ import { type ReactNode } from "react";
3
+ export { resolveKanbanDrop } from "./kanban/drop-utils.js";
4
+ export { NavigationButtons, type NavigationButtonsProps } from "./kanban/navigation-buttons.js";
5
+ export { ScrollIndicators, type ScrollIndicatorsProps } from "./kanban/scroll-indicators.js";
6
+ export { useKeyboardNavigation } from "./kanban/use-keyboard-navigation.js";
7
+ export interface KanbanColumnDefinition<ColumnId extends UniqueIdentifier = string> {
8
+ id: ColumnId;
9
+ title: ReactNode;
10
+ colorClassName?: string;
11
+ }
12
+ export interface KanbanCardState {
13
+ isDragging: boolean;
14
+ }
15
+ export interface KanbanBoardProps<Entity, ColumnId extends UniqueIdentifier = string> {
16
+ /** Entity and column IDs must be stable and unique across the whole board. */
17
+ entities: readonly Entity[];
18
+ columns: readonly KanbanColumnDefinition<ColumnId>[];
19
+ getEntityId: (entity: Entity) => UniqueIdentifier;
20
+ getColumnId: (entity: Entity) => ColumnId;
21
+ onColumnChange: (entityId: UniqueIdentifier, columnId: ColumnId, entity: Entity) => void;
22
+ renderCard: (entity: Entity, state: KanbanCardState) => ReactNode;
23
+ renderColumn?: (column: KanbanColumnDefinition<ColumnId>, entities: readonly Entity[]) => ReactNode;
24
+ isLoading?: boolean;
25
+ emptyContent?: ReactNode;
26
+ ariaLabel?: string;
27
+ scrollLeftLabel?: string;
28
+ scrollRightLabel?: string;
29
+ }
30
+ export declare function KanbanBoard<Entity, ColumnId extends UniqueIdentifier = string>({ entities, columns, getEntityId, getColumnId, onColumnChange, renderCard, renderColumn, isLoading, emptyContent, ariaLabel, scrollLeftLabel, scrollRightLabel, }: KanbanBoardProps<Entity, ColumnId>): import("react").JSX.Element;
31
+ //# sourceMappingURL=kanban-board.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kanban-board.d.ts","sourceRoot":"","sources":["../src/kanban-board.tsx"],"names":[],"mappings":"AAEA,OAAO,EAUL,KAAK,gBAAgB,EACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAA8B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,gCAA6B,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,+BAA4B,CAAC;AAC1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAkC,CAAC;AAEzE,MAAM,WAAW,sBAAsB,CAAC,QAAQ,SAAS,gBAAgB,GAAG,MAAM;IAChF,EAAE,EAAE,QAAQ,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB,CAAC,MAAM,EAAE,QAAQ,SAAS,gBAAgB,GAAG,MAAM;IAClF,8EAA8E;IAC9E,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,OAAO,EAAE,SAAS,sBAAsB,CAAC,QAAQ,CAAC,EAAE,CAAC;IACrD,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,gBAAgB,CAAC;IAClD,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,QAAQ,CAAC;IAC1C,cAAc,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzF,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,KAAK,SAAS,CAAC;IAClE,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,KAAK,SAAS,CAAC;IACpG,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,QAAQ,SAAS,gBAAgB,GAAG,MAAM,EAAE,EAC9E,QAAQ,EACR,OAAO,EACP,WAAW,EACX,WAAW,EACX,cAAc,EACd,UAAU,EACV,YAAY,EACZ,SAAiB,EACjB,YAAY,EACZ,SAA0B,EAC1B,eAAe,EACf,gBAAgB,GACjB,EAAE,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,+BA6FpC"}
@@ -0,0 +1,128 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { useSensors, useSensor, PointerSensor, TouchSensor, DndContext, closestCorners, DragOverlay } from '@dnd-kit/core';
4
+ import { Skeleton } from '@lindaui/ui/compound';
5
+ import { useState, useRef, Fragment } from 'react';
6
+ import { KanbanColumn } from './kanban-column.js';
7
+ import { N as NavigationButtons } from './navigation-buttons-e77mshh0.js';
8
+ import { S as ScrollIndicators } from './scroll-indicators-gvxapogd.js';
9
+ import { u as useKeyboardNavigation } from './use-keyboard-navigation-he1xmriz.js';
10
+
11
+ /** Resolve column and card targets without mutating the controlled collection. */ function resolveKanbanDrop({ activeId, overId, entities, columns, getEntityId, getColumnId }) {
12
+ if (overId === null) return null;
13
+ const entity = entities.find((item)=>getEntityId(item) === activeId);
14
+ if (entity === undefined) return null;
15
+ const targetEntity = entities.find((item)=>getEntityId(item) === overId);
16
+ const targetColumn = columns.find((column)=>column.id === overId);
17
+ const columnId = targetEntity !== undefined ? getColumnId(targetEntity) : targetColumn?.id;
18
+ if (columnId === undefined || columnId === getColumnId(entity)) return null;
19
+ if (!columns.some((column)=>column.id === columnId)) return null;
20
+ return {
21
+ entity,
22
+ entityId: activeId,
23
+ columnId
24
+ };
25
+ }
26
+
27
+ function KanbanBoard({ entities, columns, getEntityId, getColumnId, onColumnChange, renderCard, renderColumn, isLoading = false, emptyContent, ariaLabel = "Kanban board", scrollLeftLabel, scrollRightLabel }) {
28
+ const [activeId, setActiveId] = useState(null);
29
+ const scrollRef = useRef(null);
30
+ useKeyboardNavigation(scrollRef);
31
+ const sensors = useSensors(useSensor(PointerSensor, {
32
+ activationConstraint: {
33
+ distance: 8
34
+ }
35
+ }), useSensor(TouchSensor, {
36
+ activationConstraint: {
37
+ delay: 200,
38
+ tolerance: 5
39
+ }
40
+ }));
41
+ const handleDragStart = (event)=>setActiveId(event.active.id);
42
+ const handleDragEnd = (event)=>{
43
+ setActiveId(null);
44
+ const drop = resolveKanbanDrop({
45
+ activeId: event.active.id,
46
+ overId: event.over?.id ?? null,
47
+ entities,
48
+ columns,
49
+ getEntityId,
50
+ getColumnId
51
+ });
52
+ if (drop) onColumnChange(drop.entityId, drop.columnId, drop.entity);
53
+ };
54
+ const activeEntity = activeId !== null ? entities.find((entity)=>getEntityId(entity) === activeId) : null;
55
+ if (isLoading) {
56
+ return /*#__PURE__*/ jsx("div", {
57
+ className: "flex h-full gap-4 overflow-x-auto p-4 lg:p-6",
58
+ children: columns.map((column)=>/*#__PURE__*/ jsxs("div", {
59
+ className: "flex w-80 flex-shrink-0 flex-col gap-3",
60
+ children: [
61
+ /*#__PURE__*/ jsx(Skeleton, {
62
+ className: "h-8 w-24 rounded-lg"
63
+ }),
64
+ /*#__PURE__*/ jsx("div", {
65
+ className: "min-h-[500px] space-y-3 rounded-xl bg-surface-secondary/50 p-2",
66
+ children: Array.from({
67
+ length: 3
68
+ }).map((_, index)=>/*#__PURE__*/ jsx(Skeleton, {
69
+ className: "h-32 w-full rounded-xl"
70
+ }, index))
71
+ })
72
+ ]
73
+ }, column.id))
74
+ });
75
+ }
76
+ return /*#__PURE__*/ jsxs(DndContext, {
77
+ collisionDetection: closestCorners,
78
+ onDragEnd: handleDragEnd,
79
+ onDragStart: handleDragStart,
80
+ sensors: sensors,
81
+ children: [
82
+ /*#__PURE__*/ jsxs("div", {
83
+ className: "relative h-full w-full overflow-hidden",
84
+ children: [
85
+ /*#__PURE__*/ jsx(ScrollIndicators, {
86
+ scrollRef: scrollRef
87
+ }),
88
+ /*#__PURE__*/ jsx(NavigationButtons, {
89
+ scrollRef: scrollRef,
90
+ leftLabel: scrollLeftLabel,
91
+ rightLabel: scrollRightLabel
92
+ }),
93
+ /*#__PURE__*/ jsx("section", {
94
+ "aria-label": ariaLabel,
95
+ className: "flex h-full gap-4 overflow-x-auto overflow-y-visible p-4 lg:p-6",
96
+ ref: scrollRef,
97
+ children: columns.map((column)=>{
98
+ const items = entities.filter((entity)=>getColumnId(entity) === column.id);
99
+ return /*#__PURE__*/ jsx(Fragment, {
100
+ children: renderColumn ? renderColumn(column, items) : /*#__PURE__*/ jsx(KanbanColumn, {
101
+ id: column.id,
102
+ title: column.title,
103
+ entities: items,
104
+ getEntityId: getEntityId,
105
+ renderCard: (entity)=>renderCard(entity, {
106
+ isDragging: false
107
+ }),
108
+ colorClassName: column.colorClassName,
109
+ emptyContent: emptyContent
110
+ })
111
+ }, column.id);
112
+ })
113
+ })
114
+ ]
115
+ }),
116
+ /*#__PURE__*/ jsx(DragOverlay, {
117
+ children: activeEntity !== null && activeEntity !== undefined ? /*#__PURE__*/ jsx("div", {
118
+ className: "rotate-3 opacity-80",
119
+ children: renderCard(activeEntity, {
120
+ isDragging: true
121
+ })
122
+ }) : null
123
+ })
124
+ ]
125
+ });
126
+ }
127
+
128
+ export { KanbanBoard, NavigationButtons, ScrollIndicators, resolveKanbanDrop, useKeyboardNavigation };
@@ -0,0 +1,13 @@
1
+ import { type UniqueIdentifier } from "@dnd-kit/core";
2
+ import { type ReactNode } from "react";
3
+ export interface KanbanColumnProps<Entity> {
4
+ id: UniqueIdentifier;
5
+ title: ReactNode;
6
+ entities: readonly Entity[];
7
+ getEntityId: (entity: Entity) => UniqueIdentifier;
8
+ renderCard: (entity: Entity) => ReactNode;
9
+ colorClassName?: string;
10
+ emptyContent?: ReactNode;
11
+ }
12
+ export declare function KanbanColumn<Entity>({ id, title, entities, getEntityId, renderCard, colorClassName, emptyContent, }: KanbanColumnProps<Entity>): import("react").JSX.Element;
13
+ //# sourceMappingURL=kanban-column.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kanban-column.d.ts","sourceRoot":"","sources":["../src/kanban-column.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGpE,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjD,MAAM,WAAW,iBAAiB,CAAC,MAAM;IACvC,EAAE,EAAE,gBAAgB,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,gBAAgB,CAAC;IAClD,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,CAAC;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,SAAS,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,EACnC,EAAE,EACF,KAAK,EACL,QAAQ,EACR,WAAW,EACX,UAAU,EACV,cAA+B,EAC/B,YAAyB,GAC1B,EAAE,iBAAiB,CAAC,MAAM,CAAC,+BAoC3B"}
@@ -0,0 +1,58 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { useDroppable } from '@dnd-kit/core';
4
+ import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';
5
+ import { cn } from '@lindaui/ui/cn';
6
+ import { Fragment } from 'react';
7
+
8
+ function KanbanColumn({ id, title, entities, getEntityId, renderCard, colorClassName = "bg-accent/60", emptyContent = "No items" }) {
9
+ const { setNodeRef, isOver } = useDroppable({
10
+ id
11
+ });
12
+ return /*#__PURE__*/ jsx("div", {
13
+ className: "flex h-full w-80 flex-shrink-0 flex-col",
14
+ children: /*#__PURE__*/ jsxs("div", {
15
+ className: "flex h-full flex-col overflow-hidden rounded-2xl bg-surface/50",
16
+ children: [
17
+ /*#__PURE__*/ jsx("div", {
18
+ className: cn("h-2.5", colorClassName)
19
+ }),
20
+ /*#__PURE__*/ jsxs("div", {
21
+ className: "flex items-center justify-between px-4 py-3",
22
+ children: [
23
+ /*#__PURE__*/ jsx("h3", {
24
+ className: "font-semibold text-foreground",
25
+ children: title
26
+ }),
27
+ /*#__PURE__*/ jsx("span", {
28
+ className: "rounded-full bg-surface-secondary px-2 py-1 font-mono text-muted text-xs",
29
+ children: entities.length
30
+ })
31
+ ]
32
+ }),
33
+ /*#__PURE__*/ jsxs("div", {
34
+ className: cn("min-h-[500px] flex-1 overflow-y-auto p-2 transition-colors", isOver ? "bg-accent/10" : ""),
35
+ ref: setNodeRef,
36
+ children: [
37
+ /*#__PURE__*/ jsx(SortableContext, {
38
+ items: entities.map(getEntityId),
39
+ strategy: verticalListSortingStrategy,
40
+ children: /*#__PURE__*/ jsx("div", {
41
+ className: "space-y-3",
42
+ children: entities.map((entity)=>/*#__PURE__*/ jsx(Fragment, {
43
+ children: renderCard(entity)
44
+ }, getEntityId(entity)))
45
+ })
46
+ }),
47
+ entities.length === 0 && /*#__PURE__*/ jsx("div", {
48
+ className: "flex h-32 items-center justify-center text-muted text-sm",
49
+ children: emptyContent
50
+ })
51
+ ]
52
+ })
53
+ ]
54
+ })
55
+ });
56
+ }
57
+
58
+ export { KanbanColumn };
@@ -0,0 +1,16 @@
1
+ import type { LucideIcon } from "lucide-react";
2
+ export type KPICardColor = "default" | "success" | "primary" | "warning";
3
+ export interface KPICardProps {
4
+ color?: KPICardColor;
5
+ icon: LucideIcon;
6
+ isLoading?: boolean;
7
+ title: string;
8
+ trend?: {
9
+ value: number;
10
+ isPositive: boolean;
11
+ };
12
+ value: string | number;
13
+ }
14
+ /** Exact legacy KPI anatomy; StatCard and its featured variant remain unchanged. */
15
+ export declare function KPICard({ title, value, icon: Icon, trend, color, isLoading }: KPICardProps): import("react").JSX.Element;
16
+ //# sourceMappingURL=legacy-kpi-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy-kpi-card.d.ts","sourceRoot":"","sources":["../src/legacy-kpi-card.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AACzE,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/C,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAOD,oFAAoF;AACpF,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAiB,EAAE,SAAiB,EAAE,EAAE,YAAY,+BAe9G"}
@@ -0,0 +1,4 @@
1
+ import 'react/jsx-runtime';
2
+ import '@lindaui/ui/compound';
3
+ import '@lindaui/ui/cn';
4
+ export { K as KPICard } from './analytics-skeleton-imve37du.js';
@@ -0,0 +1,93 @@
1
+ 'use client';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+ import { Modal, Button, Spinner } from '@lindaui/ui/compound';
4
+ import { useState, useRef } from 'react';
5
+
6
+ function useLogoutDialog(onSignOut, labels) {
7
+ const [isOpen, setIsOpen] = useState(false);
8
+ const [isPending, setIsPending] = useState(false);
9
+ const [error, setError] = useState(null);
10
+ const pending = useRef(false);
11
+ const onOpenChange = (open)=>{
12
+ if (pending.current) return;
13
+ setError(null);
14
+ setIsOpen(open);
15
+ };
16
+ const confirm = async ()=>{
17
+ if (pending.current) return;
18
+ pending.current = true;
19
+ setIsPending(true);
20
+ setError(null);
21
+ try {
22
+ await onSignOut();
23
+ setIsOpen(false);
24
+ } catch {
25
+ setError(labels.logoutError);
26
+ } finally{
27
+ pending.current = false;
28
+ setIsPending(false);
29
+ }
30
+ };
31
+ return {
32
+ open: ()=>onOpenChange(true),
33
+ dialog: /*#__PURE__*/ jsx(Modal.Backdrop, {
34
+ isDismissable: !isPending,
35
+ isKeyboardDismissDisabled: isPending,
36
+ isOpen: isOpen,
37
+ onOpenChange: onOpenChange,
38
+ children: /*#__PURE__*/ jsx(Modal.Container, {
39
+ children: /*#__PURE__*/ jsxs(Modal.Dialog, {
40
+ className: "sm:max-w-md",
41
+ role: "alertdialog",
42
+ children: [
43
+ /*#__PURE__*/ jsx(Modal.Header, {
44
+ children: /*#__PURE__*/ jsx(Modal.Heading, {
45
+ children: labels.logoutTitle
46
+ })
47
+ }),
48
+ /*#__PURE__*/ jsxs(Modal.Body, {
49
+ children: [
50
+ /*#__PURE__*/ jsx("p", {
51
+ className: "text-muted text-sm leading-relaxed",
52
+ children: labels.logoutDescription
53
+ }),
54
+ error ? /*#__PURE__*/ jsx("p", {
55
+ className: "mt-3 text-danger text-sm",
56
+ role: "alert",
57
+ children: error
58
+ }) : null
59
+ ]
60
+ }),
61
+ /*#__PURE__*/ jsxs(Modal.Footer, {
62
+ children: [
63
+ /*#__PURE__*/ jsx(Button, {
64
+ autoFocus: true,
65
+ isDisabled: isPending,
66
+ onPress: ()=>onOpenChange(false),
67
+ variant: "tertiary",
68
+ children: labels.logoutCancel
69
+ }),
70
+ /*#__PURE__*/ jsx(Button, {
71
+ isPending: isPending,
72
+ onPress: confirm,
73
+ variant: "danger",
74
+ children: ({ isPending: buttonPending })=>/*#__PURE__*/ jsxs(Fragment, {
75
+ children: [
76
+ buttonPending ? /*#__PURE__*/ jsx(Spinner, {
77
+ color: "current",
78
+ size: "sm"
79
+ }) : null,
80
+ buttonPending ? labels.logoutPending : labels.logoutConfirm
81
+ ]
82
+ })
83
+ })
84
+ ]
85
+ })
86
+ ]
87
+ })
88
+ })
89
+ })
90
+ };
91
+ }
92
+
93
+ export { useLogoutDialog as u };
@@ -0,0 +1,110 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import dayjs from 'dayjs';
4
+ import { motion } from 'framer-motion';
5
+ import { cn } from '@lindaui/ui/cn';
6
+ import { I as ImageLightbox } from './image-lightbox-ci3arb6z.js';
7
+ import { W as WhatsAppAudioPlayer } from './whatsapp-audio-player-nooty6jb.js';
8
+
9
+ function formatTime(date) {
10
+ return dayjs(date).format("HH:mm");
11
+ }
12
+ function MessageBubble({ message }) {
13
+ const isBot = message.side === "right";
14
+ const hasAudio = message.media?.kind === "audio";
15
+ if (message.side === "center") return /*#__PURE__*/ jsx(motion.div, {
16
+ animate: {
17
+ opacity: 1
18
+ },
19
+ className: "my-2 flex justify-center",
20
+ initial: {
21
+ opacity: 0
22
+ },
23
+ children: /*#__PURE__*/ jsx("div", {
24
+ className: "rounded-full bg-surface-secondary px-3 py-1 text-muted text-xs",
25
+ children: message.text
26
+ })
27
+ });
28
+ return /*#__PURE__*/ jsx(motion.div, {
29
+ animate: {
30
+ opacity: 1,
31
+ y: 0
32
+ },
33
+ className: cn("flex w-full", isBot ? "justify-end" : "justify-start"),
34
+ initial: {
35
+ opacity: 0,
36
+ y: 10
37
+ },
38
+ children: /*#__PURE__*/ jsxs("div", {
39
+ className: cn("relative p-3 text-sm shadow-sm", hasAudio ? "w-[90%] max-w-[330px]" : "max-w-[85%] sm:max-w-[70%]", "rounded-2xl transition-all duration-200", isBot ? "rounded-tr-none bg-[#d9fdd3] text-[#111b21] dark:bg-[#005c4b] dark:text-white" : "rounded-tl-none bg-white text-[#111b21] dark:bg-[#202c33] dark:text-white"),
40
+ children: [
41
+ /*#__PURE__*/ jsx("div", {
42
+ className: cn("absolute top-0 h-0 w-0 border-solid", isBot ? "-right-[12px] border-t-[#d9fdd3] border-t-[10px] border-r-[12px] border-r-transparent dark:border-t-[#005c4b]" : "-left-[12px] border-t-[10px] border-t-white border-l-[12px] border-l-transparent dark:border-t-[#202c33]")
43
+ }),
44
+ message.media?.kind === "image" && /*#__PURE__*/ jsx("div", {
45
+ className: "mb-2 overflow-hidden rounded-lg",
46
+ children: /*#__PURE__*/ jsx(ImageLightbox, {
47
+ alt: "Media compartida",
48
+ src: message.media.url
49
+ })
50
+ }),
51
+ message.media?.kind === "audio" && /*#__PURE__*/ jsx("div", {
52
+ className: "mb-2",
53
+ children: /*#__PURE__*/ jsx(WhatsAppAudioPlayer, {
54
+ isBot: isBot,
55
+ src: message.media.url
56
+ })
57
+ }),
58
+ message.media?.kind === "pdf" && /*#__PURE__*/ jsx("div", {
59
+ className: "mb-2",
60
+ children: /*#__PURE__*/ jsxs("a", {
61
+ className: "flex items-center gap-1.5 rounded-lg border border-border bg-surface-secondary px-3 py-2 text-sm text-foreground transition-colors hover:bg-surface-secondary dark:border-border dark:bg-default dark:text-muted dark:hover:bg-default",
62
+ download: true,
63
+ href: message.media.url,
64
+ rel: "noopener noreferrer",
65
+ target: "_blank",
66
+ children: [
67
+ /*#__PURE__*/ jsx("span", {
68
+ children: "PDF"
69
+ }),
70
+ /*#__PURE__*/ jsx("span", {
71
+ className: "max-w-[180px] truncate",
72
+ children: message.media.label ?? "Documento adjunto"
73
+ })
74
+ ]
75
+ })
76
+ }),
77
+ /*#__PURE__*/ jsxs("div", {
78
+ className: "relative",
79
+ children: [
80
+ /*#__PURE__*/ jsxs("p", {
81
+ className: "whitespace-pre-wrap break-words",
82
+ children: [
83
+ message.text,
84
+ /*#__PURE__*/ jsxs("span", {
85
+ className: "invisible text-[10px]",
86
+ children: [
87
+ " ",
88
+ formatTime(message.timestamp),
89
+ message.authorTag ? ` ${message.authorTag}` : ""
90
+ ]
91
+ })
92
+ ]
93
+ }),
94
+ /*#__PURE__*/ jsxs("span", {
95
+ className: "absolute right-0 bottom-0 flex items-center gap-1 text-[#52616b] text-[10px] dark:text-[#d1dedb]",
96
+ children: [
97
+ formatTime(message.timestamp),
98
+ message.authorTag && /*#__PURE__*/ jsx("span", {
99
+ children: message.authorTag
100
+ })
101
+ ]
102
+ })
103
+ ]
104
+ })
105
+ ]
106
+ })
107
+ });
108
+ }
109
+
110
+ export { MessageBubble as M };
@@ -0,0 +1,59 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { TextArea, Button, Spinner } from '@lindaui/ui/compound';
4
+ import { Send, Mic } from 'lucide-react';
5
+ import { useCallback } from 'react';
6
+
7
+ /** Controlled glass composer; Enter sends and Shift+Enter retains a newline. */ function MessageComposer({ value, onValueChange, onSend, isSending = false, placeholder, disabled = false }) {
8
+ const hasText = value.trim().length > 0;
9
+ const handleChange = useCallback((e)=>onValueChange(e.target.value), [
10
+ onValueChange
11
+ ]);
12
+ const handleKeyDown = useCallback((e)=>{
13
+ if (e.key === "Enter" && !e.shiftKey && !isSending) {
14
+ e.preventDefault();
15
+ if (hasText) onSend();
16
+ }
17
+ }, [
18
+ hasText,
19
+ isSending,
20
+ onSend
21
+ ]);
22
+ return /*#__PURE__*/ jsx("div", {
23
+ className: "absolute inset-x-0 bottom-0 flex justify-center px-4 py-3",
24
+ children: /*#__PURE__*/ jsxs("div", {
25
+ className: "flex w-full items-end gap-2 rounded-3xl border border-white/30 bg-white/60 px-4 py-2 shadow-2xl backdrop-blur-2xl backdrop-saturate-200 transition-all lg:w-[70%] dark:border-white/15 dark:bg-slate-800/40",
26
+ children: [
27
+ /*#__PURE__*/ jsx(TextArea, {
28
+ "aria-label": placeholder,
29
+ className: "field-sizing-content max-h-30 min-h-0 flex-1 resize-none overflow-y-auto border-none bg-transparent py-1 text-foreground shadow-none dark:text-white",
30
+ disabled: disabled || isSending,
31
+ onChange: handleChange,
32
+ onKeyDown: handleKeyDown,
33
+ placeholder: placeholder,
34
+ rows: 1,
35
+ value: value
36
+ }),
37
+ /*#__PURE__*/ jsx(Button, {
38
+ className: "rounded-full bg-[#00a884] text-white",
39
+ isDisabled: disabled || isSending,
40
+ isIconOnly: true,
41
+ isPending: isSending,
42
+ onPress: hasText ? onSend : undefined,
43
+ size: "sm",
44
+ variant: "primary",
45
+ children: ({ isPending })=>isPending ? /*#__PURE__*/ jsx(Spinner, {
46
+ color: "current",
47
+ size: "sm"
48
+ }) : hasText ? /*#__PURE__*/ jsx(Send, {
49
+ className: "h-4 w-4"
50
+ }) : /*#__PURE__*/ jsx(Mic, {
51
+ className: "h-4 w-4"
52
+ })
53
+ })
54
+ ]
55
+ })
56
+ });
57
+ }
58
+
59
+ export { MessageComposer as M };
@@ -0,0 +1,65 @@
1
+ 'use client';
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
+ import { Button } from '@lindaui/ui/compound';
4
+ import { cn } from '@lindaui/ui/cn';
5
+ import { ChevronLeft, ChevronRight } from 'lucide-react';
6
+ import { useState, useEffect } from 'react';
7
+
8
+ function NavigationButtons({ scrollRef, columnWidth = 320, leftLabel = "Scroll left", rightLabel = "Scroll right" }) {
9
+ const [canScrollLeft, setCanScrollLeft] = useState(false);
10
+ const [canScrollRight, setCanScrollRight] = useState(false);
11
+ useEffect(()=>{
12
+ const element = scrollRef.current;
13
+ if (!element) return;
14
+ const checkScroll = ()=>{
15
+ const { scrollLeft, scrollWidth, clientWidth } = element;
16
+ setCanScrollLeft(scrollLeft > 0);
17
+ setCanScrollRight(scrollLeft < scrollWidth - clientWidth - 1);
18
+ };
19
+ checkScroll();
20
+ element.addEventListener("scroll", checkScroll);
21
+ window.addEventListener("resize", checkScroll);
22
+ return ()=>{
23
+ element.removeEventListener("scroll", checkScroll);
24
+ window.removeEventListener("resize", checkScroll);
25
+ };
26
+ }, [
27
+ scrollRef
28
+ ]);
29
+ const scroll = (direction)=>{
30
+ const element = scrollRef.current;
31
+ if (!element) return;
32
+ element.scrollTo({
33
+ behavior: "smooth",
34
+ left: element.scrollLeft + (direction === "left" ? -columnWidth : columnWidth)
35
+ });
36
+ };
37
+ return /*#__PURE__*/ jsxs(Fragment, {
38
+ children: [
39
+ /*#__PURE__*/ jsx(Button, {
40
+ "aria-label": leftLabel,
41
+ className: cn("absolute top-1/2 left-4 z-20 -translate-y-1/2 rounded-full shadow-xl transition-opacity", canScrollLeft ? "opacity-100" : "pointer-events-none opacity-0"),
42
+ isIconOnly: true,
43
+ onPress: ()=>scroll("left"),
44
+ size: "md",
45
+ variant: "primary",
46
+ children: /*#__PURE__*/ jsx(ChevronLeft, {
47
+ className: "h-6 w-6"
48
+ })
49
+ }),
50
+ /*#__PURE__*/ jsx(Button, {
51
+ "aria-label": rightLabel,
52
+ className: cn("absolute top-1/2 right-4 z-20 -translate-y-1/2 rounded-full shadow-xl transition-opacity", canScrollRight ? "opacity-100" : "pointer-events-none opacity-0"),
53
+ isIconOnly: true,
54
+ onPress: ()=>scroll("right"),
55
+ size: "md",
56
+ variant: "primary",
57
+ children: /*#__PURE__*/ jsx(ChevronRight, {
58
+ className: "h-6 w-6"
59
+ })
60
+ })
61
+ ]
62
+ });
63
+ }
64
+
65
+ export { NavigationButtons as N };