indas-ui 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/auth/ProtectedRoute.js +48 -0
- package/dist/cjs/components/auth/UnauthorizedPage.js +19 -0
- package/dist/cjs/components/auth/index.js +9 -0
- package/dist/cjs/components/chat/ai-messages.js +271 -0
- package/dist/cjs/components/chat/chat-prompt-navigator.js +110 -0
- package/dist/cjs/components/chat/chat.js +1032 -0
- package/dist/cjs/components/chat/multimodal-input.js +117 -0
- package/dist/cjs/components/dashboard/DrillDownModal.js +36 -0
- package/dist/cjs/components/dashboard/FilterBar.js +434 -0
- package/dist/cjs/components/dashboard/Tooltip.js +86 -0
- package/dist/cjs/components/dashboard/charts/Area.js +127 -0
- package/dist/cjs/components/dashboard/charts/Bar.js +111 -0
- package/dist/cjs/components/dashboard/charts/BoxPlot.js +118 -0
- package/dist/cjs/components/dashboard/charts/Bubble.js +102 -0
- package/dist/cjs/components/dashboard/charts/DashboardCard.js +12 -0
- package/dist/cjs/components/dashboard/charts/Donut.js +130 -0
- package/dist/cjs/components/dashboard/charts/FlowMap.js +238 -0
- package/dist/cjs/components/dashboard/charts/Funnel.js +38 -0
- package/dist/cjs/components/dashboard/charts/Gantt.js +271 -0
- package/dist/cjs/components/dashboard/charts/Gauge.js +143 -0
- package/dist/cjs/components/dashboard/charts/GeoMap.js +164 -0
- package/dist/cjs/components/dashboard/charts/Heatmap.js +116 -0
- package/dist/cjs/components/dashboard/charts/Line.js +75 -0
- package/dist/cjs/components/dashboard/charts/Pareto.js +110 -0
- package/dist/cjs/components/dashboard/charts/Radar.js +94 -0
- package/dist/cjs/components/dashboard/charts/Sankey.js +92 -0
- package/dist/cjs/components/dashboard/charts/Scatter.js +128 -0
- package/dist/cjs/components/dashboard/charts/Sparkline.js +134 -0
- package/dist/cjs/components/dashboard/charts/Treemap.js +104 -0
- package/dist/cjs/components/dashboard/charts/index.js +45 -0
- package/dist/cjs/components/dashboard/charts/india-map.js +464 -0
- package/dist/cjs/components/dashboard/charts/theme.js +132 -0
- package/dist/cjs/components/dashboard/config.js +118 -0
- package/dist/cjs/components/dashboard/index.js +39 -0
- package/dist/cjs/components/dashboard/kpi/KpiBeforeAfter.js +16 -0
- package/dist/cjs/components/dashboard/kpi/KpiBreakdown.js +42 -0
- package/dist/cjs/components/dashboard/kpi/KpiComparison.js +41 -0
- package/dist/cjs/components/dashboard/kpi/KpiQuickStats.js +41 -0
- package/dist/cjs/components/dashboard/kpi/KpiRating.js +38 -0
- package/dist/cjs/components/dashboard/kpi/KpiScroll.js +83 -0
- package/dist/cjs/components/dashboard/kpi/KpiTrend.js +37 -0
- package/dist/cjs/components/dashboard/kpi/index.js +22 -0
- package/dist/cjs/components/dashboard/kpi/kpi-shell.js +113 -0
- package/dist/cjs/components/dashboard/time-range.js +126 -0
- package/dist/cjs/components/datagrid/DataGrid.js +1613 -0
- package/dist/cjs/components/datagrid/cells/BooleanCell.js +42 -0
- package/dist/cjs/components/datagrid/cells/CellRenderer.js +142 -0
- package/dist/cjs/components/datagrid/cells/EditableCell.js +217 -0
- package/dist/cjs/components/datagrid/cells/SelectionCell.js +60 -0
- package/dist/cjs/components/datagrid/cells/index.js +6 -0
- package/dist/cjs/components/datagrid/columns/ActionsColumn.js +485 -0
- package/dist/cjs/components/datagrid/columns/ColumnContextMenu.js +341 -0
- package/dist/cjs/components/datagrid/columns/DraggableColumnHeader.js +150 -0
- package/dist/cjs/components/datagrid/controls/AutoResizeButton.js +10 -0
- package/dist/cjs/components/datagrid/controls/PaginationControls.js +38 -0
- package/dist/cjs/components/datagrid/controls/SummaryControls.js +30 -0
- package/dist/cjs/components/datagrid/controls/menu/ActionsMenu.js +16 -0
- package/dist/cjs/components/datagrid/controls/menu/column/ColumnChooserModal.js +25 -0
- package/dist/cjs/components/datagrid/controls/menu/column/ColumnSection.js +10 -0
- package/dist/cjs/components/datagrid/controls/menu/export/ExportSection.js +19 -0
- package/dist/cjs/components/datagrid/controls/menu/export/export.js +227 -0
- package/dist/cjs/components/datagrid/controls/menu/filter/AdvancedFilterModal.js +405 -0
- package/dist/cjs/components/datagrid/controls/menu/filter/FilterSection.js +9 -0
- package/dist/cjs/components/datagrid/controls/menu/grouping/GroupingSection.js +23 -0
- package/dist/cjs/components/datagrid/controls/menu/grouping/index.js +6 -0
- package/dist/cjs/components/datagrid/controls/menu/import/ImportSection.js +75 -0
- package/dist/cjs/components/datagrid/controls/menu/import/import.js +232 -0
- package/dist/cjs/components/datagrid/controls/menu/index.js +24 -0
- package/dist/cjs/components/datagrid/controls/menu/view/CardView.js +176 -0
- package/dist/cjs/components/datagrid/controls/menu/view/ChartView.js +401 -0
- package/dist/cjs/components/datagrid/controls/menu/view/ViewSection.js +12 -0
- package/dist/cjs/components/datagrid/hooks/useCellRangeSelection.js +127 -0
- package/dist/cjs/components/datagrid/hooks/useClipboard.js +154 -0
- package/dist/cjs/components/datagrid/hooks/useDataGridState.js +115 -0
- package/dist/cjs/components/datagrid/hooks/useKeyboardNavigation.js +120 -0
- package/dist/cjs/components/datagrid/index.js +90 -0
- package/dist/cjs/components/datagrid/rows/DraggableRow.js +34 -0
- package/dist/cjs/components/datagrid/rows/ExpandableRow.js +184 -0
- package/dist/cjs/components/datagrid/rows/FilterRow.js +188 -0
- package/dist/cjs/components/datagrid/rows/SelectColumn.js +34 -0
- package/dist/cjs/components/datagrid/rows/SummaryRow.js +34 -0
- package/dist/cjs/components/datagrid/rows/summary.js +67 -0
- package/dist/cjs/components/datagrid/search/InlineSearchCell.js +99 -0
- package/dist/cjs/components/datagrid/search/SearchHighlighter.js +133 -0
- package/dist/cjs/components/datagrid/search/SearchNavigator.js +185 -0
- package/dist/cjs/components/datagrid/search/SearchNewModal.js +238 -0
- package/dist/cjs/components/datagrid/search/advancedSearch.js +112 -0
- package/dist/cjs/components/datagrid/utils/grid-helpers.js +102 -0
- package/dist/cjs/components/datagrid/utils/grid-types.js +3 -0
- package/dist/cjs/components/draft/AutoSaveIndicator.js +70 -0
- package/dist/cjs/components/draft/DraftModal.js +220 -0
- package/dist/cjs/components/forms/date-picker/CalendarView.js +82 -0
- package/dist/cjs/components/forms/date-picker/DatePicker.js +748 -0
- package/dist/cjs/components/forms/date-picker/DateTimePicker.js +174 -0
- package/dist/cjs/components/forms/date-picker/index.js +21 -0
- package/dist/cjs/components/forms/date-picker/shared-utils.js +24 -0
- package/dist/cjs/components/forms/dropdown/Dropdown.js +427 -0
- package/dist/cjs/components/forms/dropdown/MultiSelect.js +136 -0
- package/dist/cjs/components/forms/dropdown/SingleSelect.js +254 -0
- package/dist/cjs/components/forms/dropdown/hooks/useDropdownCreate.js +88 -0
- package/dist/cjs/components/forms/dropdown/hooks/useDropdownFiltering.js +87 -0
- package/dist/cjs/components/forms/dropdown/hooks/useDropdownState.js +63 -0
- package/dist/cjs/components/forms/dropdown/index.js +6 -0
- package/dist/cjs/components/forms/dropdown/types.js +3 -0
- package/dist/cjs/components/forms/file-attachment/EmailPreview.js +419 -0
- package/dist/cjs/components/forms/file-attachment/FileAttachment.js +966 -0
- package/dist/cjs/components/forms/file-attachment/index.js +6 -0
- package/dist/cjs/components/forms/index.js +16 -0
- package/dist/cjs/components/forms/quantity-input-popup.js +135 -0
- package/dist/cjs/components/forms/remark-input/RemarkInput.js +263 -0
- package/dist/cjs/components/forms/remark-input/index.js +8 -0
- package/dist/cjs/components/forms/unified-currency-dropdown.js +202 -0
- package/dist/cjs/components/index.js +41 -0
- package/dist/cjs/components/layout/SidebarContextMenu.js +179 -0
- package/dist/cjs/components/layout/app-shell.js +81 -0
- package/dist/cjs/components/layout/bottom-nav.js +262 -0
- package/dist/cjs/components/layout/floating-action-button.js +77 -0
- package/dist/cjs/components/layout/footer.js +60 -0
- package/dist/cjs/components/layout/index.js +16 -0
- package/dist/cjs/components/layout/mobile-menu-sheet.js +195 -0
- package/dist/cjs/components/layout/side-panel.js +118 -0
- package/dist/cjs/components/layout/sidebar.js +581 -0
- package/dist/cjs/components/layout/top-header.js +270 -0
- package/dist/cjs/components/layout/userprofile-dropdown.js +100 -0
- package/dist/cjs/components/master/editable-cells/EditableCell.js +106 -0
- package/dist/cjs/components/master/editable-cells/index.js +17 -0
- package/dist/cjs/components/master/index.js +9 -0
- package/dist/cjs/components/messaging/conversation-list.js +109 -0
- package/dist/cjs/components/messaging/create-conversation-modal.js +112 -0
- package/dist/cjs/components/messaging/message-bubble.js +69 -0
- package/dist/cjs/components/messaging/message-input.js +154 -0
- package/dist/cjs/components/messaging/message-thread.js +124 -0
- package/dist/cjs/components/messaging/messaging-panel-content.js +69 -0
- package/dist/cjs/components/messaging/thread-panel.js +50 -0
- package/dist/cjs/components/modals/3DModal.js +35 -0
- package/dist/cjs/components/modals/ImageModal.js +587 -0
- package/dist/cjs/components/modals/Modal.js +311 -0
- package/dist/cjs/components/modals/StandardModal.js +28 -0
- package/dist/cjs/components/modals/api-config-modal.js +120 -0
- package/dist/cjs/components/modals/global-api-config-modal.js +127 -0
- package/dist/cjs/components/modals/index.js +17 -0
- package/dist/cjs/components/modals/logout-modal.js +45 -0
- package/dist/cjs/components/modals/modal-alert.js +295 -0
- package/dist/cjs/components/modals/password-reset-modal.js +112 -0
- package/dist/cjs/components/modals/session-expiry-warning.js +18 -0
- package/dist/cjs/components/providers/api-provider.js +19 -0
- package/dist/cjs/components/providers/query-provider.js +29 -0
- package/dist/cjs/components/providers/session-provider.js +119 -0
- package/dist/cjs/components/theme/ThemeCustomizer.js +184 -0
- package/dist/cjs/components/ui/buttons/button.js +264 -0
- package/dist/cjs/components/ui/card.js +58 -0
- package/dist/cjs/components/ui/chart.js +160 -0
- package/dist/cjs/components/ui/display/boolean-badge.js +29 -0
- package/dist/cjs/components/ui/display/card.js +20 -0
- package/dist/cjs/components/ui/display/collapsible.js +44 -0
- package/dist/cjs/components/ui/display/separator.js +44 -0
- package/dist/cjs/components/ui/display/stats-card.js +29 -0
- package/dist/cjs/components/ui/display/text.js +94 -0
- package/dist/cjs/components/ui/feedback/alert.js +61 -0
- package/dist/cjs/components/ui/feedback/badge.js +93 -0
- package/dist/cjs/components/ui/feedback/progress.js +44 -0
- package/dist/cjs/components/ui/feedback/reminder-button.js +111 -0
- package/dist/cjs/components/ui/feedback/skeleton-table.js +20 -0
- package/dist/cjs/components/ui/feedback/skeleton.js +53 -0
- package/dist/cjs/components/ui/feedback/tooltip.js +54 -0
- package/dist/cjs/components/ui/form-toggle.js +47 -0
- package/dist/cjs/components/ui/forms/checkbox.js +24 -0
- package/dist/cjs/components/ui/forms/input.js +111 -0
- package/dist/cjs/components/ui/forms/label.js +10 -0
- package/dist/cjs/components/ui/forms/switch.js +58 -0
- package/dist/cjs/components/ui/forms/textarea.js +49 -0
- package/dist/cjs/components/ui/index.js +157 -0
- package/dist/cjs/components/ui/navigation/dropdown-menu.js +84 -0
- package/dist/cjs/components/ui/navigation/header-steps.js +51 -0
- package/dist/cjs/components/ui/navigation/tabs.js +97 -0
- package/dist/cjs/components/ui/overlays/loading.js +169 -0
- package/dist/cjs/components/ui/select.js +72 -0
- package/dist/cjs/config/api.js +65 -0
- package/dist/cjs/contexts/AppConfigContext.js +37 -0
- package/dist/cjs/contexts/CurrencyContext.js +336 -0
- package/dist/cjs/contexts/DeviceContext.js +106 -0
- package/dist/cjs/contexts/EmailContext.js +727 -0
- package/dist/cjs/contexts/GlobalAlertContext.js +232 -0
- package/dist/cjs/contexts/ImpactAnalysisContext.js +60 -0
- package/dist/cjs/contexts/LanguageContext.js +104 -0
- package/dist/cjs/contexts/MessagingContext.js +726 -0
- package/dist/cjs/contexts/ModuleAuthContext.js +316 -0
- package/dist/cjs/contexts/NavigationContext.js +182 -0
- package/dist/cjs/contexts/NetworkStatusContext.js +95 -0
- package/dist/cjs/contexts/NotificationContext.js +169 -0
- package/dist/cjs/contexts/PageTitleContext.js +28 -0
- package/dist/cjs/contexts/SearchPreferencesContext.js +42 -0
- package/dist/cjs/contexts/SessionAdapterContext.js +24 -0
- package/dist/cjs/contexts/SidebarPreferencesContext.js +116 -0
- package/dist/cjs/contexts/ThemeContext.js +193 -0
- package/dist/cjs/hooks/index.js +50 -0
- package/dist/cjs/hooks/useApproval.js +250 -0
- package/dist/cjs/hooks/useBacchaSearch.js +257 -0
- package/dist/cjs/hooks/useBusinessAudit.js +54 -0
- package/dist/cjs/hooks/useColumnFreezing.js +204 -0
- package/dist/cjs/hooks/useColumnMetadata.js +48 -0
- package/dist/cjs/hooks/useConditionalFormatting.js +197 -0
- package/dist/cjs/hooks/useDebounce.js +49 -0
- package/dist/cjs/hooks/useDraft.js +181 -0
- package/dist/cjs/hooks/useFormValidation.js +68 -0
- package/dist/cjs/hooks/useGridSettings.js +85 -0
- package/dist/cjs/hooks/useGridTheme.js +204 -0
- package/dist/cjs/hooks/useId.js +21 -0
- package/dist/cjs/hooks/useIntelligentColumnSizing.js +315 -0
- package/dist/cjs/hooks/useKeyboardNavigation.js +192 -0
- package/dist/cjs/hooks/useNotifications.js +63 -0
- package/dist/cjs/hooks/usePrevious.js +20 -0
- package/dist/cjs/hooks/useRowSelection.js +150 -0
- package/dist/cjs/hooks/useSignalR.js +53 -0
- package/dist/cjs/hooks/useTheme.js +268 -0
- package/dist/cjs/hooks/useTranslation.js +20 -0
- package/dist/cjs/hooks/useUnsavedChanges.js +88 -0
- package/dist/cjs/index.js +21 -0
- package/dist/cjs/lib/api/activity/audit/audit.js +51 -0
- package/dist/cjs/lib/api/activity/audit/index.js +29 -0
- package/dist/cjs/lib/api/activity/audit/send.js +434 -0
- package/dist/cjs/lib/api/activity/email/client.js +467 -0
- package/dist/cjs/lib/api/activity/email/index.js +31 -0
- package/dist/cjs/lib/api/activity/email/password-reset.js +58 -0
- package/dist/cjs/lib/api/activity/email/templates.js +537 -0
- package/dist/cjs/lib/api/activity/email/types.js +24 -0
- package/dist/cjs/lib/api/activity/index.js +48 -0
- package/dist/cjs/lib/api/activity/messaging/messaging.js +254 -0
- package/dist/cjs/lib/api/activity/notifications/index.js +43 -0
- package/dist/cjs/lib/api/activity/notifications/notifications.js +224 -0
- package/dist/cjs/lib/api/activity/notifications/reminders.js +30 -0
- package/dist/cjs/lib/api/activity/notifications/send.js +267 -0
- package/dist/cjs/lib/api/activity/notifications/types.js +66 -0
- package/dist/cjs/lib/api/activity/notify-and-log.js +63 -0
- package/dist/cjs/lib/api/activity/remarks/index.js +6 -0
- package/dist/cjs/lib/api/activity/remarks/remarks.js +186 -0
- package/dist/cjs/lib/api/activity/storage.js +83 -0
- package/dist/cjs/lib/api/ai/chat.js +227 -0
- package/dist/cjs/lib/api/ai/types.js +6 -0
- package/dist/cjs/lib/api/approval/approvals.js +210 -0
- package/dist/cjs/lib/api/approval/index.js +13 -0
- package/dist/cjs/lib/api/auth/auth.js +154 -0
- package/dist/cjs/lib/api/auth/index.js +11 -0
- package/dist/cjs/lib/api/auth/password-reset-otp.js +192 -0
- package/dist/cjs/lib/api/auth/two-factor-auth.js +94 -0
- package/dist/cjs/lib/api/auth/two-factor.js +186 -0
- package/dist/cjs/lib/api/core/auth-helpers.js +141 -0
- package/dist/cjs/lib/api/core/client.js +305 -0
- package/dist/cjs/lib/api/core/config.js +248 -0
- package/dist/cjs/lib/api/core/index.js +43 -0
- package/dist/cjs/lib/api/core/session-validator.js +98 -0
- package/dist/cjs/lib/api/core/types.js +4 -0
- package/dist/cjs/lib/api/core/utils.js +70 -0
- package/dist/cjs/lib/api/dashboard/costing.js +15 -0
- package/dist/cjs/lib/api/dashboard/management.js +11 -0
- package/dist/cjs/lib/api/dashboard/sales.js +11 -0
- package/dist/cjs/lib/api/draft/drafts.js +279 -0
- package/dist/cjs/lib/api/draft/index.js +13 -0
- package/dist/cjs/lib/api/enquiry/enquiry.js +624 -0
- package/dist/cjs/lib/api/enquiry/index.js +20 -0
- package/dist/cjs/lib/api/enquiry/rate-enquiry.js +78 -0
- package/dist/cjs/lib/api/estimation/categories.js +113 -0
- package/dist/cjs/lib/api/estimation/category-defaults.js +47 -0
- package/dist/cjs/lib/api/estimation/company-config.js +26 -0
- package/dist/cjs/lib/api/estimation/content.js +210 -0
- package/dist/cjs/lib/api/estimation/freight.js +25 -0
- package/dist/cjs/lib/api/estimation/grid-costing-drafts.js +30 -0
- package/dist/cjs/lib/api/estimation/grid-costing.js +176 -0
- package/dist/cjs/lib/api/estimation/index.js +58 -0
- package/dist/cjs/lib/api/estimation/legacy-costing.js +51 -0
- package/dist/cjs/lib/api/estimation/machines.js +74 -0
- package/dist/cjs/lib/api/estimation/planning.js +403 -0
- package/dist/cjs/lib/api/estimation/qualities.js +245 -0
- package/dist/cjs/lib/api/estimation/quotation-load.js +52 -0
- package/dist/cjs/lib/api/estimation/quotation-save.js +109 -0
- package/dist/cjs/lib/api/estimation/quote-check.js +34 -0
- package/dist/cjs/lib/api/estimation/quotepanel.js +496 -0
- package/dist/cjs/lib/api/estimation/shipper-planning.js +220 -0
- package/dist/cjs/lib/api/estimation/wastage.js +47 -0
- package/dist/cjs/lib/api/index.js +33 -0
- package/dist/cjs/lib/api/integration/proxy.js +40 -0
- package/dist/cjs/lib/api/master/category.js +215 -0
- package/dist/cjs/lib/api/master/company.js +389 -0
- package/dist/cjs/lib/api/master/hsn.js +61 -0
- package/dist/cjs/lib/api/master/index.js +47 -0
- package/dist/cjs/lib/api/master/item.js +142 -0
- package/dist/cjs/lib/api/master/ledger.js +398 -0
- package/dist/cjs/lib/api/master/logistics.js +119 -0
- package/dist/cjs/lib/api/master/machine.js +579 -0
- package/dist/cjs/lib/api/master/material-group.js +103 -0
- package/dist/cjs/lib/api/master/other.js +63 -0
- package/dist/cjs/lib/api/master/process-types.js +5 -0
- package/dist/cjs/lib/api/master/process.js +131 -0
- package/dist/cjs/lib/api/master/production-units.js +22 -0
- package/dist/cjs/lib/api/master/rate.js +203 -0
- package/dist/cjs/lib/api/master/tool.js +88 -0
- package/dist/cjs/lib/api/master/user.js +154 -0
- package/dist/cjs/lib/api/settings/erp-parameters.js +69 -0
- package/dist/cjs/lib/api/utility/index.js +11 -0
- package/dist/cjs/lib/api/utility/menu.js +136 -0
- package/dist/cjs/lib/auth.js +10 -0
- package/dist/cjs/lib/pwa.js +59 -0
- package/dist/cjs/lib/react-query-config.js +134 -0
- package/dist/cjs/lib/security/audit-logger.js +177 -0
- package/dist/cjs/lib/security/rate-limiter.js +122 -0
- package/dist/cjs/lib/server-url.js +76 -0
- package/dist/cjs/lib/svg-utils.js +213 -0
- package/dist/cjs/lib/theme/types.js +235 -0
- package/dist/cjs/lib/theme/utils.js +363 -0
- package/dist/cjs/lib/types/index.js +3 -0
- package/dist/cjs/lib/utils/attachment-loader.js +82 -0
- package/dist/cjs/lib/utils/client-lead-utils.js +61 -0
- package/dist/cjs/lib/utils/device-detection.js +110 -0
- package/dist/cjs/lib/utils/logout-cleanup.js +312 -0
- package/dist/cjs/lib/utils/planning-prefs.js +31 -0
- package/dist/cjs/lib/utils.js +70 -0
- package/dist/cjs/lib/vision/dieline-extractor.js +321 -0
- package/dist/cjs/lib/vision/reference-grid.js +245 -0
- package/dist/cjs/locales/de.json +79 -0
- package/dist/cjs/locales/en.json +2217 -0
- package/dist/cjs/locales/es.json +79 -0
- package/dist/cjs/locales/fr.json +78 -0
- package/dist/cjs/locales/hi.json +1599 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/providers.js +43 -0
- package/dist/cjs/services/GlobalLoadingService.js +220 -0
- package/{src → dist/cjs}/styles/grid-themes.css +345 -345
- package/{src → dist/cjs}/styles/sidebar-scrollbar.css +45 -45
- package/{src → dist/cjs}/styles/tokens.css +712 -711
- package/dist/cjs/types/approval.js +22 -0
- package/dist/cjs/types/audit.js +50 -0
- package/dist/cjs/types/draft.js +22 -0
- package/dist/cjs/types/master.js +4 -0
- package/dist/cjs/types/shipper-planning.js +7 -0
- package/dist/components/auth/ProtectedRoute.d.ts +6 -0
- package/dist/components/auth/ProtectedRoute.js +45 -0
- package/dist/components/auth/UnauthorizedPage.d.ts +6 -0
- package/dist/components/auth/UnauthorizedPage.js +15 -0
- package/dist/components/auth/index.d.ts +2 -0
- package/dist/components/auth/index.js +3 -0
- package/dist/components/chat/ai-messages.d.ts +32 -0
- package/dist/components/chat/ai-messages.js +265 -0
- package/dist/components/chat/chat-prompt-navigator.d.ts +9 -0
- package/dist/components/chat/chat-prompt-navigator.js +107 -0
- package/dist/components/chat/chat.d.ts +46 -0
- package/dist/components/chat/chat.js +1029 -0
- package/dist/components/chat/multimodal-input.d.ts +12 -0
- package/dist/components/chat/multimodal-input.js +114 -0
- package/dist/components/dashboard/DrillDownModal.d.ts +15 -0
- package/dist/components/dashboard/DrillDownModal.js +33 -0
- package/dist/components/dashboard/FilterBar.d.ts +108 -0
- package/dist/components/dashboard/FilterBar.js +428 -0
- package/dist/components/dashboard/Tooltip.d.ts +24 -0
- package/dist/components/dashboard/Tooltip.js +50 -0
- package/dist/components/dashboard/charts/Area.d.ts +28 -0
- package/dist/components/dashboard/charts/Area.js +121 -0
- package/dist/components/dashboard/charts/Bar.d.ts +27 -0
- package/dist/components/dashboard/charts/Bar.js +105 -0
- package/dist/components/dashboard/charts/BoxPlot.d.ts +23 -0
- package/dist/components/dashboard/charts/BoxPlot.js +112 -0
- package/dist/components/dashboard/charts/Bubble.d.ts +36 -0
- package/dist/components/dashboard/charts/Bubble.js +96 -0
- package/dist/components/dashboard/charts/DashboardCard.d.ts +12 -0
- package/dist/components/dashboard/charts/DashboardCard.js +9 -0
- package/dist/components/dashboard/charts/Donut.d.ts +23 -0
- package/dist/components/dashboard/charts/Donut.js +124 -0
- package/dist/components/dashboard/charts/FlowMap.d.ts +38 -0
- package/dist/components/dashboard/charts/FlowMap.js +199 -0
- package/dist/components/dashboard/charts/Funnel.d.ts +30 -0
- package/dist/components/dashboard/charts/Funnel.js +35 -0
- package/dist/components/dashboard/charts/Gantt.d.ts +26 -0
- package/dist/components/dashboard/charts/Gantt.js +265 -0
- package/dist/components/dashboard/charts/Gauge.d.ts +25 -0
- package/dist/components/dashboard/charts/Gauge.js +137 -0
- package/dist/components/dashboard/charts/GeoMap.d.ts +38 -0
- package/dist/components/dashboard/charts/GeoMap.js +125 -0
- package/dist/components/dashboard/charts/Heatmap.d.ts +31 -0
- package/dist/components/dashboard/charts/Heatmap.js +110 -0
- package/dist/components/dashboard/charts/Line.d.ts +33 -0
- package/dist/components/dashboard/charts/Line.js +69 -0
- package/dist/components/dashboard/charts/Pareto.d.ts +21 -0
- package/dist/components/dashboard/charts/Pareto.js +104 -0
- package/dist/components/dashboard/charts/Radar.d.ts +32 -0
- package/dist/components/dashboard/charts/Radar.js +88 -0
- package/dist/components/dashboard/charts/Sankey.d.ts +43 -0
- package/dist/components/dashboard/charts/Sankey.js +86 -0
- package/dist/components/dashboard/charts/Scatter.d.ts +38 -0
- package/dist/components/dashboard/charts/Scatter.js +122 -0
- package/dist/components/dashboard/charts/Sparkline.d.ts +37 -0
- package/dist/components/dashboard/charts/Sparkline.js +128 -0
- package/dist/components/dashboard/charts/Treemap.d.ts +30 -0
- package/dist/components/dashboard/charts/Treemap.js +98 -0
- package/dist/components/dashboard/charts/index.d.ts +38 -0
- package/dist/components/dashboard/charts/index.js +23 -0
- package/dist/components/dashboard/charts/india-map.d.ts +22 -0
- package/dist/components/dashboard/charts/india-map.js +461 -0
- package/dist/components/dashboard/charts/theme.d.ts +107 -0
- package/dist/components/dashboard/charts/theme.js +124 -0
- package/dist/components/dashboard/config.d.ts +96 -0
- package/dist/components/dashboard/config.js +113 -0
- package/dist/components/dashboard/index.d.ts +10 -0
- package/dist/components/dashboard/index.js +13 -0
- package/dist/components/dashboard/kpi/KpiBeforeAfter.d.ts +31 -0
- package/dist/components/dashboard/kpi/KpiBeforeAfter.js +13 -0
- package/dist/components/dashboard/kpi/KpiBreakdown.d.ts +31 -0
- package/dist/components/dashboard/kpi/KpiBreakdown.js +39 -0
- package/dist/components/dashboard/kpi/KpiComparison.d.ts +36 -0
- package/dist/components/dashboard/kpi/KpiComparison.js +38 -0
- package/dist/components/dashboard/kpi/KpiQuickStats.d.ts +30 -0
- package/dist/components/dashboard/kpi/KpiQuickStats.js +38 -0
- package/dist/components/dashboard/kpi/KpiRating.d.ts +46 -0
- package/dist/components/dashboard/kpi/KpiRating.js +35 -0
- package/dist/components/dashboard/kpi/KpiScroll.d.ts +63 -0
- package/dist/components/dashboard/kpi/KpiScroll.js +80 -0
- package/dist/components/dashboard/kpi/KpiTrend.d.ts +28 -0
- package/dist/components/dashboard/kpi/KpiTrend.js +34 -0
- package/dist/components/dashboard/kpi/index.d.ts +16 -0
- package/dist/components/dashboard/kpi/index.js +10 -0
- package/dist/components/dashboard/kpi/kpi-shell.d.ts +44 -0
- package/dist/components/dashboard/kpi/kpi-shell.js +108 -0
- package/dist/components/dashboard/time-range.d.ts +12 -0
- package/dist/components/dashboard/time-range.js +118 -0
- package/dist/components/datagrid/DataGrid.d.ts +126 -0
- package/dist/components/datagrid/DataGrid.js +1577 -0
- package/dist/components/datagrid/cells/BooleanCell.d.ts +15 -0
- package/dist/components/datagrid/cells/BooleanCell.js +39 -0
- package/dist/components/datagrid/cells/CellRenderer.d.ts +25 -0
- package/dist/components/datagrid/cells/CellRenderer.js +139 -0
- package/dist/components/datagrid/cells/EditableCell.d.ts +35 -0
- package/dist/components/datagrid/cells/EditableCell.js +179 -0
- package/dist/components/datagrid/cells/SelectionCell.d.ts +11 -0
- package/dist/components/datagrid/cells/SelectionCell.js +58 -0
- package/dist/components/datagrid/cells/index.d.ts +1 -0
- package/dist/components/datagrid/cells/index.js +2 -0
- package/dist/components/datagrid/columns/ActionsColumn.d.ts +174 -0
- package/dist/components/datagrid/columns/ActionsColumn.js +448 -0
- package/dist/components/datagrid/columns/ColumnContextMenu.d.ts +16 -0
- package/dist/components/datagrid/columns/ColumnContextMenu.js +338 -0
- package/dist/components/datagrid/columns/DraggableColumnHeader.d.ts +19 -0
- package/dist/components/datagrid/columns/DraggableColumnHeader.js +147 -0
- package/dist/components/datagrid/controls/AutoResizeButton.d.ts +8 -0
- package/dist/components/datagrid/controls/AutoResizeButton.js +7 -0
- package/dist/components/datagrid/controls/PaginationControls.d.ts +13 -0
- package/dist/components/datagrid/controls/PaginationControls.js +34 -0
- package/dist/components/datagrid/controls/SummaryControls.d.ts +10 -0
- package/dist/components/datagrid/controls/SummaryControls.js +27 -0
- package/dist/components/datagrid/controls/menu/ActionsMenu.d.ts +31 -0
- package/dist/components/datagrid/controls/menu/ActionsMenu.js +13 -0
- package/dist/components/datagrid/controls/menu/column/ColumnChooserModal.d.ts +13 -0
- package/dist/components/datagrid/controls/menu/column/ColumnChooserModal.js +22 -0
- package/dist/components/datagrid/controls/menu/column/ColumnSection.d.ts +9 -0
- package/dist/components/datagrid/controls/menu/column/ColumnSection.js +7 -0
- package/dist/components/datagrid/controls/menu/export/ExportSection.d.ts +7 -0
- package/dist/components/datagrid/controls/menu/export/ExportSection.js +16 -0
- package/dist/components/datagrid/controls/menu/export/export.d.ts +21 -0
- package/dist/components/datagrid/controls/menu/export/export.js +187 -0
- package/dist/components/datagrid/controls/menu/filter/AdvancedFilterModal.d.ts +29 -0
- package/dist/components/datagrid/controls/menu/filter/AdvancedFilterModal.js +369 -0
- package/dist/components/datagrid/controls/menu/filter/FilterSection.d.ts +12 -0
- package/dist/components/datagrid/controls/menu/filter/FilterSection.js +6 -0
- package/dist/components/datagrid/controls/menu/grouping/GroupingSection.d.ts +10 -0
- package/dist/components/datagrid/controls/menu/grouping/GroupingSection.js +20 -0
- package/dist/components/datagrid/controls/menu/grouping/index.d.ts +1 -0
- package/dist/components/datagrid/controls/menu/grouping/index.js +2 -0
- package/dist/components/datagrid/controls/menu/import/ImportSection.d.ts +6 -0
- package/dist/components/datagrid/controls/menu/import/ImportSection.js +72 -0
- package/dist/components/datagrid/controls/menu/import/import.d.ts +27 -0
- package/dist/components/datagrid/controls/menu/import/import.js +193 -0
- package/dist/components/datagrid/controls/menu/index.d.ts +10 -0
- package/dist/components/datagrid/controls/menu/index.js +11 -0
- package/dist/components/datagrid/controls/menu/view/CardView.d.ts +17 -0
- package/dist/components/datagrid/controls/menu/view/CardView.js +173 -0
- package/dist/components/datagrid/controls/menu/view/ChartView.d.ts +9 -0
- package/dist/components/datagrid/controls/menu/view/ChartView.js +363 -0
- package/dist/components/datagrid/controls/menu/view/ViewSection.d.ts +7 -0
- package/dist/components/datagrid/controls/menu/view/ViewSection.js +9 -0
- package/dist/components/datagrid/hooks/useCellRangeSelection.d.ts +20 -0
- package/dist/components/datagrid/hooks/useCellRangeSelection.js +124 -0
- package/dist/components/datagrid/hooks/useClipboard.d.ts +15 -0
- package/dist/components/datagrid/hooks/useClipboard.js +151 -0
- package/dist/components/datagrid/hooks/useDataGridState.d.ts +46 -0
- package/dist/components/datagrid/hooks/useDataGridState.js +112 -0
- package/dist/components/datagrid/hooks/useKeyboardNavigation.d.ts +18 -0
- package/dist/components/datagrid/hooks/useKeyboardNavigation.js +117 -0
- package/dist/components/datagrid/index.d.ts +34 -0
- package/dist/components/datagrid/index.js +41 -0
- package/dist/components/datagrid/rows/DraggableRow.d.ts +33 -0
- package/dist/components/datagrid/rows/DraggableRow.js +31 -0
- package/dist/components/datagrid/rows/ExpandableRow.d.ts +48 -0
- package/dist/components/datagrid/rows/ExpandableRow.js +178 -0
- package/dist/components/datagrid/rows/FilterRow.d.ts +10 -0
- package/dist/components/datagrid/rows/FilterRow.js +185 -0
- package/dist/components/datagrid/rows/SelectColumn.d.ts +2 -0
- package/dist/components/datagrid/rows/SelectColumn.js +31 -0
- package/dist/components/datagrid/rows/SummaryRow.d.ts +12 -0
- package/dist/components/datagrid/rows/SummaryRow.js +31 -0
- package/dist/components/datagrid/rows/summary.d.ts +9 -0
- package/dist/components/datagrid/rows/summary.js +63 -0
- package/dist/components/datagrid/search/InlineSearchCell.d.ts +13 -0
- package/dist/components/datagrid/search/InlineSearchCell.js +96 -0
- package/dist/components/datagrid/search/SearchHighlighter.d.ts +16 -0
- package/dist/components/datagrid/search/SearchHighlighter.js +124 -0
- package/dist/components/datagrid/search/SearchNavigator.d.ts +24 -0
- package/dist/components/datagrid/search/SearchNavigator.js +148 -0
- package/dist/components/datagrid/search/SearchNewModal.d.ts +12 -0
- package/dist/components/datagrid/search/SearchNewModal.js +202 -0
- package/dist/components/datagrid/search/advancedSearch.d.ts +23 -0
- package/dist/components/datagrid/search/advancedSearch.js +109 -0
- package/dist/components/datagrid/utils/grid-helpers.d.ts +34 -0
- package/dist/components/datagrid/utils/grid-helpers.js +94 -0
- package/dist/components/datagrid/utils/grid-types.d.ts +157 -0
- package/dist/components/datagrid/utils/grid-types.js +2 -0
- package/dist/components/draft/AutoSaveIndicator.d.ts +28 -0
- package/dist/components/draft/AutoSaveIndicator.js +67 -0
- package/dist/components/draft/DraftModal.d.ts +27 -0
- package/dist/components/draft/DraftModal.js +184 -0
- package/dist/components/forms/date-picker/CalendarView.d.ts +17 -0
- package/dist/components/forms/date-picker/CalendarView.js +46 -0
- package/dist/components/forms/date-picker/DatePicker.d.ts +31 -0
- package/dist/components/forms/date-picker/DatePicker.js +712 -0
- package/dist/components/forms/date-picker/DateTimePicker.d.ts +15 -0
- package/dist/components/forms/date-picker/DateTimePicker.js +138 -0
- package/dist/components/forms/date-picker/index.d.ts +7 -0
- package/dist/components/forms/date-picker/index.js +9 -0
- package/dist/components/forms/date-picker/shared-utils.d.ts +6 -0
- package/dist/components/forms/date-picker/shared-utils.js +19 -0
- package/dist/components/forms/dropdown/Dropdown.d.ts +144 -0
- package/dist/components/forms/dropdown/Dropdown.js +384 -0
- package/dist/components/forms/dropdown/MultiSelect.d.ts +29 -0
- package/dist/components/forms/dropdown/MultiSelect.js +100 -0
- package/dist/components/forms/dropdown/SingleSelect.d.ts +39 -0
- package/dist/components/forms/dropdown/SingleSelect.js +218 -0
- package/dist/components/forms/dropdown/hooks/useDropdownCreate.d.ts +8 -0
- package/dist/components/forms/dropdown/hooks/useDropdownCreate.js +52 -0
- package/dist/components/forms/dropdown/hooks/useDropdownFiltering.d.ts +5 -0
- package/dist/components/forms/dropdown/hooks/useDropdownFiltering.js +51 -0
- package/dist/components/forms/dropdown/hooks/useDropdownState.d.ts +7 -0
- package/dist/components/forms/dropdown/hooks/useDropdownState.js +27 -0
- package/dist/components/forms/dropdown/index.d.ts +2 -0
- package/dist/components/forms/dropdown/index.js +2 -0
- package/dist/components/forms/dropdown/types.d.ts +67 -0
- package/dist/components/forms/dropdown/types.js +2 -0
- package/dist/components/forms/file-attachment/EmailPreview.d.ts +5 -0
- package/dist/components/forms/file-attachment/EmailPreview.js +383 -0
- package/dist/components/forms/file-attachment/FileAttachment.d.ts +30 -0
- package/dist/components/forms/file-attachment/FileAttachment.js +930 -0
- package/dist/components/forms/file-attachment/index.d.ts +2 -0
- package/dist/components/forms/file-attachment/index.js +2 -0
- package/dist/components/forms/index.d.ts +9 -0
- package/dist/components/forms/index.js +7 -0
- package/dist/components/forms/quantity-input-popup.d.ts +10 -0
- package/dist/components/forms/quantity-input-popup.js +99 -0
- package/dist/components/forms/remark-input/RemarkInput.d.ts +58 -0
- package/dist/components/forms/remark-input/RemarkInput.js +258 -0
- package/dist/components/forms/remark-input/index.d.ts +1 -0
- package/dist/components/forms/remark-input/index.js +2 -0
- package/dist/components/forms/unified-currency-dropdown.d.ts +26 -0
- package/dist/components/forms/unified-currency-dropdown.js +166 -0
- package/dist/components/index.d.ts +14 -0
- package/dist/components/index.js +15 -0
- package/dist/components/layout/SidebarContextMenu.d.ts +18 -0
- package/dist/components/layout/SidebarContextMenu.js +142 -0
- package/dist/components/layout/app-shell.d.ts +32 -0
- package/dist/components/layout/app-shell.js +43 -0
- package/dist/components/layout/bottom-nav.d.ts +28 -0
- package/dist/components/layout/bottom-nav.js +219 -0
- package/dist/components/layout/floating-action-button.d.ts +10 -0
- package/dist/components/layout/floating-action-button.js +74 -0
- package/dist/components/layout/footer.d.ts +37 -0
- package/dist/components/layout/footer.js +56 -0
- package/dist/components/layout/index.d.ts +8 -0
- package/dist/components/layout/index.js +6 -0
- package/dist/components/layout/mobile-menu-sheet.d.ts +7 -0
- package/dist/components/layout/mobile-menu-sheet.js +159 -0
- package/dist/components/layout/side-panel.d.ts +50 -0
- package/dist/components/layout/side-panel.js +115 -0
- package/dist/components/layout/sidebar.d.ts +12 -0
- package/dist/components/layout/sidebar.js +542 -0
- package/dist/components/layout/top-header.d.ts +8 -0
- package/dist/components/layout/top-header.js +234 -0
- package/dist/components/layout/userprofile-dropdown.d.ts +1 -0
- package/dist/components/layout/userprofile-dropdown.js +97 -0
- package/dist/components/master/editable-cells/EditableCell.d.ts +43 -0
- package/dist/components/master/editable-cells/EditableCell.js +66 -0
- package/dist/components/master/editable-cells/index.d.ts +9 -0
- package/dist/components/master/editable-cells/index.js +10 -0
- package/dist/components/master/index.d.ts +1 -0
- package/dist/components/master/index.js +3 -0
- package/dist/components/messaging/conversation-list.d.ts +13 -0
- package/dist/components/messaging/conversation-list.js +103 -0
- package/dist/components/messaging/create-conversation-modal.d.ts +9 -0
- package/dist/components/messaging/create-conversation-modal.js +109 -0
- package/dist/components/messaging/message-bubble.d.ts +15 -0
- package/dist/components/messaging/message-bubble.js +66 -0
- package/dist/components/messaging/message-input.d.ts +17 -0
- package/dist/components/messaging/message-input.js +151 -0
- package/dist/components/messaging/message-thread.d.ts +10 -0
- package/dist/components/messaging/message-thread.js +121 -0
- package/dist/components/messaging/messaging-panel-content.d.ts +5 -0
- package/dist/components/messaging/messaging-panel-content.js +66 -0
- package/dist/components/messaging/thread-panel.d.ts +10 -0
- package/dist/components/messaging/thread-panel.js +47 -0
- package/dist/components/modals/3DModal.d.ts +39 -0
- package/dist/components/modals/3DModal.js +32 -0
- package/dist/components/modals/ImageModal.d.ts +28 -0
- package/dist/components/modals/ImageModal.js +551 -0
- package/dist/components/modals/Modal.d.ts +92 -0
- package/dist/components/modals/Modal.js +264 -0
- package/dist/components/modals/StandardModal.d.ts +27 -0
- package/dist/components/modals/StandardModal.js +25 -0
- package/dist/components/modals/api-config-modal.d.ts +7 -0
- package/dist/components/modals/api-config-modal.js +117 -0
- package/dist/components/modals/global-api-config-modal.d.ts +7 -0
- package/dist/components/modals/global-api-config-modal.js +124 -0
- package/dist/components/modals/index.d.ts +7 -0
- package/dist/components/modals/index.js +8 -0
- package/dist/components/modals/logout-modal.d.ts +32 -0
- package/dist/components/modals/logout-modal.js +42 -0
- package/dist/components/modals/modal-alert.d.ts +139 -0
- package/dist/components/modals/modal-alert.js +250 -0
- package/dist/components/modals/password-reset-modal.d.ts +11 -0
- package/dist/components/modals/password-reset-modal.js +109 -0
- package/dist/components/modals/session-expiry-warning.d.ts +12 -0
- package/dist/components/modals/session-expiry-warning.js +15 -0
- package/dist/components/providers/api-provider.d.ts +10 -0
- package/dist/components/providers/api-provider.js +15 -0
- package/dist/components/providers/query-provider.d.ts +3 -0
- package/dist/components/providers/query-provider.js +26 -0
- package/dist/components/providers/session-provider.d.ts +7 -0
- package/dist/components/providers/session-provider.js +116 -0
- package/dist/components/theme/ThemeCustomizer.d.ts +37 -0
- package/dist/components/theme/ThemeCustomizer.js +178 -0
- package/dist/components/ui/buttons/button.d.ts +59 -0
- package/dist/components/ui/buttons/button.js +228 -0
- package/dist/components/ui/card.d.ts +8 -0
- package/dist/components/ui/card.js +17 -0
- package/dist/components/ui/chart.d.ts +83 -0
- package/dist/components/ui/chart.js +113 -0
- package/dist/components/ui/display/boolean-badge.d.ts +7 -0
- package/dist/components/ui/display/boolean-badge.js +23 -0
- package/dist/components/ui/display/card.d.ts +10 -0
- package/dist/components/ui/display/card.js +11 -0
- package/dist/components/ui/display/collapsible.d.ts +6 -0
- package/dist/components/ui/display/collapsible.js +6 -0
- package/dist/components/ui/display/separator.d.ts +4 -0
- package/dist/components/ui/display/separator.js +8 -0
- package/dist/components/ui/display/stats-card.d.ts +22 -0
- package/dist/components/ui/display/stats-card.js +25 -0
- package/dist/components/ui/display/text.d.ts +14 -0
- package/dist/components/ui/display/text.js +57 -0
- package/dist/components/ui/feedback/alert.d.ts +8 -0
- package/dist/components/ui/feedback/alert.js +23 -0
- package/dist/components/ui/feedback/badge.d.ts +49 -0
- package/dist/components/ui/feedback/badge.js +87 -0
- package/dist/components/ui/feedback/progress.d.ts +4 -0
- package/dist/components/ui/feedback/progress.js +8 -0
- package/dist/components/ui/feedback/reminder-button.d.ts +22 -0
- package/dist/components/ui/feedback/reminder-button.js +75 -0
- package/dist/components/ui/feedback/skeleton-table.d.ts +18 -0
- package/dist/components/ui/feedback/skeleton-table.js +17 -0
- package/dist/components/ui/feedback/skeleton.d.ts +53 -0
- package/dist/components/ui/feedback/skeleton.js +48 -0
- package/dist/components/ui/feedback/tooltip.d.ts +15 -0
- package/dist/components/ui/feedback/tooltip.js +14 -0
- package/dist/components/ui/form-toggle.d.ts +57 -0
- package/dist/components/ui/form-toggle.js +44 -0
- package/dist/components/ui/forms/checkbox.d.ts +6 -0
- package/dist/components/ui/forms/checkbox.js +17 -0
- package/dist/components/ui/forms/input.d.ts +18 -0
- package/dist/components/ui/forms/input.js +75 -0
- package/dist/components/ui/forms/label.d.ts +5 -0
- package/dist/components/ui/forms/label.js +6 -0
- package/dist/components/ui/forms/switch.d.ts +10 -0
- package/dist/components/ui/forms/switch.js +22 -0
- package/dist/components/ui/forms/textarea.d.ts +8 -0
- package/dist/components/ui/forms/textarea.js +13 -0
- package/dist/components/ui/index.d.ts +49 -0
- package/dist/components/ui/index.js +62 -0
- package/dist/components/ui/navigation/dropdown-menu.d.ts +27 -0
- package/dist/components/ui/navigation/dropdown-menu.js +34 -0
- package/dist/components/ui/navigation/header-steps.d.ts +16 -0
- package/dist/components/ui/navigation/header-steps.js +15 -0
- package/dist/components/ui/navigation/tabs.d.ts +40 -0
- package/dist/components/ui/navigation/tabs.js +59 -0
- package/dist/components/ui/overlays/loading.d.ts +47 -0
- package/dist/components/ui/overlays/loading.js +131 -0
- package/dist/components/ui/select.d.ts +13 -0
- package/dist/components/ui/select.js +27 -0
- package/dist/config/api.d.ts +30 -0
- package/dist/config/api.js +58 -0
- package/dist/contexts/AppConfigContext.d.ts +13 -0
- package/dist/contexts/AppConfigContext.js +33 -0
- package/dist/contexts/CurrencyContext.d.ts +43 -0
- package/dist/contexts/CurrencyContext.js +331 -0
- package/dist/contexts/DeviceContext.d.ts +12 -0
- package/dist/contexts/DeviceContext.js +69 -0
- package/dist/contexts/EmailContext.d.ts +112 -0
- package/dist/contexts/EmailContext.js +720 -0
- package/dist/contexts/GlobalAlertContext.d.ts +67 -0
- package/dist/contexts/GlobalAlertContext.js +192 -0
- package/dist/contexts/ImpactAnalysisContext.d.ts +11 -0
- package/dist/contexts/ImpactAnalysisContext.js +23 -0
- package/dist/contexts/LanguageContext.d.ts +21 -0
- package/dist/contexts/LanguageContext.js +66 -0
- package/dist/contexts/MessagingContext.d.ts +70 -0
- package/dist/contexts/MessagingContext.js +722 -0
- package/dist/contexts/ModuleAuthContext.d.ts +42 -0
- package/dist/contexts/ModuleAuthContext.js +278 -0
- package/dist/contexts/NavigationContext.d.ts +26 -0
- package/dist/contexts/NavigationContext.js +143 -0
- package/dist/contexts/NetworkStatusContext.d.ts +18 -0
- package/dist/contexts/NetworkStatusContext.js +87 -0
- package/dist/contexts/NotificationContext.d.ts +47 -0
- package/dist/contexts/NotificationContext.js +165 -0
- package/dist/contexts/PageTitleContext.d.ts +11 -0
- package/dist/contexts/PageTitleContext.js +23 -0
- package/dist/contexts/SearchPreferencesContext.d.ts +11 -0
- package/dist/contexts/SearchPreferencesContext.js +38 -0
- package/dist/contexts/SessionAdapterContext.d.ts +39 -0
- package/dist/contexts/SessionAdapterContext.js +20 -0
- package/dist/contexts/SidebarPreferencesContext.d.ts +19 -0
- package/dist/contexts/SidebarPreferencesContext.js +112 -0
- package/dist/contexts/ThemeContext.d.ts +63 -0
- package/dist/contexts/ThemeContext.js +153 -0
- package/dist/hooks/index.d.ts +23 -0
- package/dist/hooks/index.js +18 -0
- package/dist/hooks/useApproval.d.ts +47 -0
- package/dist/hooks/useApproval.js +247 -0
- package/dist/hooks/useBacchaSearch.d.ts +57 -0
- package/dist/hooks/useBacchaSearch.js +254 -0
- package/dist/hooks/useBusinessAudit.d.ts +24 -0
- package/dist/hooks/useBusinessAudit.js +51 -0
- package/dist/hooks/useColumnFreezing.d.ts +85 -0
- package/dist/hooks/useColumnFreezing.js +201 -0
- package/dist/hooks/useColumnMetadata.d.ts +20 -0
- package/dist/hooks/useColumnMetadata.js +44 -0
- package/dist/hooks/useConditionalFormatting.d.ts +43 -0
- package/dist/hooks/useConditionalFormatting.js +193 -0
- package/dist/hooks/useDebounce.d.ts +14 -0
- package/dist/hooks/useDebounce.js +45 -0
- package/dist/hooks/useDraft.d.ts +46 -0
- package/dist/hooks/useDraft.js +178 -0
- package/dist/hooks/useFormValidation.d.ts +37 -0
- package/dist/hooks/useFormValidation.js +65 -0
- package/dist/hooks/useGridSettings.d.ts +26 -0
- package/dist/hooks/useGridSettings.js +82 -0
- package/dist/hooks/useGridTheme.d.ts +59 -0
- package/dist/hooks/useGridTheme.js +199 -0
- package/dist/hooks/useId.d.ts +2 -0
- package/dist/hooks/useId.js +17 -0
- package/dist/hooks/useIntelligentColumnSizing.d.ts +71 -0
- package/dist/hooks/useIntelligentColumnSizing.js +310 -0
- package/dist/hooks/useKeyboardNavigation.d.ts +33 -0
- package/dist/hooks/useKeyboardNavigation.js +189 -0
- package/dist/hooks/useNotifications.d.ts +7 -0
- package/dist/hooks/useNotifications.js +56 -0
- package/dist/hooks/usePrevious.d.ts +9 -0
- package/dist/hooks/usePrevious.js +17 -0
- package/dist/hooks/useRowSelection.d.ts +45 -0
- package/dist/hooks/useRowSelection.js +147 -0
- package/dist/hooks/useSignalR.d.ts +13 -0
- package/dist/hooks/useSignalR.js +50 -0
- package/dist/hooks/useTheme.d.ts +59 -0
- package/dist/hooks/useTheme.js +261 -0
- package/dist/hooks/useTranslation.d.ts +5 -0
- package/dist/hooks/useTranslation.js +17 -0
- package/dist/hooks/useUnsavedChanges.d.ts +40 -0
- package/dist/hooks/useUnsavedChanges.js +83 -0
- package/dist/index.d.ts +2 -3173
- package/dist/index.js +4 -25937
- package/dist/lib/api/activity/audit/audit.d.ts +34 -0
- package/dist/lib/api/activity/audit/audit.js +44 -0
- package/dist/lib/api/activity/audit/index.d.ts +6 -0
- package/dist/lib/api/activity/audit/index.js +7 -0
- package/dist/lib/api/activity/audit/send.d.ts +152 -0
- package/dist/lib/api/activity/audit/send.js +403 -0
- package/dist/lib/api/activity/email/client.d.ts +167 -0
- package/dist/lib/api/activity/email/client.js +455 -0
- package/dist/lib/api/activity/email/index.d.ts +7 -0
- package/dist/lib/api/activity/email/index.js +10 -0
- package/dist/lib/api/activity/email/password-reset.d.ts +8 -0
- package/dist/lib/api/activity/email/password-reset.js +55 -0
- package/dist/lib/api/activity/email/templates.d.ts +10 -0
- package/dist/lib/api/activity/email/templates.js +531 -0
- package/dist/lib/api/activity/email/types.d.ts +237 -0
- package/dist/lib/api/activity/email/types.js +21 -0
- package/dist/lib/api/activity/index.d.ts +12 -0
- package/dist/lib/api/activity/index.js +15 -0
- package/dist/lib/api/activity/messaging/messaging.d.ts +149 -0
- package/dist/lib/api/activity/messaging/messaging.js +245 -0
- package/dist/lib/api/activity/notifications/index.d.ts +9 -0
- package/dist/lib/api/activity/notifications/index.js +9 -0
- package/dist/lib/api/activity/notifications/notifications.d.ts +59 -0
- package/dist/lib/api/activity/notifications/notifications.js +218 -0
- package/dist/lib/api/activity/notifications/reminders.d.ts +35 -0
- package/dist/lib/api/activity/notifications/reminders.js +25 -0
- package/dist/lib/api/activity/notifications/send.d.ts +122 -0
- package/dist/lib/api/activity/notifications/send.js +252 -0
- package/dist/lib/api/activity/notifications/types.d.ts +119 -0
- package/dist/lib/api/activity/notifications/types.js +62 -0
- package/dist/lib/api/activity/notify-and-log.d.ts +50 -0
- package/dist/lib/api/activity/notify-and-log.js +60 -0
- package/dist/lib/api/activity/remarks/index.d.ts +2 -0
- package/dist/lib/api/activity/remarks/index.js +2 -0
- package/dist/lib/api/activity/remarks/remarks.d.ts +83 -0
- package/dist/lib/api/activity/remarks/remarks.js +179 -0
- package/dist/lib/api/activity/storage.d.ts +28 -0
- package/dist/lib/api/activity/storage.js +79 -0
- package/dist/lib/api/ai/chat.d.ts +67 -0
- package/dist/lib/api/ai/chat.js +212 -0
- package/dist/lib/api/ai/types.d.ts +69 -0
- package/dist/lib/api/ai/types.js +5 -0
- package/dist/lib/api/approval/approvals.d.ts +66 -0
- package/dist/lib/api/approval/approvals.js +205 -0
- package/dist/lib/api/approval/index.d.ts +5 -0
- package/dist/lib/api/approval/index.js +6 -0
- package/dist/lib/api/auth/auth.d.ts +12 -0
- package/dist/lib/api/auth/auth.js +148 -0
- package/dist/lib/api/auth/index.d.ts +1 -0
- package/dist/lib/api/auth/index.js +4 -0
- package/dist/lib/api/auth/password-reset-otp.d.ts +49 -0
- package/dist/lib/api/auth/password-reset-otp.js +185 -0
- package/dist/lib/api/auth/two-factor-auth.d.ts +55 -0
- package/dist/lib/api/auth/two-factor-auth.js +84 -0
- package/dist/lib/api/auth/two-factor.d.ts +41 -0
- package/dist/lib/api/auth/two-factor.js +180 -0
- package/dist/lib/api/core/auth-helpers.d.ts +13 -0
- package/dist/lib/api/core/auth-helpers.js +137 -0
- package/dist/lib/api/core/client.d.ts +37 -0
- package/dist/lib/api/core/client.js +301 -0
- package/dist/lib/api/core/config.d.ts +46 -0
- package/dist/lib/api/core/config.js +238 -0
- package/dist/lib/api/core/index.d.ts +6 -0
- package/dist/lib/api/core/index.js +11 -0
- package/dist/lib/api/core/session-validator.d.ts +55 -0
- package/dist/lib/api/core/session-validator.js +94 -0
- package/dist/lib/api/core/types.d.ts +192 -0
- package/dist/lib/api/core/types.js +3 -0
- package/dist/lib/api/core/utils.d.ts +15 -0
- package/dist/lib/api/core/utils.js +64 -0
- package/dist/lib/api/dashboard/costing.d.ts +129 -0
- package/dist/lib/api/dashboard/costing.js +8 -0
- package/dist/lib/api/dashboard/management.d.ts +91 -0
- package/dist/lib/api/dashboard/management.js +5 -0
- package/dist/lib/api/dashboard/sales.d.ts +87 -0
- package/dist/lib/api/dashboard/sales.js +5 -0
- package/dist/lib/api/draft/drafts.d.ts +49 -0
- package/dist/lib/api/draft/drafts.js +274 -0
- package/dist/lib/api/draft/index.d.ts +5 -0
- package/dist/lib/api/draft/index.js +6 -0
- package/dist/lib/api/enquiry/enquiry.d.ts +324 -0
- package/dist/lib/api/enquiry/enquiry.js +617 -0
- package/dist/lib/api/enquiry/index.d.ts +2 -0
- package/dist/lib/api/enquiry/index.js +4 -0
- package/dist/lib/api/enquiry/rate-enquiry.d.ts +97 -0
- package/dist/lib/api/enquiry/rate-enquiry.js +69 -0
- package/dist/lib/api/estimation/categories.d.ts +28 -0
- package/dist/lib/api/estimation/categories.js +104 -0
- package/dist/lib/api/estimation/category-defaults.d.ts +56 -0
- package/dist/lib/api/estimation/category-defaults.js +41 -0
- package/dist/lib/api/estimation/company-config.d.ts +59 -0
- package/dist/lib/api/estimation/company-config.js +19 -0
- package/dist/lib/api/estimation/content.d.ts +103 -0
- package/dist/lib/api/estimation/content.js +203 -0
- package/dist/lib/api/estimation/freight.d.ts +34 -0
- package/dist/lib/api/estimation/freight.js +18 -0
- package/dist/lib/api/estimation/grid-costing-drafts.d.ts +38 -0
- package/dist/lib/api/estimation/grid-costing-drafts.js +21 -0
- package/dist/lib/api/estimation/grid-costing.d.ts +353 -0
- package/dist/lib/api/estimation/grid-costing.js +126 -0
- package/dist/lib/api/estimation/index.d.ts +10 -0
- package/dist/lib/api/estimation/index.js +22 -0
- package/dist/lib/api/estimation/legacy-costing.d.ts +42 -0
- package/dist/lib/api/estimation/legacy-costing.js +46 -0
- package/dist/lib/api/estimation/machines.d.ts +32 -0
- package/dist/lib/api/estimation/machines.js +67 -0
- package/dist/lib/api/estimation/planning.d.ts +479 -0
- package/dist/lib/api/estimation/planning.js +385 -0
- package/dist/lib/api/estimation/qualities.d.ts +128 -0
- package/dist/lib/api/estimation/qualities.js +229 -0
- package/dist/lib/api/estimation/quotation-load.d.ts +30 -0
- package/dist/lib/api/estimation/quotation-load.js +46 -0
- package/dist/lib/api/estimation/quotation-save.d.ts +88 -0
- package/dist/lib/api/estimation/quotation-save.js +101 -0
- package/dist/lib/api/estimation/quote-check.d.ts +19 -0
- package/dist/lib/api/estimation/quote-check.js +28 -0
- package/dist/lib/api/estimation/quotepanel.d.ts +304 -0
- package/dist/lib/api/estimation/quotepanel.js +489 -0
- package/dist/lib/api/estimation/shipper-planning.d.ts +71 -0
- package/dist/lib/api/estimation/shipper-planning.js +208 -0
- package/dist/lib/api/estimation/wastage.d.ts +40 -0
- package/dist/lib/api/estimation/wastage.js +40 -0
- package/dist/lib/api/index.d.ts +7 -0
- package/dist/lib/api/index.js +17 -0
- package/dist/lib/api/integration/proxy.d.ts +7 -0
- package/dist/lib/api/integration/proxy.js +34 -0
- package/dist/lib/api/master/category.d.ts +126 -0
- package/dist/lib/api/master/category.js +208 -0
- package/dist/lib/api/master/company.d.ts +167 -0
- package/dist/lib/api/master/company.js +368 -0
- package/dist/lib/api/master/hsn.d.ts +36 -0
- package/dist/lib/api/master/hsn.js +54 -0
- package/dist/lib/api/master/index.d.ts +12 -0
- package/dist/lib/api/master/index.js +27 -0
- package/dist/lib/api/master/item.d.ts +158 -0
- package/dist/lib/api/master/item.js +135 -0
- package/dist/lib/api/master/ledger.d.ts +173 -0
- package/dist/lib/api/master/ledger.js +391 -0
- package/dist/lib/api/master/logistics.d.ts +117 -0
- package/dist/lib/api/master/logistics.js +107 -0
- package/dist/lib/api/master/machine.d.ts +406 -0
- package/dist/lib/api/master/machine.js +570 -0
- package/dist/lib/api/master/material-group.d.ts +97 -0
- package/dist/lib/api/master/material-group.js +96 -0
- package/dist/lib/api/master/other.d.ts +65 -0
- package/dist/lib/api/master/other.js +56 -0
- package/dist/lib/api/master/process-types.d.ts +178 -0
- package/dist/lib/api/master/process-types.js +4 -0
- package/dist/lib/api/master/process.d.ts +94 -0
- package/dist/lib/api/master/process.js +124 -0
- package/dist/lib/api/master/production-units.d.ts +10 -0
- package/dist/lib/api/master/production-units.js +15 -0
- package/dist/lib/api/master/rate.d.ts +174 -0
- package/dist/lib/api/master/rate.js +196 -0
- package/dist/lib/api/master/tool.d.ts +48 -0
- package/dist/lib/api/master/tool.js +80 -0
- package/dist/lib/api/master/user.d.ts +473 -0
- package/dist/lib/api/master/user.js +147 -0
- package/dist/lib/api/settings/erp-parameters.d.ts +33 -0
- package/dist/lib/api/settings/erp-parameters.js +61 -0
- package/dist/lib/api/utility/index.d.ts +1 -0
- package/dist/lib/api/utility/index.js +5 -0
- package/dist/lib/api/utility/menu.d.ts +32 -0
- package/dist/lib/api/utility/menu.js +128 -0
- package/dist/lib/auth.d.ts +3 -0
- package/dist/lib/auth.js +7 -0
- package/dist/lib/pwa.d.ts +8 -0
- package/dist/lib/pwa.js +53 -0
- package/dist/lib/react-query-config.d.ts +140 -0
- package/dist/lib/react-query-config.js +131 -0
- package/dist/lib/security/audit-logger.d.ts +71 -0
- package/dist/lib/security/audit-logger.js +173 -0
- package/dist/lib/security/rate-limiter.d.ts +28 -0
- package/dist/lib/security/rate-limiter.js +118 -0
- package/dist/lib/server-url.d.ts +18 -0
- package/dist/lib/server-url.js +70 -0
- package/dist/lib/svg-utils.d.ts +62 -0
- package/dist/lib/svg-utils.js +206 -0
- package/dist/lib/theme/types.d.ts +109 -0
- package/dist/lib/theme/types.js +231 -0
- package/dist/lib/theme/utils.d.ts +73 -0
- package/dist/lib/theme/utils.js +343 -0
- package/dist/lib/types/index.d.ts +58 -0
- package/dist/lib/types/index.js +2 -0
- package/dist/lib/utils/attachment-loader.d.ts +27 -0
- package/dist/lib/utils/attachment-loader.js +79 -0
- package/dist/lib/utils/client-lead-utils.d.ts +24 -0
- package/dist/lib/utils/client-lead-utils.js +56 -0
- package/dist/lib/utils/device-detection.d.ts +19 -0
- package/dist/lib/utils/device-detection.js +105 -0
- package/dist/lib/utils/logout-cleanup.d.ts +63 -0
- package/dist/lib/utils/logout-cleanup.js +297 -0
- package/dist/lib/utils/planning-prefs.d.ts +10 -0
- package/dist/lib/utils/planning-prefs.js +27 -0
- package/dist/lib/utils.d.ts +20 -0
- package/dist/lib/utils.js +60 -0
- package/dist/lib/vision/dieline-extractor.d.ts +38 -0
- package/dist/lib/vision/dieline-extractor.js +313 -0
- package/dist/lib/vision/reference-grid.d.ts +52 -0
- package/dist/lib/vision/reference-grid.js +241 -0
- package/dist/locales/de.json +79 -0
- package/dist/locales/en.json +2217 -0
- package/dist/locales/es.json +79 -0
- package/dist/locales/fr.json +78 -0
- package/dist/locales/hi.json +1599 -0
- package/dist/providers.d.ts +14 -0
- package/dist/providers.js +15 -0
- package/dist/services/GlobalLoadingService.d.ts +216 -0
- package/dist/services/GlobalLoadingService.js +216 -0
- package/dist/styles/grid-themes.css +346 -0
- package/dist/styles/index.css +5 -0
- package/dist/{sidebar-scrollbar-NBCB2OO2.css → styles/sidebar-scrollbar.css} +45 -45
- package/dist/styles/tokens.css +713 -0
- package/dist/types/approval.d.ts +201 -0
- package/dist/types/approval.js +19 -0
- package/dist/types/audit.d.ts +87 -0
- package/dist/types/audit.js +47 -0
- package/dist/types/draft.d.ts +142 -0
- package/dist/types/draft.js +19 -0
- package/dist/types/master.d.ts +154 -0
- package/dist/types/master.js +3 -0
- package/dist/types/shipper-planning.d.ts +277 -0
- package/dist/types/shipper-planning.js +6 -0
- package/package.json +182 -119
- package/dist/chunk-4PEFU7N7.js +0 -16
- package/dist/chunk-4PEFU7N7.js.map +0 -1
- package/dist/de-EKT7SUK5.js +0 -106
- package/dist/de-EKT7SUK5.js.map +0 -1
- package/dist/en-QRFSIEHD.js +0 -1685
- package/dist/en-QRFSIEHD.js.map +0 -1
- package/dist/es-KHZMWGUI.js +0 -106
- package/dist/es-KHZMWGUI.js.map +0 -1
- package/dist/fr-X2XUXSHK.js +0 -105
- package/dist/fr-X2XUXSHK.js.map +0 -1
- package/dist/hi-YRATOE5Q.js +0 -415
- package/dist/hi-YRATOE5Q.js.map +0 -1
- package/dist/index.cjs +0 -28216
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -3173
- package/dist/index.js.map +0 -1
- /package/{src → dist/cjs}/styles/index.css +0 -0
|
@@ -0,0 +1,1032 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.Chat = Chat;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
/**
|
|
7
|
+
* Reusable chat with sidebar, sounds, floating widget, and mobile/desktop headers.
|
|
8
|
+
* Domain-specific branding (logo, title, messages) is injected via props.
|
|
9
|
+
*/
|
|
10
|
+
const react_1 = require("react");
|
|
11
|
+
const react_2 = require("next-auth/react");
|
|
12
|
+
const navigation_1 = require("next/navigation");
|
|
13
|
+
const lucide_react_1 = require("lucide-react");
|
|
14
|
+
const utils_1 = require("../../lib/utils.js");
|
|
15
|
+
const chat_1 = require("../../lib/api/ai/chat.js");
|
|
16
|
+
const GlobalAlertContext_1 = require("../../contexts/GlobalAlertContext.js");
|
|
17
|
+
const LanguageContext_1 = require("../../contexts/LanguageContext.js");
|
|
18
|
+
const side_panel_1 = require("../layout/side-panel.js");
|
|
19
|
+
const ai_messages_1 = require("./ai-messages.js");
|
|
20
|
+
const multimodal_input_1 = require("./multimodal-input.js");
|
|
21
|
+
const chat_prompt_navigator_1 = require("./chat-prompt-navigator.js");
|
|
22
|
+
const date_picker_1 = require("../forms/date-picker/index.js");
|
|
23
|
+
const utils_2 = require("../../lib/utils.js");
|
|
24
|
+
function buildSendPayload(ctx, message, autoTitle) {
|
|
25
|
+
if (ctx.mode === 'new') {
|
|
26
|
+
return { message, conversationId: undefined, newChat: true, title: autoTitle };
|
|
27
|
+
}
|
|
28
|
+
return { message, conversationId: ctx.id, newChat: false, title: null };
|
|
29
|
+
}
|
|
30
|
+
// Sidebar / search-modal date stamp: "19 May 2026, 3:42 PM".
|
|
31
|
+
function formatConversationStamp(iso) {
|
|
32
|
+
try {
|
|
33
|
+
const d = new Date(iso);
|
|
34
|
+
const date = d.toLocaleDateString(undefined, { day: '2-digit', month: 'short', year: 'numeric' });
|
|
35
|
+
const time = d.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
|
|
36
|
+
return `${date}, ${time}`;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return '';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Date-bucket key for a conversation timestamp. Buckets match the ChatGPT
|
|
43
|
+
// pattern: Today / Yesterday / Previous 7 Days / Previous 30 Days / Month YYYY.
|
|
44
|
+
function bucketForDate(iso, now = new Date()) {
|
|
45
|
+
if (!iso)
|
|
46
|
+
return { id: 'unknown', label: 'Older', sort: -1 };
|
|
47
|
+
const d = new Date(iso);
|
|
48
|
+
if (isNaN(d.getTime()))
|
|
49
|
+
return { id: 'unknown', label: 'Older', sort: -1 };
|
|
50
|
+
const startOfDay = (x) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();
|
|
51
|
+
const today = startOfDay(now);
|
|
52
|
+
const that = startOfDay(d);
|
|
53
|
+
const diffDays = Math.floor((today - that) / 86400000);
|
|
54
|
+
if (diffDays <= 0)
|
|
55
|
+
return { id: 'today', label: 'Today', sort: 1000 };
|
|
56
|
+
if (diffDays === 1)
|
|
57
|
+
return { id: 'yesterday', label: 'Yesterday', sort: 999 };
|
|
58
|
+
if (diffDays <= 7)
|
|
59
|
+
return { id: 'prev7', label: 'Previous 7 Days', sort: 998 };
|
|
60
|
+
if (diffDays <= 30)
|
|
61
|
+
return { id: 'prev30', label: 'Previous 30 Days', sort: 997 };
|
|
62
|
+
const monthLabel = d.toLocaleDateString(undefined, { month: 'long', year: 'numeric' });
|
|
63
|
+
const sort = -(d.getFullYear() * 12 + d.getMonth());
|
|
64
|
+
return { id: `m-${d.getFullYear()}-${d.getMonth()}`, label: monthLabel, sort };
|
|
65
|
+
}
|
|
66
|
+
function Chat({ mode = 'fullpage', externalMuted, title = 'Chat', sidebarTitle, bubbleLogo, logo, MessagesComponent, fullpagePath, onBeforeEditMessage, initialMessage, initialConversationId, headerActions, onMessagesChange }) {
|
|
67
|
+
const { data: session } = (0, react_2.useSession)();
|
|
68
|
+
const router = (0, navigation_1.useRouter)();
|
|
69
|
+
const alerts = (0, GlobalAlertContext_1.useGlobalAlert)();
|
|
70
|
+
const { t } = (0, LanguageContext_1.useLanguage)();
|
|
71
|
+
const [conversations, setConversations] = (0, react_1.useState)([]);
|
|
72
|
+
// Conversation context as a discriminated union — makes the invalid combo
|
|
73
|
+
// (existing-mode with no id) unrepresentable. All send-payload construction
|
|
74
|
+
// goes through buildSendPayload() so the wire shape is derived from the union.
|
|
75
|
+
// The ref mirror is updated synchronously with the state so handlers reading
|
|
76
|
+
// mid-render still see the latest value (no render-cycle gap on chat switch).
|
|
77
|
+
const [convCtx, setConvCtxState] = (0, react_1.useState)({ mode: 'new' });
|
|
78
|
+
const convCtxRef = (0, react_1.useRef)({ mode: 'new' });
|
|
79
|
+
const setConvCtx = (0, react_1.useCallback)((next) => {
|
|
80
|
+
convCtxRef.current = next;
|
|
81
|
+
setConvCtxState(next);
|
|
82
|
+
}, []);
|
|
83
|
+
// Derived views — kept as locals so existing read-sites compile without churn.
|
|
84
|
+
const currentConversationId = convCtx.mode === 'existing' ? convCtx.id : null;
|
|
85
|
+
const isNewChat = convCtx.mode === 'new';
|
|
86
|
+
const [messages, setMessages] = (0, react_1.useState)([]);
|
|
87
|
+
// Stream the latest messages array out to the parent so it can derive UI state
|
|
88
|
+
// (e.g. SynthiaPage uses it to build the Copy-Input-Specs template from the
|
|
89
|
+
// active conversation's summary).
|
|
90
|
+
(0, react_1.useEffect)(() => {
|
|
91
|
+
onMessagesChange?.(messages);
|
|
92
|
+
}, [messages, onMessagesChange]);
|
|
93
|
+
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
94
|
+
const [isSidebarOpen, setIsSidebarOpen] = (0, react_1.useState)(false);
|
|
95
|
+
const [isFloatingOpen, setIsFloatingOpen] = (0, react_1.useState)(false);
|
|
96
|
+
const [isMuted, setIsMuted] = (0, react_1.useState)(true);
|
|
97
|
+
// Search-chats modal — ChatGPT-style centered overlay with text search + date-range filter.
|
|
98
|
+
const [isSearchOpen, setIsSearchOpen] = (0, react_1.useState)(false);
|
|
99
|
+
const [searchQuery, setSearchQuery] = (0, react_1.useState)('');
|
|
100
|
+
const [searchFrom, setSearchFrom] = (0, react_1.useState)('');
|
|
101
|
+
const [searchTo, setSearchTo] = (0, react_1.useState)('');
|
|
102
|
+
// Sidebar grouping toggle: OFF → flat "Recents" list (default). ON → date buckets
|
|
103
|
+
// (Today / Yesterday / Previous 7 Days / Previous 30 Days / Month YYYY). Sticky via
|
|
104
|
+
// localStorage so power users who prefer buckets keep them across reloads.
|
|
105
|
+
const [groupByDate, setGroupByDate] = (0, react_1.useState)(false);
|
|
106
|
+
(0, react_1.useEffect)(() => {
|
|
107
|
+
try {
|
|
108
|
+
const v = localStorage.getItem('synthia.sidebarGroupByDate');
|
|
109
|
+
if (v === '1')
|
|
110
|
+
setGroupByDate(true);
|
|
111
|
+
}
|
|
112
|
+
catch { }
|
|
113
|
+
}, []);
|
|
114
|
+
(0, react_1.useEffect)(() => {
|
|
115
|
+
try {
|
|
116
|
+
localStorage.setItem('synthia.sidebarGroupByDate', groupByDate ? '1' : '0');
|
|
117
|
+
}
|
|
118
|
+
catch { }
|
|
119
|
+
}, [groupByDate]);
|
|
120
|
+
// Use external mute state if provided (e.g. from floating widget header)
|
|
121
|
+
const effectiveMuted = externalMuted ?? isMuted;
|
|
122
|
+
// Hard-limit detection — when the conversation has been closed server-side, the last assistant
|
|
123
|
+
// message carries the exact phrase below. Lock the input in that case.
|
|
124
|
+
const isConversationClosed = (() => {
|
|
125
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
126
|
+
const m = messages[i];
|
|
127
|
+
if (m.role === 'assistant') {
|
|
128
|
+
return /This conversation has reached its limit\.\s*Please start a new chat to continue\./i.test(m.content || '');
|
|
129
|
+
}
|
|
130
|
+
if (m.role === 'user')
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
})();
|
|
135
|
+
(0, react_1.useEffect)(() => {
|
|
136
|
+
if (session) {
|
|
137
|
+
loadConversations();
|
|
138
|
+
}
|
|
139
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
140
|
+
}, [session]);
|
|
141
|
+
const initialSentRef = (0, react_1.useRef)(false);
|
|
142
|
+
// Stop-generation support — abort in-flight costingbot fetch when user clicks Stop
|
|
143
|
+
const abortControllerRef = (0, react_1.useRef)(null);
|
|
144
|
+
// Scroll container for the active messages viewport (floating vs fullpage/modal)
|
|
145
|
+
const messagesScrollRef = (0, react_1.useRef)(null);
|
|
146
|
+
const handleStop = (0, react_1.useCallback)(() => {
|
|
147
|
+
abortControllerRef.current?.abort();
|
|
148
|
+
abortControllerRef.current = null;
|
|
149
|
+
}, []);
|
|
150
|
+
// The inner Messages component has its own overflow-y-auto wrapper, so the
|
|
151
|
+
// outer ref'd div doesn't scroll. Find the nearest actually-scrollable descendant.
|
|
152
|
+
const findScroller = (0, react_1.useCallback)(() => {
|
|
153
|
+
const root = messagesScrollRef.current;
|
|
154
|
+
if (!root)
|
|
155
|
+
return null;
|
|
156
|
+
if (root.scrollHeight > root.clientHeight)
|
|
157
|
+
return root;
|
|
158
|
+
const candidates = root.querySelectorAll('*');
|
|
159
|
+
for (const el of Array.from(candidates)) {
|
|
160
|
+
if (el.scrollHeight > el.clientHeight) {
|
|
161
|
+
const style = window.getComputedStyle(el);
|
|
162
|
+
if (/(auto|scroll)/.test(style.overflowY))
|
|
163
|
+
return el;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return root;
|
|
167
|
+
}, []);
|
|
168
|
+
const scrollToBottom = (0, react_1.useCallback)(() => {
|
|
169
|
+
const el = findScroller();
|
|
170
|
+
if (el)
|
|
171
|
+
el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });
|
|
172
|
+
}, [findScroller]);
|
|
173
|
+
const scrollToTop = (0, react_1.useCallback)(() => {
|
|
174
|
+
const el = findScroller();
|
|
175
|
+
if (el)
|
|
176
|
+
el.scrollTo({ top: 0, behavior: 'smooth' });
|
|
177
|
+
}, [findScroller]);
|
|
178
|
+
// Show "scroll to bottom" floating button when user has scrolled away from the latest message
|
|
179
|
+
const [showScrollDown, setShowScrollDown] = (0, react_1.useState)(false);
|
|
180
|
+
(0, react_1.useEffect)(() => {
|
|
181
|
+
const el = findScroller();
|
|
182
|
+
if (!el)
|
|
183
|
+
return;
|
|
184
|
+
const onScroll = () => {
|
|
185
|
+
const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
186
|
+
setShowScrollDown(distanceFromBottom > 120);
|
|
187
|
+
};
|
|
188
|
+
onScroll();
|
|
189
|
+
el.addEventListener('scroll', onScroll, { passive: true });
|
|
190
|
+
return () => el.removeEventListener('scroll', onScroll);
|
|
191
|
+
}, [findScroller, messages.length]);
|
|
192
|
+
const loadConversations = (0, react_1.useCallback)(async () => {
|
|
193
|
+
if (!session)
|
|
194
|
+
return;
|
|
195
|
+
const response = await (0, chat_1.getConversationsAPI)(session);
|
|
196
|
+
if (response.success && response.data) {
|
|
197
|
+
setConversations(response.data);
|
|
198
|
+
}
|
|
199
|
+
}, [session]);
|
|
200
|
+
const loadConversation = (0, react_1.useCallback)(async (conversationId) => {
|
|
201
|
+
if (!session)
|
|
202
|
+
return;
|
|
203
|
+
setConvCtx({ mode: 'existing', id: conversationId });
|
|
204
|
+
setMessages([]);
|
|
205
|
+
const response = await (0, chat_1.getMessagesAPI)(conversationId, session);
|
|
206
|
+
if (response.success && response.data) {
|
|
207
|
+
const rows = response.data;
|
|
208
|
+
const formattedMessages = [];
|
|
209
|
+
const seenUiIds = new Set();
|
|
210
|
+
// Pending ui_data waiting to be attached to the NEXT assistant row (GPT tool-call order quirk)
|
|
211
|
+
let pendingUiData = [];
|
|
212
|
+
let pendingReadonly = false;
|
|
213
|
+
for (let idx = 0; idx < rows.length; idx++) {
|
|
214
|
+
const msg = rows[idx];
|
|
215
|
+
// Backend may send the text under either MessageContent or Content — read whichever is present
|
|
216
|
+
const rawContent = msg.MessageContent ?? msg.Content ?? '';
|
|
217
|
+
// Tool rows: parse, extract __ui_data, render as historical dropdown.
|
|
218
|
+
// If missing/invalid JSON or no __ui_data → skip (non-UI tool result, not a chat bubble).
|
|
219
|
+
if (msg.Role === 'tool') {
|
|
220
|
+
let parsedPayload = null;
|
|
221
|
+
let uiDataRaw = null;
|
|
222
|
+
try {
|
|
223
|
+
parsedPayload = JSON.parse(rawContent);
|
|
224
|
+
uiDataRaw = parsedPayload?.__ui_data;
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
// Non-JSON tool content — skip silently
|
|
228
|
+
}
|
|
229
|
+
// __ui_data might be a single entry (object) or an array — normalize to array
|
|
230
|
+
const uiData = Array.isArray(uiDataRaw)
|
|
231
|
+
? uiDataRaw
|
|
232
|
+
: (uiDataRaw && typeof uiDataRaw === 'object' ? [uiDataRaw] : []);
|
|
233
|
+
if (uiData.length === 0)
|
|
234
|
+
continue;
|
|
235
|
+
// Stamp display_header from the parent payload onto each entry so the renderer can use it
|
|
236
|
+
const displayHeader = typeof parsedPayload?.display_header === 'string'
|
|
237
|
+
? parsedPayload.display_header
|
|
238
|
+
: undefined;
|
|
239
|
+
const filtered = uiData
|
|
240
|
+
.filter((e) => e?.version === 1 && Array.isArray(e.items) && e.items.length > 0 && !seenUiIds.has(e.id))
|
|
241
|
+
.map(e => ({ ...e, display_header: e.display_header ?? displayHeader }));
|
|
242
|
+
filtered.forEach(e => seenUiIds.add(e.id));
|
|
243
|
+
if (filtered.length === 0)
|
|
244
|
+
continue;
|
|
245
|
+
// Contract §3.110: live iff no USER reply follows this tool row.
|
|
246
|
+
// A user reply after the tool means the user already picked → historical/read-only.
|
|
247
|
+
const hasUserAfter = rows.slice(idx + 1).some(r => r.Role === 'user');
|
|
248
|
+
pendingUiData.push(...filtered);
|
|
249
|
+
pendingReadonly = hasUserAfter;
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
const built = {
|
|
253
|
+
id: `${msg.MessageID || idx}`,
|
|
254
|
+
conversationId: conversationId,
|
|
255
|
+
role: msg.Role,
|
|
256
|
+
content: rawContent,
|
|
257
|
+
timestamp: new Date(),
|
|
258
|
+
contentType: 'text',
|
|
259
|
+
feedback: msg.Feedback === 1 ? 'up' : msg.Feedback === 0 ? 'down' : null
|
|
260
|
+
};
|
|
261
|
+
// If this is the assistant row that the previous tool row was meant for, attach the ui_data here
|
|
262
|
+
if (msg.Role === 'assistant' && pendingUiData.length > 0) {
|
|
263
|
+
built.ui_data = pendingUiData;
|
|
264
|
+
built.uiDataReadonly = pendingReadonly;
|
|
265
|
+
pendingUiData = [];
|
|
266
|
+
pendingReadonly = false;
|
|
267
|
+
}
|
|
268
|
+
formattedMessages.push(built);
|
|
269
|
+
}
|
|
270
|
+
// Any ui_data still pending after the loop means there was no assistant after the final tool row
|
|
271
|
+
// → it's the live/active dropdown. Attach to the most recent assistant as non-readonly.
|
|
272
|
+
if (pendingUiData.length > 0) {
|
|
273
|
+
for (let j = formattedMessages.length - 1; j >= 0; j--) {
|
|
274
|
+
if (formattedMessages[j].role === 'assistant') {
|
|
275
|
+
formattedMessages[j] = {
|
|
276
|
+
...formattedMessages[j],
|
|
277
|
+
ui_data: [...(formattedMessages[j].ui_data || []), ...pendingUiData],
|
|
278
|
+
uiDataReadonly: false
|
|
279
|
+
};
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
setMessages(formattedMessages);
|
|
285
|
+
}
|
|
286
|
+
if (window.innerWidth < 768) {
|
|
287
|
+
setIsSidebarOpen(false);
|
|
288
|
+
}
|
|
289
|
+
loadConversations();
|
|
290
|
+
}, [session, loadConversations]);
|
|
291
|
+
const startNewChat = (0, react_1.useCallback)(() => {
|
|
292
|
+
setConvCtx({ mode: 'new' });
|
|
293
|
+
setMessages([]);
|
|
294
|
+
if (window.innerWidth < 768) {
|
|
295
|
+
setIsSidebarOpen(false);
|
|
296
|
+
}
|
|
297
|
+
}, [setConvCtx]);
|
|
298
|
+
const deleteConversation = (0, react_1.useCallback)(async (conversationId) => {
|
|
299
|
+
if (!session)
|
|
300
|
+
return;
|
|
301
|
+
alerts.showConfirmation(t('Delete Conversation'), t('Are you sure you want to delete this conversation?'), async () => {
|
|
302
|
+
const response = await (0, chat_1.deleteConversationAPI)(conversationId, session);
|
|
303
|
+
if (response.success) {
|
|
304
|
+
if (conversationId === currentConversationId) {
|
|
305
|
+
startNewChat();
|
|
306
|
+
}
|
|
307
|
+
loadConversations();
|
|
308
|
+
alerts.showSuccess(t('Deleted'), t('Conversation deleted successfully'));
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
alerts.showError(t('Error'), response.error || t('Failed to delete conversation'));
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}, [session, currentConversationId, startNewChat, loadConversations, alerts]);
|
|
315
|
+
const duplicateConversation = (0, react_1.useCallback)(async (conversationId) => {
|
|
316
|
+
if (!session)
|
|
317
|
+
return;
|
|
318
|
+
const response = await (0, chat_1.duplicateConversationAPI)(conversationId, session);
|
|
319
|
+
if (response.success && response.data?.ConversationID) {
|
|
320
|
+
await loadConversations();
|
|
321
|
+
alerts.showSuccess(t('Duplicated'), t('Conversation duplicated successfully'));
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
alerts.showError(t('Error'), response.error || t('Failed to duplicate conversation'));
|
|
325
|
+
}
|
|
326
|
+
}, [session, loadConversations, alerts, t]);
|
|
327
|
+
// Inline rename — which conversation is currently being edited, and the draft title
|
|
328
|
+
const [renamingId, setRenamingId] = (0, react_1.useState)(null);
|
|
329
|
+
const [renameDraft, setRenameDraft] = (0, react_1.useState)('');
|
|
330
|
+
const renameFocusedRef = (0, react_1.useRef)(false);
|
|
331
|
+
const startRename = (0, react_1.useCallback)((conversationId) => {
|
|
332
|
+
const conv = conversations.find(c => c.ConversationID === conversationId);
|
|
333
|
+
renameFocusedRef.current = false;
|
|
334
|
+
setRenamingId(conversationId);
|
|
335
|
+
setRenameDraft(conv?.Title || '');
|
|
336
|
+
}, [conversations]);
|
|
337
|
+
const commitRename = (0, react_1.useCallback)(async () => {
|
|
338
|
+
if (!session || renamingId === null)
|
|
339
|
+
return;
|
|
340
|
+
const trimmed = renameDraft.trim();
|
|
341
|
+
const conv = conversations.find(c => c.ConversationID === renamingId);
|
|
342
|
+
// No-op if empty or unchanged
|
|
343
|
+
if (!trimmed || trimmed === conv?.Title) {
|
|
344
|
+
setRenamingId(null);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
// Optimistic
|
|
348
|
+
setConversations(prev => prev.map(c => c.ConversationID === renamingId ? { ...c, Title: trimmed } : c));
|
|
349
|
+
setRenamingId(null);
|
|
350
|
+
const response = await (0, chat_1.renameConversationAPI)(renamingId, trimmed, session);
|
|
351
|
+
if (!response.success) {
|
|
352
|
+
alerts.showError(t('Error'), response.error || t('Failed to rename'));
|
|
353
|
+
loadConversations();
|
|
354
|
+
}
|
|
355
|
+
}, [session, renamingId, renameDraft, conversations, alerts, loadConversations]);
|
|
356
|
+
const cancelRename = (0, react_1.useCallback)(() => {
|
|
357
|
+
setRenamingId(null);
|
|
358
|
+
setRenameDraft('');
|
|
359
|
+
}, []);
|
|
360
|
+
const toggleStar = (0, react_1.useCallback)(async (conversationId) => {
|
|
361
|
+
if (!session)
|
|
362
|
+
return;
|
|
363
|
+
const current = conversations.find(c => c.ConversationID === conversationId);
|
|
364
|
+
const currentStarred = current?.IsStarred === 1 || current?.IsStarred === true;
|
|
365
|
+
setConversations(prev => prev.map(c => c.ConversationID === conversationId ? { ...c, IsStarred: currentStarred ? 0 : 1 } : c));
|
|
366
|
+
const response = await (0, chat_1.toggleStarConversationAPI)(conversationId, session);
|
|
367
|
+
if (!response.success) {
|
|
368
|
+
alerts.showError(t('Error'), response.error || t('Failed to update star'));
|
|
369
|
+
loadConversations();
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
loadConversations();
|
|
373
|
+
}
|
|
374
|
+
}, [session, conversations, alerts, loadConversations]);
|
|
375
|
+
// Build sidebar items with star indicator + inline rename input
|
|
376
|
+
const conversationItems = conversations.map(conv => {
|
|
377
|
+
const starred = conv.IsStarred === 1 || conv.IsStarred === true;
|
|
378
|
+
const title = conv.Title || `Conversation ${conv.ConversationID}`;
|
|
379
|
+
const isRenaming = renamingId === conv.ConversationID;
|
|
380
|
+
return {
|
|
381
|
+
id: String(conv.ConversationID),
|
|
382
|
+
searchText: title,
|
|
383
|
+
disableSelect: isRenaming,
|
|
384
|
+
label: isRenaming ? ((0, jsx_runtime_1.jsx)("input", { ref: (el) => {
|
|
385
|
+
if (el && !renameFocusedRef.current) {
|
|
386
|
+
renameFocusedRef.current = true;
|
|
387
|
+
el.focus();
|
|
388
|
+
el.select();
|
|
389
|
+
}
|
|
390
|
+
}, value: renameDraft, onChange: (e) => setRenameDraft(e.target.value), onKeyDown: (e) => {
|
|
391
|
+
// Stop keys from reaching the wrapping <button>, the global chat input, and the search bar.
|
|
392
|
+
e.stopPropagation();
|
|
393
|
+
if (e.key === 'Enter') {
|
|
394
|
+
e.preventDefault();
|
|
395
|
+
commitRename();
|
|
396
|
+
}
|
|
397
|
+
else if (e.key === 'Escape') {
|
|
398
|
+
e.preventDefault();
|
|
399
|
+
cancelRename();
|
|
400
|
+
}
|
|
401
|
+
}, onKeyUp: (e) => e.stopPropagation(), onKeyPress: (e) => e.stopPropagation(), onClick: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), className: "w-full bg-[rgb(var(--bg-surface))] border border-[rgb(var(--color-primary))] rounded-md px-2 py-0.5 outline-none text-[0.8125rem] text-[rgb(var(--fg-default))]" })) : ((0, jsx_runtime_1.jsxs)("span", { className: "flex flex-col min-w-0 gap-0", children: [(0, jsx_runtime_1.jsxs)("span", { className: "flex items-center gap-1.5 min-w-0", children: [starred && (0, jsx_runtime_1.jsx)(lucide_react_1.Star, { className: "w-3 h-3 shrink-0 fill-current text-[rgb(var(--color-primary))]" }), (0, jsx_runtime_1.jsx)("span", { className: "truncate", children: title })] }), conv.CreatedAt && ((0, jsx_runtime_1.jsx)("span", { className: "text-[0.6875rem] text-[rgb(var(--fg-muted))] truncate", children: formatConversationStamp(conv.CreatedAt) }))] }))
|
|
402
|
+
};
|
|
403
|
+
});
|
|
404
|
+
// Sidebar categories. Two modes:
|
|
405
|
+
// - groupByDate=false (default): single flat "Conversations" category — preserves
|
|
406
|
+
// the original chronological list under the "Recents" header.
|
|
407
|
+
// - groupByDate=true: bucket items by Today / Yesterday / Previous 7 Days /
|
|
408
|
+
// Previous 30 Days / Month YYYY (ChatGPT-style).
|
|
409
|
+
// Bucket grain is identical to the search modal so the two views feel consistent.
|
|
410
|
+
const conversationCategories = (() => {
|
|
411
|
+
if (!groupByDate) {
|
|
412
|
+
return [{ id: 'conversations', label: 'Conversations', items: conversationItems }];
|
|
413
|
+
}
|
|
414
|
+
const groups = new Map();
|
|
415
|
+
conversations.forEach((conv, idx) => {
|
|
416
|
+
const b = bucketForDate(conv.CreatedAt);
|
|
417
|
+
const item = conversationItems[idx];
|
|
418
|
+
if (!groups.has(b.id))
|
|
419
|
+
groups.set(b.id, { label: b.label, sort: b.sort, items: [] });
|
|
420
|
+
groups.get(b.id).items.push(item);
|
|
421
|
+
});
|
|
422
|
+
return Array.from(groups.entries())
|
|
423
|
+
.sort((a, b) => b[1].sort - a[1].sort)
|
|
424
|
+
.map(([id, g]) => ({ id, label: g.label, items: g.items }));
|
|
425
|
+
})();
|
|
426
|
+
// Toggle rendered to the right of the sidebar "Recents" header. Pill-style two-state
|
|
427
|
+
// switch — "List" (flat) vs "Group" (date buckets). Kept tiny so it doesn't crowd
|
|
428
|
+
// the header.
|
|
429
|
+
const groupingToggle = ((0, jsx_runtime_1.jsx)("button", { onClick: (e) => { e.stopPropagation(); setGroupByDate(g => !g); }, title: groupByDate ? 'Switch to flat list' : 'Group by date', className: (0, utils_1.cn)('text-[0.6rem] font-semibold uppercase tracking-wider px-1.5 py-0.5 rounded-md transition-colors', groupByDate
|
|
430
|
+
? 'bg-[rgb(var(--color-primary))]/10 text-[rgb(var(--color-primary))]'
|
|
431
|
+
: 'text-[rgb(var(--fg-muted))] hover:bg-[rgb(var(--bg-subtle))] hover:text-[rgb(var(--fg-default))]'), children: groupByDate ? 'Grouped' : 'Group' }));
|
|
432
|
+
// Context menu renderer for a conversation row — shared by floating and fullpage sidebars
|
|
433
|
+
const renderConversationMenu = (0, react_1.useCallback)((itemId, close) => {
|
|
434
|
+
const id = parseInt(itemId);
|
|
435
|
+
const conv = conversations.find(c => c.ConversationID === id);
|
|
436
|
+
const starred = conv?.IsStarred === 1 || conv?.IsStarred === true;
|
|
437
|
+
const itemCls = 'w-full px-3 py-2 text-left text-sm text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] transition-colors flex items-center gap-2.5';
|
|
438
|
+
const fire = (fn) => (e) => {
|
|
439
|
+
e.stopPropagation();
|
|
440
|
+
close();
|
|
441
|
+
fn();
|
|
442
|
+
};
|
|
443
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "py-1", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: fire(() => toggleStar(id)), className: itemCls, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Star, { className: (0, utils_1.cn)('w-3.5 h-3.5', starred && 'fill-current text-[rgb(var(--color-primary))]') }), starred ? 'Unstar' : 'Star'] }), (0, jsx_runtime_1.jsxs)("button", { onClick: fire(() => startRename(id)), className: itemCls, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Pencil, { className: "w-3.5 h-3.5" }), "Rename"] }), (0, jsx_runtime_1.jsxs)("button", { onClick: fire(() => deleteConversation(id)), className: "w-full px-3 py-2 text-left text-sm text-red-500 hover:bg-red-500/10 transition-colors flex items-center gap-2.5", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Trash2, { className: "w-3.5 h-3.5" }), "Delete"] })] }));
|
|
444
|
+
}, [conversations, toggleStar, startRename, deleteConversation]);
|
|
445
|
+
// Play a gentle two-note chime — nicer than a flat beep, soft on ears
|
|
446
|
+
const playChime = (0, react_1.useCallback)((notes, durationPerNote, peakGain) => {
|
|
447
|
+
if (effectiveMuted)
|
|
448
|
+
return;
|
|
449
|
+
try {
|
|
450
|
+
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
451
|
+
const now = audioContext.currentTime;
|
|
452
|
+
notes.forEach((freq, i) => {
|
|
453
|
+
const osc = audioContext.createOscillator();
|
|
454
|
+
const gain = audioContext.createGain();
|
|
455
|
+
osc.connect(gain);
|
|
456
|
+
gain.connect(audioContext.destination);
|
|
457
|
+
osc.frequency.value = freq;
|
|
458
|
+
osc.type = 'sine';
|
|
459
|
+
const start = now + i * durationPerNote * 0.85;
|
|
460
|
+
gain.gain.setValueAtTime(0, start);
|
|
461
|
+
gain.gain.linearRampToValueAtTime(peakGain, start + 0.015);
|
|
462
|
+
gain.gain.exponentialRampToValueAtTime(0.0001, start + durationPerNote);
|
|
463
|
+
osc.start(start);
|
|
464
|
+
osc.stop(start + durationPerNote);
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
catch (e) {
|
|
468
|
+
// Silently fail if audio not supported
|
|
469
|
+
}
|
|
470
|
+
}, [effectiveMuted]);
|
|
471
|
+
// Send: soft single "pop" — quick, low-key, doesn't compete with receive chime
|
|
472
|
+
const playSendSound = (0, react_1.useCallback)(() => {
|
|
473
|
+
if (effectiveMuted)
|
|
474
|
+
return;
|
|
475
|
+
try {
|
|
476
|
+
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
477
|
+
const now = audioContext.currentTime;
|
|
478
|
+
const osc = audioContext.createOscillator();
|
|
479
|
+
const gain = audioContext.createGain();
|
|
480
|
+
osc.connect(gain);
|
|
481
|
+
gain.connect(audioContext.destination);
|
|
482
|
+
osc.type = 'sine';
|
|
483
|
+
// Quick frequency sweep up = gentle "blip"
|
|
484
|
+
osc.frequency.setValueAtTime(520, now);
|
|
485
|
+
osc.frequency.exponentialRampToValueAtTime(880, now + 0.07);
|
|
486
|
+
gain.gain.setValueAtTime(0, now);
|
|
487
|
+
gain.gain.linearRampToValueAtTime(0.08, now + 0.01);
|
|
488
|
+
gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.09);
|
|
489
|
+
osc.start(now);
|
|
490
|
+
osc.stop(now + 0.1);
|
|
491
|
+
}
|
|
492
|
+
catch (e) {
|
|
493
|
+
// Silently fail if audio not supported
|
|
494
|
+
}
|
|
495
|
+
}, [effectiveMuted]);
|
|
496
|
+
// Receive: soft descending chime (G5 → D5) — warm acknowledgement
|
|
497
|
+
const playReceiveSound = (0, react_1.useCallback)(() => {
|
|
498
|
+
playChime([783.99, 587.33], 0.18, 0.1);
|
|
499
|
+
}, [playChime]);
|
|
500
|
+
const handleSubmit = (0, react_1.useCallback)(async (input, files, displayOverride) => {
|
|
501
|
+
if (!session || (!input.trim() && !files?.length) || isLoading || isConversationClosed)
|
|
502
|
+
return;
|
|
503
|
+
// Snapshot context at send time from the ref so a chat-switch that just
|
|
504
|
+
// happened (state setter not yet flushed) is still respected. The captured
|
|
505
|
+
// ctx is also used post-await to detect mid-flight switches.
|
|
506
|
+
const sentCtx = convCtxRef.current;
|
|
507
|
+
playSendSound();
|
|
508
|
+
// When displayOverride is set (e.g. multiselect confirm), the bubble shows the friendly labels
|
|
509
|
+
// while the backend still receives the structured `input` string with ids.
|
|
510
|
+
const bubbleText = displayOverride ?? input;
|
|
511
|
+
const conversationIdAtSend = sentCtx.mode === 'existing' ? sentCtx.id : 0;
|
|
512
|
+
const userMessage = {
|
|
513
|
+
id: `user-${Date.now()}`,
|
|
514
|
+
conversationId: conversationIdAtSend,
|
|
515
|
+
role: 'user',
|
|
516
|
+
content: bubbleText + (files?.length ? `\n\n[${files.length} file(s) attached]` : ''),
|
|
517
|
+
timestamp: new Date(),
|
|
518
|
+
contentType: 'text'
|
|
519
|
+
};
|
|
520
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
521
|
+
setIsLoading(true);
|
|
522
|
+
const autoTitle = sentCtx.mode === 'new' ? bubbleText.substring(0, 40) : null;
|
|
523
|
+
const controller = new AbortController();
|
|
524
|
+
abortControllerRef.current = controller;
|
|
525
|
+
try {
|
|
526
|
+
const response = await (0, chat_1.sendChatMessageAPI)(buildSendPayload(sentCtx, input, autoTitle), session, controller.signal);
|
|
527
|
+
// If the user switched conversations during the request, drop the response.
|
|
528
|
+
// Compare against the live ref — closure state is captured at send time
|
|
529
|
+
// and won't reflect a switch that happened during await.
|
|
530
|
+
const liveCtx = convCtxRef.current;
|
|
531
|
+
const stillOnSameConversation = sentCtx.mode === 'existing'
|
|
532
|
+
? liveCtx.mode === 'existing' && liveCtx.id === sentCtx.id
|
|
533
|
+
// new-chat case: still on the same chat if user hasn't switched at all
|
|
534
|
+
// (still in 'new' mode) or we're now on the conversation the backend
|
|
535
|
+
// just created for this send.
|
|
536
|
+
: liveCtx.mode === 'new' || (liveCtx.mode === 'existing' && liveCtx.id === response.conversationId);
|
|
537
|
+
if (!stillOnSameConversation) {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
if (response.aborted) {
|
|
541
|
+
// User clicked Stop — drop in a small marker so it's clear the reply was halted
|
|
542
|
+
const stoppedMessage = {
|
|
543
|
+
id: `assistant-stopped-${Date.now()}`,
|
|
544
|
+
conversationId: conversationIdAtSend,
|
|
545
|
+
role: 'assistant',
|
|
546
|
+
content: t('The response was interrupted by the user.'),
|
|
547
|
+
timestamp: new Date(),
|
|
548
|
+
contentType: 'text'
|
|
549
|
+
};
|
|
550
|
+
setMessages((prev) => [...prev, stoppedMessage]);
|
|
551
|
+
}
|
|
552
|
+
else if (response.success && response.data) {
|
|
553
|
+
// First reply on a new chat — promote ctx to 'existing' with the backend-assigned id.
|
|
554
|
+
if (sentCtx.mode === 'new' && response.conversationId) {
|
|
555
|
+
setConvCtx({ mode: 'existing', id: response.conversationId });
|
|
556
|
+
}
|
|
557
|
+
// Update user message with real backend MessageID (for edit/resend to work)
|
|
558
|
+
if (response.userMessageId) {
|
|
559
|
+
setMessages(prev => prev.map(m => m.id === userMessage.id ? { ...m, id: response.userMessageId } : m));
|
|
560
|
+
}
|
|
561
|
+
const aiMessage = {
|
|
562
|
+
id: `assistant-${Date.now()}`,
|
|
563
|
+
conversationId: response.conversationId || conversationIdAtSend,
|
|
564
|
+
role: 'assistant',
|
|
565
|
+
content: response.data,
|
|
566
|
+
timestamp: new Date(),
|
|
567
|
+
contentType: 'text',
|
|
568
|
+
tokens: response.tokens,
|
|
569
|
+
ui_data: response.ui_data
|
|
570
|
+
};
|
|
571
|
+
setMessages((prev) => [...prev, aiMessage]);
|
|
572
|
+
playReceiveSound();
|
|
573
|
+
loadConversations();
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
alerts.showError(t('Error'), response.error || t('Failed to send message'));
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
catch (error) {
|
|
580
|
+
alerts.showError(t('Error'), t('Connection failed'));
|
|
581
|
+
}
|
|
582
|
+
finally {
|
|
583
|
+
if (abortControllerRef.current === controller)
|
|
584
|
+
abortControllerRef.current = null;
|
|
585
|
+
setIsLoading(false);
|
|
586
|
+
}
|
|
587
|
+
}, [session, isLoading, isConversationClosed, loadConversations, alerts, playSendSound, playReceiveSound, setConvCtx, t]);
|
|
588
|
+
const handleExport = (0, react_1.useCallback)(() => {
|
|
589
|
+
if (messages.length === 0)
|
|
590
|
+
return;
|
|
591
|
+
const conversationText = messages
|
|
592
|
+
.map((msg) => `${msg.role.toUpperCase()}: ${msg.content}`)
|
|
593
|
+
.join('\n\n---\n\n');
|
|
594
|
+
const blob = new Blob([conversationText], { type: 'text/plain' });
|
|
595
|
+
const url = URL.createObjectURL(blob);
|
|
596
|
+
const a = document.createElement('a');
|
|
597
|
+
a.href = url;
|
|
598
|
+
a.download = `conversation-${currentConversationId || 'new'}-${Date.now()}.txt`;
|
|
599
|
+
document.body.appendChild(a);
|
|
600
|
+
a.click();
|
|
601
|
+
document.body.removeChild(a);
|
|
602
|
+
URL.revokeObjectURL(url);
|
|
603
|
+
alerts.showSuccess(t('Exported'), t('Conversation exported successfully'));
|
|
604
|
+
}, [messages, currentConversationId, alerts]);
|
|
605
|
+
const handleShare = (0, react_1.useCallback)(async () => {
|
|
606
|
+
if (messages.length === 0)
|
|
607
|
+
return;
|
|
608
|
+
const conversationText = messages
|
|
609
|
+
.map((msg) => `${msg.role.toUpperCase()}: ${msg.content}`)
|
|
610
|
+
.join('\n\n');
|
|
611
|
+
try {
|
|
612
|
+
if (navigator.share) {
|
|
613
|
+
await navigator.share({
|
|
614
|
+
title: `${title} Conversation`,
|
|
615
|
+
text: conversationText
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
else {
|
|
619
|
+
await navigator.clipboard.writeText(conversationText);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
catch (error) {
|
|
623
|
+
alerts.showError(t('Error'), t('Failed to share conversation'));
|
|
624
|
+
}
|
|
625
|
+
}, [messages, alerts, title]);
|
|
626
|
+
const handleEditMessage = (0, react_1.useCallback)(async (messageId, newContent) => {
|
|
627
|
+
if (!session || isLoading)
|
|
628
|
+
return;
|
|
629
|
+
// Edit/resend only makes sense on a saved conversation. A "new" chat with
|
|
630
|
+
// no id can't have a prior message to resend against — bail out cleanly.
|
|
631
|
+
const sentCtx = convCtxRef.current;
|
|
632
|
+
if (sentCtx.mode !== 'existing')
|
|
633
|
+
return;
|
|
634
|
+
// Find the index of the edited message
|
|
635
|
+
const editIndex = messages.findIndex(m => m.id === messageId);
|
|
636
|
+
if (editIndex === -1)
|
|
637
|
+
return;
|
|
638
|
+
// Backend cleanup: delete messages after this one (cascade delete like legacy)
|
|
639
|
+
if (onBeforeEditMessage) {
|
|
640
|
+
try {
|
|
641
|
+
await onBeforeEditMessage(sentCtx.id, messageId);
|
|
642
|
+
}
|
|
643
|
+
catch {
|
|
644
|
+
// Continue even if backend cleanup fails — DOM cleanup still works
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
// Cascade delete: keep only messages up to and including the edited one.
|
|
648
|
+
// Stamp a fresh client-only id so we can find this exact row later when
|
|
649
|
+
// the backend hands us the real MessageID — matching by content alone
|
|
650
|
+
// would alias to any earlier user message with the same text.
|
|
651
|
+
const optimisticEditedId = `user-edit-${Date.now()}`;
|
|
652
|
+
const updatedMessages = messages.slice(0, editIndex).concat({
|
|
653
|
+
...messages[editIndex],
|
|
654
|
+
id: optimisticEditedId,
|
|
655
|
+
content: newContent
|
|
656
|
+
});
|
|
657
|
+
setMessages(updatedMessages);
|
|
658
|
+
// Resend the edited message
|
|
659
|
+
playSendSound();
|
|
660
|
+
setIsLoading(true);
|
|
661
|
+
const controller = new AbortController();
|
|
662
|
+
abortControllerRef.current = controller;
|
|
663
|
+
try {
|
|
664
|
+
const response = await (0, chat_1.sendChatMessageAPI)(buildSendPayload(sentCtx, newContent, null), session, controller.signal);
|
|
665
|
+
// Drop the response if user switched conversations during the request.
|
|
666
|
+
const liveCtx = convCtxRef.current;
|
|
667
|
+
if (liveCtx.mode !== 'existing' || liveCtx.id !== sentCtx.id) {
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
if (response.aborted) {
|
|
671
|
+
// User clicked Stop mid-resend — mark it so they know the reply was interrupted
|
|
672
|
+
const stoppedMessage = {
|
|
673
|
+
id: `assistant-stopped-${Date.now()}`,
|
|
674
|
+
conversationId: sentCtx.id,
|
|
675
|
+
role: 'assistant',
|
|
676
|
+
content: t('The response was interrupted by the user.'),
|
|
677
|
+
timestamp: new Date(),
|
|
678
|
+
contentType: 'text'
|
|
679
|
+
};
|
|
680
|
+
setMessages(prev => [...prev, stoppedMessage]);
|
|
681
|
+
}
|
|
682
|
+
else if (response.success && response.data) {
|
|
683
|
+
// Update the edited user message with new backend MessageID
|
|
684
|
+
if (response.userMessageId) {
|
|
685
|
+
setMessages(prev => prev.map(m => m.id === optimisticEditedId
|
|
686
|
+
? { ...m, id: response.userMessageId }
|
|
687
|
+
: m));
|
|
688
|
+
}
|
|
689
|
+
const aiMessage = {
|
|
690
|
+
id: `assistant-${Date.now()}`,
|
|
691
|
+
conversationId: sentCtx.id,
|
|
692
|
+
role: 'assistant',
|
|
693
|
+
content: response.data,
|
|
694
|
+
timestamp: new Date(),
|
|
695
|
+
contentType: 'text',
|
|
696
|
+
tokens: response.tokens,
|
|
697
|
+
ui_data: response.ui_data
|
|
698
|
+
};
|
|
699
|
+
setMessages(prev => [...prev, aiMessage]);
|
|
700
|
+
playReceiveSound();
|
|
701
|
+
loadConversations();
|
|
702
|
+
}
|
|
703
|
+
else {
|
|
704
|
+
alerts.showError(t('Error'), response.error || t('Failed to resend message'));
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
catch (error) {
|
|
708
|
+
alerts.showError(t('Error'), t('Connection failed'));
|
|
709
|
+
}
|
|
710
|
+
finally {
|
|
711
|
+
if (abortControllerRef.current === controller)
|
|
712
|
+
abortControllerRef.current = null;
|
|
713
|
+
setIsLoading(false);
|
|
714
|
+
}
|
|
715
|
+
}, [session, isLoading, messages, playSendSound, playReceiveSound, loadConversations, alerts, onBeforeEditMessage, t]);
|
|
716
|
+
const handleFeedback = (0, react_1.useCallback)((messageId, rating) => {
|
|
717
|
+
if (!session)
|
|
718
|
+
return;
|
|
719
|
+
(0, chat_1.submitMessageFeedbackAPI)(messageId, rating, session);
|
|
720
|
+
}, [session]);
|
|
721
|
+
// Regenerate from an AI message — find the user prompt that triggered it and resend
|
|
722
|
+
const handleRegenerateAi = (0, react_1.useCallback)((aiMessageId) => {
|
|
723
|
+
const aiIndex = messages.findIndex(m => m.id === aiMessageId);
|
|
724
|
+
if (aiIndex === -1)
|
|
725
|
+
return;
|
|
726
|
+
for (let i = aiIndex - 1; i >= 0; i--) {
|
|
727
|
+
if (messages[i].role === 'user') {
|
|
728
|
+
handleEditMessage(messages[i].id, messages[i].content);
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}, [messages, handleEditMessage]);
|
|
733
|
+
(0, react_1.useEffect)(() => {
|
|
734
|
+
if (session && initialMessage && !initialSentRef.current) {
|
|
735
|
+
initialSentRef.current = true;
|
|
736
|
+
handleSubmit(initialMessage);
|
|
737
|
+
}
|
|
738
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
739
|
+
}, [session, initialMessage]);
|
|
740
|
+
// Load a specific conversation on mount (e.g., when expanding floating chat → fullpage via ?c=<id>)
|
|
741
|
+
const initialConvLoadedRef = (0, react_1.useRef)(false);
|
|
742
|
+
(0, react_1.useEffect)(() => {
|
|
743
|
+
if (session && initialConversationId && !initialConvLoadedRef.current) {
|
|
744
|
+
initialConvLoadedRef.current = true;
|
|
745
|
+
loadConversation(initialConversationId);
|
|
746
|
+
}
|
|
747
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
748
|
+
}, [session, initialConversationId]);
|
|
749
|
+
// Hijack the sidebar's built-in search input: when the user focuses or clicks
|
|
750
|
+
// it, open the chat-wide search modal instead of typing into the small inline
|
|
751
|
+
// filter. Immediately blur the original so the inline filter doesn't also run.
|
|
752
|
+
// Re-scans on conversations/sidebar-open changes since the SidePanel re-renders.
|
|
753
|
+
(0, react_1.useEffect)(() => {
|
|
754
|
+
const el = document.querySelector('[data-sidepanel-search]');
|
|
755
|
+
if (!el)
|
|
756
|
+
return;
|
|
757
|
+
const open = (e) => {
|
|
758
|
+
e.preventDefault();
|
|
759
|
+
e.stopPropagation();
|
|
760
|
+
setIsSearchOpen(true);
|
|
761
|
+
// Defer blur so React doesn't fight the focus event in the same tick.
|
|
762
|
+
setTimeout(() => el.blur(), 0);
|
|
763
|
+
};
|
|
764
|
+
el.addEventListener('focus', open);
|
|
765
|
+
el.addEventListener('mousedown', open);
|
|
766
|
+
return () => {
|
|
767
|
+
el.removeEventListener('focus', open);
|
|
768
|
+
el.removeEventListener('mousedown', open);
|
|
769
|
+
};
|
|
770
|
+
}, [isSidebarOpen, conversations.length, mode, isFloatingOpen]);
|
|
771
|
+
const handleSelectItem = (0, react_1.useCallback)((item) => {
|
|
772
|
+
// When user selects from list, auto-send as message.
|
|
773
|
+
// If the item carries a messageText (e.g. multiselect "Selected: ... (ids: ...)"), that goes
|
|
774
|
+
// to the backend while item.name remains the bubble text shown to the user.
|
|
775
|
+
const wire = item.messageText ?? item.name;
|
|
776
|
+
const display = item.messageText ? item.name : undefined;
|
|
777
|
+
handleSubmit(wire, undefined, display);
|
|
778
|
+
}, [handleSubmit]);
|
|
779
|
+
// Keyboard shortcuts — only active when the chat UI is mounted/visible.
|
|
780
|
+
// Floating widget: only when open. Others: always.
|
|
781
|
+
(0, react_1.useEffect)(() => {
|
|
782
|
+
const active = mode !== 'floating' || isFloatingOpen;
|
|
783
|
+
if (!active)
|
|
784
|
+
return;
|
|
785
|
+
const onKeyDown = (e) => {
|
|
786
|
+
const mod = e.ctrlKey || e.metaKey;
|
|
787
|
+
// Ctrl/Cmd + ↓ → scroll to bottom
|
|
788
|
+
if (mod && !e.shiftKey && e.key === 'ArrowDown') {
|
|
789
|
+
e.preventDefault();
|
|
790
|
+
scrollToBottom();
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
// Ctrl/Cmd + ↑ → scroll to top
|
|
794
|
+
if (mod && !e.shiftKey && e.key === 'ArrowUp') {
|
|
795
|
+
e.preventDefault();
|
|
796
|
+
scrollToTop();
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
// Ctrl/Cmd + Shift + O → new chat
|
|
800
|
+
if (mod && e.shiftKey && (e.key === 'O' || e.key === 'o')) {
|
|
801
|
+
e.preventDefault();
|
|
802
|
+
startNewChat();
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
// Ctrl/Cmd + K → focus chat input
|
|
806
|
+
if (mod && !e.shiftKey && (e.key === 'k' || e.key === 'K')) {
|
|
807
|
+
e.preventDefault();
|
|
808
|
+
const el = document.querySelector('textarea[data-chat-input]');
|
|
809
|
+
el?.focus();
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
// Ctrl/Cmd + Shift + K → open search-chats modal
|
|
813
|
+
if (mod && e.shiftKey && (e.key === 'k' || e.key === 'K')) {
|
|
814
|
+
e.preventDefault();
|
|
815
|
+
setIsSearchOpen(true);
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
// "/" while not typing → open search-chats modal (matches sidebar UX)
|
|
819
|
+
if (e.key === '/' && !mod) {
|
|
820
|
+
const target = e.target;
|
|
821
|
+
const tag = (target?.tagName || '').toLowerCase();
|
|
822
|
+
const isEditable = tag === 'input' || tag === 'textarea' || target?.isContentEditable;
|
|
823
|
+
if (!isEditable) {
|
|
824
|
+
e.preventDefault();
|
|
825
|
+
setIsSearchOpen(true);
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
// Esc → stop generation if loading; otherwise close sidebar if open
|
|
830
|
+
if (e.key === 'Escape') {
|
|
831
|
+
if (isLoading) {
|
|
832
|
+
e.preventDefault();
|
|
833
|
+
handleStop();
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
if (isSidebarOpen) {
|
|
837
|
+
e.preventDefault();
|
|
838
|
+
setIsSidebarOpen(false);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
window.addEventListener('keydown', onKeyDown);
|
|
843
|
+
return () => window.removeEventListener('keydown', onKeyDown);
|
|
844
|
+
}, [mode, isFloatingOpen, isLoading, isSidebarOpen, scrollToBottom, scrollToTop, startNewChat, handleStop]);
|
|
845
|
+
// Resolve the messages component
|
|
846
|
+
const ResolvedMessages = MessagesComponent || ai_messages_1.Messages;
|
|
847
|
+
// Default logo fallback
|
|
848
|
+
const logoElement = logo || (0, jsx_runtime_1.jsx)(lucide_react_1.Bot, { className: "w-4 h-4 text-[rgb(var(--fg-muted))]" });
|
|
849
|
+
const bubbleLogoElement = bubbleLogo || logoElement;
|
|
850
|
+
// ── Draggable floating bubble state ──────────────────────────────────
|
|
851
|
+
const [bubblePos, setBubblePos] = (0, react_1.useState)(null);
|
|
852
|
+
const dragRef = (0, react_1.useRef)(null);
|
|
853
|
+
const bubbleRef = (0, react_1.useRef)(null);
|
|
854
|
+
const handlePointerDown = (0, react_1.useCallback)((e) => {
|
|
855
|
+
const el = bubbleRef.current;
|
|
856
|
+
if (!el)
|
|
857
|
+
return;
|
|
858
|
+
el.setPointerCapture(e.pointerId);
|
|
859
|
+
const rect = el.getBoundingClientRect();
|
|
860
|
+
const posX = bubblePos?.x ?? (window.innerWidth - rect.right + rect.width / 2);
|
|
861
|
+
const posY = bubblePos?.y ?? (window.innerHeight - rect.bottom + rect.height / 2);
|
|
862
|
+
dragRef.current = {
|
|
863
|
+
startX: e.clientX,
|
|
864
|
+
startY: e.clientY,
|
|
865
|
+
startPosX: posX,
|
|
866
|
+
startPosY: posY,
|
|
867
|
+
dragged: false,
|
|
868
|
+
};
|
|
869
|
+
}, [bubblePos]);
|
|
870
|
+
const handlePointerMove = (0, react_1.useCallback)((e) => {
|
|
871
|
+
if (!dragRef.current)
|
|
872
|
+
return;
|
|
873
|
+
const dx = e.clientX - dragRef.current.startX;
|
|
874
|
+
const dy = e.clientY - dragRef.current.startY;
|
|
875
|
+
if (!dragRef.current.dragged && Math.abs(dx) + Math.abs(dy) > 5) {
|
|
876
|
+
dragRef.current.dragged = true;
|
|
877
|
+
}
|
|
878
|
+
if (dragRef.current.dragged) {
|
|
879
|
+
// Position is stored as distance from right/bottom edges
|
|
880
|
+
const newX = Math.max(8, Math.min(window.innerWidth - 64, dragRef.current.startPosX - dx));
|
|
881
|
+
const newY = Math.max(8, Math.min(window.innerHeight - 64, dragRef.current.startPosY - dy));
|
|
882
|
+
setBubblePos({ x: newX, y: newY });
|
|
883
|
+
}
|
|
884
|
+
}, []);
|
|
885
|
+
const handlePointerUp = (0, react_1.useCallback)((e) => {
|
|
886
|
+
if (!dragRef.current)
|
|
887
|
+
return;
|
|
888
|
+
const wasDragged = dragRef.current.dragged;
|
|
889
|
+
dragRef.current = null;
|
|
890
|
+
if (!wasDragged) {
|
|
891
|
+
setIsFloatingOpen(true);
|
|
892
|
+
}
|
|
893
|
+
}, []);
|
|
894
|
+
// ── Draggable panel state (header as drag handle) ────────────────────
|
|
895
|
+
const [panelPos, setPanelPos] = (0, react_1.useState)(null);
|
|
896
|
+
const panelDragRef = (0, react_1.useRef)(null);
|
|
897
|
+
const panelRef = (0, react_1.useRef)(null);
|
|
898
|
+
const handlePanelPointerDown = (0, react_1.useCallback)((e) => {
|
|
899
|
+
// Don't drag if clicking on buttons inside the header
|
|
900
|
+
if (e.target.closest('button'))
|
|
901
|
+
return;
|
|
902
|
+
const el = panelRef.current;
|
|
903
|
+
if (!el)
|
|
904
|
+
return;
|
|
905
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
906
|
+
const rect = el.getBoundingClientRect();
|
|
907
|
+
const posX = panelPos?.x ?? (window.innerWidth - rect.right);
|
|
908
|
+
const posY = panelPos?.y ?? (window.innerHeight - rect.bottom);
|
|
909
|
+
panelDragRef.current = {
|
|
910
|
+
startX: e.clientX,
|
|
911
|
+
startY: e.clientY,
|
|
912
|
+
startPosX: posX,
|
|
913
|
+
startPosY: posY,
|
|
914
|
+
dragged: false,
|
|
915
|
+
};
|
|
916
|
+
}, [panelPos]);
|
|
917
|
+
const handlePanelPointerMove = (0, react_1.useCallback)((e) => {
|
|
918
|
+
if (!panelDragRef.current)
|
|
919
|
+
return;
|
|
920
|
+
const dx = e.clientX - panelDragRef.current.startX;
|
|
921
|
+
const dy = e.clientY - panelDragRef.current.startY;
|
|
922
|
+
if (!panelDragRef.current.dragged && Math.abs(dx) + Math.abs(dy) > 5) {
|
|
923
|
+
panelDragRef.current.dragged = true;
|
|
924
|
+
}
|
|
925
|
+
if (panelDragRef.current.dragged) {
|
|
926
|
+
const newX = Math.max(0, Math.min(window.innerWidth - 200, panelDragRef.current.startPosX - dx));
|
|
927
|
+
const newY = Math.max(0, Math.min(window.innerHeight - 100, panelDragRef.current.startPosY - dy));
|
|
928
|
+
setPanelPos({ x: newX, y: newY });
|
|
929
|
+
}
|
|
930
|
+
}, []);
|
|
931
|
+
const handlePanelPointerUp = (0, react_1.useCallback)(() => {
|
|
932
|
+
panelDragRef.current = null;
|
|
933
|
+
}, []);
|
|
934
|
+
// Filtered + bucketed results for the search modal. Text match is OR over title
|
|
935
|
+
// and ContactNo; date range filters by CreatedAt. Same bucketing as the sidebar
|
|
936
|
+
// so the modal feels consistent with what users see in the side list.
|
|
937
|
+
const searchResults = (() => {
|
|
938
|
+
const q = searchQuery.trim().toLowerCase();
|
|
939
|
+
const fromTs = searchFrom ? new Date(searchFrom + 'T00:00:00').getTime() : null;
|
|
940
|
+
const toTs = searchTo ? new Date(searchTo + 'T23:59:59').getTime() : null;
|
|
941
|
+
const filtered = conversations.filter(c => {
|
|
942
|
+
if (q) {
|
|
943
|
+
const title = (c.Title || '').toLowerCase();
|
|
944
|
+
const contact = (c.ContactNo || '').toLowerCase();
|
|
945
|
+
if (!title.includes(q) && !contact.includes(q))
|
|
946
|
+
return false;
|
|
947
|
+
}
|
|
948
|
+
if ((fromTs || toTs) && c.CreatedAt) {
|
|
949
|
+
const ts = new Date(c.CreatedAt).getTime();
|
|
950
|
+
if (fromTs && ts < fromTs)
|
|
951
|
+
return false;
|
|
952
|
+
if (toTs && ts > toTs)
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
955
|
+
return true;
|
|
956
|
+
});
|
|
957
|
+
const groups = new Map();
|
|
958
|
+
filtered.forEach(c => {
|
|
959
|
+
const b = bucketForDate(c.CreatedAt);
|
|
960
|
+
if (!groups.has(b.id))
|
|
961
|
+
groups.set(b.id, { label: b.label, sort: b.sort, items: [] });
|
|
962
|
+
groups.get(b.id).items.push(c);
|
|
963
|
+
});
|
|
964
|
+
return Array.from(groups.entries())
|
|
965
|
+
.sort((a, b) => b[1].sort - a[1].sort)
|
|
966
|
+
.map(([id, g]) => ({ id, label: g.label, items: g.items }));
|
|
967
|
+
})();
|
|
968
|
+
const searchModal = isSearchOpen ? ((0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 z-[100] flex items-start justify-center pt-[10vh] px-4 bg-black/50 backdrop-blur-sm", onClick: () => setIsSearchOpen(false), children: (0, jsx_runtime_1.jsxs)("div", { className: "w-full max-w-2xl bg-[rgb(var(--bg-surface))] border border-[rgb(var(--bd-default))] rounded-xl shadow-2xl flex flex-col max-h-[80vh] overflow-hidden", onClick: e => e.stopPropagation(), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 px-4 py-3 border-b border-[rgb(var(--bd-default))]", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { className: "w-4 h-4 text-[rgb(var(--fg-muted))] shrink-0" }), (0, jsx_runtime_1.jsx)("input", { autoFocus: true, value: searchQuery, onChange: e => setSearchQuery(e.target.value), placeholder: t('Search chats...'), className: "flex-1 bg-transparent outline-none text-sm text-[rgb(var(--fg-default))] placeholder:text-[rgb(var(--fg-muted))]", onKeyDown: e => { if (e.key === 'Escape')
|
|
969
|
+
setIsSearchOpen(false); } }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setIsSearchOpen(false), className: "h-7 w-7 rounded-md hover:bg-[rgb(var(--bg-subtle))] flex items-center justify-center text-[rgb(var(--fg-muted))]", "aria-label": t('Close'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "w-4 h-4" }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 px-4 py-2 border-b border-[rgb(var(--bd-default))] text-xs text-[rgb(var(--fg-muted))]", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Calendar, { className: "w-3.5 h-3.5 shrink-0" }), (0, jsx_runtime_1.jsx)("span", { className: "whitespace-nowrap shrink-0", children: t('Date range') }), (0, jsx_runtime_1.jsx)(date_picker_1.DatePicker, { mode: "range", showFromTo: true, placeholder: t('Select date range...'), value: {
|
|
970
|
+
from: searchFrom ? new Date(searchFrom + 'T00:00:00') : undefined,
|
|
971
|
+
to: searchTo ? new Date(searchTo + 'T00:00:00') : undefined,
|
|
972
|
+
}, onChange: (val) => {
|
|
973
|
+
const range = (val && typeof val === 'object' && 'from' in val) ? val : { from: undefined, to: undefined };
|
|
974
|
+
setSearchFrom(range.from ? (0, utils_2.getLocalDateString)(range.from) : '');
|
|
975
|
+
setSearchTo(range.to ? (0, utils_2.getLocalDateString)(range.to) : '');
|
|
976
|
+
} }), (searchFrom || searchTo || searchQuery) && ((0, jsx_runtime_1.jsx)("button", { onClick: () => { setSearchFrom(''); setSearchTo(''); setSearchQuery(''); }, className: "ml-auto px-2 py-1 rounded hover:bg-[rgb(var(--bg-subtle))] text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))]", children: t('Clear') }))] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 overflow-y-auto py-2", children: searchResults.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "px-4 py-8 text-center text-sm text-[rgb(var(--fg-muted))]", children: t('No chats found') })) : (searchResults.map(group => ((0, jsx_runtime_1.jsxs)("div", { className: "mb-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "px-4 py-1 text-[0.6875rem] uppercase tracking-wide text-[rgb(var(--fg-muted))] font-medium", children: group.label }), group.items.map(c => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => {
|
|
977
|
+
loadConversation(c.ConversationID);
|
|
978
|
+
setIsSearchOpen(false);
|
|
979
|
+
}, className: "w-full flex items-center gap-2 px-4 py-2 hover:bg-[rgb(var(--bg-subtle))] text-left", children: [(c.IsStarred === 1 || c.IsStarred === true) && ((0, jsx_runtime_1.jsx)(lucide_react_1.Star, { className: "w-3 h-3 shrink-0 fill-current text-[rgb(var(--color-primary))]" })), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-sm text-[rgb(var(--fg-default))] truncate", children: c.Title || `Conversation ${c.ConversationID}` }), c.CreatedAt && ((0, jsx_runtime_1.jsx)("div", { className: "text-[0.6875rem] text-[rgb(var(--fg-muted))] truncate", children: formatConversationStamp(c.CreatedAt) }))] })] }, c.ConversationID)))] }, group.id)))) })] }) })) : null;
|
|
980
|
+
// Floating Widget Mode — bubble + backdrop + panel chrome wrapping the regular chat
|
|
981
|
+
if (mode === 'floating') {
|
|
982
|
+
if (!isFloatingOpen) {
|
|
983
|
+
return ((0, jsx_runtime_1.jsx)("button", { ref: bubbleRef, onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, onPointerUp: handlePointerUp, className: (0, utils_1.cn)("fixed z-50 touch-none select-none cursor-pointer", "h-14 w-14 rounded-full", "bg-[rgb(var(--bg-surface))]", "flex items-center justify-center", "hover:scale-110", "transition-shadow duration-200 ease-out", "border border-[rgb(var(--bd-default))]", "shadow-[0_4px_20px_rgba(0,0,0,0.15)] hover:shadow-[0_8px_30px_rgba(0,0,0,0.25)]", !dragRef.current?.dragged && "animate-floating-bubble"), style: {
|
|
984
|
+
right: bubblePos ? `${bubblePos.x}px` : '16px',
|
|
985
|
+
bottom: bubblePos ? `${bubblePos.y}px` : '16px',
|
|
986
|
+
}, "aria-label": t('Open chat'), children: bubbleLogoElement }));
|
|
987
|
+
}
|
|
988
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 bg-black/60 backdrop-blur-sm z-40 animate-in fade-in duration-200", onClick: () => setIsFloatingOpen(false) }), (0, jsx_runtime_1.jsxs)("div", { ref: panelRef, className: (0, utils_1.cn)("fixed z-50 flex flex-col", "bg-[rgb(var(--bg-surface))] rounded-xl shadow-2xl overflow-hidden", "border border-[rgb(var(--bd-default))]", !panelPos && "animate-in slide-in-from-bottom-4 duration-300", "inset-4 md:inset-auto", "md:w-[480px] md:h-[680px]"), style: {
|
|
989
|
+
...(panelPos
|
|
990
|
+
? { right: `${panelPos.x}px`, bottom: `${panelPos.y}px` }
|
|
991
|
+
: { right: '16px', bottom: '16px' }),
|
|
992
|
+
}, children: [(0, jsx_runtime_1.jsxs)("div", { onPointerDown: handlePanelPointerDown, onPointerMove: handlePanelPointerMove, onPointerUp: handlePanelPointerUp, className: "h-12 px-3 flex items-center justify-between border-b border-[rgb(var(--bd-default))] bg-[rgb(var(--bg-surface))] shrink-0 cursor-move touch-none select-none", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5", children: [logoElement, (0, jsx_runtime_1.jsx)("span", { className: "font-semibold text-sm text-[rgb(var(--fg-default))]", children: title }), process.env.NEXT_PUBLIC_SHOW_TOKENS === 'true' && currentConversationId && ((0, jsx_runtime_1.jsxs)("span", { className: "text-[10px] font-mono px-1.5 py-0.5 rounded-md bg-[rgb(var(--bg-subtle))] text-[rgb(var(--fg-muted))]", children: ["Conversation ID: #", currentConversationId] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-0.5", children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setIsMuted(!isMuted), className: "h-7 w-7 rounded-md hover:bg-[rgb(var(--bg-subtle))] flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors", title: isMuted ? "Unmute sounds" : "Mute sounds", children: isMuted ? (0, jsx_runtime_1.jsx)(lucide_react_1.VolumeX, { className: "h-3.5 w-3.5" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Volume2, { className: "h-3.5 w-3.5" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: handleExport, className: "h-7 w-7 rounded-md hover:bg-[rgb(var(--bg-subtle))] flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors", title: t('Export'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Download, { className: "h-3.5 w-3.5" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: handleShare, className: "h-7 w-7 rounded-md hover:bg-[rgb(var(--bg-subtle))] flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors", title: t('Share'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Share2, { className: "h-3.5 w-3.5" }) }), fullpagePath && ((0, jsx_runtime_1.jsx)("button", { onClick: () => {
|
|
993
|
+
setIsFloatingOpen(false);
|
|
994
|
+
const target = currentConversationId
|
|
995
|
+
? `${fullpagePath}?c=${currentConversationId}`
|
|
996
|
+
: fullpagePath;
|
|
997
|
+
router.push(target);
|
|
998
|
+
}, disabled: isLoading && !currentConversationId, className: "h-7 w-7 rounded-md hover:bg-[rgb(var(--bg-subtle))] flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent", title: isLoading && !currentConversationId ? 'Wait for first reply to expand' : 'Open fullpage', children: (0, jsx_runtime_1.jsx)(lucide_react_1.Maximize2, { className: "h-3.5 w-3.5" }) })), (0, jsx_runtime_1.jsx)("button", { onClick: () => setIsFloatingOpen(false), className: "h-7 w-7 rounded-md hover:bg-[rgb(var(--bg-subtle))] flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors", "aria-label": t('Close chat'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "h-4 w-4" }) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 flex min-h-0 overflow-hidden bg-[rgb(var(--bg-app))]", children: [(0, jsx_runtime_1.jsx)(side_panel_1.SidePanel, { title: sidebarTitle || title, categories: conversationCategories, activeItemId: String(currentConversationId), onItemSelect: (id) => loadConversation(parseInt(id)), actionButton: {
|
|
999
|
+
label: 'New Chat',
|
|
1000
|
+
icon: lucide_react_1.Plus,
|
|
1001
|
+
onClick: startNewChat
|
|
1002
|
+
}, isOpen: isSidebarOpen, onClose: () => setIsSidebarOpen(false), showSearch: true, collapsible: true, defaultCollapsed: true, showItemIcons: false, itemContextMenu: renderConversationMenu, recentsAction: groupingToggle }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 flex flex-col min-w-0 overflow-hidden", children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative flex-1 min-h-0", children: [(0, jsx_runtime_1.jsx)("div", { ref: messagesScrollRef, className: "absolute inset-0 overflow-y-auto", children: (0, jsx_runtime_1.jsx)(ResolvedMessages, { messages: messages, isLoading: isLoading, onSelectItem: handleSelectItem, onEditMessage: handleEditMessage, onRegenerateAi: handleRegenerateAi, onFeedback: handleFeedback }) }), showScrollDown && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: scrollToBottom, "aria-label": t('Scroll to bottom'), className: "absolute left-1/2 -translate-x-1/2 bottom-3 z-10 w-11 h-11 lg:w-8 lg:h-8 rounded-full bg-[rgb(var(--bg-surface))] border border-[rgb(var(--bd-default))] shadow-md hover:bg-[rgb(var(--bg-hover))] hover:shadow-lg flex items-center justify-center transition-all", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "w-4 h-4 text-[rgb(var(--fg-default))]" }) }))] }), (0, jsx_runtime_1.jsx)(multimodal_input_1.MultimodalInput, { onSubmit: handleSubmit, onStop: handleStop, isLoading: isLoading, allowFileUpload: false, compact: true, disabled: isConversationClosed, disabledReason: isConversationClosed ? 'This conversation has reached its limit. Start a new chat to continue.' : undefined })] })] })] }), searchModal] }));
|
|
1003
|
+
}
|
|
1004
|
+
// Regular Chat Mode (fullpage, modal)
|
|
1005
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex h-full w-full overflow-hidden', mode === 'fullpage' && 'bg-[rgb(var(--bg-app))]'), children: [(0, jsx_runtime_1.jsx)(side_panel_1.SidePanel, { title: sidebarTitle || title, categories: conversationCategories, activeItemId: String(currentConversationId), onItemSelect: (id) => loadConversation(parseInt(id)), actionButton: {
|
|
1006
|
+
label: 'New Chat',
|
|
1007
|
+
icon: lucide_react_1.Plus,
|
|
1008
|
+
onClick: startNewChat
|
|
1009
|
+
}, isOpen: isSidebarOpen, onClose: () => setIsSidebarOpen(false), showSearch: true, collapsible: true, defaultCollapsed: mode === 'widget', showItemIcons: false, itemContextMenu: renderConversationMenu, recentsAction: groupingToggle }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 flex flex-col min-w-0 overflow-hidden bg-[rgb(var(--bg-app))]", children: [(0, jsx_runtime_1.jsxs)("div", { className: "md:hidden h-12 flex items-center justify-between px-3 border-b border-[rgb(var(--bd-default))] bg-[rgb(var(--bg-surface))] shrink-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setIsSidebarOpen(!isSidebarOpen), className: "w-8 h-8 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-lg transition-colors shrink-0", title: t('Chat history'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeftOpen, { className: "w-4 h-4" }) }), logo && (0, jsx_runtime_1.jsx)("div", { className: "shrink-0", children: logo }), (0, jsx_runtime_1.jsx)("span", { className: "font-semibold text-sm text-[rgb(var(--fg-default))] truncate", children: title }), process.env.NEXT_PUBLIC_SHOW_TOKENS === 'true' && currentConversationId && ((0, jsx_runtime_1.jsxs)("span", { className: "text-[10px] font-mono px-1.5 py-0.5 rounded-md bg-[rgb(var(--bg-subtle))] text-[rgb(var(--fg-muted))] shrink-0", children: ["Conversation ID: #", currentConversationId] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-0.5 shrink-0", children: [headerActions, (0, jsx_runtime_1.jsx)("button", { onClick: startNewChat, className: "w-8 h-8 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--color-primary))] hover:bg-[rgb(var(--color-primary))]/5 rounded-lg transition-colors", title: t('New chat'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { className: "w-4 h-4" }) }), messages.length > 0 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { onClick: handleExport, className: "w-8 h-8 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-lg transition-colors", title: t('Export'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Download, { className: "w-3.5 h-3.5" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: handleShare, className: "w-8 h-8 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-lg transition-colors", title: t('Share'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Share2, { className: "w-3.5 h-3.5" }) })] })), fullpagePath && mode === 'modal' && ((0, jsx_runtime_1.jsx)("button", { onClick: () => {
|
|
1010
|
+
const target = currentConversationId
|
|
1011
|
+
? `${fullpagePath}?c=${currentConversationId}`
|
|
1012
|
+
: fullpagePath;
|
|
1013
|
+
router.push(target);
|
|
1014
|
+
}, disabled: isLoading && !currentConversationId, className: "w-8 h-8 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-lg transition-colors disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent", title: isLoading && !currentConversationId ? 'Wait for first reply to expand' : 'Open fullpage', children: (0, jsx_runtime_1.jsx)(lucide_react_1.Maximize2, { className: "w-3.5 h-3.5" }) }))] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "hidden md:flex h-10 items-center justify-center px-3 border-b border-[rgb(var(--bd-default))] bg-[rgb(var(--bg-surface))] shrink-0 relative", children: [process.env.NEXT_PUBLIC_SHOW_TOKENS === 'true' && currentConversationId && ((0, jsx_runtime_1.jsxs)("span", { className: "absolute left-3 text-[10px] font-mono px-1.5 py-0.5 rounded-md bg-[rgb(var(--bg-subtle))] text-[rgb(var(--fg-muted))]", children: ["Conversation ID: #", currentConversationId] })), process.env.NEXT_PUBLIC_SHOW_TOKENS === 'true' && messages.length > 0 && (() => {
|
|
1015
|
+
const totals = messages.reduce((acc, m) => {
|
|
1016
|
+
if (m.tokens) {
|
|
1017
|
+
acc.prompt += m.tokens.prompt;
|
|
1018
|
+
acc.completion += m.tokens.completion;
|
|
1019
|
+
acc.total += m.tokens.total;
|
|
1020
|
+
}
|
|
1021
|
+
return acc;
|
|
1022
|
+
}, { prompt: 0, completion: 0, total: 0 });
|
|
1023
|
+
if (totals.total === 0)
|
|
1024
|
+
return null;
|
|
1025
|
+
return ((0, jsx_runtime_1.jsxs)("span", { className: "text-[0.65rem] text-[rgb(var(--fg-muted))] font-mono", children: ["Prompt: ", totals.prompt.toLocaleString(), " \u00B7 Response: ", totals.completion.toLocaleString(), " \u00B7 Total: ", totals.total.toLocaleString(), " tokens \u00B7 ", messages.filter(m => m.tokens).length, " calls"] }));
|
|
1026
|
+
})(), (0, jsx_runtime_1.jsxs)("div", { className: "absolute right-3 flex items-center gap-0.5", children: [headerActions, (0, jsx_runtime_1.jsx)("button", { onClick: () => setIsMuted(!isMuted), className: "w-7 h-7 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-md transition-colors", title: isMuted ? "Unmute sounds" : "Mute sounds", children: isMuted ? (0, jsx_runtime_1.jsx)(lucide_react_1.VolumeX, { className: "w-3.5 h-3.5" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Volume2, { className: "w-3.5 h-3.5" }) }), messages.length > 0 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { onClick: handleExport, className: "w-7 h-7 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-md transition-colors", title: t('Export'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Download, { className: "w-3.5 h-3.5" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: handleShare, className: "w-7 h-7 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-md transition-colors", title: t('Share'), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Share2, { className: "w-3.5 h-3.5" }) })] })), fullpagePath && mode === 'modal' && ((0, jsx_runtime_1.jsx)("button", { onClick: () => {
|
|
1027
|
+
const target = currentConversationId
|
|
1028
|
+
? `${fullpagePath}?c=${currentConversationId}`
|
|
1029
|
+
: fullpagePath;
|
|
1030
|
+
router.push(target);
|
|
1031
|
+
}, disabled: isLoading && !currentConversationId, title: isLoading && !currentConversationId ? 'Wait for first reply to expand' : 'Open fullpage', className: "w-7 h-7 flex items-center justify-center text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))] rounded-md transition-colors disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Maximize2, { className: "w-3.5 h-3.5" }) }))] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "relative flex-1 min-h-0", children: [(0, jsx_runtime_1.jsx)("div", { ref: messagesScrollRef, className: "absolute inset-0 overflow-y-auto", children: (0, jsx_runtime_1.jsx)(ResolvedMessages, { messages: messages, isLoading: isLoading, onSelectItem: handleSelectItem, onEditMessage: handleEditMessage, onRegenerateAi: handleRegenerateAi, onFeedback: handleFeedback }) }), showScrollDown && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: scrollToBottom, "aria-label": t('Scroll to bottom'), className: "absolute left-1/2 -translate-x-1/2 bottom-3 z-10 w-11 h-11 lg:w-8 lg:h-8 rounded-full bg-[rgb(var(--bg-surface))] border border-[rgb(var(--bd-default))] shadow-md hover:bg-[rgb(var(--bg-hover))] hover:shadow-lg flex items-center justify-center transition-all", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "w-4 h-4 text-[rgb(var(--fg-default))]" }) })), mode === 'fullpage' && ((0, jsx_runtime_1.jsx)(chat_prompt_navigator_1.ChatPromptNavigator, { messages: messages, scrollContainer: findScroller, moduleName: title }))] }), (0, jsx_runtime_1.jsx)(multimodal_input_1.MultimodalInput, { onSubmit: handleSubmit, onStop: handleStop, isLoading: isLoading, allowFileUpload: false, compact: mode === 'widget', disabled: isConversationClosed, disabledReason: isConversationClosed ? 'This conversation has reached its limit. Start a new chat to continue.' : undefined })] }), isSidebarOpen && ((0, jsx_runtime_1.jsx)("div", { className: "md:hidden fixed inset-0 bg-black/60 backdrop-blur-sm z-40", onClick: () => setIsSidebarOpen(false) })), searchModal] }));
|
|
1032
|
+
}
|