@trops/dash-core 0.1.131 → 0.1.132

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
@@ -36148,6 +36148,717 @@ var ProvidersSection = function ProvidersSection(_ref) {
36148
36148
  });
36149
36149
  };
36150
36150
 
36151
+ var THEME_TAGS = ["dark", "light", "colorful", "minimal", "professional", "vibrant", "pastel", "high-contrast", "warm", "cool"];
36152
+
36153
+ /**
36154
+ * PublishThemeModal — multi-step stepper for publishing a theme
36155
+ * to the Dash Registry.
36156
+ *
36157
+ * Steps:
36158
+ * 0. Account — Auth check, sign-in prompt, profile display
36159
+ * 1. Details — Author name (pre-filled from profile) + description
36160
+ * 2. Tags — Predefined theme tag selection
36161
+ * 3. Publish — Review summary with color swatches, publish action
36162
+ */
36163
+ var PublishThemeModal = function PublishThemeModal(_ref) {
36164
+ var _result$registryResul, _result$registryResul2;
36165
+ var isOpen = _ref.isOpen,
36166
+ setIsOpen = _ref.setIsOpen,
36167
+ appId = _ref.appId,
36168
+ themeKey = _ref.themeKey,
36169
+ themeName = _ref.themeName;
36170
+ var _useContext = useContext(ThemeContext),
36171
+ currentTheme = _useContext.currentTheme;
36172
+ var panelStyles = getStylesForItem(themeObjects.PANEL, currentTheme, {
36173
+ grow: false
36174
+ });
36175
+
36176
+ // Stepper state
36177
+ var _useState = useState(0),
36178
+ _useState2 = _slicedToArray(_useState, 2),
36179
+ step = _useState2[0],
36180
+ setStep = _useState2[1];
36181
+
36182
+ // Step 0: Account / Auth
36183
+ var _useState3 = useState("loading"),
36184
+ _useState4 = _slicedToArray(_useState3, 2),
36185
+ authStatus = _useState4[0],
36186
+ setAuthStatus = _useState4[1];
36187
+ var _useState5 = useState(null),
36188
+ _useState6 = _slicedToArray(_useState5, 2),
36189
+ profile = _useState6[0],
36190
+ setProfile = _useState6[1];
36191
+ var _useState7 = useState(null),
36192
+ _useState8 = _slicedToArray(_useState7, 2),
36193
+ authFlow = _useState8[0],
36194
+ setAuthFlow = _useState8[1];
36195
+ var _useState9 = useState(false),
36196
+ _useState0 = _slicedToArray(_useState9, 2),
36197
+ isPolling = _useState0[0],
36198
+ setIsPolling = _useState0[1];
36199
+ var _useState1 = useState(null),
36200
+ _useState10 = _slicedToArray(_useState1, 2),
36201
+ authError = _useState10[0],
36202
+ setAuthError = _useState10[1];
36203
+
36204
+ // Step 1: Details
36205
+ var _useState11 = useState(""),
36206
+ _useState12 = _slicedToArray(_useState11, 2),
36207
+ authorName = _useState12[0],
36208
+ setAuthorName = _useState12[1];
36209
+ var _useState13 = useState(""),
36210
+ _useState14 = _slicedToArray(_useState13, 2),
36211
+ description = _useState14[0],
36212
+ setDescription = _useState14[1];
36213
+
36214
+ // Step 2: Tags
36215
+ var _useState15 = useState([]),
36216
+ _useState16 = _slicedToArray(_useState15, 2),
36217
+ selectedTags = _useState16[0],
36218
+ setSelectedTags = _useState16[1];
36219
+
36220
+ // Publish preview (colors)
36221
+ var _useState17 = useState(null),
36222
+ _useState18 = _slicedToArray(_useState17, 2),
36223
+ preview = _useState18[0],
36224
+ setPreview = _useState18[1];
36225
+
36226
+ // Step 3: Publish
36227
+ var _useState19 = useState(false),
36228
+ _useState20 = _slicedToArray(_useState19, 2),
36229
+ isPublishing = _useState20[0],
36230
+ setIsPublishing = _useState20[1];
36231
+ var _useState21 = useState(null),
36232
+ _useState22 = _slicedToArray(_useState21, 2),
36233
+ result = _useState22[0],
36234
+ setResult = _useState22[1];
36235
+
36236
+ // Fetch publish preview on open
36237
+ useEffect(function () {
36238
+ if (!isOpen || !appId || !themeKey) return;
36239
+ window.mainApi.themes.getThemePublishPreview(appId, themeKey).then(function (res) {
36240
+ if (res.success) setPreview(res);
36241
+ })["catch"](console.error);
36242
+ }, [isOpen, appId, themeKey]);
36243
+
36244
+ // Check auth status on mount
36245
+ useEffect(function () {
36246
+ if (!isOpen) return;
36247
+ var cancelled = false;
36248
+ function checkAuth() {
36249
+ return _checkAuth.apply(this, arguments);
36250
+ }
36251
+ function _checkAuth() {
36252
+ _checkAuth = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
36253
+ var status, userProfile;
36254
+ return _regeneratorRuntime.wrap(function (_context) {
36255
+ while (1) switch (_context.prev = _context.next) {
36256
+ case 0:
36257
+ _context.prev = 0;
36258
+ _context.next = 1;
36259
+ return window.mainApi.registryAuth.getStatus();
36260
+ case 1:
36261
+ status = _context.sent;
36262
+ if (!cancelled) {
36263
+ _context.next = 2;
36264
+ break;
36265
+ }
36266
+ return _context.abrupt("return");
36267
+ case 2:
36268
+ if (!status.authenticated) {
36269
+ _context.next = 5;
36270
+ break;
36271
+ }
36272
+ _context.next = 3;
36273
+ return window.mainApi.registryAuth.getProfile();
36274
+ case 3:
36275
+ userProfile = _context.sent;
36276
+ if (!cancelled) {
36277
+ _context.next = 4;
36278
+ break;
36279
+ }
36280
+ return _context.abrupt("return");
36281
+ case 4:
36282
+ if (userProfile) {
36283
+ setProfile(userProfile);
36284
+ setAuthStatus("authenticated");
36285
+ setAuthorName(userProfile.displayName || userProfile.username || "");
36286
+ } else {
36287
+ setAuthStatus("unauthenticated");
36288
+ }
36289
+ _context.next = 6;
36290
+ break;
36291
+ case 5:
36292
+ setAuthStatus("unauthenticated");
36293
+ case 6:
36294
+ _context.next = 8;
36295
+ break;
36296
+ case 7:
36297
+ _context.prev = 7;
36298
+ _context["catch"](0);
36299
+ if (!cancelled) setAuthStatus("unauthenticated");
36300
+ case 8:
36301
+ case "end":
36302
+ return _context.stop();
36303
+ }
36304
+ }, _callee, null, [[0, 7]]);
36305
+ }));
36306
+ return _checkAuth.apply(this, arguments);
36307
+ }
36308
+ checkAuth();
36309
+ return function () {
36310
+ cancelled = true;
36311
+ };
36312
+ }, [isOpen]);
36313
+ function resetState() {
36314
+ setStep(0);
36315
+ setAuthStatus("loading");
36316
+ setProfile(null);
36317
+ setAuthFlow(null);
36318
+ setIsPolling(false);
36319
+ setAuthError(null);
36320
+ setAuthorName("");
36321
+ setDescription("");
36322
+ setSelectedTags([]);
36323
+ setPreview(null);
36324
+ setIsPublishing(false);
36325
+ setResult(null);
36326
+ }
36327
+ function handleClose() {
36328
+ setIsOpen(false);
36329
+ setTimeout(resetState, 200);
36330
+ }
36331
+ function handleStepChange(nextStep) {
36332
+ if (step === 0 && nextStep > 0 && authStatus !== "authenticated") return;
36333
+ if (step === 1 && nextStep > 1 && !authorName.trim()) return;
36334
+ if (step === 2 && nextStep > 2 && selectedTags.length === 0) return;
36335
+ setStep(nextStep);
36336
+ }
36337
+ function toggleTag(tag) {
36338
+ setSelectedTags(function (prev) {
36339
+ return prev.includes(tag) ? prev.filter(function (t) {
36340
+ return t !== tag;
36341
+ }) : [].concat(_toConsumableArray(prev), [tag]);
36342
+ });
36343
+ }
36344
+ function handlePublish() {
36345
+ return _handlePublish.apply(this, arguments);
36346
+ }
36347
+ function _handlePublish() {
36348
+ _handlePublish = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
36349
+ var options, res, _t2;
36350
+ return _regeneratorRuntime.wrap(function (_context2) {
36351
+ while (1) switch (_context2.prev = _context2.next) {
36352
+ case 0:
36353
+ if (!(!appId || !themeKey)) {
36354
+ _context2.next = 1;
36355
+ break;
36356
+ }
36357
+ return _context2.abrupt("return");
36358
+ case 1:
36359
+ setIsPublishing(true);
36360
+ setResult(null);
36361
+ _context2.prev = 2;
36362
+ options = {
36363
+ authorName: authorName.trim(),
36364
+ description: description.trim() || undefined,
36365
+ tags: selectedTags
36366
+ };
36367
+ _context2.next = 3;
36368
+ return window.mainApi.themes.publishTheme(appId, themeKey, options);
36369
+ case 3:
36370
+ res = _context2.sent;
36371
+ setResult(res);
36372
+ _context2.next = 5;
36373
+ break;
36374
+ case 4:
36375
+ _context2.prev = 4;
36376
+ _t2 = _context2["catch"](2);
36377
+ setResult({
36378
+ success: false,
36379
+ error: _t2.message || "Failed to prepare theme for publish."
36380
+ });
36381
+ case 5:
36382
+ _context2.prev = 5;
36383
+ setIsPublishing(false);
36384
+ return _context2.finish(5);
36385
+ case 6:
36386
+ case "end":
36387
+ return _context2.stop();
36388
+ }
36389
+ }, _callee2, null, [[2, 4, 5, 6]]);
36390
+ }));
36391
+ return _handlePublish.apply(this, arguments);
36392
+ }
36393
+ function handleSignIn() {
36394
+ return _handleSignIn.apply(this, arguments);
36395
+ }
36396
+ function _handleSignIn() {
36397
+ _handleSignIn = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
36398
+ var flow, interval, poll;
36399
+ return _regeneratorRuntime.wrap(function (_context4) {
36400
+ while (1) switch (_context4.prev = _context4.next) {
36401
+ case 0:
36402
+ setAuthError(null);
36403
+ _context4.prev = 1;
36404
+ _context4.next = 2;
36405
+ return window.mainApi.registryAuth.initiateLogin();
36406
+ case 2:
36407
+ flow = _context4.sent;
36408
+ setAuthFlow(flow);
36409
+ if (flow.verificationUrlComplete) {
36410
+ window.mainApi.shell.openExternal(flow.verificationUrlComplete);
36411
+ }
36412
+ setIsPolling(true);
36413
+ interval = (flow.interval || 5) * 1000;
36414
+ poll = setInterval(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
36415
+ var pollResult, userProfile;
36416
+ return _regeneratorRuntime.wrap(function (_context3) {
36417
+ while (1) switch (_context3.prev = _context3.next) {
36418
+ case 0:
36419
+ _context3.prev = 0;
36420
+ _context3.next = 1;
36421
+ return window.mainApi.registryAuth.pollToken(flow.deviceCode);
36422
+ case 1:
36423
+ pollResult = _context3.sent;
36424
+ if (!(pollResult.status === "authorized")) {
36425
+ _context3.next = 3;
36426
+ break;
36427
+ }
36428
+ clearInterval(poll);
36429
+ setIsPolling(false);
36430
+ setAuthFlow(null);
36431
+ _context3.next = 2;
36432
+ return window.mainApi.registryAuth.getProfile();
36433
+ case 2:
36434
+ userProfile = _context3.sent;
36435
+ setProfile(userProfile);
36436
+ setAuthStatus("authenticated");
36437
+ if (userProfile !== null && userProfile !== void 0 && userProfile.displayName && !authorName) {
36438
+ setAuthorName(userProfile.displayName);
36439
+ }
36440
+ _context3.next = 4;
36441
+ break;
36442
+ case 3:
36443
+ if (pollResult.status === "expired") {
36444
+ clearInterval(poll);
36445
+ setIsPolling(false);
36446
+ setAuthFlow(null);
36447
+ }
36448
+ case 4:
36449
+ _context3.next = 6;
36450
+ break;
36451
+ case 5:
36452
+ _context3.prev = 5;
36453
+ _context3["catch"](0);
36454
+ clearInterval(poll);
36455
+ setIsPolling(false);
36456
+ case 6:
36457
+ case "end":
36458
+ return _context3.stop();
36459
+ }
36460
+ }, _callee3, null, [[0, 5]]);
36461
+ })), interval);
36462
+ _context4.next = 4;
36463
+ break;
36464
+ case 3:
36465
+ _context4.prev = 3;
36466
+ _context4["catch"](1);
36467
+ setAuthError("Could not reach the registry. Check your connection and try again.");
36468
+ case 4:
36469
+ case "end":
36470
+ return _context4.stop();
36471
+ }
36472
+ }, _callee4, null, [[1, 3]]);
36473
+ }));
36474
+ return _handleSignIn.apply(this, arguments);
36475
+ }
36476
+ function handleSignOut() {
36477
+ return _handleSignOut.apply(this, arguments);
36478
+ }
36479
+ function _handleSignOut() {
36480
+ _handleSignOut = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
36481
+ return _regeneratorRuntime.wrap(function (_context5) {
36482
+ while (1) switch (_context5.prev = _context5.next) {
36483
+ case 0:
36484
+ _context5.prev = 0;
36485
+ _context5.next = 1;
36486
+ return window.mainApi.registryAuth.logout();
36487
+ case 1:
36488
+ setAuthStatus("unauthenticated");
36489
+ setProfile(null);
36490
+ _context5.next = 3;
36491
+ break;
36492
+ case 2:
36493
+ _context5.prev = 2;
36494
+ _context5["catch"](0);
36495
+ case 3:
36496
+ case "end":
36497
+ return _context5.stop();
36498
+ }
36499
+ }, _callee5, null, [[0, 2]]);
36500
+ }));
36501
+ return _handleSignOut.apply(this, arguments);
36502
+ }
36503
+ var isLastStep = step === 3;
36504
+ var canAdvance = step === 0 ? authStatus === "authenticated" : step === 1 ? !!authorName.trim() : step === 2 ? selectedTags.length > 0 : true;
36505
+ var previewColors = (preview === null || preview === void 0 ? void 0 : preview.colors) || {};
36506
+ var colorEntries = [{
36507
+ label: "Primary",
36508
+ value: previewColors.primary
36509
+ }, {
36510
+ label: "Secondary",
36511
+ value: previewColors.secondary
36512
+ }, {
36513
+ label: "Tertiary",
36514
+ value: previewColors.tertiary
36515
+ }, {
36516
+ label: "Neutral",
36517
+ value: previewColors.neutral
36518
+ }].filter(function (c) {
36519
+ return c.value;
36520
+ });
36521
+ return /*#__PURE__*/jsx(Modal, {
36522
+ isOpen: isOpen,
36523
+ setIsOpen: handleClose,
36524
+ width: "w-full max-w-2xl",
36525
+ height: "h-[70vh]",
36526
+ children: /*#__PURE__*/jsxs("div", {
36527
+ className: "flex flex-col h-full rounded-lg overflow-clip border ".concat(panelStyles.backgroundColor || "", " ").concat(panelStyles.borderColor || "", " ").concat(panelStyles.textColor || ""),
36528
+ children: [/*#__PURE__*/jsxs("div", {
36529
+ className: "flex-shrink-0 flex flex-row items-center justify-between p-4 border-b border-white/10",
36530
+ children: [/*#__PURE__*/jsxs("span", {
36531
+ className: "text-lg font-semibold",
36532
+ children: ["Publish \"", themeName || themeKey || "Theme", "\""]
36533
+ }), /*#__PURE__*/jsx("button", {
36534
+ type: "button",
36535
+ onClick: handleClose,
36536
+ className: "opacity-50 hover:opacity-100 transition-opacity cursor-pointer",
36537
+ children: /*#__PURE__*/jsx(FontAwesomeIcon, {
36538
+ icon: "xmark",
36539
+ className: "h-5 w-5"
36540
+ })
36541
+ })]
36542
+ }), /*#__PURE__*/jsxs(Stepper, {
36543
+ activeStep: step,
36544
+ onStepChange: handleStepChange,
36545
+ showNavigation: false,
36546
+ className: "flex-1 min-h-0 flex flex-col px-6 pt-2",
36547
+ children: [/*#__PURE__*/jsx(Stepper.Step, {
36548
+ label: "Account",
36549
+ children: /*#__PURE__*/jsxs("div", {
36550
+ className: "flex-1 min-h-0 overflow-y-auto pb-4 space-y-5",
36551
+ children: [authStatus === "loading" && /*#__PURE__*/jsx("div", {
36552
+ className: "flex items-center justify-center py-12",
36553
+ children: /*#__PURE__*/jsxs("div", {
36554
+ className: "flex items-center gap-3 text-sm opacity-60",
36555
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
36556
+ icon: "spinner",
36557
+ className: "h-4 w-4 animate-spin"
36558
+ }), /*#__PURE__*/jsx("span", {
36559
+ children: "Checking account status..."
36560
+ })]
36561
+ })
36562
+ }), authStatus === "authenticated" && profile && /*#__PURE__*/jsxs("div", {
36563
+ className: "space-y-4",
36564
+ children: [/*#__PURE__*/jsx("p", {
36565
+ className: "text-sm opacity-70",
36566
+ children: "You're signed in and ready to publish."
36567
+ }), /*#__PURE__*/jsxs("div", {
36568
+ className: "bg-white/5 border border-white/10 rounded-lg p-4 flex items-center gap-4",
36569
+ children: [/*#__PURE__*/jsx("div", {
36570
+ className: "flex items-center justify-center h-10 w-10 rounded-full bg-green-500/20 border border-green-500/30",
36571
+ children: /*#__PURE__*/jsx(FontAwesomeIcon, {
36572
+ icon: "circle-check",
36573
+ className: "h-5 w-5 text-green-400"
36574
+ })
36575
+ }), /*#__PURE__*/jsxs("div", {
36576
+ className: "flex-1 min-w-0",
36577
+ children: [/*#__PURE__*/jsx("div", {
36578
+ className: "text-sm font-medium truncate",
36579
+ children: profile.displayName || profile.username
36580
+ }), /*#__PURE__*/jsxs("div", {
36581
+ className: "text-xs opacity-50 truncate",
36582
+ children: ["@", profile.username]
36583
+ })]
36584
+ })]
36585
+ }), /*#__PURE__*/jsx("button", {
36586
+ type: "button",
36587
+ onClick: handleSignOut,
36588
+ className: "text-xs opacity-40 hover:opacity-70 transition-opacity cursor-pointer",
36589
+ children: "Sign out"
36590
+ })]
36591
+ }), authStatus === "unauthenticated" && /*#__PURE__*/jsxs("div", {
36592
+ className: "space-y-4",
36593
+ children: [/*#__PURE__*/jsx("p", {
36594
+ className: "text-sm opacity-70",
36595
+ children: "Sign in to the Dash Registry to publish your theme."
36596
+ }), !authFlow && !isPolling && /*#__PURE__*/jsxs(Fragment, {
36597
+ children: [/*#__PURE__*/jsx("button", {
36598
+ type: "button",
36599
+ onClick: handleSignIn,
36600
+ 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",
36601
+ children: "Sign in to Registry"
36602
+ }), authError && /*#__PURE__*/jsx("div", {
36603
+ className: "bg-red-500/10 border border-red-500/20 rounded-lg p-3",
36604
+ children: /*#__PURE__*/jsxs("div", {
36605
+ className: "flex items-start gap-2",
36606
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
36607
+ icon: "circle-xmark",
36608
+ className: "h-3.5 w-3.5 text-red-400 mt-0.5 flex-shrink-0"
36609
+ }), /*#__PURE__*/jsx("span", {
36610
+ className: "text-xs text-red-300/90",
36611
+ children: authError
36612
+ })]
36613
+ })
36614
+ })]
36615
+ }), authFlow && isPolling && /*#__PURE__*/jsxs("div", {
36616
+ className: "bg-blue-500/10 border border-blue-500/20 rounded-lg p-4 space-y-3",
36617
+ children: [/*#__PURE__*/jsx("p", {
36618
+ className: "text-xs text-blue-300/90",
36619
+ children: "Enter this code in your browser:"
36620
+ }), /*#__PURE__*/jsx("div", {
36621
+ className: "text-center",
36622
+ children: /*#__PURE__*/jsx("span", {
36623
+ className: "text-2xl font-mono font-bold tracking-widest text-white",
36624
+ children: authFlow.userCode
36625
+ })
36626
+ }), /*#__PURE__*/jsx("p", {
36627
+ className: "text-xs text-blue-300/70 text-center",
36628
+ children: "Waiting for authorization..."
36629
+ })]
36630
+ })]
36631
+ })]
36632
+ })
36633
+ }), /*#__PURE__*/jsx(Stepper.Step, {
36634
+ label: "Details",
36635
+ children: /*#__PURE__*/jsxs("div", {
36636
+ className: "flex-1 min-h-0 overflow-y-auto pb-4 space-y-5",
36637
+ children: [/*#__PURE__*/jsx("p", {
36638
+ className: "text-sm opacity-70",
36639
+ children: "Provide details about your theme for the registry listing."
36640
+ }), /*#__PURE__*/jsxs("div", {
36641
+ children: [/*#__PURE__*/jsx("label", {
36642
+ className: "block text-sm font-medium opacity-70 mb-1",
36643
+ children: "Author Name"
36644
+ }), /*#__PURE__*/jsx("div", {
36645
+ className: "px-3 py-2 rounded-lg bg-white/5 border border-white/10 text-sm opacity-80",
36646
+ children: authorName || "\u2014"
36647
+ })]
36648
+ }), colorEntries.length > 0 && /*#__PURE__*/jsxs("div", {
36649
+ children: [/*#__PURE__*/jsx("label", {
36650
+ className: "block text-sm font-medium opacity-70 mb-2",
36651
+ children: "Theme Colors"
36652
+ }), /*#__PURE__*/jsx("div", {
36653
+ className: "flex flex-row gap-3",
36654
+ children: colorEntries.map(function (_ref2) {
36655
+ var label = _ref2.label,
36656
+ value = _ref2.value;
36657
+ return /*#__PURE__*/jsxs("div", {
36658
+ className: "flex flex-col items-center gap-1",
36659
+ children: [/*#__PURE__*/jsx("div", {
36660
+ className: "h-8 w-8 rounded-full border-2 border-white/20",
36661
+ style: {
36662
+ backgroundColor: value
36663
+ }
36664
+ }), /*#__PURE__*/jsx("span", {
36665
+ className: "text-[10px] opacity-50",
36666
+ children: label
36667
+ })]
36668
+ }, label);
36669
+ })
36670
+ })]
36671
+ }), /*#__PURE__*/jsx(TextArea, {
36672
+ label: "Description",
36673
+ value: description,
36674
+ onChange: setDescription,
36675
+ placeholder: "A brief description of this theme...",
36676
+ rows: 3
36677
+ })]
36678
+ })
36679
+ }), /*#__PURE__*/jsx(Stepper.Step, {
36680
+ label: "Tags",
36681
+ children: /*#__PURE__*/jsxs("div", {
36682
+ className: "flex-1 min-h-0 overflow-y-auto pb-4 space-y-5",
36683
+ children: [/*#__PURE__*/jsx("p", {
36684
+ className: "text-sm opacity-70",
36685
+ children: "Select at least one tag to categorize your theme."
36686
+ }), /*#__PURE__*/jsx("div", {
36687
+ className: "grid grid-cols-3 gap-2",
36688
+ children: THEME_TAGS.map(function (tag) {
36689
+ var isSelected = selectedTags.includes(tag);
36690
+ return /*#__PURE__*/jsx("button", {
36691
+ type: "button",
36692
+ onClick: function onClick() {
36693
+ return toggleTag(tag);
36694
+ },
36695
+ className: "px-3 py-1.5 rounded-full text-sm border transition-colors cursor-pointer ".concat(isSelected ? "bg-white/15 border-white/30 text-white" : "bg-transparent border-white/10 text-white/60 hover:border-white/20 hover:text-white/80"),
36696
+ children: tag
36697
+ }, tag);
36698
+ })
36699
+ })]
36700
+ })
36701
+ }), /*#__PURE__*/jsx(Stepper.Step, {
36702
+ label: "Publish",
36703
+ children: /*#__PURE__*/jsx("div", {
36704
+ className: "flex-1 min-h-0 overflow-y-auto pb-4 space-y-4",
36705
+ children: !result ? /*#__PURE__*/jsxs(Fragment, {
36706
+ children: [/*#__PURE__*/jsx("p", {
36707
+ className: "text-sm opacity-70",
36708
+ children: "Review your theme details before publishing."
36709
+ }), /*#__PURE__*/jsxs("div", {
36710
+ className: "bg-white/5 border border-white/10 rounded-lg p-4 space-y-2 text-sm",
36711
+ children: [/*#__PURE__*/jsxs("div", {
36712
+ className: "flex gap-2",
36713
+ children: [/*#__PURE__*/jsx("span", {
36714
+ className: "opacity-50 w-20 flex-shrink-0",
36715
+ children: "Author"
36716
+ }), /*#__PURE__*/jsx("span", {
36717
+ children: authorName
36718
+ })]
36719
+ }), description.trim() && /*#__PURE__*/jsxs("div", {
36720
+ className: "flex gap-2",
36721
+ children: [/*#__PURE__*/jsx("span", {
36722
+ className: "opacity-50 w-20 flex-shrink-0",
36723
+ children: "Description"
36724
+ }), /*#__PURE__*/jsx("span", {
36725
+ children: description
36726
+ })]
36727
+ }), /*#__PURE__*/jsxs("div", {
36728
+ className: "flex gap-2",
36729
+ children: [/*#__PURE__*/jsx("span", {
36730
+ className: "opacity-50 w-20 flex-shrink-0",
36731
+ children: "Tags"
36732
+ }), /*#__PURE__*/jsx("span", {
36733
+ children: selectedTags.length > 0 ? selectedTags.join(", ") : "None"
36734
+ })]
36735
+ }), colorEntries.length > 0 && /*#__PURE__*/jsxs("div", {
36736
+ className: "flex gap-2 items-center",
36737
+ children: [/*#__PURE__*/jsx("span", {
36738
+ className: "opacity-50 w-20 flex-shrink-0",
36739
+ children: "Colors"
36740
+ }), /*#__PURE__*/jsx("div", {
36741
+ className: "flex gap-1.5",
36742
+ children: colorEntries.map(function (_ref3) {
36743
+ var label = _ref3.label,
36744
+ value = _ref3.value;
36745
+ return /*#__PURE__*/jsx("div", {
36746
+ className: "h-5 w-5 rounded-full border border-white/20",
36747
+ style: {
36748
+ backgroundColor: value
36749
+ },
36750
+ title: "".concat(label, ": ").concat(value)
36751
+ }, label);
36752
+ })
36753
+ })]
36754
+ })]
36755
+ })]
36756
+ }) : result.success ? /*#__PURE__*/jsxs("div", {
36757
+ className: "space-y-3",
36758
+ children: [(_result$registryResul = result.registryResult) !== null && _result$registryResul !== void 0 && _result$registryResul.success ? /*#__PURE__*/jsxs("div", {
36759
+ className: "space-y-3",
36760
+ children: [/*#__PURE__*/jsxs("div", {
36761
+ className: "flex items-center gap-2",
36762
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
36763
+ icon: "circle-check",
36764
+ className: "h-4 w-4 text-green-400"
36765
+ }), /*#__PURE__*/jsx("span", {
36766
+ className: "text-sm",
36767
+ children: "Published to Dash Registry"
36768
+ })]
36769
+ }), result.registryResult.registryUrl && /*#__PURE__*/jsxs("div", {
36770
+ className: "bg-white/5 border border-white/10 rounded-lg p-3",
36771
+ children: [/*#__PURE__*/jsx("div", {
36772
+ className: "text-xs opacity-50 mb-1",
36773
+ children: "Shareable Link"
36774
+ }), /*#__PURE__*/jsx("button", {
36775
+ type: "button",
36776
+ onClick: function onClick() {
36777
+ return window.mainApi.shell.openExternal(result.registryResult.registryUrl);
36778
+ },
36779
+ className: "text-sm text-blue-400 hover:underline cursor-pointer break-all text-left",
36780
+ children: result.registryResult.registryUrl
36781
+ })]
36782
+ })]
36783
+ }) : /*#__PURE__*/jsxs("div", {
36784
+ className: "space-y-3",
36785
+ children: [/*#__PURE__*/jsxs("div", {
36786
+ className: "flex items-center gap-2",
36787
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
36788
+ icon: "circle-check",
36789
+ className: "h-4 w-4 text-green-400"
36790
+ }), /*#__PURE__*/jsx("span", {
36791
+ className: "text-sm",
36792
+ children: "Theme prepared for publishing."
36793
+ })]
36794
+ }), ((_result$registryResul2 = result.registryResult) === null || _result$registryResul2 === void 0 ? void 0 : _result$registryResul2.error) && /*#__PURE__*/jsx("div", {
36795
+ className: "bg-amber-500/10 border border-amber-500/20 rounded-lg p-3",
36796
+ children: /*#__PURE__*/jsxs("div", {
36797
+ className: "flex items-start gap-2",
36798
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
36799
+ icon: "triangle-exclamation",
36800
+ className: "h-3.5 w-3.5 text-amber-400 mt-0.5 flex-shrink-0"
36801
+ }), /*#__PURE__*/jsxs("span", {
36802
+ className: "text-xs text-amber-300/90",
36803
+ children: ["Registry upload failed:", " ", result.registryResult.error, ". Your theme was saved locally."]
36804
+ })]
36805
+ })
36806
+ })]
36807
+ }), result.filePath && /*#__PURE__*/jsxs("div", {
36808
+ className: "text-xs opacity-50 break-all",
36809
+ children: ["Saved to: ", result.filePath]
36810
+ })]
36811
+ }) : /*#__PURE__*/jsxs("div", {
36812
+ className: "flex items-center gap-2",
36813
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
36814
+ icon: "circle-xmark",
36815
+ className: "h-4 w-4 text-red-400"
36816
+ }), /*#__PURE__*/jsx("span", {
36817
+ className: "text-sm text-red-400",
36818
+ children: result.error || "Publish preparation failed."
36819
+ })]
36820
+ })
36821
+ })
36822
+ })]
36823
+ }), /*#__PURE__*/jsxs("div", {
36824
+ className: "flex-shrink-0 flex flex-row items-center px-6 py-4 border-t border-white/10",
36825
+ children: [/*#__PURE__*/jsx("div", {
36826
+ className: "flex flex-row gap-2",
36827
+ children: /*#__PURE__*/jsx(Button3, {
36828
+ title: step === 0 ? "Cancel" : "Back",
36829
+ onClick: step === 0 ? handleClose : function () {
36830
+ return setStep(step - 1);
36831
+ },
36832
+ disabled: isPublishing
36833
+ })
36834
+ }), /*#__PURE__*/jsx("div", {
36835
+ className: "flex-1 text-center",
36836
+ children: /*#__PURE__*/jsxs("span", {
36837
+ className: "text-xs opacity-40",
36838
+ children: ["Step ", step + 1, " of 4"]
36839
+ })
36840
+ }), /*#__PURE__*/jsx("div", {
36841
+ className: "flex flex-row gap-2",
36842
+ children: result !== null && result !== void 0 && result.success ? /*#__PURE__*/jsx(Button2, {
36843
+ title: "Done",
36844
+ onClick: handleClose
36845
+ }) : isLastStep ? /*#__PURE__*/jsx(Button2, {
36846
+ title: isPublishing ? "Publishing..." : "Publish",
36847
+ onClick: handlePublish,
36848
+ disabled: isPublishing
36849
+ }) : /*#__PURE__*/jsx(Button2, {
36850
+ title: "Next",
36851
+ onClick: function onClick() {
36852
+ return handleStepChange(step + 1);
36853
+ },
36854
+ disabled: !canAdvance
36855
+ })
36856
+ })]
36857
+ })]
36858
+ })
36859
+ });
36860
+ };
36861
+
36151
36862
  var TOKEN_TYPES = ["bg", "text", "border"];
36152
36863
 
36153
36864
  // --- Color Swatch Grid ---
@@ -36326,8 +37037,15 @@ var ThemeDetail = function ThemeDetail(_ref6) {
36326
37037
  onActivate = _ref6.onActivate,
36327
37038
  onOpenThemeEditor = _ref6.onOpenThemeEditor,
36328
37039
  _ref6$onDelete = _ref6.onDelete,
36329
- onDelete = _ref6$onDelete === void 0 ? null : _ref6$onDelete;
37040
+ onDelete = _ref6$onDelete === void 0 ? null : _ref6$onDelete,
37041
+ _ref6$appId = _ref6.appId,
37042
+ appId = _ref6$appId === void 0 ? null : _ref6$appId;
36330
37043
  var theme = themeKey && themes ? themes[themeKey] : null;
37044
+ var _useState = useState(false),
37045
+ _useState2 = _slicedToArray(_useState, 2),
37046
+ publishOpen = _useState2[0],
37047
+ setPublishOpen = _useState2[1];
37048
+ var canPublish = theme && !theme._registryMeta;
36331
37049
  var displayTheme = useMemo(function () {
36332
37050
  return theme ? theme[themeVariant] || {} : {};
36333
37051
  }, [theme, themeVariant]);
@@ -36394,28 +37112,440 @@ var ThemeDetail = function ThemeDetail(_ref6) {
36394
37112
  })]
36395
37113
  }), /*#__PURE__*/jsxs("div", {
36396
37114
  className: "flex-shrink-0 flex flex-row justify-between px-6 py-4 border-t border-white/10",
37115
+ children: [/*#__PURE__*/jsxs("div", {
37116
+ className: "flex flex-row gap-2",
37117
+ children: [!isActive && onDelete && /*#__PURE__*/jsx(Button, {
37118
+ title: "Delete",
37119
+ onClick: function onClick() {
37120
+ return onDelete(themeKey);
37121
+ },
37122
+ size: "sm"
37123
+ }), canPublish && /*#__PURE__*/jsx(Button, {
37124
+ title: "Publish",
37125
+ onClick: function onClick() {
37126
+ return setPublishOpen(true);
37127
+ },
37128
+ size: "sm"
37129
+ })]
37130
+ }), /*#__PURE__*/jsxs("div", {
37131
+ className: "flex flex-row gap-2",
37132
+ children: [!isActive && /*#__PURE__*/jsx(Button, {
37133
+ title: "Activate",
37134
+ onClick: function onClick() {
37135
+ return onActivate(themeKey);
37136
+ },
37137
+ size: "sm"
37138
+ }), /*#__PURE__*/jsx(Button, {
37139
+ title: "Edit",
37140
+ onClick: onOpenThemeEditor,
37141
+ size: "sm"
37142
+ })]
37143
+ })]
37144
+ }), canPublish && /*#__PURE__*/jsx(PublishThemeModal, {
37145
+ isOpen: publishOpen,
37146
+ setIsOpen: setPublishOpen,
37147
+ appId: appId,
37148
+ themeKey: themeKey,
37149
+ themeName: theme.name || themeKey
37150
+ })]
37151
+ });
37152
+ };
37153
+
37154
+ var RegistryThemeDetail = function RegistryThemeDetail(_ref) {
37155
+ var themePackage = _ref.themePackage,
37156
+ appId = _ref.appId,
37157
+ onInstallComplete = _ref.onInstallComplete;
37158
+ var _useContext = useContext(ThemeContext),
37159
+ currentTheme = _useContext.currentTheme,
37160
+ changeThemesForApplication = _useContext.changeThemesForApplication;
37161
+ var panelStyles = getStylesForItem(themeObjects.PANEL, currentTheme, {
37162
+ grow: false
37163
+ });
37164
+ var _useState = useState(false),
37165
+ _useState2 = _slicedToArray(_useState, 2),
37166
+ isInstalling = _useState2[0],
37167
+ setIsInstalling = _useState2[1];
37168
+ var _useState3 = useState(null),
37169
+ _useState4 = _slicedToArray(_useState3, 2),
37170
+ installResult = _useState4[0],
37171
+ setInstallResult = _useState4[1];
37172
+ var pkg = themePackage;
37173
+ if (!pkg) return null;
37174
+ var colors = pkg.colors || {};
37175
+ function handleInstall() {
37176
+ return _handleInstall.apply(this, arguments);
37177
+ }
37178
+ function _handleInstall() {
37179
+ _handleInstall = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
37180
+ var result, _t;
37181
+ return _regeneratorRuntime.wrap(function (_context) {
37182
+ while (1) switch (_context.prev = _context.next) {
37183
+ case 0:
37184
+ if (!(!appId || !pkg.name)) {
37185
+ _context.next = 1;
37186
+ break;
37187
+ }
37188
+ return _context.abrupt("return");
37189
+ case 1:
37190
+ setIsInstalling(true);
37191
+ setInstallResult(null);
37192
+ _context.prev = 2;
37193
+ _context.next = 3;
37194
+ return window.mainApi.themes.installThemeFromRegistry(appId, pkg.name);
37195
+ case 3:
37196
+ result = _context.sent;
37197
+ setInstallResult({
37198
+ status: result !== null && result !== void 0 && result.success ? "success" : "error",
37199
+ message: result !== null && result !== void 0 && result.success ? "Theme \"".concat(result.themeKey || pkg.displayName || pkg.name, "\" installed successfully.") : (result === null || result === void 0 ? void 0 : result.error) || "Installation failed."
37200
+ });
37201
+ if (result !== null && result !== void 0 && result.success) {
37202
+ // Refresh ThemeContext with updated themes
37203
+ if (result.themes) {
37204
+ changeThemesForApplication(result.themes);
37205
+ }
37206
+ if (onInstallComplete) {
37207
+ onInstallComplete(result);
37208
+ }
37209
+ }
37210
+ _context.next = 5;
37211
+ break;
37212
+ case 4:
37213
+ _context.prev = 4;
37214
+ _t = _context["catch"](2);
37215
+ setInstallResult({
37216
+ status: "error",
37217
+ message: _t.message || "Failed to install theme."
37218
+ });
37219
+ case 5:
37220
+ _context.prev = 5;
37221
+ setIsInstalling(false);
37222
+ return _context.finish(5);
37223
+ case 6:
37224
+ case "end":
37225
+ return _context.stop();
37226
+ }
37227
+ }, _callee, null, [[2, 4, 5, 6]]);
37228
+ }));
37229
+ return _handleInstall.apply(this, arguments);
37230
+ }
37231
+ var colorEntries = [{
37232
+ label: "Primary",
37233
+ value: colors.primary
37234
+ }, {
37235
+ label: "Secondary",
37236
+ value: colors.secondary
37237
+ }, {
37238
+ label: "Tertiary",
37239
+ value: colors.tertiary
37240
+ }, {
37241
+ label: "Neutral",
37242
+ value: colors.neutral
37243
+ }].filter(function (c) {
37244
+ return c.value;
37245
+ });
37246
+ return /*#__PURE__*/jsxs("div", {
37247
+ className: "flex flex-col flex-1 min-h-0",
37248
+ children: [/*#__PURE__*/jsxs("div", {
37249
+ className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-6 ".concat(panelStyles.textColor || "text-gray-200"),
37250
+ children: [/*#__PURE__*/jsxs("div", {
37251
+ className: "flex flex-row items-center gap-3",
37252
+ children: [/*#__PURE__*/jsx("div", {
37253
+ className: "h-5 w-5 flex-shrink-0 flex items-center justify-center",
37254
+ children: /*#__PURE__*/jsx(FontAwesomeIcon, {
37255
+ icon: "palette",
37256
+ className: "h-5 w-5"
37257
+ })
37258
+ }), /*#__PURE__*/jsxs("div", {
37259
+ children: [/*#__PURE__*/jsx(SubHeading3, {
37260
+ title: pkg.displayName || pkg.name,
37261
+ padding: false
37262
+ }), /*#__PURE__*/jsxs("div", {
37263
+ className: "flex items-center gap-2 mt-0.5",
37264
+ children: [/*#__PURE__*/jsxs("span", {
37265
+ className: "text-sm opacity-60",
37266
+ children: ["by ", pkg.author || "Unknown"]
37267
+ }), pkg.version && /*#__PURE__*/jsxs("span", {
37268
+ className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-70"),
37269
+ children: ["v", pkg.version]
37270
+ })]
37271
+ })]
37272
+ })]
37273
+ }), /*#__PURE__*/jsx("hr", {
37274
+ className: currentTheme["border-primary-medium"]
37275
+ }), colorEntries.length > 0 && /*#__PURE__*/jsxs("div", {
37276
+ children: [/*#__PURE__*/jsx("span", {
37277
+ className: "text-xs font-semibold opacity-50 mb-2 block",
37278
+ children: "COLORS"
37279
+ }), /*#__PURE__*/jsx("div", {
37280
+ className: "flex flex-row gap-3",
37281
+ children: colorEntries.map(function (_ref2) {
37282
+ var label = _ref2.label,
37283
+ value = _ref2.value;
37284
+ return /*#__PURE__*/jsxs("div", {
37285
+ className: "flex flex-col items-center gap-1",
37286
+ children: [/*#__PURE__*/jsx("div", {
37287
+ className: "h-10 w-10 rounded-full border-2 border-white/20",
37288
+ style: {
37289
+ backgroundColor: value
37290
+ }
37291
+ }), /*#__PURE__*/jsx("span", {
37292
+ className: "text-[10px] opacity-50",
37293
+ children: label
37294
+ }), /*#__PURE__*/jsx("span", {
37295
+ className: "text-[10px] opacity-30 font-mono",
37296
+ children: value
37297
+ })]
37298
+ }, label);
37299
+ })
37300
+ })]
37301
+ }), pkg.description && /*#__PURE__*/jsx("p", {
37302
+ className: "text-sm",
37303
+ children: pkg.description
37304
+ }), pkg.tags && pkg.tags.length > 0 && /*#__PURE__*/jsx("div", {
37305
+ className: "flex flex-wrap gap-1",
37306
+ children: pkg.tags.map(function (tag) {
37307
+ return /*#__PURE__*/jsx("span", {
37308
+ className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-60"),
37309
+ children: tag
37310
+ }, tag);
37311
+ })
37312
+ }), installResult && /*#__PURE__*/jsx("div", {
37313
+ className: "p-2 rounded border ".concat(installResult.status === "success" ? "bg-green-900/20 border-green-700" : "bg-red-900/30 border-red-700"),
37314
+ children: /*#__PURE__*/jsxs("div", {
37315
+ className: "flex items-center gap-2",
37316
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
37317
+ icon: installResult.status === "success" ? "circle-check" : "circle-xmark",
37318
+ className: "h-4 w-4 ".concat(installResult.status === "success" ? "text-green-400" : "text-red-400")
37319
+ }), /*#__PURE__*/jsx("span", {
37320
+ className: "text-sm ".concat(installResult.status === "error" ? "text-red-400" : ""),
37321
+ children: installResult.message
37322
+ })]
37323
+ })
37324
+ })]
37325
+ }), (installResult === null || installResult === void 0 ? void 0 : installResult.status) !== "success" && /*#__PURE__*/jsx("div", {
37326
+ className: "flex items-center justify-end px-6 py-3 border-t ".concat(currentTheme["border-primary-medium"]),
37327
+ children: /*#__PURE__*/jsx(Button, {
37328
+ title: isInstalling ? "Installing..." : "Install Theme",
37329
+ bgColor: "bg-blue-600",
37330
+ hoverBackgroundColor: isInstalling ? "" : "hover:bg-blue-700",
37331
+ textSize: "text-sm",
37332
+ padding: "py-1.5 px-4",
37333
+ onClick: handleInstall,
37334
+ disabled: isInstalling
37335
+ })
37336
+ })]
37337
+ });
37338
+ };
37339
+
37340
+ var DiscoverThemesDetail = function DiscoverThemesDetail(_ref) {
37341
+ var onBack = _ref.onBack,
37342
+ appId = _ref.appId,
37343
+ onInstallComplete = _ref.onInstallComplete;
37344
+ var _useContext = useContext(ThemeContext),
37345
+ currentTheme = _useContext.currentTheme;
37346
+ var panelStyles = getStylesForItem(themeObjects.PANEL, currentTheme, {
37347
+ grow: false
37348
+ });
37349
+ var _useState = useState([]),
37350
+ _useState2 = _slicedToArray(_useState, 2),
37351
+ packages = _useState2[0],
37352
+ setPackages = _useState2[1];
37353
+ var _useState3 = useState(false),
37354
+ _useState4 = _slicedToArray(_useState3, 2),
37355
+ isLoading = _useState4[0],
37356
+ setIsLoading = _useState4[1];
37357
+ var _useState5 = useState(null),
37358
+ _useState6 = _slicedToArray(_useState5, 2),
37359
+ error = _useState6[0],
37360
+ setError = _useState6[1];
37361
+ var _useState7 = useState(""),
37362
+ _useState8 = _slicedToArray(_useState7, 2),
37363
+ searchQuery = _useState8[0],
37364
+ setSearchQuery = _useState8[1];
37365
+ var _useState9 = useState(null),
37366
+ _useState0 = _slicedToArray(_useState9, 2),
37367
+ selectedPackageName = _useState0[0],
37368
+ setSelectedPackageName = _useState0[1];
37369
+ var search = useCallback(/*#__PURE__*/function () {
37370
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(query) {
37371
+ var _window$mainApi;
37372
+ var result, _t;
37373
+ return _regeneratorRuntime.wrap(function (_context) {
37374
+ while (1) switch (_context.prev = _context.next) {
37375
+ case 0:
37376
+ if ((_window$mainApi = window.mainApi) !== null && _window$mainApi !== void 0 && (_window$mainApi = _window$mainApi.registry) !== null && _window$mainApi !== void 0 && _window$mainApi.searchThemes) {
37377
+ _context.next = 1;
37378
+ break;
37379
+ }
37380
+ setPackages([]);
37381
+ return _context.abrupt("return");
37382
+ case 1:
37383
+ setIsLoading(true);
37384
+ setError(null);
37385
+ _context.prev = 2;
37386
+ _context.next = 3;
37387
+ return window.mainApi.registry.searchThemes(query || "", {});
37388
+ case 3:
37389
+ result = _context.sent;
37390
+ setPackages((result === null || result === void 0 ? void 0 : result.packages) || []);
37391
+ _context.next = 5;
37392
+ break;
37393
+ case 4:
37394
+ _context.prev = 4;
37395
+ _t = _context["catch"](2);
37396
+ setError(_t.message || "Failed to search theme registry");
37397
+ setPackages([]);
37398
+ case 5:
37399
+ _context.prev = 5;
37400
+ setIsLoading(false);
37401
+ return _context.finish(5);
37402
+ case 6:
37403
+ case "end":
37404
+ return _context.stop();
37405
+ }
37406
+ }, _callee, null, [[2, 4, 5, 6]]);
37407
+ }));
37408
+ return function (_x) {
37409
+ return _ref2.apply(this, arguments);
37410
+ };
37411
+ }(), []);
37412
+
37413
+ // Debounce search on query changes
37414
+ useEffect(function () {
37415
+ var timer = setTimeout(function () {
37416
+ search(searchQuery);
37417
+ }, 300);
37418
+ return function () {
37419
+ return clearTimeout(timer);
37420
+ };
37421
+ // eslint-disable-next-line react-hooks/exhaustive-deps
37422
+ }, [searchQuery]);
37423
+ var retry = function retry() {
37424
+ return search(searchQuery);
37425
+ };
37426
+ var selectedPackage = selectedPackageName ? packages.find(function (p) {
37427
+ return p.name === selectedPackageName;
37428
+ }) : null;
37429
+
37430
+ // If a package is selected, show its detail inline
37431
+ if (selectedPackage) {
37432
+ return /*#__PURE__*/jsxs("div", {
37433
+ className: "flex flex-col flex-1 min-h-0",
36397
37434
  children: [/*#__PURE__*/jsx("div", {
36398
- children: !isActive && onDelete && /*#__PURE__*/jsx(Button, {
36399
- title: "Delete",
37435
+ className: "flex-shrink-0 px-4 pt-4",
37436
+ children: /*#__PURE__*/jsxs("button", {
37437
+ type: "button",
36400
37438
  onClick: function onClick() {
36401
- return onDelete(themeKey);
37439
+ return setSelectedPackageName(null);
36402
37440
  },
36403
- size: "sm"
37441
+ className: "flex items-center gap-1.5 text-sm opacity-60 hover:opacity-100 transition-opacity",
37442
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
37443
+ icon: "arrow-left",
37444
+ className: "h-3 w-3"
37445
+ }), /*#__PURE__*/jsx("span", {
37446
+ children: "Back"
37447
+ })]
36404
37448
  })
36405
- }), /*#__PURE__*/jsxs("div", {
36406
- className: "flex flex-row gap-2",
36407
- children: [!isActive && /*#__PURE__*/jsx(Button, {
36408
- title: "Activate",
37449
+ }), /*#__PURE__*/jsx(RegistryThemeDetail, {
37450
+ themePackage: selectedPackage,
37451
+ appId: appId,
37452
+ onInstallComplete: onInstallComplete
37453
+ })]
37454
+ });
37455
+ }
37456
+
37457
+ // Package list view
37458
+ var listBody;
37459
+ if (isLoading) {
37460
+ listBody = /*#__PURE__*/jsx("div", {
37461
+ className: "flex items-center justify-center py-12",
37462
+ children: /*#__PURE__*/jsxs("div", {
37463
+ className: "text-center",
37464
+ children: [/*#__PURE__*/jsx("div", {
37465
+ className: "animate-spin rounded-full h-6 w-6 border-b-2 border-blue-500 mx-auto mb-3"
37466
+ }), /*#__PURE__*/jsx(Paragraph, {
37467
+ className: "text-sm opacity-50",
37468
+ children: "Loading themes..."
37469
+ })]
37470
+ })
37471
+ });
37472
+ } else if (error) {
37473
+ listBody = /*#__PURE__*/jsxs("div", {
37474
+ className: "px-4 py-8 text-center",
37475
+ children: [/*#__PURE__*/jsx(Paragraph, {
37476
+ className: "text-sm text-red-400 mb-3",
37477
+ children: error
37478
+ }), /*#__PURE__*/jsx(Button, {
37479
+ title: "Retry",
37480
+ bgColor: "bg-gray-700",
37481
+ hoverBackgroundColor: "hover:bg-gray-600",
37482
+ textSize: "text-sm",
37483
+ padding: "py-1 px-3",
37484
+ onClick: retry
37485
+ })]
37486
+ });
37487
+ } else if (packages.length === 0) {
37488
+ listBody = /*#__PURE__*/jsx("div", {
37489
+ className: "px-4 py-8 text-center",
37490
+ children: /*#__PURE__*/jsx(Paragraph, {
37491
+ className: "text-sm opacity-50",
37492
+ children: searchQuery ? "No themes match your search." : "No theme packages available."
37493
+ })
37494
+ });
37495
+ } else {
37496
+ listBody = /*#__PURE__*/jsx("div", {
37497
+ className: "space-y-1",
37498
+ children: packages.map(function (pkg) {
37499
+ var colors = pkg.colors || {};
37500
+ return /*#__PURE__*/jsx(Sidebar.Item, {
37501
+ icon: /*#__PURE__*/jsx("div", {
37502
+ className: "flex items-center gap-0.5",
37503
+ children: [colors.primary, colors.secondary, colors.tertiary].filter(Boolean).map(function (color, i) {
37504
+ return /*#__PURE__*/jsx("div", {
37505
+ className: "h-3 w-3 rounded-full border border-white/20",
37506
+ style: {
37507
+ backgroundColor: color
37508
+ }
37509
+ }, i);
37510
+ })
37511
+ }),
36409
37512
  onClick: function onClick() {
36410
- return onActivate(themeKey);
37513
+ return setSelectedPackageName(pkg.name);
36411
37514
  },
36412
- size: "sm"
36413
- }), /*#__PURE__*/jsx(Button, {
36414
- title: "Edit",
36415
- onClick: onOpenThemeEditor,
36416
- size: "sm"
37515
+ children: pkg.displayName || pkg.name
37516
+ }, pkg.name);
37517
+ })
37518
+ });
37519
+ }
37520
+ return /*#__PURE__*/jsxs("div", {
37521
+ className: "flex flex-col flex-1 min-h-0 ".concat(panelStyles.textColor || "text-gray-200"),
37522
+ children: [/*#__PURE__*/jsx("div", {
37523
+ className: "flex-shrink-0 px-4 pt-4",
37524
+ children: /*#__PURE__*/jsxs("button", {
37525
+ type: "button",
37526
+ onClick: onBack,
37527
+ className: "flex items-center gap-1.5 text-sm opacity-60 hover:opacity-100 transition-opacity",
37528
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
37529
+ icon: "arrow-left",
37530
+ className: "h-3 w-3"
37531
+ }), /*#__PURE__*/jsx("span", {
37532
+ children: "Back"
36417
37533
  })]
36418
- })]
37534
+ })
37535
+ }), /*#__PURE__*/jsx("div", {
37536
+ className: "flex-shrink-0 px-4 py-3",
37537
+ children: /*#__PURE__*/jsx(SearchInput, {
37538
+ value: searchQuery,
37539
+ onChange: setSearchQuery,
37540
+ placeholder: "Search themes...",
37541
+ inputClassName: "py-1.5 text-xs"
37542
+ })
37543
+ }), /*#__PURE__*/jsx("div", {
37544
+ className: "flex-1 min-h-0 overflow-y-auto px-2",
37545
+ children: listBody
37546
+ }), !isLoading && !error && packages.length > 0 && /*#__PURE__*/jsxs("div", {
37547
+ className: "flex-shrink-0 px-4 py-2 text-[10px] opacity-40 border-t border-white/10",
37548
+ children: [packages.length, " theme", packages.length !== 1 ? "s" : ""]
36419
37549
  })]
36420
37550
  });
36421
37551
  };
@@ -36461,18 +37591,31 @@ var ThemesSection = function ThemesSection(_ref) {
36461
37591
  _useState0 = _slicedToArray(_useState9, 2),
36462
37592
  wizardTheme = _useState0[0],
36463
37593
  setWizardTheme = _useState0[1];
37594
+ // null | "marketplace"
37595
+ var _useState1 = useState(null),
37596
+ _useState10 = _slicedToArray(_useState1, 2),
37597
+ installMode = _useState10[0],
37598
+ setInstallMode = _useState10[1];
36464
37599
  var themeEntries = themes ? Object.entries(themes) : [];
36465
37600
  var appId = credentials === null || credentials === void 0 ? void 0 : credentials.appId;
37601
+ var rowStyles = getStylesForItem(themeObjects.PANEL_HEADER, currentTheme, {
37602
+ grow: false
37603
+ });
36466
37604
 
36467
37605
  // Handle create request from parent — enter wizard mode
37606
+ var prevCreateRequested = useRef(false);
36468
37607
  useEffect(function () {
36469
- if (createRequested) {
37608
+ if (createRequested && !prevCreateRequested.current) {
36470
37609
  setGenerateMode(GENERATE_MODES.WIZARD);
36471
37610
  setWizardName("");
36472
37611
  setWizardMethod(null);
36473
37612
  setWizardTheme(null);
36474
37613
  setSelectedThemeKey(null);
36475
- onCreateAcknowledged && onCreateAcknowledged();
37614
+ setInstallMode(null);
37615
+ }
37616
+ prevCreateRequested.current = createRequested;
37617
+ if (createRequested && onCreateAcknowledged) {
37618
+ onCreateAcknowledged();
36476
37619
  }
36477
37620
  // eslint-disable-next-line react-hooks/exhaustive-deps
36478
37621
  }, [createRequested]);
@@ -36543,63 +37686,109 @@ var ThemesSection = function ThemesSection(_ref) {
36543
37686
  function handleEdit() {
36544
37687
  if (onOpenThemeEditor) onOpenThemeEditor();
36545
37688
  }
36546
- var rowStyles = getStylesForItem(themeObjects.PANEL_HEADER, currentTheme, {
36547
- grow: false
36548
- });
36549
37689
  var listContent = /*#__PURE__*/jsxs("div", {
36550
- className: "flex flex-col",
37690
+ className: "flex flex-col h-full",
36551
37691
  children: [/*#__PURE__*/jsxs("div", {
36552
- className: "flex flex-row items-center justify-between px-3 py-3 border-b ".concat(rowStyles.borderColor || ""),
37692
+ className: "flex-shrink-0 flex flex-col gap-2 px-3 py-2 ".concat(rowStyles.backgroundColor || ""),
36553
37693
  children: [/*#__PURE__*/jsxs("div", {
36554
- className: "flex flex-row items-center gap-2",
36555
- children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
36556
- icon: "sun",
36557
- className: "h-3 w-3 opacity-50"
36558
- }), /*#__PURE__*/jsx(Switch, {
36559
- checked: themeVariant === "dark",
36560
- onChange: handleToggleVariant
36561
- }), /*#__PURE__*/jsx(FontAwesomeIcon, {
36562
- icon: "moon",
36563
- className: "h-3 w-3 opacity-50"
37694
+ className: "flex flex-row items-center justify-between",
37695
+ children: [/*#__PURE__*/jsxs("div", {
37696
+ className: "flex flex-row items-center gap-2",
37697
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
37698
+ icon: "sun",
37699
+ className: "h-3 w-3 opacity-50"
37700
+ }), /*#__PURE__*/jsx(Switch, {
37701
+ checked: themeVariant === "dark",
37702
+ onChange: handleToggleVariant
37703
+ }), /*#__PURE__*/jsx(FontAwesomeIcon, {
37704
+ icon: "moon",
37705
+ className: "h-3 w-3 opacity-50"
37706
+ })]
37707
+ }), /*#__PURE__*/jsx("span", {
37708
+ className: "text-xs opacity-50",
37709
+ children: themeVariant === "dark" ? "Dark" : "Light"
36564
37710
  })]
36565
- }), /*#__PURE__*/jsx("span", {
36566
- className: "text-xs opacity-50",
36567
- children: themeVariant === "dark" ? "Dark" : "Light"
36568
- })]
36569
- }), /*#__PURE__*/jsxs(Sidebar.Content, {
36570
- children: [themeEntries.map(function (_ref4) {
36571
- var _ref5 = _slicedToArray(_ref4, 2),
36572
- key = _ref5[0],
36573
- theme = _ref5[1];
36574
- var isActive = key === currentThemeKey;
36575
- var isSelected = selectedThemeKey === key && generateMode === GENERATE_MODES.NONE;
36576
- return /*#__PURE__*/jsx(Sidebar.Item, {
36577
- icon: isActive ? /*#__PURE__*/jsx(FontAwesomeIcon, {
36578
- icon: "check",
36579
- className: "h-3 w-3 text-green-500"
36580
- }) : /*#__PURE__*/jsx(FontAwesomeIcon, {
36581
- icon: "palette",
36582
- className: "h-3.5 w-3.5"
36583
- }),
36584
- active: isSelected,
36585
- onClick: function onClick() {
36586
- setSelectedThemeKey(key);
36587
- setGenerateMode(GENERATE_MODES.NONE);
36588
- },
36589
- badge: isActive ? "active" : null,
36590
- className: isSelected ? "bg-white/10 opacity-100" : "",
36591
- children: theme.name || key
36592
- }, key);
36593
- }), themeEntries.length === 0 && /*#__PURE__*/jsx("span", {
36594
- className: "text-sm opacity-40 py-8 text-center",
36595
- children: "No themes available"
37711
+ }), /*#__PURE__*/jsx("div", {
37712
+ className: "flex bg-white/5 rounded-md p-0.5",
37713
+ children: [{
37714
+ key: "themes",
37715
+ label: "My Themes"
37716
+ }, {
37717
+ key: "marketplace",
37718
+ label: "Marketplace"
37719
+ }].map(function (tab) {
37720
+ var currentTab = installMode === "marketplace" ? "marketplace" : "themes";
37721
+ return /*#__PURE__*/jsx("button", {
37722
+ type: "button",
37723
+ onClick: function onClick() {
37724
+ if (tab.key === "marketplace") {
37725
+ setInstallMode("marketplace");
37726
+ setSelectedThemeKey(null);
37727
+ setGenerateMode(GENERATE_MODES.NONE);
37728
+ } else {
37729
+ setInstallMode(null);
37730
+ }
37731
+ },
37732
+ className: "flex-1 px-2 py-0.5 rounded text-[11px] transition-colors ".concat(currentTab === tab.key ? "bg-white/10 font-medium opacity-90" : "opacity-50 hover:opacity-70"),
37733
+ children: tab.label
37734
+ }, tab.key);
37735
+ })
36596
37736
  })]
37737
+ }), /*#__PURE__*/jsx("div", {
37738
+ className: "flex-1 overflow-y-auto min-h-0",
37739
+ children: /*#__PURE__*/jsxs(Sidebar.Content, {
37740
+ children: [themeEntries.map(function (_ref4) {
37741
+ var _ref5 = _slicedToArray(_ref4, 2),
37742
+ key = _ref5[0],
37743
+ theme = _ref5[1];
37744
+ var isActive = key === currentThemeKey;
37745
+ var isSelected = selectedThemeKey === key && generateMode === GENERATE_MODES.NONE && installMode !== "marketplace";
37746
+ return /*#__PURE__*/jsx(Sidebar.Item, {
37747
+ icon: isActive ? /*#__PURE__*/jsx(FontAwesomeIcon, {
37748
+ icon: "check",
37749
+ className: "h-3 w-3 text-green-500"
37750
+ }) : /*#__PURE__*/jsx(FontAwesomeIcon, {
37751
+ icon: "palette",
37752
+ className: "h-3.5 w-3.5"
37753
+ }),
37754
+ active: isSelected,
37755
+ onClick: function onClick() {
37756
+ setSelectedThemeKey(key);
37757
+ setGenerateMode(GENERATE_MODES.NONE);
37758
+ setInstallMode(null);
37759
+ },
37760
+ badge: isActive ? "active" : null,
37761
+ className: isSelected ? "bg-white/10 opacity-100" : "",
37762
+ children: theme.name || key
37763
+ }, key);
37764
+ }), themeEntries.length === 0 && /*#__PURE__*/jsx("span", {
37765
+ className: "text-sm opacity-40 py-8 text-center",
37766
+ children: "No themes available"
37767
+ })]
37768
+ })
36597
37769
  })]
36598
37770
  });
36599
37771
 
36600
37772
  // Determine detail content based on mode
36601
37773
  var detailContent = null;
36602
- if (generateMode === GENERATE_MODES.WIZARD) {
37774
+ if (installMode === "marketplace") {
37775
+ detailContent = /*#__PURE__*/jsx(DiscoverThemesDetail, {
37776
+ onBack: function onBack() {
37777
+ setInstallMode(null);
37778
+ },
37779
+ appId: appId,
37780
+ onInstallComplete: function onInstallComplete() {
37781
+ // Refresh themes after install
37782
+ if (dashApi && appId) {
37783
+ dashApi.listThemes(appId, function (e, message) {
37784
+ if (message && message.themes) {
37785
+ changeThemesForApplication(message.themes);
37786
+ }
37787
+ });
37788
+ }
37789
+ }
37790
+ });
37791
+ } else if (generateMode === GENERATE_MODES.WIZARD) {
36603
37792
  detailContent = /*#__PURE__*/jsx(ThemeQuickCreate, {
36604
37793
  wizardName: wizardName,
36605
37794
  setWizardName: setWizardName,
@@ -36625,7 +37814,8 @@ var ThemesSection = function ThemesSection(_ref) {
36625
37814
  themeVariant: themeVariant,
36626
37815
  onActivate: handleActivate,
36627
37816
  onOpenThemeEditor: handleEdit,
36628
- onDelete: handleDeleteTheme
37817
+ onDelete: handleDeleteTheme,
37818
+ appId: appId
36629
37819
  });
36630
37820
  }
36631
37821
  return /*#__PURE__*/jsx(SectionLayout, {