dp-widgets-framework 1.6.9 → 1.7.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/index.d.ts +1 -0
- package/dist/index.esm.js +393 -6
- package/dist/index.js +392 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export type { Widget, WidgetStyles, WidgetConfig, RefWidgetType, WidgetPosition
|
|
|
4
4
|
export { WidgetSettingsPanel } from './components/WidgetSettingsPanel';
|
|
5
5
|
export { WidgetPalette } from './components/WidgetPalette';
|
|
6
6
|
export { WidgetDashboard } from './components/WidgetDashboard';
|
|
7
|
+
export { default as PresentationMode } from './components/PresentationMode';
|
|
7
8
|
export { default as SavedPages } from './components/pages/SavedPagesPage';
|
|
8
9
|
export { default as DashboardPages } from './components/pages/DashboardPages';
|
|
9
10
|
export { Button } from './components/ui/button';
|
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, Send, Loader2, X, AlignVerticalSpaceAround, LineChart as LineChart$1, PieChart as PieChart$1, Table, FileText, SlidersHorizontal, GripHorizontal, Edit, MessageCircleX, Edit2 } from 'lucide-react';
|
|
10
|
+
import { ChevronDown, ChevronUp, Check, AlertCircle, MoveUp, MoveDown, Trash2, Plus, Bot, Type, Layout, LayoutGrid, BarChart as BarChart$1, Filter, Search, ArrowUp, ArrowDown, ChevronRight, RefreshCw, Send, Loader2, 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';
|
|
@@ -48077,7 +48077,8 @@ function WidgetDashboard({
|
|
|
48077
48077
|
userId,
|
|
48078
48078
|
onApplyFilters,
|
|
48079
48079
|
filterResults,
|
|
48080
|
-
isApplyingFilters = false
|
|
48080
|
+
isApplyingFilters = false,
|
|
48081
|
+
focusWidgetId
|
|
48081
48082
|
}) {
|
|
48082
48083
|
const [widgets, setWidgets] = useState([]);
|
|
48083
48084
|
const [datasetId, setDatasetId] = useState("");
|
|
@@ -48094,6 +48095,12 @@ function WidgetDashboard({
|
|
|
48094
48095
|
const [editInitialQuery, setEditInitialQuery] = useState("");
|
|
48095
48096
|
const [editingWidget, setEditingWidget] = useState(null);
|
|
48096
48097
|
const [widgetResetFunctions, setWidgetResetFunctions] = useState(/* @__PURE__ */ new Map());
|
|
48098
|
+
const displayWidgets = React__default.useMemo(() => {
|
|
48099
|
+
if (focusWidgetId) {
|
|
48100
|
+
return widgets.filter((w) => w.id === focusWidgetId);
|
|
48101
|
+
}
|
|
48102
|
+
return widgets;
|
|
48103
|
+
}, [widgets, focusWidgetId]);
|
|
48097
48104
|
const getWidgetFilterStatus = useCallback((widgetId) => {
|
|
48098
48105
|
if (!filterResults) return null;
|
|
48099
48106
|
const result = filterResults.results.find((r) => r.widgetId === widgetId);
|
|
@@ -48692,7 +48699,7 @@ function WidgetDashboard({
|
|
|
48692
48699
|
};
|
|
48693
48700
|
const getLayoutFromWidgets = () => {
|
|
48694
48701
|
const processedIds = /* @__PURE__ */ new Set();
|
|
48695
|
-
return
|
|
48702
|
+
return displayWidgets.filter((widget) => {
|
|
48696
48703
|
if (processedIds.has(widget.id)) {
|
|
48697
48704
|
return false;
|
|
48698
48705
|
}
|
|
@@ -48700,6 +48707,22 @@ function WidgetDashboard({
|
|
|
48700
48707
|
return true;
|
|
48701
48708
|
}).map((widget) => {
|
|
48702
48709
|
widget.type === "text";
|
|
48710
|
+
if (focusWidgetId && widget.id === focusWidgetId) {
|
|
48711
|
+
return {
|
|
48712
|
+
i: widget.id,
|
|
48713
|
+
x: 0,
|
|
48714
|
+
y: 0,
|
|
48715
|
+
w: 12,
|
|
48716
|
+
// Full width
|
|
48717
|
+
h: 10,
|
|
48718
|
+
// Increased height for presentation
|
|
48719
|
+
minW: 0,
|
|
48720
|
+
minH: 1,
|
|
48721
|
+
isResizable: false,
|
|
48722
|
+
static: true
|
|
48723
|
+
// Prevent any movement in focus mode
|
|
48724
|
+
};
|
|
48725
|
+
}
|
|
48703
48726
|
return {
|
|
48704
48727
|
i: widget.id,
|
|
48705
48728
|
x: widget.position_x,
|
|
@@ -48782,11 +48805,15 @@ function WidgetDashboard({
|
|
|
48782
48805
|
compactType: "vertical",
|
|
48783
48806
|
containerPadding: [0, 0],
|
|
48784
48807
|
margin: [16, 16],
|
|
48785
|
-
children:
|
|
48808
|
+
children: displayWidgets.map((w) => {
|
|
48786
48809
|
var _a, _b;
|
|
48787
48810
|
const filterStatus = w.type === "agent" ? getWidgetFilterStatus(w.id) : null;
|
|
48788
48811
|
const badgeInfo = filterStatus ? getFilterStatusBadge(filterStatus.status) : null;
|
|
48789
|
-
|
|
48812
|
+
const isFocusMode = focusWidgetId && w.id === focusWidgetId;
|
|
48813
|
+
const widgetBaseStyles = "rounded-xl border border-gray-200 !bg-white";
|
|
48814
|
+
const widgetHoverStyles = isEditing ? "hover:border-primary-500 hover:shadow-lg transition-all duration-200" : "";
|
|
48815
|
+
const widgetShadow = "shadow-[0_2px_8px_-2px_rgba(0,0,0,0.15)]";
|
|
48816
|
+
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
48817
|
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
48818
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: badgeInfo.icon }),
|
|
48792
48819
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: badgeInfo.label })
|
|
@@ -48829,6 +48856,366 @@ function WidgetDashboard({
|
|
|
48829
48856
|
] });
|
|
48830
48857
|
}
|
|
48831
48858
|
|
|
48859
|
+
const EXCLUDED_WIDGET_TYPES = ["text", "spacer", "filter", "filters", "Text", "Spacer", "Filter", "Filters"];
|
|
48860
|
+
const LaserPointerIcon = ({ className }) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
48861
|
+
"svg",
|
|
48862
|
+
{
|
|
48863
|
+
viewBox: "0 0 24 24",
|
|
48864
|
+
fill: "none",
|
|
48865
|
+
stroke: "currentColor",
|
|
48866
|
+
strokeWidth: "2",
|
|
48867
|
+
strokeLinecap: "round",
|
|
48868
|
+
strokeLinejoin: "round",
|
|
48869
|
+
className,
|
|
48870
|
+
children: [
|
|
48871
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "3", fill: "currentColor" }),
|
|
48872
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "2", x2: "12", y2: "6" }),
|
|
48873
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "18", x2: "12", y2: "22" }),
|
|
48874
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "2", y1: "12", x2: "6", y2: "12" }),
|
|
48875
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "18", y1: "12", x2: "22", y2: "12" })
|
|
48876
|
+
]
|
|
48877
|
+
}
|
|
48878
|
+
);
|
|
48879
|
+
function PresentationMode({
|
|
48880
|
+
isOpen,
|
|
48881
|
+
onClose,
|
|
48882
|
+
pageId,
|
|
48883
|
+
dashboardTitle,
|
|
48884
|
+
widgetBackendUrl = "http://localhost:3001",
|
|
48885
|
+
branding = { title: "DASHBOARD", subtitle: "COMPOSER" }
|
|
48886
|
+
}) {
|
|
48887
|
+
const [viewMode, setViewMode] = useState("grid");
|
|
48888
|
+
const [widgets, setWidgets] = useState([]);
|
|
48889
|
+
const [focusableWidgets, setFocusableWidgets] = useState([]);
|
|
48890
|
+
const [currentFocusIndex, setCurrentFocusIndex] = useState(0);
|
|
48891
|
+
const [loading, setLoading] = useState(true);
|
|
48892
|
+
const [laserPointerActive, setLaserPointerActive] = useState(false);
|
|
48893
|
+
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
|
|
48894
|
+
const focusContainerRef = useRef(null);
|
|
48895
|
+
const gridContainerRef = useRef(null);
|
|
48896
|
+
useEffect(() => {
|
|
48897
|
+
if (isOpen && pageId) {
|
|
48898
|
+
setLoading(true);
|
|
48899
|
+
setCurrentFocusIndex(0);
|
|
48900
|
+
fetch(`${widgetBackendUrl}/api/widgets?page_id=${pageId}`).then((res) => {
|
|
48901
|
+
if (!res.ok) throw new Error("Failed to fetch widgets");
|
|
48902
|
+
return res.json();
|
|
48903
|
+
}).then((data) => {
|
|
48904
|
+
const widgetsArray = Array.isArray(data) ? data : [];
|
|
48905
|
+
setWidgets(widgetsArray);
|
|
48906
|
+
const focusable = widgetsArray.filter((widget) => !EXCLUDED_WIDGET_TYPES.includes(widget.type)).sort((a, b) => {
|
|
48907
|
+
if (a.position_y !== b.position_y) return a.position_y - b.position_y;
|
|
48908
|
+
return a.position_x - b.position_x;
|
|
48909
|
+
});
|
|
48910
|
+
setFocusableWidgets(focusable);
|
|
48911
|
+
console.log(`[PresentationMode] Loaded ${widgetsArray.length} widgets, ${focusable.length} focusable`);
|
|
48912
|
+
}).catch((error) => {
|
|
48913
|
+
console.error("Failed to fetch widgets:", error);
|
|
48914
|
+
setWidgets([]);
|
|
48915
|
+
setFocusableWidgets([]);
|
|
48916
|
+
}).finally(() => {
|
|
48917
|
+
setLoading(false);
|
|
48918
|
+
});
|
|
48919
|
+
}
|
|
48920
|
+
}, [isOpen, pageId, widgetBackendUrl]);
|
|
48921
|
+
useEffect(() => {
|
|
48922
|
+
if (focusableWidgets.length > 0 && currentFocusIndex >= focusableWidgets.length) {
|
|
48923
|
+
setCurrentFocusIndex(focusableWidgets.length - 1);
|
|
48924
|
+
}
|
|
48925
|
+
}, [focusableWidgets.length, currentFocusIndex]);
|
|
48926
|
+
useEffect(() => {
|
|
48927
|
+
if (!laserPointerActive) return;
|
|
48928
|
+
const handleMouseMove = (e) => {
|
|
48929
|
+
setMousePosition({ x: e.clientX, y: e.clientY });
|
|
48930
|
+
};
|
|
48931
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
48932
|
+
return () => window.removeEventListener("mousemove", handleMouseMove);
|
|
48933
|
+
}, [laserPointerActive]);
|
|
48934
|
+
useEffect(() => {
|
|
48935
|
+
if (!isOpen || viewMode !== "grid" || !gridContainerRef.current) return;
|
|
48936
|
+
const setupWidgetInteractions = () => {
|
|
48937
|
+
var _a;
|
|
48938
|
+
const gridItems = (_a = gridContainerRef.current) == null ? void 0 : _a.querySelectorAll(".react-grid-item");
|
|
48939
|
+
if (!gridItems) return;
|
|
48940
|
+
const handleMouseEnter = (e) => {
|
|
48941
|
+
var _a2;
|
|
48942
|
+
const item = e.currentTarget;
|
|
48943
|
+
const widgetId = item.getAttribute("data-widget-id") || ((_a2 = item.querySelector("[data-widget-id]")) == null ? void 0 : _a2.getAttribute("data-widget-id"));
|
|
48944
|
+
const widget = widgets.find((w) => w.id === widgetId);
|
|
48945
|
+
if (widget && EXCLUDED_WIDGET_TYPES.includes(widget.type)) {
|
|
48946
|
+
return;
|
|
48947
|
+
}
|
|
48948
|
+
item.style.cursor = "pointer";
|
|
48949
|
+
item.style.boxShadow = "0 0 0 3px var(--primary-500, #3b82f6), 0 10px 30px -5px rgba(0, 0, 0, 0.2)";
|
|
48950
|
+
item.style.transition = "box-shadow 0.2s ease-out";
|
|
48951
|
+
item.style.zIndex = "10";
|
|
48952
|
+
};
|
|
48953
|
+
const handleMouseLeave = (e) => {
|
|
48954
|
+
const item = e.currentTarget;
|
|
48955
|
+
item.style.cursor = "";
|
|
48956
|
+
item.style.boxShadow = "";
|
|
48957
|
+
item.style.zIndex = "";
|
|
48958
|
+
};
|
|
48959
|
+
const handleClick = (e) => {
|
|
48960
|
+
var _a2;
|
|
48961
|
+
const item = e.currentTarget;
|
|
48962
|
+
const widgetId = item.getAttribute("data-widget-id") || ((_a2 = item.querySelector("[data-widget-id]")) == null ? void 0 : _a2.getAttribute("data-widget-id"));
|
|
48963
|
+
const widget = widgets.find((w) => w.id === widgetId);
|
|
48964
|
+
if (widget && EXCLUDED_WIDGET_TYPES.includes(widget.type)) {
|
|
48965
|
+
return;
|
|
48966
|
+
}
|
|
48967
|
+
if (widgetId) {
|
|
48968
|
+
const index = focusableWidgets.findIndex((w) => w.id === widgetId);
|
|
48969
|
+
if (index !== -1) {
|
|
48970
|
+
setCurrentFocusIndex(index);
|
|
48971
|
+
setViewMode("focus");
|
|
48972
|
+
}
|
|
48973
|
+
}
|
|
48974
|
+
};
|
|
48975
|
+
gridItems.forEach((item) => {
|
|
48976
|
+
item.addEventListener("mouseenter", handleMouseEnter);
|
|
48977
|
+
item.addEventListener("mouseleave", handleMouseLeave);
|
|
48978
|
+
item.addEventListener("click", handleClick);
|
|
48979
|
+
});
|
|
48980
|
+
return () => {
|
|
48981
|
+
gridItems.forEach((item) => {
|
|
48982
|
+
item.removeEventListener("mouseenter", handleMouseEnter);
|
|
48983
|
+
item.removeEventListener("mouseleave", handleMouseLeave);
|
|
48984
|
+
item.removeEventListener("click", handleClick);
|
|
48985
|
+
item.style.cursor = "";
|
|
48986
|
+
item.style.transform = "";
|
|
48987
|
+
item.style.boxShadow = "";
|
|
48988
|
+
});
|
|
48989
|
+
};
|
|
48990
|
+
};
|
|
48991
|
+
const timeoutId = setTimeout(setupWidgetInteractions, 500);
|
|
48992
|
+
const observer = new MutationObserver(() => {
|
|
48993
|
+
setupWidgetInteractions();
|
|
48994
|
+
});
|
|
48995
|
+
if (gridContainerRef.current) {
|
|
48996
|
+
observer.observe(gridContainerRef.current, {
|
|
48997
|
+
childList: true,
|
|
48998
|
+
subtree: true
|
|
48999
|
+
});
|
|
49000
|
+
}
|
|
49001
|
+
return () => {
|
|
49002
|
+
clearTimeout(timeoutId);
|
|
49003
|
+
observer.disconnect();
|
|
49004
|
+
};
|
|
49005
|
+
}, [isOpen, viewMode, widgets, focusableWidgets, loading]);
|
|
49006
|
+
const handleKeyDown = useCallback(
|
|
49007
|
+
(e) => {
|
|
49008
|
+
if (!isOpen) return;
|
|
49009
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
|
49010
|
+
return;
|
|
49011
|
+
}
|
|
49012
|
+
switch (e.key) {
|
|
49013
|
+
case "Escape":
|
|
49014
|
+
onClose();
|
|
49015
|
+
break;
|
|
49016
|
+
case "f":
|
|
49017
|
+
case "F":
|
|
49018
|
+
setViewMode((prev) => prev === "grid" ? "focus" : "grid");
|
|
49019
|
+
break;
|
|
49020
|
+
case "l":
|
|
49021
|
+
case "L":
|
|
49022
|
+
setLaserPointerActive((prev) => !prev);
|
|
49023
|
+
break;
|
|
49024
|
+
case "ArrowLeft":
|
|
49025
|
+
if (viewMode === "focus") {
|
|
49026
|
+
e.preventDefault();
|
|
49027
|
+
setCurrentFocusIndex(
|
|
49028
|
+
(prev) => prev > 0 ? prev - 1 : focusableWidgets.length - 1
|
|
49029
|
+
);
|
|
49030
|
+
}
|
|
49031
|
+
break;
|
|
49032
|
+
case "ArrowRight":
|
|
49033
|
+
if (viewMode === "focus") {
|
|
49034
|
+
e.preventDefault();
|
|
49035
|
+
setCurrentFocusIndex(
|
|
49036
|
+
(prev) => prev < focusableWidgets.length - 1 ? prev + 1 : 0
|
|
49037
|
+
);
|
|
49038
|
+
}
|
|
49039
|
+
break;
|
|
49040
|
+
}
|
|
49041
|
+
},
|
|
49042
|
+
[isOpen, onClose, viewMode, focusableWidgets.length]
|
|
49043
|
+
);
|
|
49044
|
+
useEffect(() => {
|
|
49045
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
49046
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
49047
|
+
}, [handleKeyDown]);
|
|
49048
|
+
useEffect(() => {
|
|
49049
|
+
if (isOpen) {
|
|
49050
|
+
document.body.style.overflow = "hidden";
|
|
49051
|
+
} else {
|
|
49052
|
+
document.body.style.overflow = "";
|
|
49053
|
+
}
|
|
49054
|
+
return () => {
|
|
49055
|
+
document.body.style.overflow = "";
|
|
49056
|
+
};
|
|
49057
|
+
}, [isOpen]);
|
|
49058
|
+
useEffect(() => {
|
|
49059
|
+
if (!isOpen) {
|
|
49060
|
+
setViewMode("grid");
|
|
49061
|
+
setCurrentFocusIndex(0);
|
|
49062
|
+
setLaserPointerActive(false);
|
|
49063
|
+
}
|
|
49064
|
+
}, [isOpen]);
|
|
49065
|
+
if (!isOpen) return null;
|
|
49066
|
+
const currentFocusWidget = focusableWidgets[currentFocusIndex];
|
|
49067
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fixed inset-0 z-50 bg-white flex flex-col", children: [
|
|
49068
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("header", { className: "flex items-center justify-between px-6 py-4 border-b border-gray-200 bg-white shrink-0", children: [
|
|
49069
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col", children: [
|
|
49070
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xl font-bold text-primary-700 tracking-wide", children: branding.title }),
|
|
49071
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-primary-500 tracking-[0.2em] -mt-1", children: branding.subtitle })
|
|
49072
|
+
] }) }),
|
|
49073
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute left-1/2 transform -translate-x-1/2 text-center", children: [
|
|
49074
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-lg font-bold text-gray-900 uppercase tracking-wide", children: dashboardTitle }),
|
|
49075
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-12 h-1 bg-primary-600 mx-auto mt-1 rounded" })
|
|
49076
|
+
] }),
|
|
49077
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49078
|
+
"button",
|
|
49079
|
+
{
|
|
49080
|
+
onClick: onClose,
|
|
49081
|
+
className: "p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
49082
|
+
"aria-label": "Close presentation",
|
|
49083
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-6 h-6 text-gray-600" })
|
|
49084
|
+
}
|
|
49085
|
+
)
|
|
49086
|
+
] }),
|
|
49087
|
+
/* @__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: [
|
|
49088
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-8 h-8 border-4 border-primary-600 border-t-transparent rounded-full animate-spin" }),
|
|
49089
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-600", children: "Loading widgets..." })
|
|
49090
|
+
] }) }) : viewMode === "grid" ? (
|
|
49091
|
+
/* Grid View - Show all widgets using WidgetDashboard */
|
|
49092
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full relative", ref: gridContainerRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49093
|
+
WidgetDashboard,
|
|
49094
|
+
{
|
|
49095
|
+
pageId,
|
|
49096
|
+
isEditing: false,
|
|
49097
|
+
selectedWidget: null,
|
|
49098
|
+
onWidgetSelect: () => {
|
|
49099
|
+
},
|
|
49100
|
+
openWidgetPallete: false,
|
|
49101
|
+
onCloseWidgetPallete: () => {
|
|
49102
|
+
},
|
|
49103
|
+
onApplyFilters: () => {
|
|
49104
|
+
},
|
|
49105
|
+
isApplyingFilters: false,
|
|
49106
|
+
onSaveLayoutReady: () => {
|
|
49107
|
+
},
|
|
49108
|
+
widgetBackendUrl
|
|
49109
|
+
},
|
|
49110
|
+
`presentation-grid-${pageId}`
|
|
49111
|
+
) })
|
|
49112
|
+
) : (
|
|
49113
|
+
/* Focus View - Show one widget at a time */
|
|
49114
|
+
/* @__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: [
|
|
49115
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "shrink-0 bg-white border-b border-gray-200 px-6 py-3 flex items-center justify-between", children: [
|
|
49116
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49117
|
+
"button",
|
|
49118
|
+
{
|
|
49119
|
+
onClick: () => setCurrentFocusIndex((prev) => prev > 0 ? prev - 1 : focusableWidgets.length - 1),
|
|
49120
|
+
className: "p-2 rounded-full hover:bg-gray-100 transition-colors disabled:opacity-30",
|
|
49121
|
+
disabled: focusableWidgets.length <= 1,
|
|
49122
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronLeft, { className: "w-5 h-5 text-gray-600" })
|
|
49123
|
+
}
|
|
49124
|
+
),
|
|
49125
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-gray-500", children: [
|
|
49126
|
+
currentFocusIndex + 1,
|
|
49127
|
+
" of ",
|
|
49128
|
+
focusableWidgets.length
|
|
49129
|
+
] }) }),
|
|
49130
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49131
|
+
"button",
|
|
49132
|
+
{
|
|
49133
|
+
onClick: () => setCurrentFocusIndex((prev) => prev < focusableWidgets.length - 1 ? prev + 1 : 0),
|
|
49134
|
+
className: "p-2 rounded-full hover:bg-gray-100 transition-colors disabled:opacity-30",
|
|
49135
|
+
disabled: focusableWidgets.length <= 1,
|
|
49136
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "w-5 h-5 text-gray-600" })
|
|
49137
|
+
}
|
|
49138
|
+
)
|
|
49139
|
+
] }),
|
|
49140
|
+
/* @__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(
|
|
49141
|
+
WidgetRenderer,
|
|
49142
|
+
{
|
|
49143
|
+
widget: currentFocusWidget,
|
|
49144
|
+
widgetBackendUrl,
|
|
49145
|
+
pageId,
|
|
49146
|
+
isEditing: false
|
|
49147
|
+
},
|
|
49148
|
+
`focus-widget-${currentFocusWidget.id}`
|
|
49149
|
+
) }) })
|
|
49150
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-gray-500", children: [
|
|
49151
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Maximize2, { className: "w-12 h-12 mx-auto mb-4 text-gray-300" }),
|
|
49152
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-lg font-medium", children: "No widgets available for focus view" }),
|
|
49153
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm mt-2", children: "Text, Spacer, and Filter widgets are excluded." })
|
|
49154
|
+
] }) }) })
|
|
49155
|
+
) }),
|
|
49156
|
+
/* @__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: [
|
|
49157
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 bg-gray-100 rounded-full p-1", children: [
|
|
49158
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49159
|
+
"button",
|
|
49160
|
+
{
|
|
49161
|
+
onClick: () => setViewMode("grid"),
|
|
49162
|
+
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"}`,
|
|
49163
|
+
children: [
|
|
49164
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Grid3X3, { className: "w-4 h-4" }),
|
|
49165
|
+
"Grid"
|
|
49166
|
+
]
|
|
49167
|
+
}
|
|
49168
|
+
),
|
|
49169
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49170
|
+
"button",
|
|
49171
|
+
{
|
|
49172
|
+
onClick: () => setViewMode("focus"),
|
|
49173
|
+
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"}`,
|
|
49174
|
+
children: [
|
|
49175
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Maximize2, { className: "w-4 h-4" }),
|
|
49176
|
+
"Focus"
|
|
49177
|
+
]
|
|
49178
|
+
}
|
|
49179
|
+
),
|
|
49180
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-6 bg-gray-300 mx-2" }),
|
|
49181
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49182
|
+
"button",
|
|
49183
|
+
{
|
|
49184
|
+
onClick: () => setLaserPointerActive((prev) => !prev),
|
|
49185
|
+
className: `p-2 transition-colors rounded-full ${laserPointerActive ? "bg-primary-600 text-white" : "text-gray-600 hover:text-gray-900 hover:bg-gray-200"}`,
|
|
49186
|
+
"aria-label": "Toggle laser pointer (L)",
|
|
49187
|
+
title: "Toggle laser pointer (L)",
|
|
49188
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(LaserPointerIcon, { className: "w-4 h-4" })
|
|
49189
|
+
}
|
|
49190
|
+
),
|
|
49191
|
+
viewMode === "focus" && focusableWidgets.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
49192
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-6 bg-gray-300 mx-2" }),
|
|
49193
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-gray-600 px-2", children: [
|
|
49194
|
+
currentFocusIndex + 1,
|
|
49195
|
+
" / ",
|
|
49196
|
+
focusableWidgets.length
|
|
49197
|
+
] })
|
|
49198
|
+
] })
|
|
49199
|
+
] }),
|
|
49200
|
+
/* @__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" })
|
|
49201
|
+
] }) }),
|
|
49202
|
+
laserPointerActive && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49203
|
+
"div",
|
|
49204
|
+
{
|
|
49205
|
+
className: "fixed pointer-events-none z-[100] transform -translate-x-1/2 -translate-y-1/2",
|
|
49206
|
+
style: {
|
|
49207
|
+
left: mousePosition.x,
|
|
49208
|
+
top: mousePosition.y
|
|
49209
|
+
},
|
|
49210
|
+
children: [
|
|
49211
|
+
/* @__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" }),
|
|
49212
|
+
/* @__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" })
|
|
49213
|
+
]
|
|
49214
|
+
}
|
|
49215
|
+
)
|
|
49216
|
+
] });
|
|
49217
|
+
}
|
|
49218
|
+
|
|
48832
49219
|
var __defProp = Object.defineProperty;
|
|
48833
49220
|
var __defProps = Object.defineProperties;
|
|
48834
49221
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
@@ -49290,5 +49677,5 @@ function DashboardPages({ widgetBackendUrl }) {
|
|
|
49290
49677
|
] });
|
|
49291
49678
|
}
|
|
49292
49679
|
|
|
49293
|
-
export { Button, DashboardPages, Input, SavedPages, WidgetDashboard, WidgetPalette, WidgetSettingsPanel, cn };
|
|
49680
|
+
export { Button, DashboardPages, Input, PresentationMode, SavedPages, WidgetDashboard, WidgetPalette, WidgetSettingsPanel, cn };
|
|
49294
49681
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.js
CHANGED
|
@@ -48105,7 +48105,8 @@ function WidgetDashboard({
|
|
|
48105
48105
|
userId,
|
|
48106
48106
|
onApplyFilters,
|
|
48107
48107
|
filterResults,
|
|
48108
|
-
isApplyingFilters = false
|
|
48108
|
+
isApplyingFilters = false,
|
|
48109
|
+
focusWidgetId
|
|
48109
48110
|
}) {
|
|
48110
48111
|
const [widgets, setWidgets] = React.useState([]);
|
|
48111
48112
|
const [datasetId, setDatasetId] = React.useState("");
|
|
@@ -48122,6 +48123,12 @@ function WidgetDashboard({
|
|
|
48122
48123
|
const [editInitialQuery, setEditInitialQuery] = React.useState("");
|
|
48123
48124
|
const [editingWidget, setEditingWidget] = React.useState(null);
|
|
48124
48125
|
const [widgetResetFunctions, setWidgetResetFunctions] = React.useState(/* @__PURE__ */ new Map());
|
|
48126
|
+
const displayWidgets = React.useMemo(() => {
|
|
48127
|
+
if (focusWidgetId) {
|
|
48128
|
+
return widgets.filter((w) => w.id === focusWidgetId);
|
|
48129
|
+
}
|
|
48130
|
+
return widgets;
|
|
48131
|
+
}, [widgets, focusWidgetId]);
|
|
48125
48132
|
const getWidgetFilterStatus = React.useCallback((widgetId) => {
|
|
48126
48133
|
if (!filterResults) return null;
|
|
48127
48134
|
const result = filterResults.results.find((r) => r.widgetId === widgetId);
|
|
@@ -48720,7 +48727,7 @@ function WidgetDashboard({
|
|
|
48720
48727
|
};
|
|
48721
48728
|
const getLayoutFromWidgets = () => {
|
|
48722
48729
|
const processedIds = /* @__PURE__ */ new Set();
|
|
48723
|
-
return
|
|
48730
|
+
return displayWidgets.filter((widget) => {
|
|
48724
48731
|
if (processedIds.has(widget.id)) {
|
|
48725
48732
|
return false;
|
|
48726
48733
|
}
|
|
@@ -48728,6 +48735,22 @@ function WidgetDashboard({
|
|
|
48728
48735
|
return true;
|
|
48729
48736
|
}).map((widget) => {
|
|
48730
48737
|
widget.type === "text";
|
|
48738
|
+
if (focusWidgetId && widget.id === focusWidgetId) {
|
|
48739
|
+
return {
|
|
48740
|
+
i: widget.id,
|
|
48741
|
+
x: 0,
|
|
48742
|
+
y: 0,
|
|
48743
|
+
w: 12,
|
|
48744
|
+
// Full width
|
|
48745
|
+
h: 10,
|
|
48746
|
+
// Increased height for presentation
|
|
48747
|
+
minW: 0,
|
|
48748
|
+
minH: 1,
|
|
48749
|
+
isResizable: false,
|
|
48750
|
+
static: true
|
|
48751
|
+
// Prevent any movement in focus mode
|
|
48752
|
+
};
|
|
48753
|
+
}
|
|
48731
48754
|
return {
|
|
48732
48755
|
i: widget.id,
|
|
48733
48756
|
x: widget.position_x,
|
|
@@ -48810,11 +48833,15 @@ function WidgetDashboard({
|
|
|
48810
48833
|
compactType: "vertical",
|
|
48811
48834
|
containerPadding: [0, 0],
|
|
48812
48835
|
margin: [16, 16],
|
|
48813
|
-
children:
|
|
48836
|
+
children: displayWidgets.map((w) => {
|
|
48814
48837
|
var _a, _b;
|
|
48815
48838
|
const filterStatus = w.type === "agent" ? getWidgetFilterStatus(w.id) : null;
|
|
48816
48839
|
const badgeInfo = filterStatus ? getFilterStatusBadge(filterStatus.status) : null;
|
|
48817
|
-
|
|
48840
|
+
const isFocusMode = focusWidgetId && w.id === focusWidgetId;
|
|
48841
|
+
const widgetBaseStyles = "rounded-xl border border-gray-200 !bg-white";
|
|
48842
|
+
const widgetHoverStyles = isEditing ? "hover:border-primary-500 hover:shadow-lg transition-all duration-200" : "";
|
|
48843
|
+
const widgetShadow = "shadow-[0_2px_8px_-2px_rgba(0,0,0,0.15)]";
|
|
48844
|
+
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: [
|
|
48818
48845
|
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: [
|
|
48819
48846
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: badgeInfo.icon }),
|
|
48820
48847
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: badgeInfo.label })
|
|
@@ -48857,6 +48884,366 @@ function WidgetDashboard({
|
|
|
48857
48884
|
] });
|
|
48858
48885
|
}
|
|
48859
48886
|
|
|
48887
|
+
const EXCLUDED_WIDGET_TYPES = ["text", "spacer", "filter", "filters", "Text", "Spacer", "Filter", "Filters"];
|
|
48888
|
+
const LaserPointerIcon = ({ className }) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
48889
|
+
"svg",
|
|
48890
|
+
{
|
|
48891
|
+
viewBox: "0 0 24 24",
|
|
48892
|
+
fill: "none",
|
|
48893
|
+
stroke: "currentColor",
|
|
48894
|
+
strokeWidth: "2",
|
|
48895
|
+
strokeLinecap: "round",
|
|
48896
|
+
strokeLinejoin: "round",
|
|
48897
|
+
className,
|
|
48898
|
+
children: [
|
|
48899
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "3", fill: "currentColor" }),
|
|
48900
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "2", x2: "12", y2: "6" }),
|
|
48901
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "18", x2: "12", y2: "22" }),
|
|
48902
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "2", y1: "12", x2: "6", y2: "12" }),
|
|
48903
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "18", y1: "12", x2: "22", y2: "12" })
|
|
48904
|
+
]
|
|
48905
|
+
}
|
|
48906
|
+
);
|
|
48907
|
+
function PresentationMode({
|
|
48908
|
+
isOpen,
|
|
48909
|
+
onClose,
|
|
48910
|
+
pageId,
|
|
48911
|
+
dashboardTitle,
|
|
48912
|
+
widgetBackendUrl = "http://localhost:3001",
|
|
48913
|
+
branding = { title: "DASHBOARD", subtitle: "COMPOSER" }
|
|
48914
|
+
}) {
|
|
48915
|
+
const [viewMode, setViewMode] = React.useState("grid");
|
|
48916
|
+
const [widgets, setWidgets] = React.useState([]);
|
|
48917
|
+
const [focusableWidgets, setFocusableWidgets] = React.useState([]);
|
|
48918
|
+
const [currentFocusIndex, setCurrentFocusIndex] = React.useState(0);
|
|
48919
|
+
const [loading, setLoading] = React.useState(true);
|
|
48920
|
+
const [laserPointerActive, setLaserPointerActive] = React.useState(false);
|
|
48921
|
+
const [mousePosition, setMousePosition] = React.useState({ x: 0, y: 0 });
|
|
48922
|
+
const focusContainerRef = React.useRef(null);
|
|
48923
|
+
const gridContainerRef = React.useRef(null);
|
|
48924
|
+
React.useEffect(() => {
|
|
48925
|
+
if (isOpen && pageId) {
|
|
48926
|
+
setLoading(true);
|
|
48927
|
+
setCurrentFocusIndex(0);
|
|
48928
|
+
fetch(`${widgetBackendUrl}/api/widgets?page_id=${pageId}`).then((res) => {
|
|
48929
|
+
if (!res.ok) throw new Error("Failed to fetch widgets");
|
|
48930
|
+
return res.json();
|
|
48931
|
+
}).then((data) => {
|
|
48932
|
+
const widgetsArray = Array.isArray(data) ? data : [];
|
|
48933
|
+
setWidgets(widgetsArray);
|
|
48934
|
+
const focusable = widgetsArray.filter((widget) => !EXCLUDED_WIDGET_TYPES.includes(widget.type)).sort((a, b) => {
|
|
48935
|
+
if (a.position_y !== b.position_y) return a.position_y - b.position_y;
|
|
48936
|
+
return a.position_x - b.position_x;
|
|
48937
|
+
});
|
|
48938
|
+
setFocusableWidgets(focusable);
|
|
48939
|
+
console.log(`[PresentationMode] Loaded ${widgetsArray.length} widgets, ${focusable.length} focusable`);
|
|
48940
|
+
}).catch((error) => {
|
|
48941
|
+
console.error("Failed to fetch widgets:", error);
|
|
48942
|
+
setWidgets([]);
|
|
48943
|
+
setFocusableWidgets([]);
|
|
48944
|
+
}).finally(() => {
|
|
48945
|
+
setLoading(false);
|
|
48946
|
+
});
|
|
48947
|
+
}
|
|
48948
|
+
}, [isOpen, pageId, widgetBackendUrl]);
|
|
48949
|
+
React.useEffect(() => {
|
|
48950
|
+
if (focusableWidgets.length > 0 && currentFocusIndex >= focusableWidgets.length) {
|
|
48951
|
+
setCurrentFocusIndex(focusableWidgets.length - 1);
|
|
48952
|
+
}
|
|
48953
|
+
}, [focusableWidgets.length, currentFocusIndex]);
|
|
48954
|
+
React.useEffect(() => {
|
|
48955
|
+
if (!laserPointerActive) return;
|
|
48956
|
+
const handleMouseMove = (e) => {
|
|
48957
|
+
setMousePosition({ x: e.clientX, y: e.clientY });
|
|
48958
|
+
};
|
|
48959
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
48960
|
+
return () => window.removeEventListener("mousemove", handleMouseMove);
|
|
48961
|
+
}, [laserPointerActive]);
|
|
48962
|
+
React.useEffect(() => {
|
|
48963
|
+
if (!isOpen || viewMode !== "grid" || !gridContainerRef.current) return;
|
|
48964
|
+
const setupWidgetInteractions = () => {
|
|
48965
|
+
var _a;
|
|
48966
|
+
const gridItems = (_a = gridContainerRef.current) == null ? void 0 : _a.querySelectorAll(".react-grid-item");
|
|
48967
|
+
if (!gridItems) return;
|
|
48968
|
+
const handleMouseEnter = (e) => {
|
|
48969
|
+
var _a2;
|
|
48970
|
+
const item = e.currentTarget;
|
|
48971
|
+
const widgetId = item.getAttribute("data-widget-id") || ((_a2 = item.querySelector("[data-widget-id]")) == null ? void 0 : _a2.getAttribute("data-widget-id"));
|
|
48972
|
+
const widget = widgets.find((w) => w.id === widgetId);
|
|
48973
|
+
if (widget && EXCLUDED_WIDGET_TYPES.includes(widget.type)) {
|
|
48974
|
+
return;
|
|
48975
|
+
}
|
|
48976
|
+
item.style.cursor = "pointer";
|
|
48977
|
+
item.style.boxShadow = "0 0 0 3px var(--primary-500, #3b82f6), 0 10px 30px -5px rgba(0, 0, 0, 0.2)";
|
|
48978
|
+
item.style.transition = "box-shadow 0.2s ease-out";
|
|
48979
|
+
item.style.zIndex = "10";
|
|
48980
|
+
};
|
|
48981
|
+
const handleMouseLeave = (e) => {
|
|
48982
|
+
const item = e.currentTarget;
|
|
48983
|
+
item.style.cursor = "";
|
|
48984
|
+
item.style.boxShadow = "";
|
|
48985
|
+
item.style.zIndex = "";
|
|
48986
|
+
};
|
|
48987
|
+
const handleClick = (e) => {
|
|
48988
|
+
var _a2;
|
|
48989
|
+
const item = e.currentTarget;
|
|
48990
|
+
const widgetId = item.getAttribute("data-widget-id") || ((_a2 = item.querySelector("[data-widget-id]")) == null ? void 0 : _a2.getAttribute("data-widget-id"));
|
|
48991
|
+
const widget = widgets.find((w) => w.id === widgetId);
|
|
48992
|
+
if (widget && EXCLUDED_WIDGET_TYPES.includes(widget.type)) {
|
|
48993
|
+
return;
|
|
48994
|
+
}
|
|
48995
|
+
if (widgetId) {
|
|
48996
|
+
const index = focusableWidgets.findIndex((w) => w.id === widgetId);
|
|
48997
|
+
if (index !== -1) {
|
|
48998
|
+
setCurrentFocusIndex(index);
|
|
48999
|
+
setViewMode("focus");
|
|
49000
|
+
}
|
|
49001
|
+
}
|
|
49002
|
+
};
|
|
49003
|
+
gridItems.forEach((item) => {
|
|
49004
|
+
item.addEventListener("mouseenter", handleMouseEnter);
|
|
49005
|
+
item.addEventListener("mouseleave", handleMouseLeave);
|
|
49006
|
+
item.addEventListener("click", handleClick);
|
|
49007
|
+
});
|
|
49008
|
+
return () => {
|
|
49009
|
+
gridItems.forEach((item) => {
|
|
49010
|
+
item.removeEventListener("mouseenter", handleMouseEnter);
|
|
49011
|
+
item.removeEventListener("mouseleave", handleMouseLeave);
|
|
49012
|
+
item.removeEventListener("click", handleClick);
|
|
49013
|
+
item.style.cursor = "";
|
|
49014
|
+
item.style.transform = "";
|
|
49015
|
+
item.style.boxShadow = "";
|
|
49016
|
+
});
|
|
49017
|
+
};
|
|
49018
|
+
};
|
|
49019
|
+
const timeoutId = setTimeout(setupWidgetInteractions, 500);
|
|
49020
|
+
const observer = new MutationObserver(() => {
|
|
49021
|
+
setupWidgetInteractions();
|
|
49022
|
+
});
|
|
49023
|
+
if (gridContainerRef.current) {
|
|
49024
|
+
observer.observe(gridContainerRef.current, {
|
|
49025
|
+
childList: true,
|
|
49026
|
+
subtree: true
|
|
49027
|
+
});
|
|
49028
|
+
}
|
|
49029
|
+
return () => {
|
|
49030
|
+
clearTimeout(timeoutId);
|
|
49031
|
+
observer.disconnect();
|
|
49032
|
+
};
|
|
49033
|
+
}, [isOpen, viewMode, widgets, focusableWidgets, loading]);
|
|
49034
|
+
const handleKeyDown = React.useCallback(
|
|
49035
|
+
(e) => {
|
|
49036
|
+
if (!isOpen) return;
|
|
49037
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
|
49038
|
+
return;
|
|
49039
|
+
}
|
|
49040
|
+
switch (e.key) {
|
|
49041
|
+
case "Escape":
|
|
49042
|
+
onClose();
|
|
49043
|
+
break;
|
|
49044
|
+
case "f":
|
|
49045
|
+
case "F":
|
|
49046
|
+
setViewMode((prev) => prev === "grid" ? "focus" : "grid");
|
|
49047
|
+
break;
|
|
49048
|
+
case "l":
|
|
49049
|
+
case "L":
|
|
49050
|
+
setLaserPointerActive((prev) => !prev);
|
|
49051
|
+
break;
|
|
49052
|
+
case "ArrowLeft":
|
|
49053
|
+
if (viewMode === "focus") {
|
|
49054
|
+
e.preventDefault();
|
|
49055
|
+
setCurrentFocusIndex(
|
|
49056
|
+
(prev) => prev > 0 ? prev - 1 : focusableWidgets.length - 1
|
|
49057
|
+
);
|
|
49058
|
+
}
|
|
49059
|
+
break;
|
|
49060
|
+
case "ArrowRight":
|
|
49061
|
+
if (viewMode === "focus") {
|
|
49062
|
+
e.preventDefault();
|
|
49063
|
+
setCurrentFocusIndex(
|
|
49064
|
+
(prev) => prev < focusableWidgets.length - 1 ? prev + 1 : 0
|
|
49065
|
+
);
|
|
49066
|
+
}
|
|
49067
|
+
break;
|
|
49068
|
+
}
|
|
49069
|
+
},
|
|
49070
|
+
[isOpen, onClose, viewMode, focusableWidgets.length]
|
|
49071
|
+
);
|
|
49072
|
+
React.useEffect(() => {
|
|
49073
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
49074
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
49075
|
+
}, [handleKeyDown]);
|
|
49076
|
+
React.useEffect(() => {
|
|
49077
|
+
if (isOpen) {
|
|
49078
|
+
document.body.style.overflow = "hidden";
|
|
49079
|
+
} else {
|
|
49080
|
+
document.body.style.overflow = "";
|
|
49081
|
+
}
|
|
49082
|
+
return () => {
|
|
49083
|
+
document.body.style.overflow = "";
|
|
49084
|
+
};
|
|
49085
|
+
}, [isOpen]);
|
|
49086
|
+
React.useEffect(() => {
|
|
49087
|
+
if (!isOpen) {
|
|
49088
|
+
setViewMode("grid");
|
|
49089
|
+
setCurrentFocusIndex(0);
|
|
49090
|
+
setLaserPointerActive(false);
|
|
49091
|
+
}
|
|
49092
|
+
}, [isOpen]);
|
|
49093
|
+
if (!isOpen) return null;
|
|
49094
|
+
const currentFocusWidget = focusableWidgets[currentFocusIndex];
|
|
49095
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fixed inset-0 z-50 bg-white flex flex-col", children: [
|
|
49096
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("header", { className: "flex items-center justify-between px-6 py-4 border-b border-gray-200 bg-white shrink-0", children: [
|
|
49097
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col", children: [
|
|
49098
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xl font-bold text-primary-700 tracking-wide", children: branding.title }),
|
|
49099
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-primary-500 tracking-[0.2em] -mt-1", children: branding.subtitle })
|
|
49100
|
+
] }) }),
|
|
49101
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute left-1/2 transform -translate-x-1/2 text-center", children: [
|
|
49102
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-lg font-bold text-gray-900 uppercase tracking-wide", children: dashboardTitle }),
|
|
49103
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-12 h-1 bg-primary-600 mx-auto mt-1 rounded" })
|
|
49104
|
+
] }),
|
|
49105
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49106
|
+
"button",
|
|
49107
|
+
{
|
|
49108
|
+
onClick: onClose,
|
|
49109
|
+
className: "p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
49110
|
+
"aria-label": "Close presentation",
|
|
49111
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(lucideReact.X, { className: "w-6 h-6 text-gray-600" })
|
|
49112
|
+
}
|
|
49113
|
+
)
|
|
49114
|
+
] }),
|
|
49115
|
+
/* @__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: [
|
|
49116
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-8 h-8 border-4 border-primary-600 border-t-transparent rounded-full animate-spin" }),
|
|
49117
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-600", children: "Loading widgets..." })
|
|
49118
|
+
] }) }) : viewMode === "grid" ? (
|
|
49119
|
+
/* Grid View - Show all widgets using WidgetDashboard */
|
|
49120
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full relative", ref: gridContainerRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49121
|
+
WidgetDashboard,
|
|
49122
|
+
{
|
|
49123
|
+
pageId,
|
|
49124
|
+
isEditing: false,
|
|
49125
|
+
selectedWidget: null,
|
|
49126
|
+
onWidgetSelect: () => {
|
|
49127
|
+
},
|
|
49128
|
+
openWidgetPallete: false,
|
|
49129
|
+
onCloseWidgetPallete: () => {
|
|
49130
|
+
},
|
|
49131
|
+
onApplyFilters: () => {
|
|
49132
|
+
},
|
|
49133
|
+
isApplyingFilters: false,
|
|
49134
|
+
onSaveLayoutReady: () => {
|
|
49135
|
+
},
|
|
49136
|
+
widgetBackendUrl
|
|
49137
|
+
},
|
|
49138
|
+
`presentation-grid-${pageId}`
|
|
49139
|
+
) })
|
|
49140
|
+
) : (
|
|
49141
|
+
/* Focus View - Show one widget at a time */
|
|
49142
|
+
/* @__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: [
|
|
49143
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "shrink-0 bg-white border-b border-gray-200 px-6 py-3 flex items-center justify-between", children: [
|
|
49144
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49145
|
+
"button",
|
|
49146
|
+
{
|
|
49147
|
+
onClick: () => setCurrentFocusIndex((prev) => prev > 0 ? prev - 1 : focusableWidgets.length - 1),
|
|
49148
|
+
className: "p-2 rounded-full hover:bg-gray-100 transition-colors disabled:opacity-30",
|
|
49149
|
+
disabled: focusableWidgets.length <= 1,
|
|
49150
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(lucideReact.ChevronLeft, { className: "w-5 h-5 text-gray-600" })
|
|
49151
|
+
}
|
|
49152
|
+
),
|
|
49153
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-gray-500", children: [
|
|
49154
|
+
currentFocusIndex + 1,
|
|
49155
|
+
" of ",
|
|
49156
|
+
focusableWidgets.length
|
|
49157
|
+
] }) }),
|
|
49158
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49159
|
+
"button",
|
|
49160
|
+
{
|
|
49161
|
+
onClick: () => setCurrentFocusIndex((prev) => prev < focusableWidgets.length - 1 ? prev + 1 : 0),
|
|
49162
|
+
className: "p-2 rounded-full hover:bg-gray-100 transition-colors disabled:opacity-30",
|
|
49163
|
+
disabled: focusableWidgets.length <= 1,
|
|
49164
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(lucideReact.ChevronRight, { className: "w-5 h-5 text-gray-600" })
|
|
49165
|
+
}
|
|
49166
|
+
)
|
|
49167
|
+
] }),
|
|
49168
|
+
/* @__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(
|
|
49169
|
+
WidgetRenderer,
|
|
49170
|
+
{
|
|
49171
|
+
widget: currentFocusWidget,
|
|
49172
|
+
widgetBackendUrl,
|
|
49173
|
+
pageId,
|
|
49174
|
+
isEditing: false
|
|
49175
|
+
},
|
|
49176
|
+
`focus-widget-${currentFocusWidget.id}`
|
|
49177
|
+
) }) })
|
|
49178
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-gray-500", children: [
|
|
49179
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(lucideReact.Maximize2, { className: "w-12 h-12 mx-auto mb-4 text-gray-300" }),
|
|
49180
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-lg font-medium", children: "No widgets available for focus view" }),
|
|
49181
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm mt-2", children: "Text, Spacer, and Filter widgets are excluded." })
|
|
49182
|
+
] }) }) })
|
|
49183
|
+
) }),
|
|
49184
|
+
/* @__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: [
|
|
49185
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 bg-gray-100 rounded-full p-1", children: [
|
|
49186
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49187
|
+
"button",
|
|
49188
|
+
{
|
|
49189
|
+
onClick: () => setViewMode("grid"),
|
|
49190
|
+
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"}`,
|
|
49191
|
+
children: [
|
|
49192
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(lucideReact.Grid3X3, { className: "w-4 h-4" }),
|
|
49193
|
+
"Grid"
|
|
49194
|
+
]
|
|
49195
|
+
}
|
|
49196
|
+
),
|
|
49197
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49198
|
+
"button",
|
|
49199
|
+
{
|
|
49200
|
+
onClick: () => setViewMode("focus"),
|
|
49201
|
+
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"}`,
|
|
49202
|
+
children: [
|
|
49203
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(lucideReact.Maximize2, { className: "w-4 h-4" }),
|
|
49204
|
+
"Focus"
|
|
49205
|
+
]
|
|
49206
|
+
}
|
|
49207
|
+
),
|
|
49208
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-6 bg-gray-300 mx-2" }),
|
|
49209
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49210
|
+
"button",
|
|
49211
|
+
{
|
|
49212
|
+
onClick: () => setLaserPointerActive((prev) => !prev),
|
|
49213
|
+
className: `p-2 transition-colors rounded-full ${laserPointerActive ? "bg-primary-600 text-white" : "text-gray-600 hover:text-gray-900 hover:bg-gray-200"}`,
|
|
49214
|
+
"aria-label": "Toggle laser pointer (L)",
|
|
49215
|
+
title: "Toggle laser pointer (L)",
|
|
49216
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(LaserPointerIcon, { className: "w-4 h-4" })
|
|
49217
|
+
}
|
|
49218
|
+
),
|
|
49219
|
+
viewMode === "focus" && focusableWidgets.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
49220
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-6 bg-gray-300 mx-2" }),
|
|
49221
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-gray-600 px-2", children: [
|
|
49222
|
+
currentFocusIndex + 1,
|
|
49223
|
+
" / ",
|
|
49224
|
+
focusableWidgets.length
|
|
49225
|
+
] })
|
|
49226
|
+
] })
|
|
49227
|
+
] }),
|
|
49228
|
+
/* @__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" })
|
|
49229
|
+
] }) }),
|
|
49230
|
+
laserPointerActive && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49231
|
+
"div",
|
|
49232
|
+
{
|
|
49233
|
+
className: "fixed pointer-events-none z-[100] transform -translate-x-1/2 -translate-y-1/2",
|
|
49234
|
+
style: {
|
|
49235
|
+
left: mousePosition.x,
|
|
49236
|
+
top: mousePosition.y
|
|
49237
|
+
},
|
|
49238
|
+
children: [
|
|
49239
|
+
/* @__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" }),
|
|
49240
|
+
/* @__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" })
|
|
49241
|
+
]
|
|
49242
|
+
}
|
|
49243
|
+
)
|
|
49244
|
+
] });
|
|
49245
|
+
}
|
|
49246
|
+
|
|
48860
49247
|
var __defProp = Object.defineProperty;
|
|
48861
49248
|
var __defProps = Object.defineProperties;
|
|
48862
49249
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
@@ -49321,6 +49708,7 @@ function DashboardPages({ widgetBackendUrl }) {
|
|
|
49321
49708
|
exports.Button = Button;
|
|
49322
49709
|
exports.DashboardPages = DashboardPages;
|
|
49323
49710
|
exports.Input = Input;
|
|
49711
|
+
exports.PresentationMode = PresentationMode;
|
|
49324
49712
|
exports.SavedPages = SavedPages;
|
|
49325
49713
|
exports.WidgetDashboard = WidgetDashboard;
|
|
49326
49714
|
exports.WidgetPalette = WidgetPalette;
|