@iblai/iblai-js 1.4.2 → 1.4.3

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.
@@ -117858,7 +117858,7 @@ var Content2$1 = PopoverContent$1;
117858
117858
 
117859
117859
  const Popover = Root2$1;
117860
117860
  const PopoverTrigger = Trigger$1;
117861
- const PopoverContent = React.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => (jsx(Portal$2, { children: jsx(Content2$1, { ref: ref, align: align, sideOffset: sideOffset, className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-none", className), ...props }) })));
117861
+ const PopoverContent = React.forwardRef(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (jsx(Portal$2, { children: jsx(Content2$1, { ref: ref, align: align, sideOffset: sideOffset, className: cn('bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-none', className), ...props }) })));
117862
117862
  PopoverContent.displayName = Content2$1.displayName;
117863
117863
 
117864
117864
  const offsetFormatCache = {};
@@ -185752,6 +185752,14 @@ const useReports = ({ tenantKey, selectedMentorId, usergroupIds, }) => {
185752
185752
  };
185753
185753
  };
185754
185754
 
185755
+ // Format as YYYY-MM-DD using local date parts so the picked calendar date
185756
+ // is preserved regardless of the user's timezone (avoids the UTC shift from toISOString()).
185757
+ const toISODate = (date) => {
185758
+ const year = date.getFullYear();
185759
+ const month = String(date.getMonth() + 1).padStart(2, '0');
185760
+ const day = String(date.getDate()).padStart(2, '0');
185761
+ return `${year}-${month}-${day}`;
185762
+ };
185755
185763
  const toTitleCase = (value) => {
185756
185764
  if (!value)
185757
185765
  return '';
@@ -185807,6 +185815,17 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
185807
185815
  });
185808
185816
  const [isCombiningReports, setIsCombiningReports] = useState(false);
185809
185817
  const cancelCombiningRef = useRef(false);
185818
+ const [regenerateHintReportKey, setRegenerateHintReportKey] = useState(null);
185819
+ const [hasSeenRegenerateHint, setHasSeenRegenerateHint] = useState(false);
185820
+ const dismissRegenerateHint = useCallback(() => {
185821
+ setRegenerateHintReportKey(null);
185822
+ setHasSeenRegenerateHint(true);
185823
+ }, []);
185824
+ const maybeShowRegenerateHint = useCallback((reportKey) => {
185825
+ if (!reportKey || hasSeenRegenerateHint)
185826
+ return;
185827
+ setRegenerateHintReportKey(reportKey);
185828
+ }, [hasSeenRegenerateHint]);
185810
185829
  const parseCSV = useCallback((csvText) => {
185811
185830
  const lines = csvText.trim().split('\n');
185812
185831
  if (lines.length === 0) {
@@ -185875,6 +185894,7 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
185875
185894
  }
185876
185895
  }
185877
185896
  }, [parseCSV, fetchAuthenticatedContent, downloadAuthenticatedReport]);
185897
+ const lastDownloadedReportKeyRef = useRef(null);
185878
185898
  const handleCsvEditorSave = useCallback((data) => {
185879
185899
  // Convert data back to CSV and trigger download
185880
185900
  const csvContent = [
@@ -185900,19 +185920,21 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
185900
185920
  URL.revokeObjectURL(url);
185901
185921
  toast.success('Report saved successfully');
185902
185922
  setCsvEditorData({ isOpen: false, headers: [], rows: [], reportUrl: null });
185903
- }, []);
185923
+ maybeShowRegenerateHint(lastDownloadedReportKeyRef.current);
185924
+ }, [maybeShowRegenerateHint]);
185904
185925
  const handleCsvEditorCancel = useCallback(() => {
185905
185926
  setCsvEditorData({ isOpen: false, headers: [], rows: [], reportUrl: null });
185906
185927
  }, []);
185907
185928
  const handleAutoDownload = useCallback(async (url) => {
185908
185929
  try {
185909
185930
  await downloadAuthenticatedReport(url);
185931
+ maybeShowRegenerateHint(lastDownloadedReportKeyRef.current);
185910
185932
  }
185911
185933
  catch (error) {
185912
185934
  console.error('Failed to auto-download report:', error);
185913
185935
  toast.error('Failed to download report');
185914
185936
  }
185915
- }, [downloadAuthenticatedReport]);
185937
+ }, [downloadAuthenticatedReport, maybeShowRegenerateHint]);
185916
185938
  // Check if a report is one of the recommendation reports to combine
185917
185939
  const isRecommendationReport = useCallback((reportDisplayName) => {
185918
185940
  return combinedRecommendationReports.some((name) => reportDisplayName.toLowerCase() === name.toLowerCase());
@@ -186009,11 +186031,20 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
186009
186031
  parseCSV,
186010
186032
  fetchAuthenticatedContent,
186011
186033
  ]);
186012
- const handleReportClick = useCallback((report) => {
186013
- var _a, _b;
186034
+ const buildDateRangeBody = useCallback((dateRange) => {
186035
+ const body = {};
186036
+ if (dateRange === null || dateRange === void 0 ? void 0 : dateRange.from)
186037
+ body.start_date = toISODate(dateRange.from);
186038
+ if (dateRange === null || dateRange === void 0 ? void 0 : dateRange.to)
186039
+ body.end_date = toISODate(dateRange.to);
186040
+ return body;
186041
+ }, []);
186042
+ const handleReportClick = useCallback((report, dateRange) => {
186043
+ var _a, _b, _c;
186014
186044
  const isChatHistory = report.display_name === 'All Mentor Chat History';
186045
+ lastDownloadedReportKeyRef.current = (_a = report.report_name) !== null && _a !== void 0 ? _a : null;
186015
186046
  // If report is already completed with a URL, use the pre-existing URL
186016
- if (((_a = report.status) === null || _a === void 0 ? void 0 : _a.state) === 'completed' && ((_b = report.status) === null || _b === void 0 ? void 0 : _b.url)) {
186047
+ if (((_b = report.status) === null || _b === void 0 ? void 0 : _b.state) === 'completed' && ((_c = report.status) === null || _c === void 0 ? void 0 : _c.url)) {
186017
186048
  if (isChatHistory) {
186018
186049
  handleAutoDownload(report.status.url);
186019
186050
  }
@@ -186028,23 +186059,35 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
186028
186059
  handleCombinedRecommendationReports();
186029
186060
  return;
186030
186061
  }
186031
- // Otherwise, generate the report
186062
+ // Otherwise, generate the report. Chat history auto-downloads inside the hook, so we
186063
+ // hook into onCompletion to surface the regenerate hint once the file has landed;
186064
+ // all other reports open the CSV editor and fire the hint on save.
186032
186065
  initializeReportDownload({
186033
186066
  report,
186034
186067
  autoDownload: isChatHistory,
186035
- onCompletion: isChatHistory ? undefined : handleReportCompletion,
186036
- extraRequestBody: { force: true, source: window.location.origin },
186068
+ onCompletion: isChatHistory
186069
+ ? () => { var _a; return maybeShowRegenerateHint((_a = report.report_name) !== null && _a !== void 0 ? _a : null); }
186070
+ : handleReportCompletion,
186071
+ extraRequestBody: {
186072
+ force: true,
186073
+ source: window.location.origin,
186074
+ ...buildDateRangeBody(dateRange),
186075
+ },
186037
186076
  });
186038
186077
  }, [
186078
+ buildDateRangeBody,
186039
186079
  handleAutoDownload,
186040
186080
  handleReportCompletion,
186081
+ maybeShowRegenerateHint,
186041
186082
  metadata === null || metadata === void 0 ? void 0 : metadata.enable_combined_recommendation_report,
186042
186083
  isRecommendationReport,
186043
186084
  handleCombinedRecommendationReports,
186044
186085
  initializeReportDownload,
186045
186086
  ]);
186046
- const handleRegenerateReport = useCallback((report) => {
186087
+ const handleRegenerateReport = useCallback((report, dateRange) => {
186088
+ var _a;
186047
186089
  const isChatHistory = report.display_name === 'All Mentor Chat History';
186090
+ lastDownloadedReportKeyRef.current = (_a = report.report_name) !== null && _a !== void 0 ? _a : null;
186048
186091
  // Check if this is a recommendation report and combining is enabled
186049
186092
  if ((metadata === null || metadata === void 0 ? void 0 : metadata.enable_combined_recommendation_report) &&
186050
186093
  isRecommendationReport(report.display_name || toTitleCase(report.report_name))) {
@@ -186055,11 +186098,19 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
186055
186098
  initializeReportDownload({
186056
186099
  report,
186057
186100
  autoDownload: isChatHistory,
186058
- onCompletion: isChatHistory ? undefined : handleReportCompletion,
186059
- extraRequestBody: { force: true, source: window.location.origin },
186101
+ onCompletion: isChatHistory
186102
+ ? () => { var _a; return maybeShowRegenerateHint((_a = report.report_name) !== null && _a !== void 0 ? _a : null); }
186103
+ : handleReportCompletion,
186104
+ extraRequestBody: {
186105
+ force: true,
186106
+ source: window.location.origin,
186107
+ ...buildDateRangeBody(dateRange),
186108
+ },
186060
186109
  });
186061
186110
  }, [
186111
+ buildDateRangeBody,
186062
186112
  handleReportCompletion,
186113
+ maybeShowRegenerateHint,
186063
186114
  metadata === null || metadata === void 0 ? void 0 : metadata.enable_combined_recommendation_report,
186064
186115
  isRecommendationReport,
186065
186116
  handleCombinedRecommendationReports,
@@ -186100,7 +186151,7 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
186100
186151
  return (jsx("div", { className: "flex flex-col items-center justify-center space-y-4", children: jsx(EmptyStats, { title: 'No reports available yet.' }) }));
186101
186152
  }
186102
186153
  return (jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8 items-stretch", children: filteredReports.map((report, index) => {
186103
- var _a, _b, _c, _d;
186154
+ var _a, _b, _c;
186104
186155
  const reportKey = (_a = report.report_name) !== null && _a !== void 0 ? _a : `report-${index}`;
186105
186156
  const hasIdentifier = Boolean(report.report_name);
186106
186157
  const isActive = isGenerating && hasIdentifier && activeReportName === reportKey;
@@ -186108,12 +186159,7 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
186108
186159
  const isCombinableReport = (metadata === null || metadata === void 0 ? void 0 : metadata.enable_combined_recommendation_report) &&
186109
186160
  isRecommendationReport(report.display_name || toTitleCase(report.report_name));
186110
186161
  const hasCompletedReport = ((_b = report.status) === null || _b === void 0 ? void 0 : _b.state) === 'completed' && ((_c = report.status) === null || _c === void 0 ? void 0 : _c.url);
186111
- return (jsx(Card, { "aria-label": `${report.display_name || toTitleCase(report.report_name)} report card`, className: "bg-white border-gray-200 h-full flex flex-col", "data-testid": isCombinableReport ? 'combined-recommendation-report-card' : undefined, children: jsx(CardContent, { className: "p-6 flex-1 flex flex-col", children: jsxs("div", { className: "flex-1", children: [jsxs("div", { className: "flex justify-between items-start mb-2", children: [jsx("h3", { className: "text-base font-medium text-gray-700 flex-1 pr-2", children: (() => {
186112
- const displayName = report.display_name || toTitleCase(report.report_name);
186113
- return displayName === 'All Mentor Chat History'
186114
- ? 'Chat History'
186115
- : displayName;
186116
- })() }), jsxs("div", { className: "flex items-center gap-1 flex-shrink-0", children: [hasCompletedReport && (jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 bg-transparent hover:bg-[#155dfc] hover:text-white border-[#155dfc] text-[#155dfc]", onClick: () => handleRegenerateReport(report), disabled: isDisabled, "aria-label": "Regenerate report", children: isActive ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(RefreshCw, { className: "h-4 w-4" })) })), jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 bg-transparent hover:bg-[#155dfc] hover:text-white border-[#155dfc] text-[#155dfc]", onClick: () => handleReportClick(report), disabled: isDisabled, "aria-label": "Download report", children: isActive && !hasCompletedReport ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Download, { className: "h-4 w-4" })) })] })] }), jsx("p", { className: "text-sm text-gray-600", children: report.description || 'Generate and download this report' }), hasCompletedReport && ((_d = report.status) === null || _d === void 0 ? void 0 : _d.created_at) && (jsxs("p", { className: "text-xs text-gray-400 mt-2", children: ["Generated: ", formatReportDate(report.status.created_at)] }))] }) }) }, reportKey));
186162
+ return (jsx(ReportCard, { report: report, isActive: isActive, isDisabled: isDisabled, isCombinableReport: Boolean(isCombinableReport), hasCompletedReport: Boolean(hasCompletedReport), showRegenerateHint: regenerateHintReportKey === reportKey, onDismissRegenerateHint: dismissRegenerateHint, formatReportDate: formatReportDate, onDownloadClick: handleReportClick, onRegenerateClick: handleRegenerateReport }, reportKey));
186117
186163
  }) }));
186118
186164
  }, [
186119
186165
  activeReportName,
@@ -186125,9 +186171,86 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
186125
186171
  isLoading,
186126
186172
  isRecommendationReport,
186127
186173
  filteredReports,
186174
+ regenerateHintReportKey,
186175
+ dismissRegenerateHint,
186128
186176
  ]);
186129
186177
  return (jsxs("div", { className: "space-y-6 relative", children: [jsx(Dialog$1, { open: isCombiningReports, onOpenChange: (open) => !open && handleCancelCombining(), children: jsxs(DialogContent$1, { "aria-describedby": "combining-reports-description", "data-testid": "combining-reports-dialog", children: [jsx(DialogHeader, { children: jsx(DialogTitle$1, { className: "ibl-dialog-title", children: "Combining Reports" }) }), jsxs("div", { className: "flex flex-col items-center gap-4 py-4", children: [jsx(LoaderCircle, { className: "h-8 w-8 animate-spin text-blue-600" }), jsx("p", { id: "combining-reports-description", className: "text-sm text-[#646464]", children: "Loading & combining recommendations data" })] }), jsx(DialogFooter, { children: jsx(Button$1, { variant: "outline", onClick: handleCancelCombining, "data-testid": "cancel-combining-button", children: "Cancel" }) })] }) }), content, csvEditorData.isOpen && (jsx(CSVEditor, { csvData: { headers: csvEditorData.headers, rows: csvEditorData.rows }, onSave: handleCsvEditorSave, onCancel: handleCsvEditorCancel }))] }));
186130
186178
  }
186179
+ function ReportCard({ report, isActive, isDisabled, isCombinableReport, hasCompletedReport, showRegenerateHint, onDismissRegenerateHint, formatReportDate, onDownloadClick, onRegenerateClick, }) {
186180
+ var _a;
186181
+ const [dateRange, setDateRange] = useState(undefined);
186182
+ const [popoverMode, setPopoverMode] = useState(null);
186183
+ const displayName = report.display_name || toTitleCase(report.report_name);
186184
+ const headerTitle = displayName === 'All Mentor Chat History' ? 'Chat History' : displayName;
186185
+ const closePopover = () => {
186186
+ setPopoverMode(null);
186187
+ setDateRange(undefined);
186188
+ };
186189
+ const handleConfirm = () => {
186190
+ if (popoverMode === 'regenerate') {
186191
+ onRegenerateClick(report, dateRange);
186192
+ }
186193
+ else {
186194
+ onDownloadClick(report, dateRange);
186195
+ }
186196
+ closePopover();
186197
+ };
186198
+ const handleDownloadButtonClick = () => {
186199
+ // Completed reports just download the existing URL — skip the picker.
186200
+ if (hasCompletedReport) {
186201
+ onDownloadClick(report);
186202
+ return;
186203
+ }
186204
+ setPopoverMode('download');
186205
+ };
186206
+ const handleRegenerateButtonClick = () => {
186207
+ // Clicking Regenerate also dismisses any onboarding hint attached to it.
186208
+ if (showRegenerateHint)
186209
+ onDismissRegenerateHint();
186210
+ setPopoverMode('regenerate');
186211
+ };
186212
+ const dialogOpen = popoverMode !== null;
186213
+ const hasDateSelection = Boolean(dateRange === null || dateRange === void 0 ? void 0 : dateRange.from);
186214
+ return (jsxs(Fragment$1, { children: [jsx(Card, { "aria-label": `${displayName} report card`, className: "bg-white border-gray-200 h-full flex flex-col", "data-testid": isCombinableReport ? 'combined-recommendation-report-card' : undefined, children: jsx(CardContent, { className: "p-6 flex-1 flex flex-col", children: jsxs("div", { className: "flex-1", children: [jsxs("div", { className: "flex justify-between items-start mb-2", children: [jsx("h3", { className: "text-base font-medium text-gray-700 flex-1 pr-2", children: headerTitle }), jsxs("div", { className: "flex items-center gap-1 flex-shrink-0", children: [hasCompletedReport && (jsxs(Popover, { open: showRegenerateHint, onOpenChange: (next) => {
186215
+ if (!next)
186216
+ onDismissRegenerateHint();
186217
+ }, children: [jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: jsx(PopoverTrigger, { asChild: true, children: jsx(Button$1, { variant: "outline", size: "sm", className: cn('h-8 w-8 p-0 bg-transparent hover:bg-[#155dfc] hover:text-white border-[#155dfc] text-[#155dfc]', showRegenerateHint &&
186218
+ 'ring-2 ring-[#155dfc] ring-offset-2 animate-pulse'), onClick: handleRegenerateButtonClick, disabled: isDisabled, "aria-label": "Regenerate report", children: isActive ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(RefreshCw, { className: "h-4 w-4" })) }) }) }), jsx(TooltipContent, { side: "top", children: "Regenerate report" })] }), jsx(PopoverContent, { side: "top", align: "end", className: "w-64", "data-testid": "regenerate-hint-popover", onOpenAutoFocus: (e) => e.preventDefault(), children: jsxs("div", { className: "space-y-2", children: [jsx("p", { className: "text-sm font-semibold text-gray-900", children: "Need fresh data?" }), jsx("p", { className: "text-xs text-gray-600", children: "Click the refresh icon any time to regenerate this report with the latest data." }), jsx("div", { className: "flex justify-end pt-1", children: jsx(Button$1, { size: "sm", className: "h-7 text-xs", onClick: onDismissRegenerateHint, children: "Got it" }) })] }) })] })), jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 bg-transparent hover:bg-[#155dfc] hover:text-white border-[#155dfc] text-[#155dfc]", onClick: handleDownloadButtonClick, disabled: isDisabled, "aria-label": "Download report", children: isActive && !hasCompletedReport ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Download, { className: "h-4 w-4" })) }) }), jsx(TooltipContent, { side: "top", children: hasCompletedReport ? 'Download report' : 'Generate & download report' })] })] })] }), jsx("p", { className: "text-sm text-gray-600", children: report.description || 'Generate and download this report' }), hasCompletedReport && ((_a = report.status) === null || _a === void 0 ? void 0 : _a.created_at) && (jsxs("p", { className: "text-xs text-gray-400 mt-2", children: ["Generated: ", formatReportDate(report.status.created_at)] }))] }) }) }), jsx(Dialog$1, { open: dialogOpen, onOpenChange: (next) => (next ? null : closePopover()), children: jsxs(DialogContent$1, { className: "w-[calc(100vw-2rem)] max-w-[720px] p-0 overflow-hidden", "data-testid": "report-date-range-popover", "aria-describedby": "report-date-range-description", children: [jsxs(DialogHeader, { className: "px-4 py-3 border-b", children: [jsxs(DialogTitle$1, { className: "flex items-center gap-2 text-sm font-medium text-gray-700", children: [jsx(Calendar$1, { className: "h-4 w-4 text-[#155dfc]" }), "Select date range (optional)"] }), jsx("p", { id: "report-date-range-description", className: "sr-only", children: "Pick a start and end date to scope the report, or leave blank for the full range." })] }), jsx("div", { className: "px-4 py-3", children: jsx(Calendar, { mode: "range", numberOfMonths: 2, defaultMonth: dateRange === null || dateRange === void 0 ? void 0 : dateRange.from, selected: dateRange, onSelect: setDateRange, disabled: (date) => date > new Date() || date < new Date('1900-01-01'), components: { DayButton: ReportRangeDayButton }, className: "w-full", classNames: {
186219
+ root: 'w-full',
186220
+ months: 'flex gap-4 flex-col md:flex-row relative w-full',
186221
+ month: 'flex flex-col w-full gap-4 flex-1',
186222
+ } }) }), jsxs(DialogFooter, { className: "flex items-center justify-between gap-2 border-t px-4 py-3 sm:justify-between", children: [jsx(Button$1, { type: "button", variant: "ghost", size: "sm", onClick: () => setDateRange(undefined), disabled: !hasDateSelection, children: "Clear" }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(Button$1, { type: "button", variant: "outline", size: "sm", onClick: closePopover, children: "Cancel" }), jsx(Button$1, { type: "button", size: "sm", onClick: handleConfirm, className: "bg-[#155dfc] text-white hover:bg-[#0f4bd1]", children: popoverMode === 'regenerate' ? 'Regenerate' : 'Generate' })] })] })] }) })] }));
186223
+ }
186224
+ function ReportRangeDayButton({ day, modifiers, className, ...props }) {
186225
+ const { range_start, range_end, range_middle, selected, today, disabled, outside } = modifiers;
186226
+ const baseClasses = 'flex items-center justify-center w-full h-full text-sm font-normal transition-colors';
186227
+ let stateClasses = 'text-gray-900 hover:bg-blue-50 focus:bg-blue-50 focus:outline-none rounded-md';
186228
+ if (range_start && range_end) {
186229
+ stateClasses = 'bg-[#155dfc] text-white hover:bg-[#0f4bd1] rounded-md';
186230
+ }
186231
+ else if (range_start) {
186232
+ stateClasses = 'bg-[#155dfc] text-white hover:bg-[#0f4bd1] rounded-l-md rounded-r-none';
186233
+ }
186234
+ else if (range_end) {
186235
+ stateClasses = 'bg-[#155dfc] text-white hover:bg-[#0f4bd1] rounded-r-md rounded-l-none';
186236
+ }
186237
+ else if (range_middle) {
186238
+ stateClasses = 'bg-blue-100 text-blue-900 hover:bg-blue-200 rounded-none';
186239
+ }
186240
+ else if (selected) {
186241
+ stateClasses = 'bg-[#155dfc] text-white hover:bg-[#0f4bd1] rounded-md';
186242
+ }
186243
+ else if (today) {
186244
+ stateClasses = 'bg-gray-100 text-gray-900 font-semibold hover:bg-blue-50 rounded-md';
186245
+ }
186246
+ if (outside && !selected && !range_start && !range_end && !range_middle) {
186247
+ stateClasses = 'text-gray-300 hover:bg-transparent rounded-md';
186248
+ }
186249
+ if (disabled) {
186250
+ stateClasses = 'text-gray-300 opacity-50 cursor-not-allowed rounded-md';
186251
+ }
186252
+ return (jsx("button", { type: "button", "data-day": day.date.toLocaleDateString(), ...props, className: `${baseClasses} ${stateClasses} ${className !== null && className !== void 0 ? className : ''}` }));
186253
+ }
186131
186254
 
186132
186255
  // Utility function to format date to YYYY-MM-DD
186133
186256
  const formatDateToYYYYMMDD$1 = (date) => {
@@ -107843,7 +107843,7 @@ var Content2$1 = PopoverContent$1;
107843
107843
 
107844
107844
  const Popover = Root2;
107845
107845
  const PopoverTrigger = Trigger$1;
107846
- const PopoverContent = React.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => (jsx(Portal$2, { children: jsx(Content2$1, { ref: ref, align: align, sideOffset: sideOffset, className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-none", className), ...props }) })));
107846
+ const PopoverContent = React.forwardRef(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (jsx(Portal$2, { children: jsx(Content2$1, { ref: ref, align: align, sideOffset: sideOffset, className: cn('bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-none', className), ...props }) })));
107847
107847
  PopoverContent.displayName = Content2$1.displayName;
107848
107848
 
107849
107849
  const offsetFormatCache = {};
@@ -1,6 +1,18 @@
1
1
  import { Locator, Page } from '@playwright/test';
2
2
  export declare function inviteUserTest(page: Page, inviteModal: Locator): Promise<void>;
3
3
  export declare function navigateToAccountComponent(page: Page, profileBtn: Locator): Promise<Locator>;
4
+ /**
5
+ * Click a report card's primary action and confirm the date-range picker, so callers
6
+ * always end up in the post-generation state.
7
+ *
8
+ * Prefers the "Regenerate report" button when present (completed reports) because the plain
9
+ * "Download report" button on a completed card re-downloads the existing URL and skips the
10
+ * picker. When no Regenerate button exists, clicks "Download report" — which on a
11
+ * non-completed card also opens the picker.
12
+ *
13
+ * Either way we wait for the picker and click Generate/Regenerate to start the report.
14
+ */
15
+ export declare function triggerReportFromCard(page: Page, card: Locator): Promise<void>;
4
16
  export declare function navigateToDataReports(page: Page): Promise<void>;
5
17
  export declare function shouldDisplayReportCards(page: Page, REPORT_CARDS: {
6
18
  name: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iblai/iblai-js",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "Unified JavaScript SDK for IBL.ai — re-exports data-layer, web-containers, and web-utils under a single package",
5
5
  "type": "module",
6
6
  "engines": {
@@ -63,7 +63,7 @@
63
63
  "winston": "3.19.0",
64
64
  "@iblai/data-layer": "1.3.2",
65
65
  "@iblai/mcp": "1.3.0",
66
- "@iblai/web-containers": "1.3.2",
66
+ "@iblai/web-containers": "1.3.3",
67
67
  "@iblai/web-utils": "1.2.8"
68
68
  },
69
69
  "peerDependencies": {