@trops/dash-core 0.1.257 → 0.1.260

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.esm.js CHANGED
@@ -3565,17 +3565,14 @@ var InstallProgressModal = function InstallProgressModal(_ref) {
3565
3565
  widgets = _ref$widgets === void 0 ? [] : _ref$widgets,
3566
3566
  _ref$isComplete = _ref.isComplete,
3567
3567
  isComplete = _ref$isComplete === void 0 ? false : _ref$isComplete,
3568
- onDone = _ref.onDone;
3568
+ onDone = _ref.onDone,
3569
+ _ref$onCancel = _ref.onCancel,
3570
+ onCancel = _ref$onCancel === void 0 ? null : _ref$onCancel;
3569
3571
  var _useContext = useContext(ThemeContext),
3570
3572
  currentTheme = _useContext.currentTheme;
3571
3573
  var panelStyles = getStylesForItem(themeObjects.PANEL, currentTheme, {
3572
3574
  grow: false
3573
3575
  });
3574
-
3575
- // Prevent dismissal while installation is in progress
3576
- var guardedSetIsOpen = function guardedSetIsOpen(val) {
3577
- if (isComplete) setIsOpen(val);
3578
- };
3579
3576
  var doneCount = widgets.filter(function (w) {
3580
3577
  return w.status === "installed" || w.status === "already-installed" || w.status === "failed";
3581
3578
  }).length;
@@ -3606,7 +3603,7 @@ var InstallProgressModal = function InstallProgressModal(_ref) {
3606
3603
  }
3607
3604
  return /*#__PURE__*/jsx(Modal, {
3608
3605
  isOpen: isOpen,
3609
- setIsOpen: guardedSetIsOpen,
3606
+ setIsOpen: setIsOpen,
3610
3607
  width: "w-[440px]",
3611
3608
  height: "auto",
3612
3609
  children: /*#__PURE__*/jsxs("div", {
@@ -3636,9 +3633,19 @@ var InstallProgressModal = function InstallProgressModal(_ref) {
3636
3633
  })]
3637
3634
  }, idx);
3638
3635
  })
3639
- }), /*#__PURE__*/jsx("div", {
3640
- className: "flex items-center justify-end px-5 py-3 border-t ".concat(currentTheme["border-primary-medium"] || "border-white/10"),
3641
- children: /*#__PURE__*/jsx(Button, {
3636
+ }), /*#__PURE__*/jsxs("div", {
3637
+ className: "flex items-center justify-between px-5 py-3 border-t ".concat(currentTheme["border-primary-medium"] || "border-white/10"),
3638
+ children: [/*#__PURE__*/jsx("div", {
3639
+ children: !isComplete && onCancel && /*#__PURE__*/jsx("button", {
3640
+ type: "button",
3641
+ onClick: function onClick() {
3642
+ if (onCancel) onCancel();
3643
+ setIsOpen(false);
3644
+ },
3645
+ className: "text-sm text-gray-500 hover:text-gray-300 transition-colors",
3646
+ children: "Cancel"
3647
+ })
3648
+ }), /*#__PURE__*/jsx(Button, {
3642
3649
  title: "Done",
3643
3650
  bgColor: isComplete ? "bg-blue-600" : "bg-gray-700",
3644
3651
  hoverBackgroundColor: isComplete ? "hover:bg-blue-700" : "",
@@ -3648,12 +3655,273 @@ var InstallProgressModal = function InstallProgressModal(_ref) {
3648
3655
  if (isComplete && onDone) onDone();
3649
3656
  },
3650
3657
  disabled: !isComplete
3651
- })
3658
+ })]
3652
3659
  })]
3653
3660
  })
3654
3661
  });
3655
3662
  };
3656
3663
 
3664
+ /**
3665
+ * useRegistryAuth — reusable hook for device-code OAuth against the Dash Registry.
3666
+ *
3667
+ * Encapsulates the full auth state machine: check status, initiate login,
3668
+ * poll for token, and cancel. Cleans up the poll interval on unmount.
3669
+ *
3670
+ * @returns {{
3671
+ * isAuthenticated: boolean,
3672
+ * isAuthenticating: boolean,
3673
+ * authFlow: { userCode: string, verificationUrlComplete: string } | null,
3674
+ * authError: string | null,
3675
+ * checkAuth: () => Promise<boolean>,
3676
+ * initiateAuth: () => Promise<void>,
3677
+ * cancelAuth: () => void,
3678
+ * }}
3679
+ */
3680
+ function useRegistryAuth() {
3681
+ var _useState = useState(false),
3682
+ _useState2 = _slicedToArray(_useState, 2),
3683
+ isAuthenticated = _useState2[0],
3684
+ setIsAuthenticated = _useState2[1];
3685
+ var _useState3 = useState(false),
3686
+ _useState4 = _slicedToArray(_useState3, 2),
3687
+ isAuthenticating = _useState4[0],
3688
+ setIsAuthenticating = _useState4[1];
3689
+ var _useState5 = useState(null),
3690
+ _useState6 = _slicedToArray(_useState5, 2),
3691
+ authFlow = _useState6[0],
3692
+ setAuthFlow = _useState6[1];
3693
+ var _useState7 = useState(null),
3694
+ _useState8 = _slicedToArray(_useState7, 2),
3695
+ authError = _useState8[0],
3696
+ setAuthError = _useState8[1];
3697
+ var pollIntervalRef = useRef(null);
3698
+ var onAuthorizedRef = useRef(null);
3699
+
3700
+ // Clean up polling on unmount
3701
+ useEffect(function () {
3702
+ return function () {
3703
+ if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);
3704
+ };
3705
+ }, []);
3706
+ var checkAuth = useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
3707
+ var status, authed;
3708
+ return _regeneratorRuntime.wrap(function (_context) {
3709
+ while (1) switch (_context.prev = _context.next) {
3710
+ case 0:
3711
+ _context.prev = 0;
3712
+ _context.next = 1;
3713
+ return window.mainApi.registryAuth.getStatus();
3714
+ case 1:
3715
+ status = _context.sent;
3716
+ authed = !!(status !== null && status !== void 0 && status.authenticated);
3717
+ setIsAuthenticated(authed);
3718
+ return _context.abrupt("return", authed);
3719
+ case 2:
3720
+ _context.prev = 2;
3721
+ _context["catch"](0);
3722
+ return _context.abrupt("return", false);
3723
+ case 3:
3724
+ case "end":
3725
+ return _context.stop();
3726
+ }
3727
+ }, _callee, null, [[0, 2]]);
3728
+ })), []);
3729
+ var cancelAuth = useCallback(function () {
3730
+ if (pollIntervalRef.current) {
3731
+ clearInterval(pollIntervalRef.current);
3732
+ pollIntervalRef.current = null;
3733
+ }
3734
+ setIsAuthenticating(false);
3735
+ setAuthFlow(null);
3736
+ }, []);
3737
+ var initiateAuth = useCallback(/*#__PURE__*/function () {
3738
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(onAuthorized) {
3739
+ var flow, interval;
3740
+ return _regeneratorRuntime.wrap(function (_context3) {
3741
+ while (1) switch (_context3.prev = _context3.next) {
3742
+ case 0:
3743
+ setAuthError(null);
3744
+ onAuthorizedRef.current = onAuthorized || null;
3745
+ _context3.prev = 1;
3746
+ _context3.next = 2;
3747
+ return window.mainApi.registryAuth.initiateLogin();
3748
+ case 2:
3749
+ flow = _context3.sent;
3750
+ setAuthFlow(flow);
3751
+ if (flow.verificationUrlComplete) {
3752
+ window.mainApi.shell.openExternal(flow.verificationUrlComplete);
3753
+ }
3754
+ setIsAuthenticating(true);
3755
+ interval = (flow.interval || 5) * 1000;
3756
+ pollIntervalRef.current = setInterval(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
3757
+ var pollResult;
3758
+ return _regeneratorRuntime.wrap(function (_context2) {
3759
+ while (1) switch (_context2.prev = _context2.next) {
3760
+ case 0:
3761
+ _context2.prev = 0;
3762
+ _context2.next = 1;
3763
+ return window.mainApi.registryAuth.pollToken(flow.deviceCode);
3764
+ case 1:
3765
+ pollResult = _context2.sent;
3766
+ if (pollResult.status === "authorized") {
3767
+ clearInterval(pollIntervalRef.current);
3768
+ pollIntervalRef.current = null;
3769
+ setIsAuthenticating(false);
3770
+ setAuthFlow(null);
3771
+ setIsAuthenticated(true);
3772
+ if (onAuthorizedRef.current) {
3773
+ onAuthorizedRef.current();
3774
+ }
3775
+ } else if (pollResult.status === "expired") {
3776
+ clearInterval(pollIntervalRef.current);
3777
+ pollIntervalRef.current = null;
3778
+ setIsAuthenticating(false);
3779
+ setAuthFlow(null);
3780
+ setAuthError("Authorization expired. Please try again.");
3781
+ }
3782
+ _context2.next = 3;
3783
+ break;
3784
+ case 2:
3785
+ _context2.prev = 2;
3786
+ _context2["catch"](0);
3787
+ clearInterval(pollIntervalRef.current);
3788
+ pollIntervalRef.current = null;
3789
+ setIsAuthenticating(false);
3790
+ case 3:
3791
+ case "end":
3792
+ return _context2.stop();
3793
+ }
3794
+ }, _callee2, null, [[0, 2]]);
3795
+ })), interval);
3796
+ _context3.next = 4;
3797
+ break;
3798
+ case 3:
3799
+ _context3.prev = 3;
3800
+ _context3["catch"](1);
3801
+ setAuthError("Could not reach the registry. Check your connection and try again.");
3802
+ case 4:
3803
+ case "end":
3804
+ return _context3.stop();
3805
+ }
3806
+ }, _callee3, null, [[1, 3]]);
3807
+ }));
3808
+ return function (_x) {
3809
+ return _ref2.apply(this, arguments);
3810
+ };
3811
+ }(), [cancelAuth]);
3812
+ return {
3813
+ isAuthenticated: isAuthenticated,
3814
+ isAuthenticating: isAuthenticating,
3815
+ authFlow: authFlow,
3816
+ authError: authError,
3817
+ checkAuth: checkAuth,
3818
+ initiateAuth: initiateAuth,
3819
+ cancelAuth: cancelAuth
3820
+ };
3821
+ }
3822
+
3823
+ var RegistryAuthPrompt = function RegistryAuthPrompt(_ref) {
3824
+ var onAuthenticated = _ref.onAuthenticated,
3825
+ _ref$onCancel = _ref.onCancel,
3826
+ onCancel = _ref$onCancel === void 0 ? null : _ref$onCancel,
3827
+ _ref$message = _ref.message,
3828
+ message = _ref$message === void 0 ? "Sign in to install from the Dash Registry." : _ref$message;
3829
+ var _useRegistryAuth = useRegistryAuth(),
3830
+ isAuthenticating = _useRegistryAuth.isAuthenticating,
3831
+ authFlow = _useRegistryAuth.authFlow,
3832
+ authError = _useRegistryAuth.authError,
3833
+ checkAuth = _useRegistryAuth.checkAuth,
3834
+ initiateAuth = _useRegistryAuth.initiateAuth,
3835
+ cancelAuth = _useRegistryAuth.cancelAuth;
3836
+ var checkedRef = useRef(false);
3837
+
3838
+ // Check auth on mount — if already authenticated, short-circuit
3839
+ useEffect(function () {
3840
+ if (checkedRef.current) return;
3841
+ checkedRef.current = true;
3842
+ checkAuth().then(function (authed) {
3843
+ if (authed && onAuthenticated) onAuthenticated();
3844
+ });
3845
+ }, [checkAuth, onAuthenticated]);
3846
+ function handleSignIn() {
3847
+ initiateAuth(function () {
3848
+ if (onAuthenticated) onAuthenticated();
3849
+ });
3850
+ }
3851
+ function handleCancel() {
3852
+ cancelAuth();
3853
+ if (onCancel) onCancel();
3854
+ }
3855
+
3856
+ // Polling state: show user code
3857
+ if (authFlow && isAuthenticating) {
3858
+ return /*#__PURE__*/jsxs("div", {
3859
+ className: "flex flex-col gap-3 p-4",
3860
+ children: [/*#__PURE__*/jsxs("div", {
3861
+ className: "bg-blue-500/10 border border-blue-500/20 rounded-lg p-4 space-y-3",
3862
+ children: [/*#__PURE__*/jsx("p", {
3863
+ className: "text-xs text-blue-300/90",
3864
+ children: "Enter this code in your browser:"
3865
+ }), /*#__PURE__*/jsx("div", {
3866
+ className: "text-center",
3867
+ children: /*#__PURE__*/jsx("span", {
3868
+ className: "text-2xl font-mono font-bold tracking-widest text-white",
3869
+ children: authFlow.userCode
3870
+ })
3871
+ }), /*#__PURE__*/jsx("p", {
3872
+ className: "text-xs text-blue-300/70 text-center",
3873
+ children: "Waiting for authorization \u2014 install will resume automatically..."
3874
+ })]
3875
+ }), onCancel && /*#__PURE__*/jsx("button", {
3876
+ type: "button",
3877
+ onClick: handleCancel,
3878
+ className: "self-center text-xs text-gray-500 hover:text-gray-300 transition-colors",
3879
+ children: "Cancel"
3880
+ })]
3881
+ });
3882
+ }
3883
+
3884
+ // Default: not-started / error state
3885
+ return /*#__PURE__*/jsxs("div", {
3886
+ className: "flex flex-col gap-3 p-4",
3887
+ children: [/*#__PURE__*/jsx("div", {
3888
+ className: "bg-yellow-500/10 border border-yellow-500/20 rounded-lg p-3",
3889
+ children: /*#__PURE__*/jsxs("div", {
3890
+ className: "flex items-start gap-2",
3891
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
3892
+ icon: "lock",
3893
+ className: "h-3.5 w-3.5 text-yellow-400 mt-0.5 flex-shrink-0"
3894
+ }), /*#__PURE__*/jsx("span", {
3895
+ className: "text-sm text-yellow-300/90",
3896
+ children: message
3897
+ })]
3898
+ })
3899
+ }), /*#__PURE__*/jsx("button", {
3900
+ type: "button",
3901
+ onClick: handleSignIn,
3902
+ className: "px-4 py-2 rounded-lg text-sm bg-blue-500/20 border border-blue-500/30 text-blue-300 hover:bg-blue-500/30 transition-colors cursor-pointer",
3903
+ children: "Sign in to Registry"
3904
+ }), authError && /*#__PURE__*/jsx("div", {
3905
+ className: "bg-red-500/10 border border-red-500/20 rounded-lg p-3",
3906
+ children: /*#__PURE__*/jsxs("div", {
3907
+ className: "flex items-start gap-2",
3908
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
3909
+ icon: "circle-xmark",
3910
+ className: "h-3.5 w-3.5 text-red-400 mt-0.5 flex-shrink-0"
3911
+ }), /*#__PURE__*/jsx("span", {
3912
+ className: "text-xs text-red-300/90",
3913
+ children: authError
3914
+ })]
3915
+ })
3916
+ }), onCancel && /*#__PURE__*/jsx("button", {
3917
+ type: "button",
3918
+ onClick: handleCancel,
3919
+ className: "self-center text-xs text-gray-500 hover:text-gray-300 transition-colors",
3920
+ children: "Cancel"
3921
+ })]
3922
+ });
3923
+ };
3924
+
3657
3925
  function _createForOfIteratorHelper$g(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$g(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
3658
3926
  function _unsupportedIterableToArray$g(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray$g(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$g(r, a) : void 0; } }
3659
3927
  function _arrayLikeToArray$g(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
@@ -3684,41 +3952,27 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3684
3952
  _useState8 = _slicedToArray(_useState7, 2),
3685
3953
  installResult = _useState8[0],
3686
3954
  setInstallResult = _useState8[1];
3687
- var _useState9 = useState(null),
3955
+ var _useState9 = useState(false),
3688
3956
  _useState0 = _slicedToArray(_useState9, 2),
3689
- authFlow = _useState0[0],
3690
- setAuthFlow = _useState0[1];
3691
- var _useState1 = useState(false),
3957
+ showProgressModal = _useState0[0],
3958
+ setShowProgressModal = _useState0[1];
3959
+ var _useState1 = useState([]),
3692
3960
  _useState10 = _slicedToArray(_useState1, 2),
3693
- isPolling = _useState10[0],
3694
- setIsPolling = _useState10[1];
3695
- var _useState11 = useState(null),
3961
+ progressWidgets = _useState10[0],
3962
+ setProgressWidgets = _useState10[1];
3963
+ var _useState11 = useState(false),
3696
3964
  _useState12 = _slicedToArray(_useState11, 2),
3697
- authError = _useState12[0],
3698
- setAuthError = _useState12[1];
3699
- var _useState13 = useState(false),
3700
- _useState14 = _slicedToArray(_useState13, 2),
3701
- showProgressModal = _useState14[0],
3702
- setShowProgressModal = _useState14[1];
3703
- var _useState15 = useState([]),
3704
- _useState16 = _slicedToArray(_useState15, 2),
3705
- progressWidgets = _useState16[0],
3706
- setProgressWidgets = _useState16[1];
3707
- var _useState17 = useState(false),
3708
- _useState18 = _slicedToArray(_useState17, 2),
3709
- progressComplete = _useState18[0],
3710
- setProgressComplete = _useState18[1];
3965
+ progressComplete = _useState12[0],
3966
+ setProgressComplete = _useState12[1];
3711
3967
  var progressResultRef = useRef(null);
3712
- var pollIntervalRef = useRef(null);
3713
3968
  var cleanupProgressRef = useRef(null);
3714
3969
  var pkg = dashboardPackage;
3715
3970
  if (!pkg) return null;
3716
3971
 
3717
- // Clean up polling and progress listener on unmount
3972
+ // Clean up progress listener on unmount
3718
3973
  // eslint-disable-next-line react-hooks/rules-of-hooks
3719
3974
  useEffect(function () {
3720
3975
  return function () {
3721
- if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);
3722
3976
  if (cleanupProgressRef.current) cleanupProgressRef.current();
3723
3977
  };
3724
3978
  }, []);
@@ -3732,10 +3986,6 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3732
3986
  setPreviewLoading(true);
3733
3987
  setPreview(null);
3734
3988
  setInstallResult(null);
3735
- setAuthFlow(null);
3736
- setIsPolling(false);
3737
- setAuthError(null);
3738
- if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);
3739
3989
  (_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) {
3740
3990
  if (!cancelled) setPreview(result);
3741
3991
  })["catch"](function (err) {
@@ -3763,8 +4013,6 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3763
4013
  case 1:
3764
4014
  setIsInstalling(true);
3765
4015
  setInstallResult(null);
3766
- setAuthFlow(null);
3767
- setAuthError(null);
3768
4016
 
3769
4017
  // Initialize progress modal from widget deps
3770
4018
  deps = widgetDeps.length > 0 ? widgetDeps : [];
@@ -3872,83 +4120,6 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3872
4120
  }
3873
4121
  }
3874
4122
  }, [pkg.name, onInstallComplete]);
3875
- function handleSignIn() {
3876
- return _handleSignIn.apply(this, arguments);
3877
- }
3878
- function _handleSignIn() {
3879
- _handleSignIn = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
3880
- var flow, interval;
3881
- return _regeneratorRuntime.wrap(function (_context3) {
3882
- while (1) switch (_context3.prev = _context3.next) {
3883
- case 0:
3884
- setAuthError(null);
3885
- _context3.prev = 1;
3886
- _context3.next = 2;
3887
- return window.mainApi.registryAuth.initiateLogin();
3888
- case 2:
3889
- flow = _context3.sent;
3890
- setAuthFlow(flow);
3891
-
3892
- // Open verification URL in browser
3893
- if (flow.verificationUrlComplete) {
3894
- window.mainApi.shell.openExternal(flow.verificationUrlComplete);
3895
- }
3896
-
3897
- // Start polling for token
3898
- setIsPolling(true);
3899
- interval = (flow.interval || 5) * 1000;
3900
- pollIntervalRef.current = setInterval(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
3901
- var pollResult;
3902
- return _regeneratorRuntime.wrap(function (_context2) {
3903
- while (1) switch (_context2.prev = _context2.next) {
3904
- case 0:
3905
- _context2.prev = 0;
3906
- _context2.next = 1;
3907
- return window.mainApi.registryAuth.pollToken(flow.deviceCode);
3908
- case 1:
3909
- pollResult = _context2.sent;
3910
- if (pollResult.status === "authorized") {
3911
- clearInterval(pollIntervalRef.current);
3912
- pollIntervalRef.current = null;
3913
- setIsPolling(false);
3914
- setAuthFlow(null);
3915
- // DASH-136: Auto-retry install after successful auth
3916
- handleInstall();
3917
- } else if (pollResult.status === "expired") {
3918
- clearInterval(pollIntervalRef.current);
3919
- pollIntervalRef.current = null;
3920
- setIsPolling(false);
3921
- setAuthFlow(null);
3922
- setAuthError("Authorization expired. Please try again.");
3923
- }
3924
- _context2.next = 3;
3925
- break;
3926
- case 2:
3927
- _context2.prev = 2;
3928
- _context2["catch"](0);
3929
- clearInterval(pollIntervalRef.current);
3930
- pollIntervalRef.current = null;
3931
- setIsPolling(false);
3932
- case 3:
3933
- case "end":
3934
- return _context2.stop();
3935
- }
3936
- }, _callee2, null, [[0, 2]]);
3937
- })), interval);
3938
- _context3.next = 4;
3939
- break;
3940
- case 3:
3941
- _context3.prev = 3;
3942
- _context3["catch"](1);
3943
- setAuthError("Could not reach the registry. Check your connection and try again.");
3944
- case 4:
3945
- case "end":
3946
- return _context3.stop();
3947
- }
3948
- }, _callee3, null, [[1, 3]]);
3949
- }));
3950
- return _handleSignIn.apply(this, arguments);
3951
- }
3952
4123
  var widgetDeps = (preview === null || preview === void 0 ? void 0 : preview.widgets) || pkg.widgets || [];
3953
4124
  var providers = (preview === null || preview === void 0 ? void 0 : preview.providers) || [];
3954
4125
 
@@ -4192,55 +4363,15 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
4192
4363
  children: installResult.message
4193
4364
  })]
4194
4365
  })
4195
- }), (installResult === null || installResult === void 0 ? void 0 : installResult.status) === "auth" && /*#__PURE__*/jsxs("div", {
4196
- className: "space-y-3",
4197
- children: [/*#__PURE__*/jsx("div", {
4198
- className: "bg-yellow-500/10 border border-yellow-500/20 rounded-lg p-3",
4199
- children: /*#__PURE__*/jsxs("div", {
4200
- className: "flex items-start gap-2",
4201
- children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
4202
- icon: "lock",
4203
- className: "h-3.5 w-3.5 text-yellow-400 mt-0.5 flex-shrink-0"
4204
- }), /*#__PURE__*/jsx("span", {
4205
- className: "text-sm text-yellow-300/90",
4206
- children: installResult.message
4207
- })]
4208
- })
4209
- }), !authFlow && !isPolling && /*#__PURE__*/jsxs(Fragment, {
4210
- children: [/*#__PURE__*/jsx("button", {
4211
- type: "button",
4212
- onClick: handleSignIn,
4213
- className: "px-4 py-2 rounded-lg text-sm bg-blue-500/20 border border-blue-500/30 text-blue-300 hover:bg-blue-500/30 transition-colors cursor-pointer",
4214
- children: "Sign in to Registry"
4215
- }), authError && /*#__PURE__*/jsx("div", {
4216
- className: "bg-red-500/10 border border-red-500/20 rounded-lg p-3",
4217
- children: /*#__PURE__*/jsxs("div", {
4218
- className: "flex items-start gap-2",
4219
- children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
4220
- icon: "circle-xmark",
4221
- className: "h-3.5 w-3.5 text-red-400 mt-0.5 flex-shrink-0"
4222
- }), /*#__PURE__*/jsx("span", {
4223
- className: "text-xs text-red-300/90",
4224
- children: authError
4225
- })]
4226
- })
4227
- })]
4228
- }), authFlow && isPolling && /*#__PURE__*/jsxs("div", {
4229
- className: "bg-blue-500/10 border border-blue-500/20 rounded-lg p-4 space-y-3",
4230
- children: [/*#__PURE__*/jsx("p", {
4231
- className: "text-xs text-blue-300/90",
4232
- children: "Enter this code in your browser:"
4233
- }), /*#__PURE__*/jsx("div", {
4234
- className: "text-center",
4235
- children: /*#__PURE__*/jsx("span", {
4236
- className: "text-2xl font-mono font-bold tracking-widest text-white",
4237
- children: authFlow.userCode
4238
- })
4239
- }), /*#__PURE__*/jsx("p", {
4240
- className: "text-xs text-blue-300/70 text-center",
4241
- children: "Waiting for authorization \u2014 install will resume automatically..."
4242
- })]
4243
- })]
4366
+ }), (installResult === null || installResult === void 0 ? void 0 : installResult.status) === "auth" && /*#__PURE__*/jsx(RegistryAuthPrompt, {
4367
+ onAuthenticated: function onAuthenticated() {
4368
+ setInstallResult(null);
4369
+ handleInstall();
4370
+ },
4371
+ onCancel: function onCancel() {
4372
+ return setInstallResult(null);
4373
+ },
4374
+ message: installResult.message
4244
4375
  })]
4245
4376
  }), (installResult === null || installResult === void 0 ? void 0 : installResult.status) !== "success" && (installResult === null || installResult === void 0 ? void 0 : installResult.status) !== "auth" && /*#__PURE__*/jsx("div", {
4246
4377
  className: "flex items-center justify-end px-6 py-3 border-t ".concat(currentTheme["border-primary-medium"]),
@@ -4488,7 +4619,8 @@ var LayoutManagerModal = function LayoutManagerModal(_ref) {
4488
4619
  onOpenWizard = _ref$onOpenWizard === void 0 ? null : _ref$onOpenWizard;
4489
4620
  var _useContext = useContext(ThemeContext),
4490
4621
  themes = _useContext.themes,
4491
- appThemeKey = _useContext.themeKey;
4622
+ appThemeKey = _useContext.themeKey,
4623
+ loadThemes = _useContext.loadThemes;
4492
4624
  var _useState = useState(null),
4493
4625
  _useState2 = _slicedToArray(_useState, 2),
4494
4626
  creationMethod = _useState2[0],
@@ -4695,6 +4827,7 @@ var LayoutManagerModal = function LayoutManagerModal(_ref) {
4695
4827
  result = _context2.sent;
4696
4828
  if (result && result.success) {
4697
4829
  onReloadWorkspaces && onReloadWorkspaces();
4830
+ loadThemes();
4698
4831
  if (onOpenWorkspace && result.workspace) {
4699
4832
  onOpenWorkspace(result.workspace);
4700
4833
  }
@@ -4724,6 +4857,7 @@ var LayoutManagerModal = function LayoutManagerModal(_ref) {
4724
4857
  return window.mainApi.workspace.saveWorkspaceForApplication(appId, updatedWorkspace);
4725
4858
  case 8:
4726
4859
  onReloadWorkspaces && onReloadWorkspaces();
4860
+ loadThemes();
4727
4861
  if (onOpenWorkspace) {
4728
4862
  onOpenWorkspace(updatedWorkspace);
4729
4863
  }
@@ -5669,6 +5803,23 @@ var LayoutQuickAddMenu = function LayoutQuickAddMenu(_ref) {
5669
5803
  });
5670
5804
  };
5671
5805
 
5806
+ /**
5807
+ * Strip the Electron IPC error prefix from error messages.
5808
+ *
5809
+ * Raw IPC errors look like:
5810
+ * "Error invoking remote method 'widget:install': Error: Failed to fetch: Unauthorized"
5811
+ *
5812
+ * This extracts just the meaningful part after the last "Error: " prefix.
5813
+ *
5814
+ * @param {string} message - Raw error message
5815
+ * @returns {string} Cleaned error message
5816
+ */
5817
+ function cleanIpcError(message) {
5818
+ if (!message || typeof message !== "string") return message;
5819
+ var match = message.match(/Error invoking remote method '[^']+': (?:Error: )?(.*)/);
5820
+ return match ? match[1] : message;
5821
+ }
5822
+
5672
5823
  function _createForOfIteratorHelper$f(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$f(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
5673
5824
  function _unsupportedIterableToArray$f(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray$f(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$f(r, a) : void 0; } }
5674
5825
  function _arrayLikeToArray$f(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
@@ -5730,8 +5881,12 @@ var useRegistrySearch = function useRegistrySearch() {
5730
5881
  setInstallError = _useState12[1];
5731
5882
  var _useState13 = useState(false),
5732
5883
  _useState14 = _slicedToArray(_useState13, 2),
5733
- showAllPackages = _useState14[0],
5734
- setShowAllPackages = _useState14[1];
5884
+ needsAuth = _useState14[0],
5885
+ setNeedsAuth = _useState14[1];
5886
+ var _useState15 = useState(false),
5887
+ _useState16 = _slicedToArray(_useState15, 2),
5888
+ showAllPackages = _useState16[0],
5889
+ setShowAllPackages = _useState16[1];
5735
5890
 
5736
5891
  // Discover app capabilities from window.mainApi
5737
5892
  var appCapabilities = useMemo(function () {
@@ -5896,9 +6051,12 @@ var useRegistrySearch = function useRegistrySearch() {
5896
6051
  };
5897
6052
  // eslint-disable-next-line react-hooks/exhaustive-deps
5898
6053
  }, [searchQuery, showAllPackages]);
6054
+ var clearNeedsAuth = useCallback(function () {
6055
+ return setNeedsAuth(false);
6056
+ }, []);
5899
6057
  var installPackage = useCallback(/*#__PURE__*/function () {
5900
6058
  var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(widget) {
5901
- var packageName, packageScope, downloadUrl, packageVersion, scopedId, resolvedUrl, _t2;
6059
+ var _window$mainApi2, status, packageName, packageScope, downloadUrl, packageVersion, scopedId, resolvedUrl, msg, _t3;
5902
6060
  return _regeneratorRuntime.wrap(function (_context2) {
5903
6061
  while (1) switch (_context2.prev = _context2.next) {
5904
6062
  case 0:
@@ -5910,28 +6068,53 @@ var useRegistrySearch = function useRegistrySearch() {
5910
6068
  case 1:
5911
6069
  setIsInstalling(true);
5912
6070
  setInstallError(null);
6071
+ setNeedsAuth(false);
5913
6072
  _context2.prev = 2;
6073
+ _context2.prev = 3;
6074
+ _context2.next = 4;
6075
+ return (_window$mainApi2 = window.mainApi) === null || _window$mainApi2 === void 0 || (_window$mainApi2 = _window$mainApi2.registryAuth) === null || _window$mainApi2 === void 0 ? void 0 : _window$mainApi2.getStatus();
6076
+ case 4:
6077
+ status = _context2.sent;
6078
+ if (status !== null && status !== void 0 && status.authenticated) {
6079
+ _context2.next = 5;
6080
+ break;
6081
+ }
6082
+ setNeedsAuth(true);
6083
+ setIsInstalling(false);
6084
+ return _context2.abrupt("return");
6085
+ case 5:
6086
+ _context2.next = 7;
6087
+ break;
6088
+ case 6:
6089
+ _context2.prev = 6;
6090
+ _context2["catch"](3);
6091
+ case 7:
5914
6092
  packageName = widget.packageName, packageScope = widget.packageScope, downloadUrl = widget.downloadUrl, packageVersion = widget.packageVersion; // Build scoped ID (e.g. "@trops/slack") for the install key
5915
6093
  scopedId = packageScope ? "@".concat(packageScope.replace(/^@/, ""), "/").concat(packageName) : packageName; // Resolve placeholders in the download URL
5916
6094
  resolvedUrl = downloadUrl.replace(/\{version\}/g, packageVersion).replace(/\{name\}/g, packageName);
5917
- _context2.next = 3;
6095
+ _context2.next = 8;
5918
6096
  return window.mainApi.widgets.install(scopedId, resolvedUrl);
5919
- case 3:
5920
- _context2.next = 5;
6097
+ case 8:
6098
+ _context2.next = 10;
5921
6099
  break;
5922
- case 4:
5923
- _context2.prev = 4;
5924
- _t2 = _context2["catch"](2);
5925
- setInstallError(_t2.message || "Failed to install package");
5926
- case 5:
5927
- _context2.prev = 5;
6100
+ case 9:
6101
+ _context2.prev = 9;
6102
+ _t3 = _context2["catch"](2);
6103
+ msg = cleanIpcError(_t3.message || "Failed to install package");
6104
+ if (msg.toLowerCase().includes("unauthorized") || msg.toLowerCase().includes("authentication required")) {
6105
+ setNeedsAuth(true);
6106
+ } else {
6107
+ setInstallError(msg);
6108
+ }
6109
+ case 10:
6110
+ _context2.prev = 10;
5928
6111
  setIsInstalling(false);
5929
- return _context2.finish(5);
5930
- case 6:
6112
+ return _context2.finish(10);
6113
+ case 11:
5931
6114
  case "end":
5932
6115
  return _context2.stop();
5933
6116
  }
5934
- }, _callee2, null, [[2, 4, 5, 6]]);
6117
+ }, _callee2, null, [[2, 9, 10, 11], [3, 6]]);
5935
6118
  }));
5936
6119
  return function (_x2) {
5937
6120
  return _ref3.apply(this, arguments);
@@ -5949,6 +6132,8 @@ var useRegistrySearch = function useRegistrySearch() {
5949
6132
  setSearchQuery: setSearchQuery,
5950
6133
  isInstalling: isInstalling,
5951
6134
  installError: installError,
6135
+ needsAuth: needsAuth,
6136
+ clearNeedsAuth: clearNeedsAuth,
5952
6137
  search: search,
5953
6138
  installPackage: installPackage,
5954
6139
  retry: retry,
@@ -16323,6 +16508,10 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
16323
16508
  _useState64 = _slicedToArray(_useState63, 2),
16324
16509
  installError = _useState64[0],
16325
16510
  setInstallError = _useState64[1];
16511
+ var _useState65 = useState(false),
16512
+ _useState66 = _slicedToArray(_useState65, 2),
16513
+ needsAuth = _useState66[0],
16514
+ setNeedsAuth = _useState66[1];
16326
16515
 
16327
16516
  // Phase 3: Recent Widgets - localStorage functions
16328
16517
  var loadRecentWidgets = function loadRecentWidgets() {
@@ -16917,7 +17106,7 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
16917
17106
  // Install a package from the registry
16918
17107
  var handleInstallPackage = /*#__PURE__*/function () {
16919
17108
  var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
16920
- var packageName, downloadUrl, packageVersion, resolvedUrl, _t2;
17109
+ var _window$mainApi, status, packageName, downloadUrl, packageVersion, resolvedUrl, msg, _t3;
16921
17110
  return _regeneratorRuntime.wrap(function (_context2) {
16922
17111
  while (1) switch (_context2.prev = _context2.next) {
16923
17112
  case 0:
@@ -16929,32 +17118,57 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
16929
17118
  case 1:
16930
17119
  setIsInstalling(true);
16931
17120
  setInstallError(null);
17121
+ setNeedsAuth(false);
16932
17122
  _context2.prev = 2;
17123
+ _context2.prev = 3;
17124
+ _context2.next = 4;
17125
+ return (_window$mainApi = window.mainApi) === null || _window$mainApi === void 0 || (_window$mainApi = _window$mainApi.registryAuth) === null || _window$mainApi === void 0 ? void 0 : _window$mainApi.getStatus();
17126
+ case 4:
17127
+ status = _context2.sent;
17128
+ if (status !== null && status !== void 0 && status.authenticated) {
17129
+ _context2.next = 5;
17130
+ break;
17131
+ }
17132
+ setNeedsAuth(true);
17133
+ setIsInstalling(false);
17134
+ return _context2.abrupt("return");
17135
+ case 5:
17136
+ _context2.next = 7;
17137
+ break;
17138
+ case 6:
17139
+ _context2.prev = 6;
17140
+ _context2["catch"](3);
17141
+ case 7:
16933
17142
  packageName = selectedWidget.packageName, downloadUrl = selectedWidget.downloadUrl, packageVersion = selectedWidget.packageVersion; // Resolve version placeholder in download URL
16934
17143
  resolvedUrl = downloadUrl.replace(/\{version\}/g, packageVersion).replace(/\{name\}/g, packageName);
16935
- _context2.next = 3;
17144
+ _context2.next = 8;
16936
17145
  return window.mainApi.widgets.install(packageName, resolvedUrl);
16937
- case 3:
17146
+ case 8:
16938
17147
 
16939
17148
  // Switch to Installed tab after successful install
16940
17149
  setSelectedSource("Installed");
16941
17150
  setSelectedWidget(null);
16942
17151
  setSelectedPackage(null);
16943
- _context2.next = 5;
17152
+ _context2.next = 10;
16944
17153
  break;
16945
- case 4:
16946
- _context2.prev = 4;
16947
- _t2 = _context2["catch"](2);
16948
- setInstallError(_t2.message || "Failed to install package");
16949
- case 5:
16950
- _context2.prev = 5;
17154
+ case 9:
17155
+ _context2.prev = 9;
17156
+ _t3 = _context2["catch"](2);
17157
+ msg = cleanIpcError(_t3.message || "Failed to install package");
17158
+ if (msg.toLowerCase().includes("unauthorized") || msg.toLowerCase().includes("authentication required")) {
17159
+ setNeedsAuth(true);
17160
+ } else {
17161
+ setInstallError(msg);
17162
+ }
17163
+ case 10:
17164
+ _context2.prev = 10;
16951
17165
  setIsInstalling(false);
16952
- return _context2.finish(5);
16953
- case 6:
17166
+ return _context2.finish(10);
17167
+ case 11:
16954
17168
  case "end":
16955
17169
  return _context2.stop();
16956
17170
  }
16957
- }, _callee2, null, [[2, 4, 5, 6]]);
17171
+ }, _callee2, null, [[2, 9, 10, 11], [3, 6]]);
16958
17172
  }));
16959
17173
  return function handleInstallPackage() {
16960
17174
  return _ref3.apply(this, arguments);
@@ -17273,6 +17487,18 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
17273
17487
  className: "text-xs text-red-400",
17274
17488
  children: installError
17275
17489
  })
17490
+ }), needsAuth && /*#__PURE__*/jsx("div", {
17491
+ className: "mt-3",
17492
+ children: /*#__PURE__*/jsx(RegistryAuthPrompt, {
17493
+ onAuthenticated: function onAuthenticated() {
17494
+ setNeedsAuth(false);
17495
+ handleInstallPackage();
17496
+ },
17497
+ onCancel: function onCancel() {
17498
+ return setNeedsAuth(false);
17499
+ },
17500
+ message: "Sign in to install this widget from the Dash Registry."
17501
+ })
17276
17502
  })]
17277
17503
  });
17278
17504
  };
@@ -23125,7 +23351,13 @@ var RegistryPackageDetail = function RegistryPackageDetail(_ref) {
23125
23351
  _ref$installError = _ref.installError,
23126
23352
  installError = _ref$installError === void 0 ? null : _ref$installError,
23127
23353
  _ref$isInstalled = _ref.isInstalled,
23128
- isInstalled = _ref$isInstalled === void 0 ? false : _ref$isInstalled;
23354
+ isInstalled = _ref$isInstalled === void 0 ? false : _ref$isInstalled,
23355
+ _ref$showAuth = _ref.showAuth,
23356
+ showAuth = _ref$showAuth === void 0 ? false : _ref$showAuth,
23357
+ _ref$onAuthSuccess = _ref.onAuthSuccess,
23358
+ onAuthSuccess = _ref$onAuthSuccess === void 0 ? null : _ref$onAuthSuccess,
23359
+ _ref$onAuthCancel = _ref.onAuthCancel,
23360
+ onAuthCancel = _ref$onAuthCancel === void 0 ? null : _ref$onAuthCancel;
23129
23361
  var _useContext = useContext(ThemeContext),
23130
23362
  currentTheme = _useContext.currentTheme;
23131
23363
  var panelStyles = getStylesForItem(themeObjects.PANEL, currentTheme, {
@@ -23261,7 +23493,11 @@ var RegistryPackageDetail = function RegistryPackageDetail(_ref) {
23261
23493
  children: installError
23262
23494
  })
23263
23495
  })]
23264
- }), /*#__PURE__*/jsx("div", {
23496
+ }), showAuth && /*#__PURE__*/jsx(RegistryAuthPrompt, {
23497
+ onAuthenticated: onAuthSuccess,
23498
+ onCancel: onAuthCancel,
23499
+ message: "Sign in to install this widget from the Dash Registry."
23500
+ }), !showAuth && /*#__PURE__*/jsx("div", {
23265
23501
  className: "flex items-center justify-end px-6 py-3 border-t ".concat(currentTheme["border-primary-medium"]),
23266
23502
  children: /*#__PURE__*/jsx(Button, {
23267
23503
  title: isInstalled ? "Installed" : isInstalling ? "Installing..." : "Install Package",
@@ -23276,267 +23512,6 @@ var RegistryPackageDetail = function RegistryPackageDetail(_ref) {
23276
23512
  });
23277
23513
  };
23278
23514
 
23279
- /**
23280
- * useRegistryAuth — reusable hook for device-code OAuth against the Dash Registry.
23281
- *
23282
- * Encapsulates the full auth state machine: check status, initiate login,
23283
- * poll for token, and cancel. Cleans up the poll interval on unmount.
23284
- *
23285
- * @returns {{
23286
- * isAuthenticated: boolean,
23287
- * isAuthenticating: boolean,
23288
- * authFlow: { userCode: string, verificationUrlComplete: string } | null,
23289
- * authError: string | null,
23290
- * checkAuth: () => Promise<boolean>,
23291
- * initiateAuth: () => Promise<void>,
23292
- * cancelAuth: () => void,
23293
- * }}
23294
- */
23295
- function useRegistryAuth() {
23296
- var _useState = useState(false),
23297
- _useState2 = _slicedToArray(_useState, 2),
23298
- isAuthenticated = _useState2[0],
23299
- setIsAuthenticated = _useState2[1];
23300
- var _useState3 = useState(false),
23301
- _useState4 = _slicedToArray(_useState3, 2),
23302
- isAuthenticating = _useState4[0],
23303
- setIsAuthenticating = _useState4[1];
23304
- var _useState5 = useState(null),
23305
- _useState6 = _slicedToArray(_useState5, 2),
23306
- authFlow = _useState6[0],
23307
- setAuthFlow = _useState6[1];
23308
- var _useState7 = useState(null),
23309
- _useState8 = _slicedToArray(_useState7, 2),
23310
- authError = _useState8[0],
23311
- setAuthError = _useState8[1];
23312
- var pollIntervalRef = useRef(null);
23313
- var onAuthorizedRef = useRef(null);
23314
-
23315
- // Clean up polling on unmount
23316
- useEffect(function () {
23317
- return function () {
23318
- if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);
23319
- };
23320
- }, []);
23321
- var checkAuth = useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
23322
- var status, authed;
23323
- return _regeneratorRuntime.wrap(function (_context) {
23324
- while (1) switch (_context.prev = _context.next) {
23325
- case 0:
23326
- _context.prev = 0;
23327
- _context.next = 1;
23328
- return window.mainApi.registryAuth.getStatus();
23329
- case 1:
23330
- status = _context.sent;
23331
- authed = !!(status !== null && status !== void 0 && status.authenticated);
23332
- setIsAuthenticated(authed);
23333
- return _context.abrupt("return", authed);
23334
- case 2:
23335
- _context.prev = 2;
23336
- _context["catch"](0);
23337
- return _context.abrupt("return", false);
23338
- case 3:
23339
- case "end":
23340
- return _context.stop();
23341
- }
23342
- }, _callee, null, [[0, 2]]);
23343
- })), []);
23344
- var cancelAuth = useCallback(function () {
23345
- if (pollIntervalRef.current) {
23346
- clearInterval(pollIntervalRef.current);
23347
- pollIntervalRef.current = null;
23348
- }
23349
- setIsAuthenticating(false);
23350
- setAuthFlow(null);
23351
- }, []);
23352
- var initiateAuth = useCallback(/*#__PURE__*/function () {
23353
- var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(onAuthorized) {
23354
- var flow, interval;
23355
- return _regeneratorRuntime.wrap(function (_context3) {
23356
- while (1) switch (_context3.prev = _context3.next) {
23357
- case 0:
23358
- setAuthError(null);
23359
- onAuthorizedRef.current = onAuthorized || null;
23360
- _context3.prev = 1;
23361
- _context3.next = 2;
23362
- return window.mainApi.registryAuth.initiateLogin();
23363
- case 2:
23364
- flow = _context3.sent;
23365
- setAuthFlow(flow);
23366
- if (flow.verificationUrlComplete) {
23367
- window.mainApi.shell.openExternal(flow.verificationUrlComplete);
23368
- }
23369
- setIsAuthenticating(true);
23370
- interval = (flow.interval || 5) * 1000;
23371
- pollIntervalRef.current = setInterval(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
23372
- var pollResult;
23373
- return _regeneratorRuntime.wrap(function (_context2) {
23374
- while (1) switch (_context2.prev = _context2.next) {
23375
- case 0:
23376
- _context2.prev = 0;
23377
- _context2.next = 1;
23378
- return window.mainApi.registryAuth.pollToken(flow.deviceCode);
23379
- case 1:
23380
- pollResult = _context2.sent;
23381
- if (pollResult.status === "authorized") {
23382
- clearInterval(pollIntervalRef.current);
23383
- pollIntervalRef.current = null;
23384
- setIsAuthenticating(false);
23385
- setAuthFlow(null);
23386
- setIsAuthenticated(true);
23387
- if (onAuthorizedRef.current) {
23388
- onAuthorizedRef.current();
23389
- }
23390
- } else if (pollResult.status === "expired") {
23391
- clearInterval(pollIntervalRef.current);
23392
- pollIntervalRef.current = null;
23393
- setIsAuthenticating(false);
23394
- setAuthFlow(null);
23395
- setAuthError("Authorization expired. Please try again.");
23396
- }
23397
- _context2.next = 3;
23398
- break;
23399
- case 2:
23400
- _context2.prev = 2;
23401
- _context2["catch"](0);
23402
- clearInterval(pollIntervalRef.current);
23403
- pollIntervalRef.current = null;
23404
- setIsAuthenticating(false);
23405
- case 3:
23406
- case "end":
23407
- return _context2.stop();
23408
- }
23409
- }, _callee2, null, [[0, 2]]);
23410
- })), interval);
23411
- _context3.next = 4;
23412
- break;
23413
- case 3:
23414
- _context3.prev = 3;
23415
- _context3["catch"](1);
23416
- setAuthError("Could not reach the registry. Check your connection and try again.");
23417
- case 4:
23418
- case "end":
23419
- return _context3.stop();
23420
- }
23421
- }, _callee3, null, [[1, 3]]);
23422
- }));
23423
- return function (_x) {
23424
- return _ref2.apply(this, arguments);
23425
- };
23426
- }(), [cancelAuth]);
23427
- return {
23428
- isAuthenticated: isAuthenticated,
23429
- isAuthenticating: isAuthenticating,
23430
- authFlow: authFlow,
23431
- authError: authError,
23432
- checkAuth: checkAuth,
23433
- initiateAuth: initiateAuth,
23434
- cancelAuth: cancelAuth
23435
- };
23436
- }
23437
-
23438
- var RegistryAuthPrompt = function RegistryAuthPrompt(_ref) {
23439
- var onAuthenticated = _ref.onAuthenticated,
23440
- _ref$onCancel = _ref.onCancel,
23441
- onCancel = _ref$onCancel === void 0 ? null : _ref$onCancel,
23442
- _ref$message = _ref.message,
23443
- message = _ref$message === void 0 ? "Sign in to install from the Dash Registry." : _ref$message;
23444
- var _useRegistryAuth = useRegistryAuth(),
23445
- isAuthenticating = _useRegistryAuth.isAuthenticating,
23446
- authFlow = _useRegistryAuth.authFlow,
23447
- authError = _useRegistryAuth.authError,
23448
- checkAuth = _useRegistryAuth.checkAuth,
23449
- initiateAuth = _useRegistryAuth.initiateAuth,
23450
- cancelAuth = _useRegistryAuth.cancelAuth;
23451
- var checkedRef = useRef(false);
23452
-
23453
- // Check auth on mount — if already authenticated, short-circuit
23454
- useEffect(function () {
23455
- if (checkedRef.current) return;
23456
- checkedRef.current = true;
23457
- checkAuth().then(function (authed) {
23458
- if (authed && onAuthenticated) onAuthenticated();
23459
- });
23460
- }, [checkAuth, onAuthenticated]);
23461
- function handleSignIn() {
23462
- initiateAuth(function () {
23463
- if (onAuthenticated) onAuthenticated();
23464
- });
23465
- }
23466
- function handleCancel() {
23467
- cancelAuth();
23468
- if (onCancel) onCancel();
23469
- }
23470
-
23471
- // Polling state: show user code
23472
- if (authFlow && isAuthenticating) {
23473
- return /*#__PURE__*/jsxs("div", {
23474
- className: "flex flex-col gap-3 p-4",
23475
- children: [/*#__PURE__*/jsxs("div", {
23476
- className: "bg-blue-500/10 border border-blue-500/20 rounded-lg p-4 space-y-3",
23477
- children: [/*#__PURE__*/jsx("p", {
23478
- className: "text-xs text-blue-300/90",
23479
- children: "Enter this code in your browser:"
23480
- }), /*#__PURE__*/jsx("div", {
23481
- className: "text-center",
23482
- children: /*#__PURE__*/jsx("span", {
23483
- className: "text-2xl font-mono font-bold tracking-widest text-white",
23484
- children: authFlow.userCode
23485
- })
23486
- }), /*#__PURE__*/jsx("p", {
23487
- className: "text-xs text-blue-300/70 text-center",
23488
- children: "Waiting for authorization \u2014 install will resume automatically..."
23489
- })]
23490
- }), onCancel && /*#__PURE__*/jsx("button", {
23491
- type: "button",
23492
- onClick: handleCancel,
23493
- className: "self-center text-xs text-gray-500 hover:text-gray-300 transition-colors",
23494
- children: "Cancel"
23495
- })]
23496
- });
23497
- }
23498
-
23499
- // Default: not-started / error state
23500
- return /*#__PURE__*/jsxs("div", {
23501
- className: "flex flex-col gap-3 p-4",
23502
- children: [/*#__PURE__*/jsx("div", {
23503
- className: "bg-yellow-500/10 border border-yellow-500/20 rounded-lg p-3",
23504
- children: /*#__PURE__*/jsxs("div", {
23505
- className: "flex items-start gap-2",
23506
- children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
23507
- icon: "lock",
23508
- className: "h-3.5 w-3.5 text-yellow-400 mt-0.5 flex-shrink-0"
23509
- }), /*#__PURE__*/jsx("span", {
23510
- className: "text-sm text-yellow-300/90",
23511
- children: message
23512
- })]
23513
- })
23514
- }), /*#__PURE__*/jsx("button", {
23515
- type: "button",
23516
- onClick: handleSignIn,
23517
- className: "px-4 py-2 rounded-lg text-sm bg-blue-500/20 border border-blue-500/30 text-blue-300 hover:bg-blue-500/30 transition-colors cursor-pointer",
23518
- children: "Sign in to Registry"
23519
- }), authError && /*#__PURE__*/jsx("div", {
23520
- className: "bg-red-500/10 border border-red-500/20 rounded-lg p-3",
23521
- children: /*#__PURE__*/jsxs("div", {
23522
- className: "flex items-start gap-2",
23523
- children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
23524
- icon: "circle-xmark",
23525
- className: "h-3.5 w-3.5 text-red-400 mt-0.5 flex-shrink-0"
23526
- }), /*#__PURE__*/jsx("span", {
23527
- className: "text-xs text-red-300/90",
23528
- children: authError
23529
- })]
23530
- })
23531
- }), onCancel && /*#__PURE__*/jsx("button", {
23532
- type: "button",
23533
- onClick: handleCancel,
23534
- className: "self-center text-xs text-gray-500 hover:text-gray-300 transition-colors",
23535
- children: "Cancel"
23536
- })]
23537
- });
23538
- };
23539
-
23540
23515
  function getWidgetSearchQuery(componentKey) {
23541
23516
  var parts = componentKey.split(".");
23542
23517
  if (parts.length >= 3) {
@@ -38962,7 +38937,8 @@ var DashboardsSection = function DashboardsSection(_ref) {
38962
38937
  setInstallMode = _useState12[1];
38963
38938
  var appId = credentials === null || credentials === void 0 ? void 0 : credentials.appId;
38964
38939
  var _useContext = useContext(ThemeContext),
38965
- currentTheme = _useContext.currentTheme;
38940
+ currentTheme = _useContext.currentTheme,
38941
+ loadThemes = _useContext.loadThemes;
38966
38942
  var headerStyles = getStylesForItem(themeObjects.PANEL_HEADER, currentTheme, {
38967
38943
  grow: false
38968
38944
  });
@@ -39173,6 +39149,7 @@ var DashboardsSection = function DashboardsSection(_ref) {
39173
39149
  appId: appId,
39174
39150
  onInstallComplete: function onInstallComplete() {
39175
39151
  onReloadWorkspaces && onReloadWorkspaces();
39152
+ loadThemes();
39176
39153
  }
39177
39154
  });
39178
39155
  } else if (selectedWorkspace) {
@@ -44632,6 +44609,8 @@ var DiscoverWidgetsDetail = function DiscoverWidgetsDetail(_ref) {
44632
44609
  setSearchQuery = _useRegistrySearch.setSearchQuery,
44633
44610
  isInstalling = _useRegistrySearch.isInstalling,
44634
44611
  installError = _useRegistrySearch.installError,
44612
+ needsAuth = _useRegistrySearch.needsAuth,
44613
+ clearNeedsAuth = _useRegistrySearch.clearNeedsAuth,
44635
44614
  installPackage = _useRegistrySearch.installPackage,
44636
44615
  retry = _useRegistrySearch.retry,
44637
44616
  showAllPackages = _useRegistrySearch.showAllPackages,
@@ -44832,7 +44811,13 @@ var DiscoverWidgetsDetail = function DiscoverWidgetsDetail(_ref) {
44832
44811
  installError: installError,
44833
44812
  isInstalled: selectedWidget ? isPackageInstalled(packages.find(function (p) {
44834
44813
  return p.name === selectedPackageName;
44835
- }) || {}) : false
44814
+ }) || {}) : false,
44815
+ showAuth: needsAuth,
44816
+ onAuthSuccess: function onAuthSuccess() {
44817
+ clearNeedsAuth();
44818
+ installPackage(selectedWidget);
44819
+ },
44820
+ onAuthCancel: clearNeedsAuth
44836
44821
  })]
44837
44822
  });
44838
44823
  }
@@ -48091,6 +48076,10 @@ var SidebarDiscoverContent = function SidebarDiscoverContent(_ref2) {
48091
48076
  _useState2 = _slicedToArray(_useState, 2),
48092
48077
  selectedPackageName = _useState2[0],
48093
48078
  setSelectedPackageName = _useState2[1];
48079
+ var _useState3 = useState(null),
48080
+ _useState4 = _slicedToArray(_useState3, 2),
48081
+ pendingInstallPkg = _useState4[0],
48082
+ setPendingInstallPkg = _useState4[1];
48094
48083
 
48095
48084
  // Check if a package is installed by name or scope/name
48096
48085
  var isPackageInstalled = useCallback(function (pkg) {
@@ -48135,19 +48124,22 @@ var SidebarDiscoverContent = function SidebarDiscoverContent(_ref2) {
48135
48124
  }
48136
48125
  return _context.abrupt("return");
48137
48126
  case 1:
48127
+ setPendingInstallPkg(pkg);
48138
48128
  installable = {
48139
48129
  isRegistry: true,
48140
48130
  packageName: pkg.name,
48131
+ packageScope: pkg.scope || null,
48141
48132
  downloadUrl: pkg.downloadUrl || "",
48142
48133
  packageVersion: pkg.version || ""
48143
48134
  };
48144
48135
  _context.next = 2;
48145
48136
  return registry.installPackage(installable);
48146
48137
  case 2:
48147
- // If no install error, signal success
48148
- if (!registry.installError) {
48138
+ // If no install error and no auth needed, signal success
48139
+ if (!registry.installError && !registry.needsAuth) {
48149
48140
  onInstallSuccess(pkg.displayName || pkg.name);
48150
48141
  setSelectedPackageName(null);
48142
+ setPendingInstallPkg(null);
48151
48143
  }
48152
48144
  case 3:
48153
48145
  case "end":
@@ -48242,8 +48234,21 @@ var SidebarDiscoverContent = function SidebarDiscoverContent(_ref2) {
48242
48234
  }), registry.installError && /*#__PURE__*/jsx("div", {
48243
48235
  className: "text-xs text-red-400 bg-red-500/10 rounded px-2 py-1.5 mb-3",
48244
48236
  children: registry.installError
48237
+ }), registry.needsAuth && /*#__PURE__*/jsx("div", {
48238
+ className: "mb-3",
48239
+ children: /*#__PURE__*/jsx(RegistryAuthPrompt, {
48240
+ onAuthenticated: function onAuthenticated() {
48241
+ registry.clearNeedsAuth();
48242
+ if (pendingInstallPkg) handleInstall(pendingInstallPkg);
48243
+ },
48244
+ onCancel: function onCancel() {
48245
+ registry.clearNeedsAuth();
48246
+ setPendingInstallPkg(null);
48247
+ },
48248
+ message: "Sign in to install this widget from the Dash Registry."
48249
+ })
48245
48250
  })]
48246
- }), /*#__PURE__*/jsx("div", {
48251
+ }), !registry.needsAuth && /*#__PURE__*/jsx("div", {
48247
48252
  className: "px-3 py-2 flex-shrink-0",
48248
48253
  children: /*#__PURE__*/jsx("button", {
48249
48254
  type: "button",
@@ -48371,45 +48376,45 @@ var WidgetSidebar = function WidgetSidebar(_ref4) {
48371
48376
  currentTheme = _useContext.currentTheme;
48372
48377
 
48373
48378
  // Tab state
48374
- var _useState3 = useState("installed"),
48375
- _useState4 = _slicedToArray(_useState3, 2),
48376
- activeTab = _useState4[0],
48377
- setActiveTab = _useState4[1]; // "installed" | "discover"
48378
- var _useState5 = useState(null),
48379
+ var _useState5 = useState("installed"),
48379
48380
  _useState6 = _slicedToArray(_useState5, 2),
48380
- installSuccess = _useState6[0],
48381
- setInstallSuccess = _useState6[1];
48381
+ activeTab = _useState6[0],
48382
+ setActiveTab = _useState6[1]; // "installed" | "discover"
48383
+ var _useState7 = useState(null),
48384
+ _useState8 = _slicedToArray(_useState7, 2),
48385
+ installSuccess = _useState8[0],
48386
+ setInstallSuccess = _useState8[1];
48382
48387
 
48383
48388
  // Registry hook (only active when discover tab is shown)
48384
48389
  var registry = useRegistrySearch();
48385
48390
 
48386
48391
  // Filter state
48387
- var _useState7 = useState(""),
48388
- _useState8 = _slicedToArray(_useState7, 2),
48389
- searchQuery = _useState8[0],
48390
- setSearchQuery = _useState8[1];
48391
- var _useState9 = useState("all"),
48392
+ var _useState9 = useState(""),
48392
48393
  _useState0 = _slicedToArray(_useState9, 2),
48393
- filterAuthor = _useState0[0],
48394
- setFilterAuthor = _useState0[1];
48394
+ searchQuery = _useState0[0],
48395
+ setSearchQuery = _useState0[1];
48395
48396
  var _useState1 = useState("all"),
48396
48397
  _useState10 = _slicedToArray(_useState1, 2),
48397
- filterProvider = _useState10[0],
48398
- setFilterProvider = _useState10[1];
48398
+ filterAuthor = _useState10[0],
48399
+ setFilterAuthor = _useState10[1];
48399
48400
  var _useState11 = useState("all"),
48400
48401
  _useState12 = _slicedToArray(_useState11, 2),
48401
- filterHasEvents = _useState12[0],
48402
- setFilterHasEvents = _useState12[1];
48402
+ filterProvider = _useState12[0],
48403
+ setFilterProvider = _useState12[1];
48403
48404
  var _useState13 = useState("all"),
48404
48405
  _useState14 = _slicedToArray(_useState13, 2),
48405
- filterHasHandlers = _useState14[0],
48406
- setFilterHasHandlers = _useState14[1];
48406
+ filterHasEvents = _useState14[0],
48407
+ setFilterHasEvents = _useState14[1];
48408
+ var _useState15 = useState("all"),
48409
+ _useState16 = _slicedToArray(_useState15, 2),
48410
+ filterHasHandlers = _useState16[0],
48411
+ setFilterHasHandlers = _useState16[1];
48407
48412
 
48408
48413
  // Counter to trigger re-computation when installed widgets change
48409
- var _useState15 = useState(0),
48410
- _useState16 = _slicedToArray(_useState15, 2),
48411
- widgetVersion = _useState16[0],
48412
- setWidgetVersion = _useState16[1];
48414
+ var _useState17 = useState(0),
48415
+ _useState18 = _slicedToArray(_useState17, 2),
48416
+ widgetVersion = _useState18[0],
48417
+ setWidgetVersion = _useState18[1];
48413
48418
  useEffect(function () {
48414
48419
  var handleWidgetsUpdated = function handleWidgetsUpdated() {
48415
48420
  return setWidgetVersion(function (v) {
@@ -48437,10 +48442,10 @@ var WidgetSidebar = function WidgetSidebar(_ref4) {
48437
48442
 
48438
48443
  // Set of installed package identifiers for "Installed" badge in Discover tab.
48439
48444
  // Stores folder names, package names, and "author/name" keys for matching.
48440
- var _useState17 = useState(new Set()),
48441
- _useState18 = _slicedToArray(_useState17, 2),
48442
- installedPackageNames = _useState18[0],
48443
- setInstalledPackageNames = _useState18[1];
48445
+ var _useState19 = useState(new Set()),
48446
+ _useState20 = _slicedToArray(_useState19, 2),
48447
+ installedPackageNames = _useState20[0],
48448
+ setInstalledPackageNames = _useState20[1];
48444
48449
  useEffect(function () {
48445
48450
  var cancelled = false;
48446
48451
  var loadInstalled = /*#__PURE__*/function () {