@trops/dash-core 0.1.93 → 0.1.94

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.js CHANGED
@@ -26384,6 +26384,257 @@ var ThemeManagerModal = function ThemeManagerModal(_ref) {
26384
26384
  });
26385
26385
  };
26386
26386
 
26387
+ var StarRating = function StarRating(_ref) {
26388
+ var appId = _ref.appId,
26389
+ packageName = _ref.packageName,
26390
+ _ref$interactive = _ref.interactive,
26391
+ interactive = _ref$interactive === void 0 ? true : _ref$interactive;
26392
+ var _useContext = React.useContext(DashReact.ThemeContext),
26393
+ currentTheme = _useContext.currentTheme;
26394
+ var _useState = React.useState(0),
26395
+ _useState2 = _slicedToArray(_useState, 2),
26396
+ rating = _useState2[0],
26397
+ setRating = _useState2[1];
26398
+ var _useState3 = React.useState(0),
26399
+ _useState4 = _slicedToArray(_useState3, 2),
26400
+ hoverRating = _useState4[0],
26401
+ setHoverRating = _useState4[1];
26402
+ var _useState5 = React.useState(true),
26403
+ _useState6 = _slicedToArray(_useState5, 2),
26404
+ loading = _useState6[0],
26405
+ setLoading = _useState6[1];
26406
+ React.useEffect(function () {
26407
+ var _window$mainApi;
26408
+ if (!appId || !packageName) return;
26409
+ var cancelled = false;
26410
+ setLoading(true);
26411
+ (_window$mainApi = window.mainApi) === null || _window$mainApi === void 0 || (_window$mainApi = _window$mainApi.dashboardRatings) === null || _window$mainApi === void 0 || _window$mainApi.getDashboardRating(appId, packageName).then(function (result) {
26412
+ if (!cancelled && result !== null && result !== void 0 && result.rating) {
26413
+ setRating(result.rating);
26414
+ }
26415
+ })["catch"](function () {})["finally"](function () {
26416
+ if (!cancelled) setLoading(false);
26417
+ });
26418
+ return function () {
26419
+ cancelled = true;
26420
+ };
26421
+ }, [appId, packageName]);
26422
+ function handleClick(_x) {
26423
+ return _handleClick.apply(this, arguments);
26424
+ }
26425
+ function _handleClick() {
26426
+ _handleClick = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(value) {
26427
+ var newRating, _window$mainApi2;
26428
+ return _regeneratorRuntime.wrap(function (_context) {
26429
+ while (1) switch (_context.prev = _context.next) {
26430
+ case 0:
26431
+ if (!(!interactive || !appId || !packageName)) {
26432
+ _context.next = 1;
26433
+ break;
26434
+ }
26435
+ return _context.abrupt("return");
26436
+ case 1:
26437
+ newRating = value === rating ? 0 : value;
26438
+ setRating(newRating);
26439
+ _context.prev = 2;
26440
+ _context.next = 3;
26441
+ return (_window$mainApi2 = window.mainApi) === null || _window$mainApi2 === void 0 || (_window$mainApi2 = _window$mainApi2.dashboardRatings) === null || _window$mainApi2 === void 0 ? void 0 : _window$mainApi2.saveDashboardRating(appId, packageName, newRating);
26442
+ case 3:
26443
+ _context.next = 5;
26444
+ break;
26445
+ case 4:
26446
+ _context.prev = 4;
26447
+ _context["catch"](2);
26448
+ case 5:
26449
+ case "end":
26450
+ return _context.stop();
26451
+ }
26452
+ }, _callee, null, [[2, 4]]);
26453
+ }));
26454
+ return _handleClick.apply(this, arguments);
26455
+ }
26456
+ if (loading) return null;
26457
+ var displayRating = hoverRating || rating;
26458
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
26459
+ className: "flex items-center gap-0.5",
26460
+ onMouseLeave: function onMouseLeave() {
26461
+ return setHoverRating(0);
26462
+ },
26463
+ children: [1, 2, 3, 4, 5].map(function (star) {
26464
+ return /*#__PURE__*/jsxRuntime.jsx("button", {
26465
+ type: "button",
26466
+ disabled: !interactive,
26467
+ onClick: function onClick() {
26468
+ return handleClick(star);
26469
+ },
26470
+ onMouseEnter: function onMouseEnter() {
26471
+ return interactive && setHoverRating(star);
26472
+ },
26473
+ className: "p-0.5 transition-colors ".concat(interactive ? "cursor-pointer hover:scale-110" : "cursor-default"),
26474
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26475
+ icon: star <= displayRating ? "star" : ["far", "star"],
26476
+ className: "h-3.5 w-3.5 ".concat(star <= displayRating ? "text-yellow-400" : currentTheme["text-primary-medium"] || "text-gray-500")
26477
+ })
26478
+ }, star);
26479
+ })
26480
+ });
26481
+ };
26482
+
26483
+ var PublishDashboardModal = function PublishDashboardModal(_ref) {
26484
+ var isOpen = _ref.isOpen,
26485
+ setIsOpen = _ref.setIsOpen,
26486
+ appId = _ref.appId,
26487
+ workspaceId = _ref.workspaceId,
26488
+ workspaceName = _ref.workspaceName;
26489
+ var _useContext = React.useContext(DashReact.ThemeContext),
26490
+ currentTheme = _useContext.currentTheme;
26491
+ var panelStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL, currentTheme, {
26492
+ grow: false
26493
+ });
26494
+ var _useState = React.useState(""),
26495
+ _useState2 = _slicedToArray(_useState, 2),
26496
+ description = _useState2[0],
26497
+ setDescription = _useState2[1];
26498
+ var _useState3 = React.useState(""),
26499
+ _useState4 = _slicedToArray(_useState3, 2),
26500
+ tags = _useState4[0],
26501
+ setTags = _useState4[1];
26502
+ var _useState5 = React.useState(""),
26503
+ _useState6 = _slicedToArray(_useState5, 2),
26504
+ icon = _useState6[0],
26505
+ setIcon = _useState6[1];
26506
+ var _useState7 = React.useState(false),
26507
+ _useState8 = _slicedToArray(_useState7, 2),
26508
+ isPublishing = _useState8[0],
26509
+ setIsPublishing = _useState8[1];
26510
+ var _useState9 = React.useState(null),
26511
+ _useState0 = _slicedToArray(_useState9, 2),
26512
+ result = _useState0[0],
26513
+ setResult = _useState0[1];
26514
+ function handleClose() {
26515
+ setIsOpen(false);
26516
+ // Reset state after a brief delay to avoid flash
26517
+ setTimeout(function () {
26518
+ setDescription("");
26519
+ setTags("");
26520
+ setIcon("");
26521
+ setIsPublishing(false);
26522
+ setResult(null);
26523
+ }, 200);
26524
+ }
26525
+ function handlePublish() {
26526
+ return _handlePublish.apply(this, arguments);
26527
+ }
26528
+ function _handlePublish() {
26529
+ _handlePublish = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
26530
+ var options, res, _t;
26531
+ return _regeneratorRuntime.wrap(function (_context) {
26532
+ while (1) switch (_context.prev = _context.next) {
26533
+ case 0:
26534
+ if (!(!appId || !workspaceId)) {
26535
+ _context.next = 1;
26536
+ break;
26537
+ }
26538
+ return _context.abrupt("return");
26539
+ case 1:
26540
+ setIsPublishing(true);
26541
+ setResult(null);
26542
+ _context.prev = 2;
26543
+ options = {
26544
+ description: description.trim() || undefined,
26545
+ tags: tags.split(",").map(function (t) {
26546
+ return t.trim();
26547
+ }).filter(Boolean),
26548
+ icon: icon.trim() || undefined
26549
+ };
26550
+ _context.next = 3;
26551
+ return window.mainApi.dashboardConfig.prepareDashboardForPublish(appId, workspaceId, options);
26552
+ case 3:
26553
+ res = _context.sent;
26554
+ setResult(res);
26555
+ _context.next = 5;
26556
+ break;
26557
+ case 4:
26558
+ _context.prev = 4;
26559
+ _t = _context["catch"](2);
26560
+ setResult({
26561
+ success: false,
26562
+ error: _t.message || "Failed to prepare dashboard for publish."
26563
+ });
26564
+ case 5:
26565
+ _context.prev = 5;
26566
+ setIsPublishing(false);
26567
+ return _context.finish(5);
26568
+ case 6:
26569
+ case "end":
26570
+ return _context.stop();
26571
+ }
26572
+ }, _callee, null, [[2, 4, 5, 6]]);
26573
+ }));
26574
+ return _handlePublish.apply(this, arguments);
26575
+ }
26576
+ return /*#__PURE__*/jsxRuntime.jsx(DashReact.ConfirmationModal, {
26577
+ isOpen: isOpen,
26578
+ setIsOpen: handleClose,
26579
+ title: "Publish \"".concat(workspaceName || "Dashboard", "\""),
26580
+ confirmLabel: isPublishing ? "Preparing..." : "Prepare for Publish",
26581
+ onConfirm: result ? handleClose : handlePublish,
26582
+ onCancel: handleClose,
26583
+ disabled: isPublishing,
26584
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
26585
+ className: "space-y-4 ".concat(panelStyles.textColor || "text-gray-200"),
26586
+ children: !result ? /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
26587
+ children: [/*#__PURE__*/jsxRuntime.jsx("p", {
26588
+ className: "text-sm opacity-70",
26589
+ children: "This will create a publish-ready ZIP file that can be submitted to the dashboard registry."
26590
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26591
+ className: "space-y-3",
26592
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26593
+ label: "Description",
26594
+ value: description,
26595
+ onChange: setDescription,
26596
+ placeholder: "A brief description of this dashboard..."
26597
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26598
+ label: "Tags (comma-separated)",
26599
+ value: tags,
26600
+ onChange: setTags,
26601
+ placeholder: "productivity, slack, monitoring"
26602
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.InputText, {
26603
+ label: "Icon (FontAwesome name)",
26604
+ value: icon,
26605
+ onChange: setIcon,
26606
+ placeholder: "chart-line"
26607
+ })]
26608
+ })]
26609
+ }) : result.success ? /*#__PURE__*/jsxRuntime.jsxs("div", {
26610
+ className: "space-y-3",
26611
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26612
+ className: "flex items-center gap-2",
26613
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26614
+ icon: "circle-check",
26615
+ className: "h-4 w-4 text-green-400"
26616
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
26617
+ className: "text-sm",
26618
+ children: "Dashboard prepared for publishing."
26619
+ })]
26620
+ }), result.filePath && /*#__PURE__*/jsxRuntime.jsxs("div", {
26621
+ className: "text-xs opacity-50 break-all",
26622
+ children: ["Saved to: ", result.filePath]
26623
+ })]
26624
+ }) : /*#__PURE__*/jsxRuntime.jsxs("div", {
26625
+ className: "flex items-center gap-2",
26626
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26627
+ icon: "circle-xmark",
26628
+ className: "h-4 w-4 text-red-400"
26629
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
26630
+ className: "text-sm text-red-400",
26631
+ children: result.error || "Publish preparation failed."
26632
+ })]
26633
+ })
26634
+ })
26635
+ });
26636
+ };
26637
+
26387
26638
  function ownKeys$8(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
26388
26639
  function _objectSpread$8(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$8(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$8(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
26389
26640
  var LayoutPreview = function LayoutPreview(_ref) {
@@ -26443,6 +26694,7 @@ var LayoutPreview = function LayoutPreview(_ref) {
26443
26694
  });
26444
26695
  };
26445
26696
  var DashboardDetail = function DashboardDetail(_ref2) {
26697
+ var _ws$_dashboardConfig, _ws$_dashboardConfig2;
26446
26698
  var workspace = _ref2.workspace,
26447
26699
  _ref2$menuItems = _ref2.menuItems,
26448
26700
  menuItems = _ref2$menuItems === void 0 ? [] : _ref2$menuItems,
@@ -26466,6 +26718,71 @@ var DashboardDetail = function DashboardDetail(_ref2) {
26466
26718
  var appId = credentials === null || credentials === void 0 ? void 0 : credentials.appId;
26467
26719
  var _useContext = React.useContext(DashReact.ThemeContext),
26468
26720
  themes = _useContext.themes;
26721
+ var _useState = React.useState(null),
26722
+ _useState2 = _slicedToArray(_useState, 2),
26723
+ exportStatus = _useState2[0],
26724
+ setExportStatus = _useState2[1];
26725
+ var _useState3 = React.useState(false),
26726
+ _useState4 = _slicedToArray(_useState3, 2),
26727
+ publishOpen = _useState4[0],
26728
+ setPublishOpen = _useState4[1];
26729
+ var registryPackage = (_ws$_dashboardConfig = ws._dashboardConfig) === null || _ws$_dashboardConfig === void 0 ? void 0 : _ws$_dashboardConfig.registryPackage;
26730
+ var isShareable = ((_ws$_dashboardConfig2 = ws._dashboardConfig) === null || _ws$_dashboardConfig2 === void 0 ? void 0 : _ws$_dashboardConfig2.shareable) !== false;
26731
+ function handleExport() {
26732
+ return _handleExport.apply(this, arguments);
26733
+ }
26734
+ function _handleExport() {
26735
+ _handleExport = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
26736
+ var result, _t;
26737
+ return _regeneratorRuntime.wrap(function (_context) {
26738
+ while (1) switch (_context.prev = _context.next) {
26739
+ case 0:
26740
+ if (appId) {
26741
+ _context.next = 1;
26742
+ break;
26743
+ }
26744
+ return _context.abrupt("return");
26745
+ case 1:
26746
+ setExportStatus({
26747
+ status: "loading"
26748
+ });
26749
+ _context.prev = 2;
26750
+ _context.next = 3;
26751
+ return window.mainApi.dashboardConfig.exportDashboardConfig(appId, ws.id, {});
26752
+ case 3:
26753
+ result = _context.sent;
26754
+ if (result !== null && result !== void 0 && result.success) {
26755
+ setExportStatus({
26756
+ status: "success",
26757
+ message: "Exported successfully."
26758
+ });
26759
+ } else {
26760
+ setExportStatus({
26761
+ status: "error",
26762
+ message: (result === null || result === void 0 ? void 0 : result.error) || "Export failed."
26763
+ });
26764
+ }
26765
+ _context.next = 5;
26766
+ break;
26767
+ case 4:
26768
+ _context.prev = 4;
26769
+ _t = _context["catch"](2);
26770
+ setExportStatus({
26771
+ status: "error",
26772
+ message: _t.message || "Export failed."
26773
+ });
26774
+ case 5:
26775
+ setTimeout(function () {
26776
+ return setExportStatus(null);
26777
+ }, 3000);
26778
+ case 6:
26779
+ case "end":
26780
+ return _context.stop();
26781
+ }
26782
+ }, _callee, null, [[2, 4]]);
26783
+ }));
26784
+ return _handleExport.apply(this, arguments);
26785
+ }
26469
26786
  var folderOptions = menuItems.map(function (m) {
26470
26787
  return {
26471
26788
  label: m.name,
@@ -26561,42 +26878,556 @@ var DashboardDetail = function DashboardDetail(_ref2) {
26561
26878
  onChange: function onChange(val) {
26562
26879
  return handleChangeTheme(val);
26563
26880
  },
26564
- options: themeOptions,
26565
- placeholder: "App Default"
26566
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26567
- className: "flex flex-row items-center gap-2",
26881
+ options: themeOptions,
26882
+ placeholder: "App Default"
26883
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
26884
+ className: "flex flex-row items-center gap-2",
26885
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26886
+ icon: "th-large",
26887
+ className: "h-3 w-3 opacity-50"
26888
+ }), /*#__PURE__*/jsxRuntime.jsxs("span", {
26889
+ className: "text-sm opacity-70",
26890
+ children: [widgetCount, " widget", widgetCount !== 1 ? "s" : ""]
26891
+ })]
26892
+ })]
26893
+ }), registryPackage && /*#__PURE__*/jsxRuntime.jsxs("div", {
26894
+ className: "flex-shrink-0 flex items-center gap-2",
26895
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26896
+ icon: "store",
26897
+ className: "h-3 w-3 opacity-50"
26898
+ }), /*#__PURE__*/jsxRuntime.jsxs("span", {
26899
+ className: "text-xs opacity-60",
26900
+ children: ["Imported from registry:", " ", /*#__PURE__*/jsxRuntime.jsx("span", {
26901
+ className: "font-medium",
26902
+ children: registryPackage
26903
+ })]
26904
+ })]
26905
+ }), registryPackage && appId && /*#__PURE__*/jsxRuntime.jsx("div", {
26906
+ className: "flex-shrink-0",
26907
+ children: /*#__PURE__*/jsxRuntime.jsx(StarRating, {
26908
+ appId: appId,
26909
+ packageName: registryPackage,
26910
+ interactive: true
26911
+ })
26912
+ }), exportStatus && /*#__PURE__*/jsxRuntime.jsxs("div", {
26913
+ className: "flex-shrink-0 flex items-center gap-2",
26914
+ children: [exportStatus.status === "loading" && /*#__PURE__*/jsxRuntime.jsx("div", {
26915
+ className: "animate-spin rounded-full h-3.5 w-3.5 border-b-2 border-blue-500"
26916
+ }), exportStatus.status === "success" && /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26917
+ icon: "circle-check",
26918
+ className: "h-3.5 w-3.5 text-green-400"
26919
+ }), exportStatus.status === "error" && /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26920
+ icon: "circle-xmark",
26921
+ className: "h-3.5 w-3.5 text-red-400"
26922
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
26923
+ className: "text-xs ".concat(exportStatus.status === "error" ? "text-red-400" : "opacity-60"),
26924
+ children: exportStatus.message
26925
+ })]
26926
+ }), /*#__PURE__*/jsxRuntime.jsx(LayoutPreview, {
26927
+ layout: ws.layout
26928
+ })]
26929
+ }), !isEditing && /*#__PURE__*/jsxRuntime.jsxs("div", {
26930
+ className: "flex-shrink-0 flex flex-row justify-end gap-2 px-6 py-4 border-t border-white/10",
26931
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
26932
+ title: "Export ZIP",
26933
+ onClick: handleExport,
26934
+ size: "sm"
26935
+ }), isShareable && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
26936
+ title: "Publish",
26937
+ onClick: function onClick() {
26938
+ return setPublishOpen(true);
26939
+ },
26940
+ size: "sm"
26941
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
26942
+ title: "Rename",
26943
+ onClick: function onClick() {
26944
+ return onStartRename(ws);
26945
+ },
26946
+ size: "sm"
26947
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
26948
+ title: "Duplicate",
26949
+ onClick: function onClick() {
26950
+ return onDuplicate(ws);
26951
+ },
26952
+ size: "sm"
26953
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
26954
+ title: "Delete",
26955
+ onClick: function onClick() {
26956
+ return onDelete(ws);
26957
+ },
26958
+ size: "sm"
26959
+ })]
26960
+ }), /*#__PURE__*/jsxRuntime.jsx(PublishDashboardModal, {
26961
+ isOpen: publishOpen,
26962
+ setIsOpen: setPublishOpen,
26963
+ appId: appId,
26964
+ workspaceId: ws.id,
26965
+ workspaceName: ws.name
26966
+ })]
26967
+ });
26968
+ };
26969
+
26970
+ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
26971
+ var dashboardPackage = _ref.dashboardPackage,
26972
+ appId = _ref.appId;
26973
+ var _useContext = React.useContext(DashReact.ThemeContext),
26974
+ currentTheme = _useContext.currentTheme;
26975
+ var panelStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL, currentTheme, {
26976
+ grow: false
26977
+ });
26978
+ var _useState = React.useState(null),
26979
+ _useState2 = _slicedToArray(_useState, 2),
26980
+ preview = _useState2[0],
26981
+ setPreview = _useState2[1];
26982
+ var _useState3 = React.useState(false),
26983
+ _useState4 = _slicedToArray(_useState3, 2),
26984
+ previewLoading = _useState4[0],
26985
+ setPreviewLoading = _useState4[1];
26986
+ var _useState5 = React.useState(false),
26987
+ _useState6 = _slicedToArray(_useState5, 2),
26988
+ isInstalling = _useState6[0],
26989
+ setIsInstalling = _useState6[1];
26990
+ var _useState7 = React.useState(null),
26991
+ _useState8 = _slicedToArray(_useState7, 2),
26992
+ installResult = _useState8[0],
26993
+ setInstallResult = _useState8[1];
26994
+ var pkg = dashboardPackage;
26995
+ if (!pkg) return null;
26996
+
26997
+ // Load preview data on mount
26998
+ // eslint-disable-next-line react-hooks/rules-of-hooks
26999
+ React.useEffect(function () {
27000
+ var _window$mainApi;
27001
+ if (!pkg.name) return;
27002
+ var cancelled = false;
27003
+ setPreviewLoading(true);
27004
+ setPreview(null);
27005
+ setInstallResult(null);
27006
+ (_window$mainApi = window.mainApi) === null || _window$mainApi === void 0 || (_window$mainApi = _window$mainApi.dashboardConfig) === null || _window$mainApi === void 0 || _window$mainApi.getDashboardPreview(pkg.name).then(function (result) {
27007
+ if (!cancelled) setPreview(result);
27008
+ })["catch"](function (err) {
27009
+ })["finally"](function () {
27010
+ if (!cancelled) setPreviewLoading(false);
27011
+ });
27012
+ return function () {
27013
+ cancelled = true;
27014
+ };
27015
+ }, [pkg.name]);
27016
+ function handleInstall() {
27017
+ return _handleInstall.apply(this, arguments);
27018
+ }
27019
+ function _handleInstall() {
27020
+ _handleInstall = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
27021
+ var _result$workspace, result, _t;
27022
+ return _regeneratorRuntime.wrap(function (_context) {
27023
+ while (1) switch (_context.prev = _context.next) {
27024
+ case 0:
27025
+ if (!(!appId || !pkg.name)) {
27026
+ _context.next = 1;
27027
+ break;
27028
+ }
27029
+ return _context.abrupt("return");
27030
+ case 1:
27031
+ setIsInstalling(true);
27032
+ setInstallResult(null);
27033
+ _context.prev = 2;
27034
+ _context.next = 3;
27035
+ return window.mainApi.dashboardConfig.installDashboardFromRegistry(appId, pkg.name);
27036
+ case 3:
27037
+ result = _context.sent;
27038
+ setInstallResult({
27039
+ status: result !== null && result !== void 0 && result.success ? "success" : "error",
27040
+ message: result !== null && result !== void 0 && result.success ? "Dashboard \"".concat(((_result$workspace = result.workspace) === null || _result$workspace === void 0 ? void 0 : _result$workspace.name) || pkg.name, "\" installed successfully.") : (result === null || result === void 0 ? void 0 : result.error) || "Installation failed."
27041
+ });
27042
+ _context.next = 5;
27043
+ break;
27044
+ case 4:
27045
+ _context.prev = 4;
27046
+ _t = _context["catch"](2);
27047
+ setInstallResult({
27048
+ status: "error",
27049
+ message: _t.message || "Failed to install dashboard."
27050
+ });
27051
+ case 5:
27052
+ _context.prev = 5;
27053
+ setIsInstalling(false);
27054
+ return _context.finish(5);
27055
+ case 6:
27056
+ case "end":
27057
+ return _context.stop();
27058
+ }
27059
+ }, _callee, null, [[2, 4, 5, 6]]);
27060
+ }));
27061
+ return _handleInstall.apply(this, arguments);
27062
+ }
27063
+ var compatibility = preview === null || preview === void 0 ? void 0 : preview.compatibility;
27064
+ var widgetDeps = (preview === null || preview === void 0 ? void 0 : preview.widgets) || pkg.widgets || [];
27065
+ var providers = (preview === null || preview === void 0 ? void 0 : preview.providers) || [];
27066
+ var wiring = (preview === null || preview === void 0 ? void 0 : preview.wiring) || [];
27067
+ function getCompatIcon(status) {
27068
+ if (status === "installed") return {
27069
+ icon: "circle-check",
27070
+ color: "text-green-400"
27071
+ };
27072
+ if (status === "available") return {
27073
+ icon: "circle-down",
27074
+ color: "text-blue-400"
27075
+ };
27076
+ return {
27077
+ icon: "circle-xmark",
27078
+ color: "text-red-400"
27079
+ };
27080
+ }
27081
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
27082
+ className: "flex flex-col flex-1 min-h-0",
27083
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27084
+ className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-6 ".concat(panelStyles.textColor || "text-gray-200"),
27085
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27086
+ className: "flex flex-row items-center gap-3",
27087
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27088
+ className: "h-5 w-5 flex-shrink-0 flex items-center justify-center",
27089
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27090
+ icon: pkg.icon || "clone",
27091
+ className: "h-5 w-5"
27092
+ })
27093
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27094
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
27095
+ title: pkg.displayName || pkg.name,
27096
+ padding: false
27097
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27098
+ className: "flex items-center gap-2 mt-0.5",
27099
+ children: [/*#__PURE__*/jsxRuntime.jsxs("span", {
27100
+ className: "text-sm opacity-60",
27101
+ children: ["by ", pkg.author || "Unknown"]
27102
+ }), pkg.version && /*#__PURE__*/jsxRuntime.jsxs("span", {
27103
+ className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-70"),
27104
+ children: ["v", pkg.version]
27105
+ })]
27106
+ })]
27107
+ })]
27108
+ }), appId && /*#__PURE__*/jsxRuntime.jsx(StarRating, {
27109
+ appId: appId,
27110
+ packageName: pkg.name,
27111
+ interactive: false
27112
+ }), /*#__PURE__*/jsxRuntime.jsx("hr", {
27113
+ className: currentTheme["border-primary-medium"]
27114
+ }), pkg.description && /*#__PURE__*/jsxRuntime.jsx("p", {
27115
+ className: "text-sm",
27116
+ children: pkg.description
27117
+ }), pkg.tags && pkg.tags.length > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
27118
+ className: "flex flex-wrap gap-1",
27119
+ children: pkg.tags.map(function (tag) {
27120
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
27121
+ className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-60"),
27122
+ children: tag
27123
+ }, tag);
27124
+ })
27125
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
27126
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27127
+ className: "text-xs font-semibold opacity-50 mb-1 block",
27128
+ children: "REQUIRED WIDGETS"
27129
+ }), previewLoading ? /*#__PURE__*/jsxRuntime.jsxs("div", {
27130
+ className: "flex items-center gap-2 py-2",
27131
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27132
+ className: "animate-spin rounded-full h-4 w-4 border-b-2 border-blue-500"
27133
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27134
+ className: "text-xs opacity-50",
27135
+ children: "Checking compatibility..."
27136
+ })]
27137
+ }) : /*#__PURE__*/jsxRuntime.jsx("div", {
27138
+ className: "space-y-1.5",
27139
+ children: widgetDeps.map(function (w, idx) {
27140
+ var _compatibility$widget;
27141
+ var status = (compatibility === null || compatibility === void 0 || (_compatibility$widget = compatibility.widgets) === null || _compatibility$widget === void 0 ? void 0 : _compatibility$widget[w.name || w.packageName]) || "unknown";
27142
+ var compat = getCompatIcon(status);
27143
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
27144
+ className: "p-2 rounded ".concat(currentTheme["bg-primary-medium"], " flex items-center gap-2"),
27145
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27146
+ icon: compat.icon,
27147
+ className: "h-3.5 w-3.5 ".concat(compat.color)
27148
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27149
+ className: "text-sm",
27150
+ children: w.displayName || w.name || w.packageName
27151
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27152
+ className: "text-xs opacity-40 ml-auto",
27153
+ children: status === "installed" ? "Installed" : status === "available" ? "Will install" : "Unavailable"
27154
+ })]
27155
+ }, idx);
27156
+ })
27157
+ })]
27158
+ }), providers.length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
27159
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27160
+ className: "text-xs font-semibold opacity-50 mb-1 block",
27161
+ children: "REQUIRED PROVIDERS"
27162
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
27163
+ className: "space-y-1",
27164
+ children: providers.map(function (p, idx) {
27165
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
27166
+ className: "flex items-center gap-2",
27167
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27168
+ className: "text-xs px-1.5 py-0.5 rounded bg-blue-900/30 text-blue-400",
27169
+ children: p.type
27170
+ }), p.required && /*#__PURE__*/jsxRuntime.jsx("span", {
27171
+ className: "text-[10px] opacity-40",
27172
+ children: "Required"
27173
+ })]
27174
+ }, idx);
27175
+ })
27176
+ })]
27177
+ }), wiring.length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
27178
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27179
+ className: "text-xs font-semibold opacity-50 mb-1 block",
27180
+ children: "EVENT WIRING"
27181
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
27182
+ className: "space-y-1",
27183
+ children: wiring.map(function (w, idx) {
27184
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
27185
+ className: "text-xs p-2 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-70"),
27186
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
27187
+ className: "font-medium",
27188
+ children: w.from || "Source"
27189
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27190
+ icon: "arrow-right",
27191
+ className: "h-2.5 w-2.5 mx-1.5 opacity-50"
27192
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27193
+ className: "font-medium",
27194
+ children: w.to || "Target"
27195
+ }), w.event && /*#__PURE__*/jsxRuntime.jsxs("span", {
27196
+ className: "opacity-50 ml-1.5",
27197
+ children: ["(", w.event, ")"]
27198
+ })]
27199
+ }, idx);
27200
+ })
27201
+ })]
27202
+ }), installResult && /*#__PURE__*/jsxRuntime.jsx("div", {
27203
+ className: "p-2 rounded border ".concat(installResult.status === "success" ? "bg-green-900/20 border-green-700" : "bg-red-900/30 border-red-700"),
27204
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
27205
+ className: "flex items-center gap-2",
27206
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27207
+ icon: installResult.status === "success" ? "circle-check" : "circle-xmark",
27208
+ className: "h-4 w-4 ".concat(installResult.status === "success" ? "text-green-400" : "text-red-400")
27209
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27210
+ className: "text-sm ".concat(installResult.status === "error" ? "text-red-400" : ""),
27211
+ children: installResult.message
27212
+ })]
27213
+ })
27214
+ })]
27215
+ }), (installResult === null || installResult === void 0 ? void 0 : installResult.status) !== "success" && /*#__PURE__*/jsxRuntime.jsx("div", {
27216
+ className: "flex items-center justify-end px-6 py-3 border-t ".concat(currentTheme["border-primary-medium"]),
27217
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
27218
+ title: isInstalling ? "Installing..." : "Install Dashboard",
27219
+ bgColor: "bg-blue-600",
27220
+ hoverBackgroundColor: isInstalling ? "" : "hover:bg-blue-700",
27221
+ textSize: "text-sm",
27222
+ padding: "py-1.5 px-4",
27223
+ onClick: handleInstall,
27224
+ disabled: isInstalling
27225
+ })
27226
+ })]
27227
+ });
27228
+ };
27229
+
27230
+ var DiscoverDashboardsDetail = function DiscoverDashboardsDetail(_ref) {
27231
+ var onBack = _ref.onBack,
27232
+ appId = _ref.appId;
27233
+ var _useContext = React.useContext(DashReact.ThemeContext),
27234
+ currentTheme = _useContext.currentTheme;
27235
+ var panelStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL, currentTheme, {
27236
+ grow: false
27237
+ });
27238
+ var _useState = React.useState([]),
27239
+ _useState2 = _slicedToArray(_useState, 2),
27240
+ packages = _useState2[0],
27241
+ setPackages = _useState2[1];
27242
+ var _useState3 = React.useState(false),
27243
+ _useState4 = _slicedToArray(_useState3, 2),
27244
+ isLoading = _useState4[0],
27245
+ setIsLoading = _useState4[1];
27246
+ var _useState5 = React.useState(null),
27247
+ _useState6 = _slicedToArray(_useState5, 2),
27248
+ error = _useState6[0],
27249
+ setError = _useState6[1];
27250
+ var _useState7 = React.useState(""),
27251
+ _useState8 = _slicedToArray(_useState7, 2),
27252
+ searchQuery = _useState8[0],
27253
+ setSearchQuery = _useState8[1];
27254
+ var _useState9 = React.useState(null),
27255
+ _useState0 = _slicedToArray(_useState9, 2),
27256
+ selectedPackageName = _useState0[0],
27257
+ setSelectedPackageName = _useState0[1];
27258
+ var search = React.useCallback(/*#__PURE__*/function () {
27259
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(query) {
27260
+ var _window$mainApi;
27261
+ var result, _t;
27262
+ return _regeneratorRuntime.wrap(function (_context) {
27263
+ while (1) switch (_context.prev = _context.next) {
27264
+ case 0:
27265
+ if ((_window$mainApi = window.mainApi) !== null && _window$mainApi !== void 0 && (_window$mainApi = _window$mainApi.registry) !== null && _window$mainApi !== void 0 && _window$mainApi.searchDashboards) {
27266
+ _context.next = 1;
27267
+ break;
27268
+ }
27269
+ setPackages([]);
27270
+ return _context.abrupt("return");
27271
+ case 1:
27272
+ setIsLoading(true);
27273
+ setError(null);
27274
+ _context.prev = 2;
27275
+ _context.next = 3;
27276
+ return window.mainApi.registry.searchDashboards(query || "", {});
27277
+ case 3:
27278
+ result = _context.sent;
27279
+ setPackages((result === null || result === void 0 ? void 0 : result.packages) || []);
27280
+ _context.next = 5;
27281
+ break;
27282
+ case 4:
27283
+ _context.prev = 4;
27284
+ _t = _context["catch"](2);
27285
+ setError(_t.message || "Failed to search dashboard registry");
27286
+ setPackages([]);
27287
+ case 5:
27288
+ _context.prev = 5;
27289
+ setIsLoading(false);
27290
+ return _context.finish(5);
27291
+ case 6:
27292
+ case "end":
27293
+ return _context.stop();
27294
+ }
27295
+ }, _callee, null, [[2, 4, 5, 6]]);
27296
+ }));
27297
+ return function (_x) {
27298
+ return _ref2.apply(this, arguments);
27299
+ };
27300
+ }(), []);
27301
+
27302
+ // Debounce search on query changes
27303
+ React.useEffect(function () {
27304
+ var timer = setTimeout(function () {
27305
+ search(searchQuery);
27306
+ }, 300);
27307
+ return function () {
27308
+ return clearTimeout(timer);
27309
+ };
27310
+ // eslint-disable-next-line react-hooks/exhaustive-deps
27311
+ }, [searchQuery]);
27312
+ var retry = function retry() {
27313
+ return search(searchQuery);
27314
+ };
27315
+ var selectedPackage = selectedPackageName ? packages.find(function (p) {
27316
+ return p.name === selectedPackageName;
27317
+ }) : null;
27318
+
27319
+ // If a package is selected, show its detail inline
27320
+ if (selectedPackage) {
27321
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
27322
+ className: "flex flex-col flex-1 min-h-0",
27323
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27324
+ className: "flex-shrink-0 px-4 pt-4",
27325
+ children: /*#__PURE__*/jsxRuntime.jsxs("button", {
27326
+ type: "button",
27327
+ onClick: function onClick() {
27328
+ return setSelectedPackageName(null);
27329
+ },
27330
+ className: "flex items-center gap-1.5 text-sm opacity-60 hover:opacity-100 transition-opacity",
26568
27331
  children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
26569
- icon: "th-large",
26570
- className: "h-3 w-3 opacity-50"
26571
- }), /*#__PURE__*/jsxRuntime.jsxs("span", {
26572
- className: "text-sm opacity-70",
26573
- children: [widgetCount, " widget", widgetCount !== 1 ? "s" : ""]
27332
+ icon: "arrow-left",
27333
+ className: "h-3 w-3"
27334
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27335
+ children: "Back"
26574
27336
  })]
26575
- })]
26576
- }), /*#__PURE__*/jsxRuntime.jsx(LayoutPreview, {
26577
- layout: ws.layout
27337
+ })
27338
+ }), /*#__PURE__*/jsxRuntime.jsx(RegistryDashboardDetail, {
27339
+ dashboardPackage: selectedPackage,
27340
+ appId: appId
26578
27341
  })]
26579
- }), !isEditing && /*#__PURE__*/jsxRuntime.jsxs("div", {
26580
- className: "flex-shrink-0 flex flex-row justify-end gap-2 px-6 py-4 border-t border-white/10",
26581
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
26582
- title: "Rename",
26583
- onClick: function onClick() {
26584
- return onStartRename(ws);
26585
- },
26586
- size: "sm"
26587
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
26588
- title: "Duplicate",
26589
- onClick: function onClick() {
26590
- return onDuplicate(ws);
26591
- },
26592
- size: "sm"
27342
+ });
27343
+ }
27344
+
27345
+ // Package list view
27346
+ var listBody;
27347
+ if (isLoading) {
27348
+ listBody = /*#__PURE__*/jsxRuntime.jsx("div", {
27349
+ className: "flex items-center justify-center py-12",
27350
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
27351
+ className: "text-center",
27352
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27353
+ className: "animate-spin rounded-full h-6 w-6 border-b-2 border-blue-500 mx-auto mb-3"
27354
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Paragraph, {
27355
+ className: "text-sm opacity-50",
27356
+ children: "Loading dashboards..."
27357
+ })]
27358
+ })
27359
+ });
27360
+ } else if (error) {
27361
+ listBody = /*#__PURE__*/jsxRuntime.jsxs("div", {
27362
+ className: "px-4 py-8 text-center",
27363
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Paragraph, {
27364
+ className: "text-sm text-red-400 mb-3",
27365
+ children: error
26593
27366
  }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
26594
- title: "Delete",
26595
- onClick: function onClick() {
26596
- return onDelete(ws);
26597
- },
26598
- size: "sm"
27367
+ title: "Retry",
27368
+ bgColor: "bg-gray-700",
27369
+ hoverBackgroundColor: "hover:bg-gray-600",
27370
+ textSize: "text-sm",
27371
+ padding: "py-1 px-3",
27372
+ onClick: retry
26599
27373
  })]
27374
+ });
27375
+ } else if (packages.length === 0) {
27376
+ listBody = /*#__PURE__*/jsxRuntime.jsx("div", {
27377
+ className: "px-4 py-8 text-center",
27378
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Paragraph, {
27379
+ className: "text-sm opacity-50",
27380
+ children: searchQuery ? "No dashboards match your search." : "No dashboard packages available."
27381
+ })
27382
+ });
27383
+ } else {
27384
+ listBody = /*#__PURE__*/jsxRuntime.jsx("div", {
27385
+ className: "space-y-1",
27386
+ children: packages.map(function (pkg) {
27387
+ var widgetCount = (pkg.widgets || []).length;
27388
+ return /*#__PURE__*/jsxRuntime.jsx(DashReact.Sidebar.Item, {
27389
+ icon: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27390
+ icon: pkg.icon || "clone",
27391
+ className: "h-3.5 w-3.5"
27392
+ }),
27393
+ onClick: function onClick() {
27394
+ return setSelectedPackageName(pkg.name);
27395
+ },
27396
+ badge: widgetCount > 0 ? "".concat(widgetCount) : undefined,
27397
+ children: pkg.displayName || pkg.name
27398
+ }, pkg.name);
27399
+ })
27400
+ });
27401
+ }
27402
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
27403
+ className: "flex flex-col flex-1 min-h-0 ".concat(panelStyles.textColor || "text-gray-200"),
27404
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27405
+ className: "flex-shrink-0 px-4 pt-4",
27406
+ children: /*#__PURE__*/jsxRuntime.jsxs("button", {
27407
+ type: "button",
27408
+ onClick: onBack,
27409
+ className: "flex items-center gap-1.5 text-sm opacity-60 hover:opacity-100 transition-opacity",
27410
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27411
+ icon: "arrow-left",
27412
+ className: "h-3 w-3"
27413
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27414
+ children: "Back"
27415
+ })]
27416
+ })
27417
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
27418
+ className: "flex-shrink-0 px-4 py-3",
27419
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.SearchInput, {
27420
+ value: searchQuery,
27421
+ onChange: setSearchQuery,
27422
+ placeholder: "Search dashboards...",
27423
+ inputClassName: "py-1.5 text-xs"
27424
+ })
27425
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
27426
+ className: "flex-1 min-h-0 overflow-y-auto px-2",
27427
+ children: listBody
27428
+ }), !isLoading && !error && packages.length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
27429
+ className: "flex-shrink-0 px-4 py-2 text-[10px] opacity-40 border-t border-white/10",
27430
+ children: [packages.length, " dashboard", packages.length !== 1 ? "s" : ""]
26600
27431
  })]
26601
27432
  });
26602
27433
  };
@@ -26613,7 +27444,11 @@ var DashboardsSection = function DashboardsSection(_ref) {
26613
27444
  _ref$credentials = _ref.credentials,
26614
27445
  credentials = _ref$credentials === void 0 ? null : _ref$credentials,
26615
27446
  _ref$onReloadWorkspac = _ref.onReloadWorkspaces,
26616
- onReloadWorkspaces = _ref$onReloadWorkspac === void 0 ? null : _ref$onReloadWorkspac;
27447
+ onReloadWorkspaces = _ref$onReloadWorkspac === void 0 ? null : _ref$onReloadWorkspac,
27448
+ _ref$createRequested = _ref.createRequested,
27449
+ createRequested = _ref$createRequested === void 0 ? false : _ref$createRequested,
27450
+ _ref$onCreateAcknowle = _ref.onCreateAcknowledged,
27451
+ onCreateAcknowledged = _ref$onCreateAcknowle === void 0 ? null : _ref$onCreateAcknowle;
26617
27452
  var _useState = React.useState(null),
26618
27453
  _useState2 = _slicedToArray(_useState, 2),
26619
27454
  selectedId = _useState2[0],
@@ -26638,6 +27473,15 @@ var DashboardsSection = function DashboardsSection(_ref) {
26638
27473
  _useState10 = _slicedToArray(_useState1, 2),
26639
27474
  viewMode = _useState10[0],
26640
27475
  setViewMode = _useState10[1];
27476
+ // null | "marketplace" | "import-result"
27477
+ var _useState11 = React.useState(null),
27478
+ _useState12 = _slicedToArray(_useState11, 2),
27479
+ installMode = _useState12[0],
27480
+ setInstallMode = _useState12[1];
27481
+ var _useState13 = React.useState(null),
27482
+ _useState14 = _slicedToArray(_useState13, 2),
27483
+ importResult = _useState14[0],
27484
+ setImportResult = _useState14[1];
26641
27485
  var appId = credentials === null || credentials === void 0 ? void 0 : credentials.appId;
26642
27486
  var _useContext = React.useContext(DashReact.ThemeContext),
26643
27487
  currentTheme = _useContext.currentTheme;
@@ -26717,6 +27561,84 @@ var DashboardsSection = function DashboardsSection(_ref) {
26717
27561
  setDeleteTarget(null);
26718
27562
  });
26719
27563
  }
27564
+
27565
+ // Respond to external create trigger from header button (marketplace)
27566
+ var prevCreateRequested = React.useRef(false);
27567
+ React.useEffect(function () {
27568
+ if (createRequested && !prevCreateRequested.current) {
27569
+ setSelectedId(null);
27570
+ setInstallMode("marketplace");
27571
+ setImportResult(null);
27572
+ }
27573
+ prevCreateRequested.current = createRequested;
27574
+ if (createRequested && onCreateAcknowledged) {
27575
+ onCreateAcknowledged();
27576
+ }
27577
+ // eslint-disable-next-line react-hooks/exhaustive-deps
27578
+ }, [createRequested]);
27579
+ function handleImport() {
27580
+ return _handleImport.apply(this, arguments);
27581
+ }
27582
+ function _handleImport() {
27583
+ _handleImport = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
27584
+ var result, _result$workspace, _t;
27585
+ return _regeneratorRuntime.wrap(function (_context) {
27586
+ while (1) switch (_context.prev = _context.next) {
27587
+ case 0:
27588
+ if (appId) {
27589
+ _context.next = 1;
27590
+ break;
27591
+ }
27592
+ return _context.abrupt("return");
27593
+ case 1:
27594
+ setInstallMode("import-result");
27595
+ setImportResult({
27596
+ status: "loading",
27597
+ message: "Importing dashboard..."
27598
+ });
27599
+ _context.prev = 2;
27600
+ _context.next = 3;
27601
+ return window.mainApi.dashboardConfig.importDashboardConfig(appId);
27602
+ case 3:
27603
+ result = _context.sent;
27604
+ if (result) {
27605
+ _context.next = 4;
27606
+ break;
27607
+ }
27608
+ // User cancelled the file picker
27609
+ setInstallMode(null);
27610
+ setImportResult(null);
27611
+ return _context.abrupt("return");
27612
+ case 4:
27613
+ if (result.success) {
27614
+ setImportResult({
27615
+ status: "success",
27616
+ message: "Dashboard \"".concat(((_result$workspace = result.workspace) === null || _result$workspace === void 0 ? void 0 : _result$workspace.name) || "Untitled", "\" imported successfully.")
27617
+ });
27618
+ onReloadWorkspaces && onReloadWorkspaces();
27619
+ } else {
27620
+ setImportResult({
27621
+ status: "error",
27622
+ message: result.error || "Import failed."
27623
+ });
27624
+ }
27625
+ _context.next = 6;
27626
+ break;
27627
+ case 5:
27628
+ _context.prev = 5;
27629
+ _t = _context["catch"](2);
27630
+ setImportResult({
27631
+ status: "error",
27632
+ message: _t.message || "Failed to import dashboard."
27633
+ });
27634
+ case 6:
27635
+ case "end":
27636
+ return _context.stop();
27637
+ }
27638
+ }, _callee, null, [[2, 5]]);
27639
+ }));
27640
+ return _handleImport.apply(this, arguments);
27641
+ }
26720
27642
  var selectedWorkspace = workspaces.find(function (ws) {
26721
27643
  return ws.id === selectedId;
26722
27644
  });
@@ -26766,13 +27688,33 @@ var DashboardsSection = function DashboardsSection(_ref) {
26766
27688
  className: "flex flex-col h-full",
26767
27689
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
26768
27690
  className: "flex-shrink-0 flex flex-col gap-2 px-3 pt-3 pb-2 ".concat(headerStyles.backgroundColor || ""),
26769
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SearchInput, {
26770
- value: searchQuery,
26771
- onChange: setSearchQuery,
26772
- placeholder: "Search dashboards..."
27691
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
27692
+ className: "flex items-center gap-2",
27693
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27694
+ className: "flex-1",
27695
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.SearchInput, {
27696
+ value: searchQuery,
27697
+ onChange: setSearchQuery,
27698
+ placeholder: "Search dashboards..."
27699
+ })
27700
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.ButtonIcon, {
27701
+ icon: "file-import",
27702
+ onClick: handleImport,
27703
+ size: "sm",
27704
+ title: "Import dashboard"
27705
+ })]
26773
27706
  }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Tabs3, {
26774
- value: viewMode,
26775
- onValueChange: setViewMode,
27707
+ value: installMode === "marketplace" ? "marketplace" : viewMode,
27708
+ onValueChange: function onValueChange(val) {
27709
+ if (val === "marketplace") {
27710
+ setInstallMode("marketplace");
27711
+ setSelectedId(null);
27712
+ } else {
27713
+ setInstallMode(null);
27714
+ setImportResult(null);
27715
+ setViewMode(val);
27716
+ }
27717
+ },
26776
27718
  backgroundColor: "bg-transparent",
26777
27719
  spacing: "p-0",
26778
27720
  children: /*#__PURE__*/jsxRuntime.jsxs(DashReact.Tabs3.List, {
@@ -26786,6 +27728,10 @@ var DashboardsSection = function DashboardsSection(_ref) {
26786
27728
  value: "alphabetical",
26787
27729
  className: "flex-1",
26788
27730
  children: "A-Z"
27731
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Tabs3.Trigger, {
27732
+ value: "marketplace",
27733
+ className: "flex-1",
27734
+ children: "Marketplace"
26789
27735
  })]
26790
27736
  })
26791
27737
  })]
@@ -26799,26 +27745,68 @@ var DashboardsSection = function DashboardsSection(_ref) {
26799
27745
  })
26800
27746
  })]
26801
27747
  });
26802
- var detailContent = selectedWorkspace ? /*#__PURE__*/jsxRuntime.jsx(DashboardDetail, {
26803
- workspace: selectedWorkspace,
26804
- menuItems: menuItems,
26805
- editingId: editingId,
26806
- editName: editName,
26807
- setEditName: setEditName,
26808
- onStartRename: handleStartRename,
26809
- onSaveRename: handleSaveRename,
26810
- onCancelRename: function onCancelRename() {
26811
- setEditingId(null);
26812
- setEditName("");
26813
- },
26814
- onDuplicate: handleDuplicate,
26815
- onDelete: function onDelete(ws) {
26816
- return setDeleteTarget(ws);
26817
- },
26818
- dashApi: dashApi,
26819
- credentials: credentials,
26820
- onReloadWorkspaces: onReloadWorkspaces
26821
- }) : null;
27748
+ var detailContent = null;
27749
+ if (installMode === "marketplace") {
27750
+ detailContent = /*#__PURE__*/jsxRuntime.jsx(DiscoverDashboardsDetail, {
27751
+ onBack: function onBack() {
27752
+ setInstallMode(null);
27753
+ setViewMode("grouped");
27754
+ },
27755
+ appId: appId
27756
+ });
27757
+ } else if (installMode === "import-result") {
27758
+ detailContent = /*#__PURE__*/jsxRuntime.jsxs("div", {
27759
+ className: "flex flex-col flex-1 min-h-0 p-6 space-y-4",
27760
+ children: [(importResult === null || importResult === void 0 ? void 0 : importResult.status) === "loading" && /*#__PURE__*/jsxRuntime.jsxs("div", {
27761
+ className: "flex items-center gap-3",
27762
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27763
+ className: "animate-spin rounded-full h-5 w-5 border-b-2 border-blue-500"
27764
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27765
+ className: "text-sm opacity-70",
27766
+ children: importResult.message
27767
+ })]
27768
+ }), (importResult === null || importResult === void 0 ? void 0 : importResult.status) === "success" && /*#__PURE__*/jsxRuntime.jsxs("div", {
27769
+ className: "flex items-center gap-2",
27770
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27771
+ icon: "circle-check",
27772
+ className: "h-4 w-4 text-green-400"
27773
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27774
+ className: "text-sm",
27775
+ children: importResult.message
27776
+ })]
27777
+ }), (importResult === null || importResult === void 0 ? void 0 : importResult.status) === "error" && /*#__PURE__*/jsxRuntime.jsxs("div", {
27778
+ className: "flex items-center gap-2",
27779
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27780
+ icon: "circle-xmark",
27781
+ className: "h-4 w-4 text-red-400"
27782
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
27783
+ className: "text-sm text-red-400",
27784
+ children: importResult.message
27785
+ })]
27786
+ })]
27787
+ });
27788
+ } else if (selectedWorkspace) {
27789
+ detailContent = /*#__PURE__*/jsxRuntime.jsx(DashboardDetail, {
27790
+ workspace: selectedWorkspace,
27791
+ menuItems: menuItems,
27792
+ editingId: editingId,
27793
+ editName: editName,
27794
+ setEditName: setEditName,
27795
+ onStartRename: handleStartRename,
27796
+ onSaveRename: handleSaveRename,
27797
+ onCancelRename: function onCancelRename() {
27798
+ setEditingId(null);
27799
+ setEditName("");
27800
+ },
27801
+ onDuplicate: handleDuplicate,
27802
+ onDelete: function onDelete(ws) {
27803
+ return setDeleteTarget(ws);
27804
+ },
27805
+ dashApi: dashApi,
27806
+ credentials: credentials,
27807
+ onReloadWorkspaces: onReloadWorkspaces
27808
+ });
27809
+ }
26822
27810
  return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
26823
27811
  children: [/*#__PURE__*/jsxRuntime.jsx(SectionLayout, {
26824
27812
  listContent: listContent,
@@ -32149,9 +33137,9 @@ var AppSettingsModal = function AppSettingsModal(_ref) {
32149
33137
  children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading2, {
32150
33138
  title: activeDef.label,
32151
33139
  padding: false
32152
- }), (activeSection === "folders" || activeSection === "providers" || activeSection === "themes" || activeSection === "widgets") && /*#__PURE__*/jsxRuntime.jsx(DashReact.ButtonIcon3, {
33140
+ }), (activeSection === "dashboards" || activeSection === "folders" || activeSection === "providers" || activeSection === "themes" || activeSection === "widgets") && /*#__PURE__*/jsxRuntime.jsx(DashReact.ButtonIcon3, {
32153
33141
  icon: "plus",
32154
- text: activeSection === "folders" ? "New Folder" : activeSection === "providers" ? "New Provider" : activeSection === "widgets" ? "Install Widgets" : "New Theme",
33142
+ text: activeSection === "dashboards" ? "Marketplace" : activeSection === "folders" ? "New Folder" : activeSection === "providers" ? "New Provider" : activeSection === "widgets" ? "Install Widgets" : "New Theme",
32155
33143
  onClick: function onClick() {
32156
33144
  return setCreateRequested(true);
32157
33145
  },
@@ -32168,7 +33156,11 @@ var AppSettingsModal = function AppSettingsModal(_ref) {
32168
33156
  menuItems: menuItems,
32169
33157
  dashApi: dashApi,
32170
33158
  credentials: credentials,
32171
- onReloadWorkspaces: onReloadWorkspaces
33159
+ onReloadWorkspaces: onReloadWorkspaces,
33160
+ createRequested: createRequested,
33161
+ onCreateAcknowledged: function onCreateAcknowledged() {
33162
+ return setCreateRequested(false);
33163
+ }
32172
33164
  }), activeSection === "folders" && /*#__PURE__*/jsxRuntime.jsx(FoldersSection, {
32173
33165
  menuItems: menuItems,
32174
33166
  workspaces: workspaces,