dp-widgets-framework 1.6.9 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +610 -13
- package/dist/index.js +609 -11
- package/package.json +2 -1
package/dist/index.esm.js
CHANGED
|
@@ -7,7 +7,7 @@ import * as LabelPrimitive from '@radix-ui/react-label';
|
|
|
7
7
|
import { cva } from 'class-variance-authority';
|
|
8
8
|
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
9
9
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
10
|
-
import { ChevronDown, ChevronUp, Check, AlertCircle, MoveUp, MoveDown, Trash2, Plus, Bot, Type, Layout, LayoutGrid, BarChart as BarChart$1, Filter, Search, ArrowUp, ArrowDown, ChevronRight, RefreshCw,
|
|
10
|
+
import { ChevronDown, ChevronUp, Check, AlertCircle, MoveUp, MoveDown, Trash2, Plus, Bot, Type, Layout, LayoutGrid, BarChart as BarChart$1, Filter, Search, ArrowUp, ArrowDown, ChevronRight, RefreshCw, Loader2, Download, Send, X, AlignVerticalSpaceAround, LineChart as LineChart$1, PieChart as PieChart$1, Table, FileText, SlidersHorizontal, GripHorizontal, Edit, MessageCircleX, ChevronLeft, Maximize2, Grid3X3, Edit2 } from 'lucide-react';
|
|
11
11
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
12
12
|
import { Slot, createSlot, createSlottable } from '@radix-ui/react-slot';
|
|
13
13
|
import { debounce as debounce$1 } from 'lodash';
|
|
@@ -17,6 +17,7 @@ import { v4 } from 'uuid';
|
|
|
17
17
|
import * as ReactDOM from 'react-dom';
|
|
18
18
|
import { TextMessage, Role } from '@copilotkit/runtime-client-gql';
|
|
19
19
|
import { CopilotKit, useCopilotContext, useCoAgent, useCopilotChat } from '@copilotkit/react-core';
|
|
20
|
+
import jsPDF from 'jspdf';
|
|
20
21
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
21
22
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
22
23
|
import { format } from 'date-fns';
|
|
@@ -44409,6 +44410,175 @@ function SpacerWidget({ widget }) {
|
|
|
44409
44410
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full", style: styles });
|
|
44410
44411
|
}
|
|
44411
44412
|
|
|
44413
|
+
const WISENBAKER_PRIMARY = "#8f002d";
|
|
44414
|
+
const WISENBAKER_GRAY = "#475569";
|
|
44415
|
+
function parseMarkdown(text) {
|
|
44416
|
+
const segments = [];
|
|
44417
|
+
const regex = /\*\*(.+?)\*\*/g;
|
|
44418
|
+
let lastIndex = 0;
|
|
44419
|
+
let match;
|
|
44420
|
+
while ((match = regex.exec(text)) !== null) {
|
|
44421
|
+
if (match.index > lastIndex) {
|
|
44422
|
+
segments.push({ text: text.slice(lastIndex, match.index), bold: false });
|
|
44423
|
+
}
|
|
44424
|
+
segments.push({ text: match[1], bold: true });
|
|
44425
|
+
lastIndex = regex.lastIndex;
|
|
44426
|
+
}
|
|
44427
|
+
if (lastIndex < text.length) {
|
|
44428
|
+
segments.push({ text: text.slice(lastIndex), bold: false });
|
|
44429
|
+
}
|
|
44430
|
+
return segments.length > 0 ? segments : [{ text, bold: false }];
|
|
44431
|
+
}
|
|
44432
|
+
function formatLine(line) {
|
|
44433
|
+
const bulletMatch = line.match(/^(\s*)[\*\-•]\s+(.*)$/);
|
|
44434
|
+
if (bulletMatch) {
|
|
44435
|
+
const indent = bulletMatch[1].length;
|
|
44436
|
+
return { text: bulletMatch[2], isBullet: true, indent };
|
|
44437
|
+
}
|
|
44438
|
+
const numberedMatch = line.match(/^(\s*)\d+\.\s+(.*)$/);
|
|
44439
|
+
if (numberedMatch) {
|
|
44440
|
+
const indent = numberedMatch[1].length;
|
|
44441
|
+
return { text: numberedMatch[2], isBullet: true, indent };
|
|
44442
|
+
}
|
|
44443
|
+
return { text: line, isBullet: false, indent: 0 };
|
|
44444
|
+
}
|
|
44445
|
+
function generateExportFilename(widgetId) {
|
|
44446
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
44447
|
+
return `NSight_Chat_Export_${widgetId}_${date}.pdf`;
|
|
44448
|
+
}
|
|
44449
|
+
function exportChatToPDF(options) {
|
|
44450
|
+
const { widgetId, messages, dashboardName } = options;
|
|
44451
|
+
const doc = new jsPDF();
|
|
44452
|
+
let yPosition = 25;
|
|
44453
|
+
const pageHeight = doc.internal.pageSize.height;
|
|
44454
|
+
const pageWidth = doc.internal.pageSize.width;
|
|
44455
|
+
const margin = 20;
|
|
44456
|
+
const contentWidth = pageWidth - margin * 2;
|
|
44457
|
+
const maxWidth = contentWidth - 10;
|
|
44458
|
+
const checkPageBreak = (requiredSpace = 20) => {
|
|
44459
|
+
if (yPosition > pageHeight - requiredSpace) {
|
|
44460
|
+
doc.addPage();
|
|
44461
|
+
yPosition = 25;
|
|
44462
|
+
}
|
|
44463
|
+
};
|
|
44464
|
+
const renderFormattedText = (text, x, maxW, baseIndent = 0) => {
|
|
44465
|
+
const lines = text.split("\n");
|
|
44466
|
+
lines.forEach((line) => {
|
|
44467
|
+
const { text: lineText, isBullet, indent } = formatLine(line);
|
|
44468
|
+
const lineIndent = x + baseIndent + indent * 2;
|
|
44469
|
+
if (isBullet) {
|
|
44470
|
+
checkPageBreak(10);
|
|
44471
|
+
doc.setFont("helvetica", "normal");
|
|
44472
|
+
doc.text("\u2022", lineIndent, yPosition);
|
|
44473
|
+
}
|
|
44474
|
+
const textX = isBullet ? lineIndent + 5 : lineIndent;
|
|
44475
|
+
const textMaxWidth = maxW - (textX - x);
|
|
44476
|
+
const segments = parseMarkdown(lineText);
|
|
44477
|
+
let currentLine = "";
|
|
44478
|
+
let currentX = textX;
|
|
44479
|
+
segments.forEach((segment) => {
|
|
44480
|
+
doc.setFont("helvetica", segment.bold ? "bold" : "normal");
|
|
44481
|
+
const words = segment.text.split(" ");
|
|
44482
|
+
words.forEach((word, wordIndex) => {
|
|
44483
|
+
const testLine = currentLine + (currentLine ? " " : "") + word;
|
|
44484
|
+
const testWidth = doc.getTextWidth(testLine);
|
|
44485
|
+
if (testWidth > textMaxWidth && currentLine) {
|
|
44486
|
+
checkPageBreak(10);
|
|
44487
|
+
doc.text(currentLine, currentX, yPosition);
|
|
44488
|
+
yPosition += 5;
|
|
44489
|
+
currentLine = word;
|
|
44490
|
+
currentX = isBullet ? lineIndent + 5 : x + baseIndent;
|
|
44491
|
+
} else {
|
|
44492
|
+
currentLine = testLine;
|
|
44493
|
+
}
|
|
44494
|
+
});
|
|
44495
|
+
});
|
|
44496
|
+
if (currentLine) {
|
|
44497
|
+
checkPageBreak(10);
|
|
44498
|
+
const lastSegment = segments[segments.length - 1];
|
|
44499
|
+
doc.setFont("helvetica", (lastSegment == null ? void 0 : lastSegment.bold) ? "bold" : "normal");
|
|
44500
|
+
doc.text(currentLine, currentX, yPosition);
|
|
44501
|
+
yPosition += 5;
|
|
44502
|
+
}
|
|
44503
|
+
});
|
|
44504
|
+
};
|
|
44505
|
+
doc.setFontSize(18);
|
|
44506
|
+
doc.setFont("helvetica", "bold");
|
|
44507
|
+
doc.setTextColor(WISENBAKER_PRIMARY);
|
|
44508
|
+
doc.text("Wisenbaker AI Analytics", margin, yPosition);
|
|
44509
|
+
yPosition += 8;
|
|
44510
|
+
doc.setFontSize(11);
|
|
44511
|
+
doc.setFont("helvetica", "normal");
|
|
44512
|
+
doc.setTextColor(WISENBAKER_GRAY);
|
|
44513
|
+
doc.text("Chat Export", margin, yPosition);
|
|
44514
|
+
yPosition += 12;
|
|
44515
|
+
doc.setFontSize(9);
|
|
44516
|
+
doc.setTextColor("#666666");
|
|
44517
|
+
if (dashboardName) {
|
|
44518
|
+
doc.setFont("helvetica", "bold");
|
|
44519
|
+
doc.text("Dashboard:", margin, yPosition);
|
|
44520
|
+
doc.setFont("helvetica", "normal");
|
|
44521
|
+
doc.text(dashboardName, margin + 38, yPosition);
|
|
44522
|
+
yPosition += 5;
|
|
44523
|
+
}
|
|
44524
|
+
doc.setFont("helvetica", "bold");
|
|
44525
|
+
doc.text("Exported:", margin, yPosition);
|
|
44526
|
+
doc.setFont("helvetica", "normal");
|
|
44527
|
+
doc.text((/* @__PURE__ */ new Date()).toLocaleString(), margin + 38, yPosition);
|
|
44528
|
+
doc.setFont("helvetica", "bold");
|
|
44529
|
+
doc.text("Messages:", margin + 100, yPosition);
|
|
44530
|
+
doc.setFont("helvetica", "normal");
|
|
44531
|
+
doc.text(String(messages.length), margin + 130, yPosition);
|
|
44532
|
+
yPosition += 12;
|
|
44533
|
+
doc.setDrawColor(200, 200, 200);
|
|
44534
|
+
doc.setLineWidth(0.5);
|
|
44535
|
+
doc.line(margin, yPosition, pageWidth - margin, yPosition);
|
|
44536
|
+
yPosition += 8;
|
|
44537
|
+
messages.forEach((message, index) => {
|
|
44538
|
+
checkPageBreak(30);
|
|
44539
|
+
const isUser = message.role === "user";
|
|
44540
|
+
const roleLabel = isUser ? "You" : "AI Assistant";
|
|
44541
|
+
const timestamp = message.createdAt ? new Date(message.createdAt).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) : "";
|
|
44542
|
+
const bgColor = isUser ? [143, 0, 45] : [241, 243, 245];
|
|
44543
|
+
doc.setFillColor(bgColor[0], bgColor[1], bgColor[2]);
|
|
44544
|
+
doc.setFontSize(9);
|
|
44545
|
+
doc.setFont("helvetica", "bold");
|
|
44546
|
+
doc.setTextColor(isUser ? WISENBAKER_PRIMARY : WISENBAKER_GRAY);
|
|
44547
|
+
doc.text(roleLabel, margin, yPosition);
|
|
44548
|
+
if (timestamp) {
|
|
44549
|
+
doc.setFont("helvetica", "normal");
|
|
44550
|
+
doc.setTextColor("#888888");
|
|
44551
|
+
doc.text(timestamp, margin + doc.getTextWidth(roleLabel) + 5, yPosition);
|
|
44552
|
+
}
|
|
44553
|
+
yPosition += 6;
|
|
44554
|
+
doc.setFontSize(10);
|
|
44555
|
+
doc.setTextColor("#333333");
|
|
44556
|
+
doc.setFont("helvetica", "normal");
|
|
44557
|
+
renderFormattedText(message.content, margin + 5, maxWidth - 5, 0);
|
|
44558
|
+
yPosition += 8;
|
|
44559
|
+
if (index < messages.length - 1) {
|
|
44560
|
+
doc.setDrawColor(230, 230, 230);
|
|
44561
|
+
doc.setLineWidth(0.3);
|
|
44562
|
+
doc.line(margin + 10, yPosition - 4, pageWidth - margin - 10, yPosition - 4);
|
|
44563
|
+
}
|
|
44564
|
+
});
|
|
44565
|
+
const totalPages = doc.getNumberOfPages();
|
|
44566
|
+
for (let i = 1; i <= totalPages; i++) {
|
|
44567
|
+
doc.setPage(i);
|
|
44568
|
+
doc.setFontSize(8);
|
|
44569
|
+
doc.setTextColor("#999999");
|
|
44570
|
+
doc.setFont("helvetica", "normal");
|
|
44571
|
+
doc.text(
|
|
44572
|
+
`Wisenbaker AI Analytics \u2022 Page ${i} of ${totalPages}`,
|
|
44573
|
+
pageWidth / 2,
|
|
44574
|
+
pageHeight - 10,
|
|
44575
|
+
{ align: "center" }
|
|
44576
|
+
);
|
|
44577
|
+
}
|
|
44578
|
+
const filename = generateExportFilename(widgetId);
|
|
44579
|
+
doc.save(filename);
|
|
44580
|
+
}
|
|
44581
|
+
|
|
44412
44582
|
var __defProp$b = Object.defineProperty;
|
|
44413
44583
|
var __defProps$9 = Object.defineProperties;
|
|
44414
44584
|
var __getOwnPropDescs$9 = Object.getOwnPropertyDescriptors;
|
|
@@ -44457,7 +44627,8 @@ function CopilotKitChatbot({
|
|
|
44457
44627
|
styles,
|
|
44458
44628
|
onResetReady,
|
|
44459
44629
|
widgetIds,
|
|
44460
|
-
datasetId
|
|
44630
|
+
datasetId,
|
|
44631
|
+
dashboardName
|
|
44461
44632
|
}) {
|
|
44462
44633
|
var _a, _b, _c, _d;
|
|
44463
44634
|
const { threadId, setThreadId } = useCopilotContext();
|
|
@@ -44474,7 +44645,24 @@ function CopilotKitChatbot({
|
|
|
44474
44645
|
const { reset, visibleMessages, appendMessage, isLoading } = useCopilotChat();
|
|
44475
44646
|
const [inputValue, setInputValue] = useState("");
|
|
44476
44647
|
const [chatMessages, setChatMessages] = useState([]);
|
|
44648
|
+
const [isExporting, setIsExporting] = useState(false);
|
|
44477
44649
|
const messagesEndRef = React__default.useRef(null);
|
|
44650
|
+
const handleExport = async () => {
|
|
44651
|
+
if (chatMessages.length === 0) return;
|
|
44652
|
+
setIsExporting(true);
|
|
44653
|
+
try {
|
|
44654
|
+
exportChatToPDF({
|
|
44655
|
+
widgetId: widget.id,
|
|
44656
|
+
widgetTitle: widget.title,
|
|
44657
|
+
messages: chatMessages,
|
|
44658
|
+
dashboardName
|
|
44659
|
+
});
|
|
44660
|
+
} catch (error) {
|
|
44661
|
+
console.error("Export failed:", error);
|
|
44662
|
+
} finally {
|
|
44663
|
+
setIsExporting(false);
|
|
44664
|
+
}
|
|
44665
|
+
};
|
|
44478
44666
|
const scrollToBottom = () => {
|
|
44479
44667
|
var _a2;
|
|
44480
44668
|
const el = messagesEndRef.current;
|
|
@@ -44549,6 +44737,25 @@ function CopilotKitChatbot({
|
|
|
44549
44737
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-medium", children: widget.title })
|
|
44550
44738
|
] }) }),
|
|
44551
44739
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 h-full flex flex-col", children: [
|
|
44740
|
+
chatMessages.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-start px-4 py-2 border-b border-gray-100", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
44741
|
+
"button",
|
|
44742
|
+
{
|
|
44743
|
+
onClick: handleExport,
|
|
44744
|
+
disabled: isExporting,
|
|
44745
|
+
className: cn(
|
|
44746
|
+
"flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md",
|
|
44747
|
+
"bg-gray-100 border border-gray-200",
|
|
44748
|
+
"text-gray-700 hover:bg-gray-200 hover:border-gray-300",
|
|
44749
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
44750
|
+
"transition-colors duration-150"
|
|
44751
|
+
),
|
|
44752
|
+
title: "Export conversation as PDF",
|
|
44753
|
+
children: [
|
|
44754
|
+
isExporting ? /* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "h-3.5 w-3.5" }),
|
|
44755
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Export PDF" })
|
|
44756
|
+
]
|
|
44757
|
+
}
|
|
44758
|
+
) }),
|
|
44552
44759
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto p-4 space-y-4", children: chatMessages.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center text-gray-500 text-xs mt-8", children: ((_b = widget.config) == null ? void 0 : _b.copilotInitialMessage) || ((_c = widget.config) == null ? void 0 : _c.placeholder) || "How can I help you today?" }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
44553
44760
|
chatMessages.map((message) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
44554
44761
|
"div",
|
|
@@ -44624,7 +44831,8 @@ function ChatbotWidget({
|
|
|
44624
44831
|
widgetBackendUrl,
|
|
44625
44832
|
onResetReady,
|
|
44626
44833
|
widgetIds,
|
|
44627
|
-
datasetId
|
|
44834
|
+
datasetId,
|
|
44835
|
+
dashboardName
|
|
44628
44836
|
}) {
|
|
44629
44837
|
var _a, _b;
|
|
44630
44838
|
const styles = getStyleValues$4((_a = widget.config) == null ? void 0 : _a.styles);
|
|
@@ -44648,7 +44856,8 @@ function ChatbotWidget({
|
|
|
44648
44856
|
styles,
|
|
44649
44857
|
onResetReady,
|
|
44650
44858
|
widgetIds,
|
|
44651
|
-
datasetId
|
|
44859
|
+
datasetId,
|
|
44860
|
+
dashboardName
|
|
44652
44861
|
}
|
|
44653
44862
|
)
|
|
44654
44863
|
}
|
|
@@ -47165,7 +47374,8 @@ function WidgetRenderer({
|
|
|
47165
47374
|
datasetId,
|
|
47166
47375
|
pageId,
|
|
47167
47376
|
onApplyFilters,
|
|
47168
|
-
isEditing = false
|
|
47377
|
+
isEditing = false,
|
|
47378
|
+
dashboardName
|
|
47169
47379
|
}) {
|
|
47170
47380
|
const handleConfigUpdate = (config) => {
|
|
47171
47381
|
if (onConfigUpdate) {
|
|
@@ -47197,7 +47407,7 @@ function WidgetRenderer({
|
|
|
47197
47407
|
}
|
|
47198
47408
|
);
|
|
47199
47409
|
case "chatbot":
|
|
47200
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(ChatbotWidget, { widget, showHeader: false, widgetBackendUrl, onResetReady, widgetIds, datasetId });
|
|
47410
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(ChatbotWidget, { widget, showHeader: false, widgetBackendUrl, onResetReady, widgetIds, datasetId, dashboardName });
|
|
47201
47411
|
case "filters":
|
|
47202
47412
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47203
47413
|
FiltersWidget,
|
|
@@ -48077,7 +48287,8 @@ function WidgetDashboard({
|
|
|
48077
48287
|
userId,
|
|
48078
48288
|
onApplyFilters,
|
|
48079
48289
|
filterResults,
|
|
48080
|
-
isApplyingFilters = false
|
|
48290
|
+
isApplyingFilters = false,
|
|
48291
|
+
focusWidgetId
|
|
48081
48292
|
}) {
|
|
48082
48293
|
const [widgets, setWidgets] = useState([]);
|
|
48083
48294
|
const [datasetId, setDatasetId] = useState("");
|
|
@@ -48094,6 +48305,12 @@ function WidgetDashboard({
|
|
|
48094
48305
|
const [editInitialQuery, setEditInitialQuery] = useState("");
|
|
48095
48306
|
const [editingWidget, setEditingWidget] = useState(null);
|
|
48096
48307
|
const [widgetResetFunctions, setWidgetResetFunctions] = useState(/* @__PURE__ */ new Map());
|
|
48308
|
+
const displayWidgets = React__default.useMemo(() => {
|
|
48309
|
+
if (focusWidgetId) {
|
|
48310
|
+
return widgets.filter((w) => w.id === focusWidgetId);
|
|
48311
|
+
}
|
|
48312
|
+
return widgets;
|
|
48313
|
+
}, [widgets, focusWidgetId]);
|
|
48097
48314
|
const getWidgetFilterStatus = useCallback((widgetId) => {
|
|
48098
48315
|
if (!filterResults) return null;
|
|
48099
48316
|
const result = filterResults.results.find((r) => r.widgetId === widgetId);
|
|
@@ -48692,7 +48909,7 @@ function WidgetDashboard({
|
|
|
48692
48909
|
};
|
|
48693
48910
|
const getLayoutFromWidgets = () => {
|
|
48694
48911
|
const processedIds = /* @__PURE__ */ new Set();
|
|
48695
|
-
return
|
|
48912
|
+
return displayWidgets.filter((widget) => {
|
|
48696
48913
|
if (processedIds.has(widget.id)) {
|
|
48697
48914
|
return false;
|
|
48698
48915
|
}
|
|
@@ -48700,6 +48917,22 @@ function WidgetDashboard({
|
|
|
48700
48917
|
return true;
|
|
48701
48918
|
}).map((widget) => {
|
|
48702
48919
|
widget.type === "text";
|
|
48920
|
+
if (focusWidgetId && widget.id === focusWidgetId) {
|
|
48921
|
+
return {
|
|
48922
|
+
i: widget.id,
|
|
48923
|
+
x: 0,
|
|
48924
|
+
y: 0,
|
|
48925
|
+
w: 12,
|
|
48926
|
+
// Full width
|
|
48927
|
+
h: 10,
|
|
48928
|
+
// Increased height for presentation
|
|
48929
|
+
minW: 0,
|
|
48930
|
+
minH: 1,
|
|
48931
|
+
isResizable: false,
|
|
48932
|
+
static: true
|
|
48933
|
+
// Prevent any movement in focus mode
|
|
48934
|
+
};
|
|
48935
|
+
}
|
|
48703
48936
|
return {
|
|
48704
48937
|
i: widget.id,
|
|
48705
48938
|
x: widget.position_x,
|
|
@@ -48782,11 +49015,15 @@ function WidgetDashboard({
|
|
|
48782
49015
|
compactType: "vertical",
|
|
48783
49016
|
containerPadding: [0, 0],
|
|
48784
49017
|
margin: [16, 16],
|
|
48785
|
-
children:
|
|
48786
|
-
var _a, _b;
|
|
49018
|
+
children: displayWidgets.map((w) => {
|
|
49019
|
+
var _a, _b, _c;
|
|
48787
49020
|
const filterStatus = w.type === "agent" ? getWidgetFilterStatus(w.id) : null;
|
|
48788
49021
|
const badgeInfo = filterStatus ? getFilterStatusBadge(filterStatus.status) : null;
|
|
48789
|
-
|
|
49022
|
+
const isFocusMode = focusWidgetId && w.id === focusWidgetId;
|
|
49023
|
+
const widgetBaseStyles = "rounded-xl border border-gray-200 !bg-white";
|
|
49024
|
+
const widgetHoverStyles = isEditing ? "hover:border-primary-500 hover:shadow-lg transition-all duration-200" : "";
|
|
49025
|
+
const widgetShadow = "shadow-[0_2px_8px_-2px_rgba(0,0,0,0.15)]";
|
|
49026
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "data-widget-id": w.id, className: `${w.type === "text" || w.type === "spacer" ? `${((_b = (_a = w == null ? void 0 : w.config) == null ? void 0 : _a.content) == null ? void 0 : _b.divider) === "yes" && "border-b border-gray-300"} ${isEditing ? `${widgetBaseStyles} ${widgetShadow} ${widgetHoverStyles}` : "flex items-center"}` : `${widgetBaseStyles} ${widgetShadow} ${widgetHoverStyles} p-4 ${isEditing ? "pb-14" : "pb-5"}`} ${isFocusMode ? "h-full" : ""} relative`, children: [
|
|
48790
49027
|
w.type === "agent" && badgeInfo && !isApplyingFilters && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-2 right-2 z-10", title: (filterStatus == null ? void 0 : filterStatus.reason) || (filterStatus == null ? void 0 : filterStatus.error) || "", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { variant: badgeInfo.variant, className: "text-[10px] px-2 py-0.5 gap-1", children: [
|
|
48791
49028
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: badgeInfo.icon }),
|
|
48792
49029
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: badgeInfo.label })
|
|
@@ -48818,7 +49055,7 @@ function WidgetDashboard({
|
|
|
48818
49055
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { onClick: () => handleClearChat(w == null ? void 0 : w.id), onMouseOver: () => setVisibleClearButton(w == null ? void 0 : w.id), onMouseLeave: () => setVisibleClearButton(""), className: "absolute top-[12px] right-0 z-40 flex align-middle justify-center gap-2 text-sm px-4 py-2 border-primary-300 rounded-l-sm w-fit bg-primary-700 text-white cursor-pointer shadow-md transition-all", children: /* @__PURE__ */ jsxRuntimeExports.jsx(MessageCircleX, { className: "w-5 h-5" }) }),
|
|
48819
49056
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `absolute top-[56px] right-[16px] z-50 w-max py-1 text-xs px-2 rounded-sm text-white bg-gray-950 ${visibleClearButton === (w == null ? void 0 : w.id) ? "block" : "hidden"}`, children: "Clear Chat" })
|
|
48820
49057
|
] }),
|
|
48821
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(WidgetRenderer, { widget: w, widgetBackendUrl, onResetReady: handleResetReady, widgetIds: widgets.filter((widget) => widget.type !== "chatbot").map((widget) => widget.id), datasetId, pageId, onApplyFilters, isEditing })
|
|
49058
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(WidgetRenderer, { widget: w, widgetBackendUrl, onResetReady: handleResetReady, widgetIds: widgets.filter((widget) => widget.type !== "chatbot").map((widget) => widget.id), datasetId, pageId, onApplyFilters, isEditing, dashboardName: ((_c = pageData == null ? void 0 : pageData.basic) == null ? void 0 : _c.title) || (pageData == null ? void 0 : pageData.name) || (pageData == null ? void 0 : pageData.title) })
|
|
48822
49059
|
] })
|
|
48823
49060
|
] }, w.id);
|
|
48824
49061
|
})
|
|
@@ -48829,6 +49066,366 @@ function WidgetDashboard({
|
|
|
48829
49066
|
] });
|
|
48830
49067
|
}
|
|
48831
49068
|
|
|
49069
|
+
const EXCLUDED_WIDGET_TYPES = ["text", "spacer", "filter", "filters", "Text", "Spacer", "Filter", "Filters"];
|
|
49070
|
+
const LaserPointerIcon = ({ className }) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49071
|
+
"svg",
|
|
49072
|
+
{
|
|
49073
|
+
viewBox: "0 0 24 24",
|
|
49074
|
+
fill: "none",
|
|
49075
|
+
stroke: "currentColor",
|
|
49076
|
+
strokeWidth: "2",
|
|
49077
|
+
strokeLinecap: "round",
|
|
49078
|
+
strokeLinejoin: "round",
|
|
49079
|
+
className,
|
|
49080
|
+
children: [
|
|
49081
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "3", fill: "currentColor" }),
|
|
49082
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "2", x2: "12", y2: "6" }),
|
|
49083
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "18", x2: "12", y2: "22" }),
|
|
49084
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "2", y1: "12", x2: "6", y2: "12" }),
|
|
49085
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "18", y1: "12", x2: "22", y2: "12" })
|
|
49086
|
+
]
|
|
49087
|
+
}
|
|
49088
|
+
);
|
|
49089
|
+
function PresentationMode({
|
|
49090
|
+
isOpen,
|
|
49091
|
+
onClose,
|
|
49092
|
+
pageId,
|
|
49093
|
+
dashboardTitle,
|
|
49094
|
+
widgetBackendUrl = "http://localhost:3001",
|
|
49095
|
+
branding = { title: "DASHBOARD", subtitle: "COMPOSER" }
|
|
49096
|
+
}) {
|
|
49097
|
+
const [viewMode, setViewMode] = useState("grid");
|
|
49098
|
+
const [widgets, setWidgets] = useState([]);
|
|
49099
|
+
const [focusableWidgets, setFocusableWidgets] = useState([]);
|
|
49100
|
+
const [currentFocusIndex, setCurrentFocusIndex] = useState(0);
|
|
49101
|
+
const [loading, setLoading] = useState(true);
|
|
49102
|
+
const [laserPointerActive, setLaserPointerActive] = useState(false);
|
|
49103
|
+
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
|
|
49104
|
+
const focusContainerRef = useRef(null);
|
|
49105
|
+
const gridContainerRef = useRef(null);
|
|
49106
|
+
useEffect(() => {
|
|
49107
|
+
if (isOpen && pageId) {
|
|
49108
|
+
setLoading(true);
|
|
49109
|
+
setCurrentFocusIndex(0);
|
|
49110
|
+
fetch(`${widgetBackendUrl}/api/widgets?page_id=${pageId}`).then((res) => {
|
|
49111
|
+
if (!res.ok) throw new Error("Failed to fetch widgets");
|
|
49112
|
+
return res.json();
|
|
49113
|
+
}).then((data) => {
|
|
49114
|
+
const widgetsArray = Array.isArray(data) ? data : [];
|
|
49115
|
+
setWidgets(widgetsArray);
|
|
49116
|
+
const focusable = widgetsArray.filter((widget) => !EXCLUDED_WIDGET_TYPES.includes(widget.type)).sort((a, b) => {
|
|
49117
|
+
if (a.position_y !== b.position_y) return a.position_y - b.position_y;
|
|
49118
|
+
return a.position_x - b.position_x;
|
|
49119
|
+
});
|
|
49120
|
+
setFocusableWidgets(focusable);
|
|
49121
|
+
console.log(`[PresentationMode] Loaded ${widgetsArray.length} widgets, ${focusable.length} focusable`);
|
|
49122
|
+
}).catch((error) => {
|
|
49123
|
+
console.error("Failed to fetch widgets:", error);
|
|
49124
|
+
setWidgets([]);
|
|
49125
|
+
setFocusableWidgets([]);
|
|
49126
|
+
}).finally(() => {
|
|
49127
|
+
setLoading(false);
|
|
49128
|
+
});
|
|
49129
|
+
}
|
|
49130
|
+
}, [isOpen, pageId, widgetBackendUrl]);
|
|
49131
|
+
useEffect(() => {
|
|
49132
|
+
if (focusableWidgets.length > 0 && currentFocusIndex >= focusableWidgets.length) {
|
|
49133
|
+
setCurrentFocusIndex(focusableWidgets.length - 1);
|
|
49134
|
+
}
|
|
49135
|
+
}, [focusableWidgets.length, currentFocusIndex]);
|
|
49136
|
+
useEffect(() => {
|
|
49137
|
+
if (!laserPointerActive) return;
|
|
49138
|
+
const handleMouseMove = (e) => {
|
|
49139
|
+
setMousePosition({ x: e.clientX, y: e.clientY });
|
|
49140
|
+
};
|
|
49141
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
49142
|
+
return () => window.removeEventListener("mousemove", handleMouseMove);
|
|
49143
|
+
}, [laserPointerActive]);
|
|
49144
|
+
useEffect(() => {
|
|
49145
|
+
if (!isOpen || viewMode !== "grid" || !gridContainerRef.current) return;
|
|
49146
|
+
const setupWidgetInteractions = () => {
|
|
49147
|
+
var _a;
|
|
49148
|
+
const gridItems = (_a = gridContainerRef.current) == null ? void 0 : _a.querySelectorAll(".react-grid-item");
|
|
49149
|
+
if (!gridItems) return;
|
|
49150
|
+
const handleMouseEnter = (e) => {
|
|
49151
|
+
var _a2;
|
|
49152
|
+
const item = e.currentTarget;
|
|
49153
|
+
const widgetId = item.getAttribute("data-widget-id") || ((_a2 = item.querySelector("[data-widget-id]")) == null ? void 0 : _a2.getAttribute("data-widget-id"));
|
|
49154
|
+
const widget = widgets.find((w) => w.id === widgetId);
|
|
49155
|
+
if (widget && EXCLUDED_WIDGET_TYPES.includes(widget.type)) {
|
|
49156
|
+
return;
|
|
49157
|
+
}
|
|
49158
|
+
item.style.cursor = "pointer";
|
|
49159
|
+
item.style.boxShadow = "0 0 0 3px var(--primary-500, #3b82f6), 0 10px 30px -5px rgba(0, 0, 0, 0.2)";
|
|
49160
|
+
item.style.transition = "box-shadow 0.2s ease-out";
|
|
49161
|
+
item.style.zIndex = "10";
|
|
49162
|
+
};
|
|
49163
|
+
const handleMouseLeave = (e) => {
|
|
49164
|
+
const item = e.currentTarget;
|
|
49165
|
+
item.style.cursor = "";
|
|
49166
|
+
item.style.boxShadow = "";
|
|
49167
|
+
item.style.zIndex = "";
|
|
49168
|
+
};
|
|
49169
|
+
const handleClick = (e) => {
|
|
49170
|
+
var _a2;
|
|
49171
|
+
const item = e.currentTarget;
|
|
49172
|
+
const widgetId = item.getAttribute("data-widget-id") || ((_a2 = item.querySelector("[data-widget-id]")) == null ? void 0 : _a2.getAttribute("data-widget-id"));
|
|
49173
|
+
const widget = widgets.find((w) => w.id === widgetId);
|
|
49174
|
+
if (widget && EXCLUDED_WIDGET_TYPES.includes(widget.type)) {
|
|
49175
|
+
return;
|
|
49176
|
+
}
|
|
49177
|
+
if (widgetId) {
|
|
49178
|
+
const index = focusableWidgets.findIndex((w) => w.id === widgetId);
|
|
49179
|
+
if (index !== -1) {
|
|
49180
|
+
setCurrentFocusIndex(index);
|
|
49181
|
+
setViewMode("focus");
|
|
49182
|
+
}
|
|
49183
|
+
}
|
|
49184
|
+
};
|
|
49185
|
+
gridItems.forEach((item) => {
|
|
49186
|
+
item.addEventListener("mouseenter", handleMouseEnter);
|
|
49187
|
+
item.addEventListener("mouseleave", handleMouseLeave);
|
|
49188
|
+
item.addEventListener("click", handleClick);
|
|
49189
|
+
});
|
|
49190
|
+
return () => {
|
|
49191
|
+
gridItems.forEach((item) => {
|
|
49192
|
+
item.removeEventListener("mouseenter", handleMouseEnter);
|
|
49193
|
+
item.removeEventListener("mouseleave", handleMouseLeave);
|
|
49194
|
+
item.removeEventListener("click", handleClick);
|
|
49195
|
+
item.style.cursor = "";
|
|
49196
|
+
item.style.transform = "";
|
|
49197
|
+
item.style.boxShadow = "";
|
|
49198
|
+
});
|
|
49199
|
+
};
|
|
49200
|
+
};
|
|
49201
|
+
const timeoutId = setTimeout(setupWidgetInteractions, 500);
|
|
49202
|
+
const observer = new MutationObserver(() => {
|
|
49203
|
+
setupWidgetInteractions();
|
|
49204
|
+
});
|
|
49205
|
+
if (gridContainerRef.current) {
|
|
49206
|
+
observer.observe(gridContainerRef.current, {
|
|
49207
|
+
childList: true,
|
|
49208
|
+
subtree: true
|
|
49209
|
+
});
|
|
49210
|
+
}
|
|
49211
|
+
return () => {
|
|
49212
|
+
clearTimeout(timeoutId);
|
|
49213
|
+
observer.disconnect();
|
|
49214
|
+
};
|
|
49215
|
+
}, [isOpen, viewMode, widgets, focusableWidgets, loading]);
|
|
49216
|
+
const handleKeyDown = useCallback(
|
|
49217
|
+
(e) => {
|
|
49218
|
+
if (!isOpen) return;
|
|
49219
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
|
49220
|
+
return;
|
|
49221
|
+
}
|
|
49222
|
+
switch (e.key) {
|
|
49223
|
+
case "Escape":
|
|
49224
|
+
onClose();
|
|
49225
|
+
break;
|
|
49226
|
+
case "f":
|
|
49227
|
+
case "F":
|
|
49228
|
+
setViewMode((prev) => prev === "grid" ? "focus" : "grid");
|
|
49229
|
+
break;
|
|
49230
|
+
case "l":
|
|
49231
|
+
case "L":
|
|
49232
|
+
setLaserPointerActive((prev) => !prev);
|
|
49233
|
+
break;
|
|
49234
|
+
case "ArrowLeft":
|
|
49235
|
+
if (viewMode === "focus") {
|
|
49236
|
+
e.preventDefault();
|
|
49237
|
+
setCurrentFocusIndex(
|
|
49238
|
+
(prev) => prev > 0 ? prev - 1 : focusableWidgets.length - 1
|
|
49239
|
+
);
|
|
49240
|
+
}
|
|
49241
|
+
break;
|
|
49242
|
+
case "ArrowRight":
|
|
49243
|
+
if (viewMode === "focus") {
|
|
49244
|
+
e.preventDefault();
|
|
49245
|
+
setCurrentFocusIndex(
|
|
49246
|
+
(prev) => prev < focusableWidgets.length - 1 ? prev + 1 : 0
|
|
49247
|
+
);
|
|
49248
|
+
}
|
|
49249
|
+
break;
|
|
49250
|
+
}
|
|
49251
|
+
},
|
|
49252
|
+
[isOpen, onClose, viewMode, focusableWidgets.length]
|
|
49253
|
+
);
|
|
49254
|
+
useEffect(() => {
|
|
49255
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
49256
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
49257
|
+
}, [handleKeyDown]);
|
|
49258
|
+
useEffect(() => {
|
|
49259
|
+
if (isOpen) {
|
|
49260
|
+
document.body.style.overflow = "hidden";
|
|
49261
|
+
} else {
|
|
49262
|
+
document.body.style.overflow = "";
|
|
49263
|
+
}
|
|
49264
|
+
return () => {
|
|
49265
|
+
document.body.style.overflow = "";
|
|
49266
|
+
};
|
|
49267
|
+
}, [isOpen]);
|
|
49268
|
+
useEffect(() => {
|
|
49269
|
+
if (!isOpen) {
|
|
49270
|
+
setViewMode("grid");
|
|
49271
|
+
setCurrentFocusIndex(0);
|
|
49272
|
+
setLaserPointerActive(false);
|
|
49273
|
+
}
|
|
49274
|
+
}, [isOpen]);
|
|
49275
|
+
if (!isOpen) return null;
|
|
49276
|
+
const currentFocusWidget = focusableWidgets[currentFocusIndex];
|
|
49277
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fixed inset-0 z-50 bg-white flex flex-col", children: [
|
|
49278
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("header", { className: "flex items-center justify-between px-6 py-4 border-b border-gray-200 bg-white shrink-0", children: [
|
|
49279
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col", children: [
|
|
49280
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xl font-bold text-primary-700 tracking-wide", children: branding.title }),
|
|
49281
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-primary-500 tracking-[0.2em] -mt-1", children: branding.subtitle })
|
|
49282
|
+
] }) }),
|
|
49283
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute left-1/2 transform -translate-x-1/2 text-center", children: [
|
|
49284
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-lg font-bold text-gray-900 uppercase tracking-wide", children: dashboardTitle }),
|
|
49285
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-12 h-1 bg-primary-600 mx-auto mt-1 rounded" })
|
|
49286
|
+
] }),
|
|
49287
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49288
|
+
"button",
|
|
49289
|
+
{
|
|
49290
|
+
onClick: onClose,
|
|
49291
|
+
className: "p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
49292
|
+
"aria-label": "Close presentation",
|
|
49293
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-6 h-6 text-gray-600" })
|
|
49294
|
+
}
|
|
49295
|
+
)
|
|
49296
|
+
] }),
|
|
49297
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("main", { className: `flex-1 min-h-0 ${viewMode === "grid" ? "overflow-auto bg-gray-50 p-6" : "overflow-hidden bg-gray-100"}`, children: loading ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3", children: [
|
|
49298
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-8 h-8 border-4 border-primary-600 border-t-transparent rounded-full animate-spin" }),
|
|
49299
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-600", children: "Loading widgets..." })
|
|
49300
|
+
] }) }) : viewMode === "grid" ? (
|
|
49301
|
+
/* Grid View - Show all widgets using WidgetDashboard */
|
|
49302
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full relative", ref: gridContainerRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49303
|
+
WidgetDashboard,
|
|
49304
|
+
{
|
|
49305
|
+
pageId,
|
|
49306
|
+
isEditing: false,
|
|
49307
|
+
selectedWidget: null,
|
|
49308
|
+
onWidgetSelect: () => {
|
|
49309
|
+
},
|
|
49310
|
+
openWidgetPallete: false,
|
|
49311
|
+
onCloseWidgetPallete: () => {
|
|
49312
|
+
},
|
|
49313
|
+
onApplyFilters: () => {
|
|
49314
|
+
},
|
|
49315
|
+
isApplyingFilters: false,
|
|
49316
|
+
onSaveLayoutReady: () => {
|
|
49317
|
+
},
|
|
49318
|
+
widgetBackendUrl
|
|
49319
|
+
},
|
|
49320
|
+
`presentation-grid-${pageId}`
|
|
49321
|
+
) })
|
|
49322
|
+
) : (
|
|
49323
|
+
/* Focus View - Show one widget at a time */
|
|
49324
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full flex flex-col", ref: focusContainerRef, children: focusableWidgets.length > 0 && currentFocusWidget ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col min-h-0", children: [
|
|
49325
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "shrink-0 bg-white border-b border-gray-200 px-6 py-3 flex items-center justify-between", children: [
|
|
49326
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49327
|
+
"button",
|
|
49328
|
+
{
|
|
49329
|
+
onClick: () => setCurrentFocusIndex((prev) => prev > 0 ? prev - 1 : focusableWidgets.length - 1),
|
|
49330
|
+
className: "p-2 rounded-full hover:bg-gray-100 transition-colors disabled:opacity-30",
|
|
49331
|
+
disabled: focusableWidgets.length <= 1,
|
|
49332
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronLeft, { className: "w-5 h-5 text-gray-600" })
|
|
49333
|
+
}
|
|
49334
|
+
),
|
|
49335
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-gray-500", children: [
|
|
49336
|
+
currentFocusIndex + 1,
|
|
49337
|
+
" of ",
|
|
49338
|
+
focusableWidgets.length
|
|
49339
|
+
] }) }),
|
|
49340
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49341
|
+
"button",
|
|
49342
|
+
{
|
|
49343
|
+
onClick: () => setCurrentFocusIndex((prev) => prev < focusableWidgets.length - 1 ? prev + 1 : 0),
|
|
49344
|
+
className: "p-2 rounded-full hover:bg-gray-100 transition-colors disabled:opacity-30",
|
|
49345
|
+
disabled: focusableWidgets.length <= 1,
|
|
49346
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "w-5 h-5 text-gray-600" })
|
|
49347
|
+
}
|
|
49348
|
+
)
|
|
49349
|
+
] }),
|
|
49350
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 bg-white p-6 min-h-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full w-full rounded-xl border border-gray-200 bg-white shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49351
|
+
WidgetRenderer,
|
|
49352
|
+
{
|
|
49353
|
+
widget: currentFocusWidget,
|
|
49354
|
+
widgetBackendUrl,
|
|
49355
|
+
pageId,
|
|
49356
|
+
isEditing: false
|
|
49357
|
+
},
|
|
49358
|
+
`focus-widget-${currentFocusWidget.id}`
|
|
49359
|
+
) }) })
|
|
49360
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-gray-500", children: [
|
|
49361
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Maximize2, { className: "w-12 h-12 mx-auto mb-4 text-gray-300" }),
|
|
49362
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-lg font-medium", children: "No widgets available for focus view" }),
|
|
49363
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm mt-2", children: "Text, Spacer, and Filter widgets are excluded." })
|
|
49364
|
+
] }) }) })
|
|
49365
|
+
) }),
|
|
49366
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("footer", { className: "bg-white border-t border-gray-200 py-4 shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3", children: [
|
|
49367
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 bg-gray-100 rounded-full p-1", children: [
|
|
49368
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49369
|
+
"button",
|
|
49370
|
+
{
|
|
49371
|
+
onClick: () => setViewMode("grid"),
|
|
49372
|
+
className: `flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium transition-all ${viewMode === "grid" ? "bg-primary-700 text-white shadow-md" : "text-gray-600 hover:text-gray-900"}`,
|
|
49373
|
+
children: [
|
|
49374
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Grid3X3, { className: "w-4 h-4" }),
|
|
49375
|
+
"Grid"
|
|
49376
|
+
]
|
|
49377
|
+
}
|
|
49378
|
+
),
|
|
49379
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49380
|
+
"button",
|
|
49381
|
+
{
|
|
49382
|
+
onClick: () => setViewMode("focus"),
|
|
49383
|
+
className: `flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium transition-all ${viewMode === "focus" ? "bg-primary-700 text-white shadow-md" : "text-gray-600 hover:text-gray-900"}`,
|
|
49384
|
+
children: [
|
|
49385
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Maximize2, { className: "w-4 h-4" }),
|
|
49386
|
+
"Focus"
|
|
49387
|
+
]
|
|
49388
|
+
}
|
|
49389
|
+
),
|
|
49390
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-6 bg-gray-300 mx-2" }),
|
|
49391
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49392
|
+
"button",
|
|
49393
|
+
{
|
|
49394
|
+
onClick: () => setLaserPointerActive((prev) => !prev),
|
|
49395
|
+
className: `p-2 transition-colors rounded-full ${laserPointerActive ? "bg-primary-600 text-white" : "text-gray-600 hover:text-gray-900 hover:bg-gray-200"}`,
|
|
49396
|
+
"aria-label": "Toggle laser pointer (L)",
|
|
49397
|
+
title: "Toggle laser pointer (L)",
|
|
49398
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(LaserPointerIcon, { className: "w-4 h-4" })
|
|
49399
|
+
}
|
|
49400
|
+
),
|
|
49401
|
+
viewMode === "focus" && focusableWidgets.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
49402
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-6 bg-gray-300 mx-2" }),
|
|
49403
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-gray-600 px-2", children: [
|
|
49404
|
+
currentFocusIndex + 1,
|
|
49405
|
+
" / ",
|
|
49406
|
+
focusableWidgets.length
|
|
49407
|
+
] })
|
|
49408
|
+
] })
|
|
49409
|
+
] }),
|
|
49410
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-400 uppercase tracking-wider", children: "ESC TO EXIT \u2022 F TO TOGGLE \u2022 L FOR LASER \u2022 ARROWS TO NAVIGATE" })
|
|
49411
|
+
] }) }),
|
|
49412
|
+
laserPointerActive && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49413
|
+
"div",
|
|
49414
|
+
{
|
|
49415
|
+
className: "fixed pointer-events-none z-[100] transform -translate-x-1/2 -translate-y-1/2",
|
|
49416
|
+
style: {
|
|
49417
|
+
left: mousePosition.x,
|
|
49418
|
+
top: mousePosition.y
|
|
49419
|
+
},
|
|
49420
|
+
children: [
|
|
49421
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 w-8 h-8 -translate-x-1/2 -translate-y-1/2 bg-red-500/20 rounded-full blur-md" }),
|
|
49422
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute w-4 h-4 -translate-x-1/2 -translate-y-1/2 bg-red-500 rounded-full shadow-lg shadow-red-500/50" })
|
|
49423
|
+
]
|
|
49424
|
+
}
|
|
49425
|
+
)
|
|
49426
|
+
] });
|
|
49427
|
+
}
|
|
49428
|
+
|
|
48832
49429
|
var __defProp = Object.defineProperty;
|
|
48833
49430
|
var __defProps = Object.defineProperties;
|
|
48834
49431
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
@@ -49290,5 +49887,5 @@ function DashboardPages({ widgetBackendUrl }) {
|
|
|
49290
49887
|
] });
|
|
49291
49888
|
}
|
|
49292
49889
|
|
|
49293
|
-
export { Button, DashboardPages, Input, SavedPages, WidgetDashboard, WidgetPalette, WidgetSettingsPanel, cn };
|
|
49890
|
+
export { Button, DashboardPages, Input, PresentationMode, SavedPages, WidgetDashboard, WidgetPalette, WidgetSettingsPanel, cn };
|
|
49294
49891
|
//# sourceMappingURL=index.esm.js.map
|