@trops/dash-core 0.1.268 → 0.1.270

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -23127,6 +23127,465 @@ var WidgetHelpers = /*#__PURE__*/function () {
23127
23127
  }]);
23128
23128
  }();
23129
23129
 
23130
+ var RegistryPackageDetail = function RegistryPackageDetail(_ref) {
23131
+ var widget = _ref.widget,
23132
+ onInstall = _ref.onInstall,
23133
+ _ref$isInstalling = _ref.isInstalling,
23134
+ isInstalling = _ref$isInstalling === void 0 ? false : _ref$isInstalling,
23135
+ _ref$installError = _ref.installError,
23136
+ installError = _ref$installError === void 0 ? null : _ref$installError,
23137
+ _ref$isInstalled = _ref.isInstalled,
23138
+ isInstalled = _ref$isInstalled === void 0 ? false : _ref$isInstalled,
23139
+ _ref$showAuth = _ref.showAuth,
23140
+ showAuth = _ref$showAuth === void 0 ? false : _ref$showAuth,
23141
+ _ref$onAuthSuccess = _ref.onAuthSuccess,
23142
+ onAuthSuccess = _ref$onAuthSuccess === void 0 ? null : _ref$onAuthSuccess,
23143
+ _ref$onAuthCancel = _ref.onAuthCancel,
23144
+ onAuthCancel = _ref$onAuthCancel === void 0 ? null : _ref$onAuthCancel;
23145
+ var _useContext = React.useContext(DashReact.ThemeContext),
23146
+ currentTheme = _useContext.currentTheme;
23147
+ var panelStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL, currentTheme, {
23148
+ grow: false
23149
+ });
23150
+ if (!widget) return null;
23151
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
23152
+ className: "flex flex-col flex-1 min-h-0",
23153
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
23154
+ className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-6 ".concat(panelStyles.textColor || "text-gray-200"),
23155
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
23156
+ className: "flex flex-row items-center gap-3",
23157
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
23158
+ className: "h-5 w-5 flex-shrink-0 flex items-center justify-center",
23159
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23160
+ icon: widget.icon || "cube",
23161
+ className: "h-5 w-5"
23162
+ })
23163
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
23164
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
23165
+ className: "flex items-center gap-2",
23166
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
23167
+ title: widget.packageDisplayName,
23168
+ padding: false
23169
+ }), isInstalled && /*#__PURE__*/jsxRuntime.jsx("span", {
23170
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-emerald-500/20 text-emerald-400 flex-shrink-0",
23171
+ children: "Installed"
23172
+ })]
23173
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
23174
+ className: "flex items-center gap-2 mt-0.5",
23175
+ children: [/*#__PURE__*/jsxRuntime.jsxs("span", {
23176
+ className: "text-sm opacity-60",
23177
+ children: ["by ", widget.packageAuthor || "Unknown"]
23178
+ }), /*#__PURE__*/jsxRuntime.jsxs("span", {
23179
+ className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-70"),
23180
+ children: ["v", widget.packageVersion]
23181
+ })]
23182
+ })]
23183
+ })]
23184
+ }), /*#__PURE__*/jsxRuntime.jsx("hr", {
23185
+ className: currentTheme["border-primary-medium"]
23186
+ }), widget.packageDescription && /*#__PURE__*/jsxRuntime.jsx("p", {
23187
+ className: "text-sm",
23188
+ children: widget.packageDescription
23189
+ }), widget.packageTags && widget.packageTags.length > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
23190
+ className: "flex flex-wrap gap-1",
23191
+ children: widget.packageTags.map(function (tag) {
23192
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
23193
+ className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-60"),
23194
+ children: tag
23195
+ }, tag);
23196
+ })
23197
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
23198
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
23199
+ className: "text-xs font-semibold opacity-50 mb-1 block",
23200
+ children: "INCLUDED WIDGETS"
23201
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
23202
+ className: "space-y-1.5",
23203
+ children: (widget.packageWidgets || []).map(function (w, idx) {
23204
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
23205
+ className: "p-2 rounded ".concat(currentTheme["bg-primary-medium"]),
23206
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
23207
+ className: "text-sm font-medium",
23208
+ children: w.displayName || w.name
23209
+ }), w.description && /*#__PURE__*/jsxRuntime.jsx("div", {
23210
+ className: "text-xs opacity-50 mt-0.5",
23211
+ children: w.description
23212
+ }), getUserConfigurableProviders(w.providers).length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
23213
+ className: "space-y-1 mt-1",
23214
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
23215
+ className: "flex gap-1 flex-wrap",
23216
+ children: getUserConfigurableProviders(w.providers).map(function (p, pidx) {
23217
+ return /*#__PURE__*/jsxRuntime.jsxs("span", {
23218
+ className: "text-xs px-1.5 py-0.5 rounded bg-blue-900/30 text-blue-400",
23219
+ children: [p.type, p.required ? " *" : ""]
23220
+ }, pidx);
23221
+ })
23222
+ }), getUserConfigurableProviders(w.providers).some(function (p) {
23223
+ var _p$requiredTools;
23224
+ return ((_p$requiredTools = p.requiredTools) === null || _p$requiredTools === void 0 ? void 0 : _p$requiredTools.length) > 0;
23225
+ }) && /*#__PURE__*/jsxRuntime.jsx("div", {
23226
+ className: "flex flex-wrap gap-1 ml-1",
23227
+ children: getUserConfigurableProviders(w.providers).filter(function (p) {
23228
+ var _p$requiredTools2;
23229
+ return ((_p$requiredTools2 = p.requiredTools) === null || _p$requiredTools2 === void 0 ? void 0 : _p$requiredTools2.length) > 0;
23230
+ }).flatMap(function (p) {
23231
+ return p.requiredTools.map(function (tool) {
23232
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
23233
+ className: "text-[10px] font-mono px-1.5 py-0.5 rounded bg-white/5 opacity-60",
23234
+ children: tool
23235
+ }, "".concat(p.type, "-").concat(tool));
23236
+ });
23237
+ })
23238
+ })]
23239
+ })]
23240
+ }, idx);
23241
+ })
23242
+ })]
23243
+ }), widget.appOrigin && /*#__PURE__*/jsxRuntime.jsxs("div", {
23244
+ className: "flex items-center gap-1.5 text-xs opacity-50",
23245
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23246
+ icon: "laptop",
23247
+ className: "h-3 w-3"
23248
+ }), /*#__PURE__*/jsxRuntime.jsxs("span", {
23249
+ children: ["Built for ", widget.appOrigin]
23250
+ })]
23251
+ }), widget.missingApis && widget.missingApis.length > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
23252
+ className: "p-2 rounded bg-yellow-900/30 border border-yellow-700",
23253
+ children: /*#__PURE__*/jsxRuntime.jsxs("p", {
23254
+ className: "text-xs text-yellow-400",
23255
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23256
+ icon: "triangle-exclamation",
23257
+ className: "mr-1"
23258
+ }), "Incompatible \u2014 requires ", widget.missingApis.join(", "), " API", widget.missingApis.length !== 1 ? "s" : ""]
23259
+ })
23260
+ }), widget.repository && /*#__PURE__*/jsxRuntime.jsxs("div", {
23261
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
23262
+ className: "text-xs font-semibold opacity-50 mb-1 block",
23263
+ children: "REPOSITORY"
23264
+ }), /*#__PURE__*/jsxRuntime.jsx("button", {
23265
+ type: "button",
23266
+ onClick: function onClick() {
23267
+ var _window$mainApi;
23268
+ return (_window$mainApi = window.mainApi) === null || _window$mainApi === void 0 || (_window$mainApi = _window$mainApi.shell) === null || _window$mainApi === void 0 ? void 0 : _window$mainApi.openExternal(widget.repository);
23269
+ },
23270
+ className: "text-sm text-blue-400 hover:text-blue-300 hover:underline transition-colors break-all text-left",
23271
+ children: widget.repository
23272
+ })]
23273
+ }), installError && /*#__PURE__*/jsxRuntime.jsx("div", {
23274
+ className: "p-2 rounded bg-red-900/30 border border-red-700",
23275
+ children: /*#__PURE__*/jsxRuntime.jsx("p", {
23276
+ className: "text-xs text-red-400",
23277
+ children: installError
23278
+ })
23279
+ })]
23280
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
23281
+ className: "flex items-center justify-end px-6 py-3 border-t ".concat(currentTheme["border-primary-medium"]),
23282
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
23283
+ title: isInstalled ? "Installed" : isInstalling ? "Installing..." : "Install Package",
23284
+ bgColor: isInstalled ? "bg-emerald-600/50" : "bg-blue-600",
23285
+ hoverBackgroundColor: isInstalled || isInstalling ? "" : "hover:bg-blue-700",
23286
+ textSize: "text-sm",
23287
+ padding: "py-1.5 px-4",
23288
+ onClick: onInstall,
23289
+ disabled: isInstalling || isInstalled
23290
+ })
23291
+ }), /*#__PURE__*/jsxRuntime.jsx(RegistryAuthModal, {
23292
+ isOpen: showAuth,
23293
+ setIsOpen: function setIsOpen(open) {
23294
+ if (!open && onAuthCancel) onAuthCancel();
23295
+ },
23296
+ onAuthenticated: onAuthSuccess,
23297
+ onCancel: onAuthCancel,
23298
+ message: "Sign in to install this widget from the Dash Registry."
23299
+ })]
23300
+ });
23301
+ };
23302
+
23303
+ /**
23304
+ * Extract a search query from a widget component key.
23305
+ *
23306
+ * Scoped IDs look like "scope.packageName.WidgetName" — we can do an exact
23307
+ * package lookup with the middle segment. Plain names are just the widget
23308
+ * class name, so we fall back to a search.
23309
+ */
23310
+ function getWidgetSearchQuery(componentKey) {
23311
+ var parts = componentKey.split(".");
23312
+ if (parts.length >= 3) {
23313
+ return {
23314
+ packageName: parts[1],
23315
+ widgetName: parts[2],
23316
+ scope: parts[0]
23317
+ };
23318
+ }
23319
+ return {
23320
+ packageName: null,
23321
+ widgetName: componentKey,
23322
+ scope: null
23323
+ };
23324
+ }
23325
+
23326
+ /**
23327
+ * Convert a raw registry package object into the flat widget shape
23328
+ * expected by RegistryPackageDetail.
23329
+ */
23330
+ function packageToFlatWidget(pkg) {
23331
+ return {
23332
+ key: "".concat(pkg.name, "/0"),
23333
+ name: pkg.displayName || pkg.name,
23334
+ icon: pkg.icon || null,
23335
+ isRegistry: true,
23336
+ packageName: pkg.name,
23337
+ packageScope: pkg.scope || null,
23338
+ packageDisplayName: pkg.displayName || pkg.name,
23339
+ packageVersion: pkg.version,
23340
+ packageAuthor: pkg.author || "",
23341
+ packageDescription: pkg.description || "",
23342
+ packageTags: pkg.tags || [],
23343
+ packageCategory: pkg.category || "",
23344
+ downloadUrl: pkg.downloadUrl || "",
23345
+ repository: pkg.repository || "",
23346
+ publishedAt: pkg.publishedAt || "",
23347
+ packageWidgets: pkg.widgets || [],
23348
+ appOrigin: pkg.appOrigin || null,
23349
+ packageProviders: pkg.providers || [],
23350
+ missingApis: []
23351
+ };
23352
+ }
23353
+
23354
+ var WidgetNotFound = function WidgetNotFound(_ref) {
23355
+ var component = _ref.component;
23356
+ var _useState = React.useState(false),
23357
+ _useState2 = _slicedToArray(_useState, 2),
23358
+ showModal = _useState2[0],
23359
+ setShowModal = _useState2[1];
23360
+ var _useState3 = React.useState(null),
23361
+ _useState4 = _slicedToArray(_useState3, 2),
23362
+ registryWidget = _useState4[0],
23363
+ setRegistryWidget = _useState4[1];
23364
+ var _useState5 = React.useState(false),
23365
+ _useState6 = _slicedToArray(_useState5, 2),
23366
+ isLoading = _useState6[0],
23367
+ setIsLoading = _useState6[1];
23368
+ var _useState7 = React.useState(false),
23369
+ _useState8 = _slicedToArray(_useState7, 2),
23370
+ notFound = _useState8[0],
23371
+ setNotFound = _useState8[1];
23372
+ var _useState9 = React.useState(false),
23373
+ _useState0 = _slicedToArray(_useState9, 2),
23374
+ isInstalling = _useState0[0],
23375
+ setIsInstalling = _useState0[1];
23376
+ var _useState1 = React.useState(null),
23377
+ _useState10 = _slicedToArray(_useState1, 2),
23378
+ installError = _useState10[0],
23379
+ setInstallError = _useState10[1];
23380
+ var _useState11 = React.useState(false),
23381
+ _useState12 = _slicedToArray(_useState11, 2),
23382
+ needsAuth = _useState12[0],
23383
+ setNeedsAuth = _useState12[1];
23384
+ var lookupWidget = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
23385
+ var _getWidgetSearchQuery, packageName, widgetName, pkg, result;
23386
+ return _regeneratorRuntime.wrap(function (_context) {
23387
+ while (1) switch (_context.prev = _context.next) {
23388
+ case 0:
23389
+ setShowModal(true);
23390
+ setIsLoading(true);
23391
+ setNotFound(false);
23392
+ setRegistryWidget(null);
23393
+ setInstallError(null);
23394
+ setNeedsAuth(false);
23395
+ _getWidgetSearchQuery = getWidgetSearchQuery(component), packageName = _getWidgetSearchQuery.packageName, widgetName = _getWidgetSearchQuery.widgetName;
23396
+ _context.prev = 1;
23397
+ pkg = null; // Scoped ID — exact package lookup
23398
+ if (!packageName) {
23399
+ _context.next = 3;
23400
+ break;
23401
+ }
23402
+ _context.next = 2;
23403
+ return window.mainApi.registry.getPackage(packageName);
23404
+ case 2:
23405
+ pkg = _context.sent;
23406
+ case 3:
23407
+ if (pkg) {
23408
+ _context.next = 5;
23409
+ break;
23410
+ }
23411
+ _context.next = 4;
23412
+ return window.mainApi.registry.search(widgetName);
23413
+ case 4:
23414
+ result = _context.sent;
23415
+ pkg = (result.packages || []).find(function (p) {
23416
+ return (p.widgets || []).some(function (w) {
23417
+ return w.name === widgetName;
23418
+ });
23419
+ });
23420
+ case 5:
23421
+ if (pkg) {
23422
+ setRegistryWidget(packageToFlatWidget(pkg));
23423
+ } else {
23424
+ setNotFound(true);
23425
+ }
23426
+ _context.next = 7;
23427
+ break;
23428
+ case 6:
23429
+ _context.prev = 6;
23430
+ _context["catch"](1);
23431
+ setNotFound(true);
23432
+ case 7:
23433
+ setIsLoading(false);
23434
+ case 8:
23435
+ case "end":
23436
+ return _context.stop();
23437
+ }
23438
+ }, _callee, null, [[1, 6]]);
23439
+ })), [component]);
23440
+ var handleInstall = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
23441
+ var _window$mainApi, status, packageName, packageScope, downloadUrl, packageVersion, scopedId, resolvedUrl, msg, _t3;
23442
+ return _regeneratorRuntime.wrap(function (_context2) {
23443
+ while (1) switch (_context2.prev = _context2.next) {
23444
+ case 0:
23445
+ if (registryWidget) {
23446
+ _context2.next = 1;
23447
+ break;
23448
+ }
23449
+ return _context2.abrupt("return");
23450
+ case 1:
23451
+ setIsInstalling(true);
23452
+ setInstallError(null);
23453
+ setNeedsAuth(false);
23454
+ _context2.prev = 2;
23455
+ _context2.prev = 3;
23456
+ _context2.next = 4;
23457
+ 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();
23458
+ case 4:
23459
+ status = _context2.sent;
23460
+ if (status !== null && status !== void 0 && status.authenticated) {
23461
+ _context2.next = 5;
23462
+ break;
23463
+ }
23464
+ setNeedsAuth(true);
23465
+ setIsInstalling(false);
23466
+ return _context2.abrupt("return");
23467
+ case 5:
23468
+ _context2.next = 7;
23469
+ break;
23470
+ case 6:
23471
+ _context2.prev = 6;
23472
+ _context2["catch"](3);
23473
+ case 7:
23474
+ packageName = registryWidget.packageName, packageScope = registryWidget.packageScope, downloadUrl = registryWidget.downloadUrl, packageVersion = registryWidget.packageVersion;
23475
+ scopedId = packageScope ? "@".concat(packageScope.replace(/^@/, ""), "/").concat(packageName) : packageName;
23476
+ resolvedUrl = downloadUrl.replace(/\{version\}/g, packageVersion).replace(/\{name\}/g, packageName);
23477
+ _context2.next = 8;
23478
+ return window.mainApi.widgets.install(scopedId, resolvedUrl);
23479
+ case 8:
23480
+ setShowModal(false);
23481
+ _context2.next = 10;
23482
+ break;
23483
+ case 9:
23484
+ _context2.prev = 9;
23485
+ _t3 = _context2["catch"](2);
23486
+ msg = _t3.message || "Failed to install package";
23487
+ if (msg.toLowerCase().includes("unauthorized")) {
23488
+ setNeedsAuth(true);
23489
+ } else {
23490
+ setInstallError(msg);
23491
+ }
23492
+ case 10:
23493
+ setIsInstalling(false);
23494
+ case 11:
23495
+ case "end":
23496
+ return _context2.stop();
23497
+ }
23498
+ }, _callee2, null, [[2, 9], [3, 6]]);
23499
+ })), [registryWidget]);
23500
+ var handleAuthSuccess = React.useCallback(function () {
23501
+ setNeedsAuth(false);
23502
+ handleInstall();
23503
+ }, [handleInstall]);
23504
+ var handleClose = React.useCallback(function () {
23505
+ setShowModal(false);
23506
+ }, []);
23507
+ return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
23508
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
23509
+ className: "flex flex-col h-full justify-center items-center w-full z-10 gap-2 p-4 text-center",
23510
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23511
+ icon: "triangle-exclamation",
23512
+ className: "h-6 w-6 text-amber-500"
23513
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
23514
+ className: "text-sm font-semibold text-gray-300",
23515
+ children: "Widget Not Found"
23516
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
23517
+ className: "text-xs text-gray-500 font-mono",
23518
+ children: component
23519
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
23520
+ className: "text-xs text-gray-600 mt-1",
23521
+ children: "This widget may have been uninstalled or renamed."
23522
+ }), /*#__PURE__*/jsxRuntime.jsxs("button", {
23523
+ type: "button",
23524
+ className: "flex items-center gap-1.5 text-xs text-blue-400 hover:text-blue-300 transition-colors mt-2",
23525
+ onClick: lookupWidget,
23526
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23527
+ icon: "magnifying-glass",
23528
+ className: "h-3 w-3"
23529
+ }), "Find in Registry"]
23530
+ })]
23531
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Modal, {
23532
+ isOpen: showModal,
23533
+ setIsOpen: setShowModal,
23534
+ width: "w-1/3",
23535
+ height: "auto",
23536
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
23537
+ className: "relative",
23538
+ children: [/*#__PURE__*/jsxRuntime.jsx("button", {
23539
+ type: "button",
23540
+ className: "absolute top-3 right-3 z-10 text-gray-500 hover:text-gray-300 transition-colors",
23541
+ onClick: handleClose,
23542
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23543
+ icon: "xmark",
23544
+ className: "h-4 w-4"
23545
+ })
23546
+ }), isLoading && /*#__PURE__*/jsxRuntime.jsx("div", {
23547
+ className: "flex items-center justify-center p-12",
23548
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23549
+ icon: "spinner",
23550
+ className: "h-5 w-5 text-gray-400 animate-spin"
23551
+ })
23552
+ }), !isLoading && registryWidget && /*#__PURE__*/jsxRuntime.jsx(RegistryPackageDetail, {
23553
+ widget: registryWidget,
23554
+ onInstall: handleInstall,
23555
+ isInstalling: isInstalling,
23556
+ installError: installError
23557
+ }), !isLoading && notFound && /*#__PURE__*/jsxRuntime.jsxs("div", {
23558
+ className: "flex flex-col items-center justify-center gap-3 p-12 text-center",
23559
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23560
+ icon: "triangle-exclamation",
23561
+ className: "h-6 w-6 text-amber-500"
23562
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
23563
+ className: "text-sm text-gray-400",
23564
+ children: "This widget is not available in the registry."
23565
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
23566
+ title: "Close",
23567
+ bgColor: "bg-gray-600",
23568
+ hoverBackgroundColor: "hover:bg-gray-700",
23569
+ textSize: "text-sm",
23570
+ padding: "py-1.5 px-4",
23571
+ onClick: handleClose
23572
+ })]
23573
+ })]
23574
+ })
23575
+ }), /*#__PURE__*/jsxRuntime.jsx(RegistryAuthModal, {
23576
+ isOpen: needsAuth && !!registryWidget,
23577
+ setIsOpen: function setIsOpen(open) {
23578
+ if (!open) setNeedsAuth(false);
23579
+ },
23580
+ onAuthenticated: handleAuthSuccess,
23581
+ onCancel: function onCancel() {
23582
+ return setNeedsAuth(false);
23583
+ },
23584
+ message: "Sign in to install this widget from the Dash Registry."
23585
+ })]
23586
+ });
23587
+ };
23588
+
23130
23589
  function ownKeys$q(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
23131
23590
  function _objectSpread$q(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$q(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$q(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
23132
23591
  function _callSuper$2(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$2() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
@@ -23217,728 +23676,277 @@ var WidgetRenderer = function WidgetRenderer(_ref) {
23217
23676
  var _ComponentManager$get;
23218
23677
  var isLayout = ComponentManager.isLayoutContainer(component);
23219
23678
  // grab the component from the map
23220
- var WidgetComponent = isLayout === false ? m[component]["component"] : (_ComponentManager$get = ComponentManager.getComponent(component)) === null || _ComponentManager$get === void 0 ? void 0 : _ComponentManager$get.component;
23679
+ var WidgetComponent = (_ComponentManager$get = ComponentManager.getComponent(component)) === null || _ComponentManager$get === void 0 ? void 0 : _ComponentManager$get.component;
23221
23680
 
23222
23681
  // get the config details from the .dash file
23223
23682
  var config = ComponentManager.config(component, params);
23224
23683
  var styles = null;
23225
23684
  // if the config is not null, then we can check for styles
23226
23685
  if (config !== null && config !== undefined) {
23227
- // check to see if the config has styles
23228
- // if it does, then we can use those styles
23229
- // otherwise, we will use the default styles
23230
- // styles will be an object with the styles for the widget
23231
- // and set the styles from the config if they exist
23232
- styles = "styles" in config ? config["styles"] : null;
23233
- }
23234
-
23235
- // user input for the customization of the widget
23236
- var userPrefs = params["userPrefs"];
23237
-
23238
- // Check to make sure this is a Component
23239
- if (typeof WidgetComponent !== "function") return null;
23240
- if (isLayout === false) {
23241
- params["width"] = "w-full";
23242
- }
23243
- if ("width" in params === false) {
23244
- params["width"] = "w-full";
23245
- }
23246
- params["componentName"] = component;
23247
-
23248
- // init will inject the params from the widget into the widgetAPI
23249
- // widgetApi.init(params);
23250
-
23251
- var bgColor = "";
23252
- if (styles !== null) {
23253
- bgColor = "backgroundColor" in styles ? styles["backgroundColor"] : "";
23254
- }
23255
-
23256
- // Build widgetData for WidgetContext — hooks read from this
23257
- var uuidString = DashReact.getUUID(params.uuid);
23258
- var widgetData = _objectSpread$q(_objectSpread$q({}, params), {}, {
23259
- uuidString: uuidString,
23260
- providers: (config === null || config === void 0 ? void 0 : config.providers) || [],
23261
- notifications: (config === null || config === void 0 ? void 0 : config.notifications) || []
23262
- });
23263
-
23264
- // need to set the electron api here.
23265
- var w = WidgetApi;
23266
- w.init({
23267
- id: widgetKey,
23268
- name: component
23269
- });
23270
- w.setElectronApi(dashApi);
23271
- w.setPublisher(DashboardPublisher);
23272
-
23273
- // init the helpers — pass WidgetApi (which has publishEvent/registerListeners
23274
- // that delegate to DashboardPublisher), not the raw Electron dashApi
23275
- var helpers = new WidgetHelpers(params, w);
23276
-
23277
- // Memoize context value to prevent unnecessary re-renders
23278
- var widgetContextValue = {
23279
- widgetData: widgetData
23280
- };
23281
- var hasScheduledTasks = ((config === null || config === void 0 ? void 0 : config.scheduledTasks) || []).length > 0;
23282
- var widgetElement = children === null ? /*#__PURE__*/jsxRuntime.jsx(WidgetComponent, _objectSpread$q(_objectSpread$q(_objectSpread$q({
23283
- id: "widget-nokids-".concat(widgetKey),
23284
- listen: function listen(listeners, handlers) {
23285
- return helpers.listen(listeners, handlers);
23286
- },
23287
- publishEvent: function publishEvent(eventName, payload) {
23288
- return helpers.publishEvent(eventName, payload);
23289
- },
23290
- api: w
23291
- }, params), userPrefs), {}, {
23292
- backgroundColor: bgColor,
23293
- widgetConfig: helpers.config(),
23294
- widgetEventNames: helpers.events()
23295
- }), "widget-nokids-".concat(widgetKey)) : /*#__PURE__*/jsxRuntime.jsx(WidgetComponent, _objectSpread$q(_objectSpread$q(_objectSpread$q({
23296
- listen: function listen(listeners, handlers) {
23297
- return helpers.listen(listeners, handlers);
23298
- },
23299
- publishEvent: function publishEvent(eventName, payload) {
23300
- return helpers.publishEvent(eventName, payload);
23301
- },
23302
- api: w,
23303
- id: "widget-kids-".concat(widgetKey)
23304
- }, params), userPrefs), {}, {
23305
- backgroundColor: bgColor,
23306
- children: children
23307
- }), "widget-kids-".concat(widgetKey));
23308
-
23309
- // Wrap widget rendering with WidgetContext + error boundary
23310
- return /*#__PURE__*/jsxRuntime.jsx(WidgetContext.Provider, {
23311
- value: widgetContextValue,
23312
- children: /*#__PURE__*/jsxRuntime.jsx(WidgetErrorBoundary, {
23313
- widgetName: component,
23314
- children: hasScheduledTasks ? /*#__PURE__*/jsxRuntime.jsxs("div", {
23315
- className: "flex flex-col w-full h-full min-h-0",
23316
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
23317
- className: "flex-1 min-h-0 overflow-auto",
23318
- children: widgetElement
23319
- }), /*#__PURE__*/jsxRuntime.jsx(WidgetCardStatusBar, {
23320
- item: params
23321
- })]
23322
- }) : widgetElement
23323
- })
23324
- });
23325
- }
23326
- } catch (e) {
23327
- return null;
23328
- }
23329
- return null;
23330
- };
23331
-
23332
- /**
23333
- * WidgetFactory
23334
- * Get the "component" and params and dynamically generate the Component
23335
- */
23336
- var WidgetFactory = {
23337
- getComponent: function getComponent(component) {
23338
- try {
23339
- return ComponentManager.getComponent(component);
23340
- } catch (e) {
23341
- return null;
23342
- }
23343
- },
23344
- render: function render(component, key) {
23345
- var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
23346
- var children = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
23347
- return /*#__PURE__*/jsxRuntime.jsx(WidgetRenderer, {
23348
- component: component,
23349
- widgetKey: key,
23350
- params: params,
23351
- children: children
23352
- });
23353
- },
23354
- renderChildren: function renderChildren(children) {
23355
- return React.Children.map(children, function (el) {
23356
- return el;
23357
- // const clonedComponent = React.cloneElement(el);
23358
- // return clonedComponent;
23359
- });
23360
- },
23361
- /**
23362
- * config
23363
- * Get the developer's component configuration and enhance that configuration with
23364
- * required fields if they are not present
23365
- *
23366
- * @param {object} component
23367
- * @returns
23368
- */
23369
- config: function config(component) {
23370
- if (component) {
23371
- var requiredFields = {
23372
- type: {
23373
- value: "text"
23374
- },
23375
- required: {
23376
- value: false
23377
- },
23378
- options: {
23379
- value: []
23380
- },
23381
- defaultValue: {
23382
- value: ""
23383
- },
23384
- events: [] // events that will be published
23385
- };
23386
-
23387
- // get the component configuration from the map
23388
- var components = ComponentManager.map();
23389
-
23390
- // let c = deepCopy(components['component']);
23391
- var c = JSON.parse(JSON.stringify(components[component]));
23392
- c["component"] = component;
23393
- if ("userConfig" in c === false) {
23394
- c["userConfig"] = {};
23395
- return c;
23686
+ // check to see if the config has styles
23687
+ // if it does, then we can use those styles
23688
+ // otherwise, we will use the default styles
23689
+ // styles will be an object with the styles for the widget
23690
+ // and set the styles from the config if they exist
23691
+ styles = "styles" in config ? config["styles"] : null;
23396
23692
  }
23397
- var userPrefs = {};
23398
- // now we can make sure the configuration is "complete"
23399
- Object.keys(c["userConfig"]).forEach(function (key) {
23400
- // check the required fields!
23401
- Object.keys(requiredFields).forEach(function (k) {
23402
- if (k in c["userConfig"][key] === false) {
23403
- c["userConfig"][key][k] = requiredFields[k]["value"];
23404
- }
23693
+
23694
+ // user input for the customization of the widget
23695
+ var userPrefs = params["userPrefs"];
23696
+
23697
+ // Check to make sure this is a Component
23698
+ if (typeof WidgetComponent !== "function") {
23699
+ return /*#__PURE__*/jsxRuntime.jsx(WidgetNotFound, {
23700
+ component: component
23405
23701
  });
23406
- // tack on the user preferences
23407
- userPrefs[key] = WidgetFactory.userPrefsForItem(c, key, c["userConfig"][key]);
23408
- });
23409
- c["userPrefs"] = userPrefs;
23410
- return c;
23411
- }
23412
- return null;
23413
- },
23414
- workspace: function workspace(component) {
23415
- var components = WidgetFactory.map();
23416
- if (component !== undefined && components) {
23417
- if (component in components) {
23418
- var c = components[component];
23419
- if ("workspace" in c) {
23420
- return c["workspace"];
23421
- }
23422
23702
  }
23423
- }
23424
- return null;
23425
- },
23426
- map: function map() {
23427
- return ComponentManager.map();
23428
- },
23429
- /**
23430
- * userConfig
23431
- * We want to make sure all of the keys are available, and if not, set defaults...
23432
- * @param {object} config the current configuration object
23433
- * @returns
23434
- */
23435
- userPrefsForItem: function userPrefsForItem(item, key, config) {
23436
- try {
23437
- // console.log('value: ', item['userPrefs'][key]);
23438
- // console.log('user prefs config item ', item, key, config);
23439
-
23440
- var prefsForItem = {};
23441
- if ("userPrefs" in item) {
23442
- if (key in item["userPrefs"]) {
23443
- prefsForItem = _defineProperty({}, key, item["userPrefs"][key]);
23444
- } else {
23445
- if ("defaultValue" in config) {
23446
- prefsForItem = _defineProperty({}, key, config["defaultValue"]);
23447
- }
23448
- }
23449
- } else {
23450
- // no user preferences in the item yet so we can try and set the defaults.
23451
- // console.log('config item ', config);
23452
- prefsForItem[key] = "defaultValue" in config ? config["defaultValue"] : "";
23703
+ if (isLayout === false) {
23704
+ params["width"] = "w-full";
23705
+ }
23706
+ if ("width" in params === false) {
23707
+ params["width"] = "w-full";
23453
23708
  }
23709
+ params["componentName"] = component;
23454
23710
 
23455
- // console.log('config item prefs ', prefsForItem);
23456
- return prefsForItem;
23457
- } catch (e) {
23458
- return {};
23459
- }
23460
- }
23461
- };
23711
+ // init will inject the params from the widget into the widgetAPI
23712
+ // widgetApi.init(params);
23462
23713
 
23463
- var _excluded$3 = ["title", "description", "icon"];
23464
- var ExternalWidget = function ExternalWidget(_ref) {
23465
- var title = _ref.title,
23466
- description = _ref.description,
23467
- icon = _ref.icon;
23468
- _objectWithoutProperties(_ref, _excluded$3);
23469
- return /*#__PURE__*/jsxRuntime.jsx(DashReact.Panel, {
23470
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
23471
- className: "flex flex-col items-center justify-center gap-2 py-6 text-center opacity-70",
23472
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23473
- icon: icon || "puzzle-piece",
23474
- className: "h-6 w-6 opacity-50"
23475
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Heading, {
23476
- title: title || "External Widget",
23477
- padding: false
23478
- }), description && /*#__PURE__*/jsxRuntime.jsx("p", {
23479
- className: "text-sm text-gray-400 max-w-xs",
23480
- children: description
23481
- })]
23482
- })
23483
- });
23484
- };
23714
+ var bgColor = "";
23715
+ if (styles !== null) {
23716
+ bgColor = "backgroundColor" in styles ? styles["backgroundColor"] : "";
23717
+ }
23485
23718
 
23486
- var RegistryPackageDetail = function RegistryPackageDetail(_ref) {
23487
- var widget = _ref.widget,
23488
- onInstall = _ref.onInstall,
23489
- _ref$isInstalling = _ref.isInstalling,
23490
- isInstalling = _ref$isInstalling === void 0 ? false : _ref$isInstalling,
23491
- _ref$installError = _ref.installError,
23492
- installError = _ref$installError === void 0 ? null : _ref$installError,
23493
- _ref$isInstalled = _ref.isInstalled,
23494
- isInstalled = _ref$isInstalled === void 0 ? false : _ref$isInstalled,
23495
- _ref$showAuth = _ref.showAuth,
23496
- showAuth = _ref$showAuth === void 0 ? false : _ref$showAuth,
23497
- _ref$onAuthSuccess = _ref.onAuthSuccess,
23498
- onAuthSuccess = _ref$onAuthSuccess === void 0 ? null : _ref$onAuthSuccess,
23499
- _ref$onAuthCancel = _ref.onAuthCancel,
23500
- onAuthCancel = _ref$onAuthCancel === void 0 ? null : _ref$onAuthCancel;
23501
- var _useContext = React.useContext(DashReact.ThemeContext),
23502
- currentTheme = _useContext.currentTheme;
23503
- var panelStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL, currentTheme, {
23504
- grow: false
23505
- });
23506
- if (!widget) return null;
23507
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
23508
- className: "flex flex-col flex-1 min-h-0",
23509
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
23510
- className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-6 ".concat(panelStyles.textColor || "text-gray-200"),
23511
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
23512
- className: "flex flex-row items-center gap-3",
23513
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
23514
- className: "h-5 w-5 flex-shrink-0 flex items-center justify-center",
23515
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23516
- icon: widget.icon || "cube",
23517
- className: "h-5 w-5"
23518
- })
23519
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
23520
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
23521
- className: "flex items-center gap-2",
23522
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
23523
- title: widget.packageDisplayName,
23524
- padding: false
23525
- }), isInstalled && /*#__PURE__*/jsxRuntime.jsx("span", {
23526
- className: "text-[10px] px-1.5 py-0.5 rounded bg-emerald-500/20 text-emerald-400 flex-shrink-0",
23527
- children: "Installed"
23528
- })]
23529
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
23530
- className: "flex items-center gap-2 mt-0.5",
23531
- children: [/*#__PURE__*/jsxRuntime.jsxs("span", {
23532
- className: "text-sm opacity-60",
23533
- children: ["by ", widget.packageAuthor || "Unknown"]
23534
- }), /*#__PURE__*/jsxRuntime.jsxs("span", {
23535
- className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-70"),
23536
- children: ["v", widget.packageVersion]
23537
- })]
23538
- })]
23539
- })]
23540
- }), /*#__PURE__*/jsxRuntime.jsx("hr", {
23541
- className: currentTheme["border-primary-medium"]
23542
- }), widget.packageDescription && /*#__PURE__*/jsxRuntime.jsx("p", {
23543
- className: "text-sm",
23544
- children: widget.packageDescription
23545
- }), widget.packageTags && widget.packageTags.length > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
23546
- className: "flex flex-wrap gap-1",
23547
- children: widget.packageTags.map(function (tag) {
23548
- return /*#__PURE__*/jsxRuntime.jsx("span", {
23549
- className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-60"),
23550
- children: tag
23551
- }, tag);
23552
- })
23553
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
23554
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
23555
- className: "text-xs font-semibold opacity-50 mb-1 block",
23556
- children: "INCLUDED WIDGETS"
23557
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
23558
- className: "space-y-1.5",
23559
- children: (widget.packageWidgets || []).map(function (w, idx) {
23560
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
23561
- className: "p-2 rounded ".concat(currentTheme["bg-primary-medium"]),
23562
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
23563
- className: "text-sm font-medium",
23564
- children: w.displayName || w.name
23565
- }), w.description && /*#__PURE__*/jsxRuntime.jsx("div", {
23566
- className: "text-xs opacity-50 mt-0.5",
23567
- children: w.description
23568
- }), getUserConfigurableProviders(w.providers).length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
23569
- className: "space-y-1 mt-1",
23570
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
23571
- className: "flex gap-1 flex-wrap",
23572
- children: getUserConfigurableProviders(w.providers).map(function (p, pidx) {
23573
- return /*#__PURE__*/jsxRuntime.jsxs("span", {
23574
- className: "text-xs px-1.5 py-0.5 rounded bg-blue-900/30 text-blue-400",
23575
- children: [p.type, p.required ? " *" : ""]
23576
- }, pidx);
23577
- })
23578
- }), getUserConfigurableProviders(w.providers).some(function (p) {
23579
- var _p$requiredTools;
23580
- return ((_p$requiredTools = p.requiredTools) === null || _p$requiredTools === void 0 ? void 0 : _p$requiredTools.length) > 0;
23581
- }) && /*#__PURE__*/jsxRuntime.jsx("div", {
23582
- className: "flex flex-wrap gap-1 ml-1",
23583
- children: getUserConfigurableProviders(w.providers).filter(function (p) {
23584
- var _p$requiredTools2;
23585
- return ((_p$requiredTools2 = p.requiredTools) === null || _p$requiredTools2 === void 0 ? void 0 : _p$requiredTools2.length) > 0;
23586
- }).flatMap(function (p) {
23587
- return p.requiredTools.map(function (tool) {
23588
- return /*#__PURE__*/jsxRuntime.jsx("span", {
23589
- className: "text-[10px] font-mono px-1.5 py-0.5 rounded bg-white/5 opacity-60",
23590
- children: tool
23591
- }, "".concat(p.type, "-").concat(tool));
23592
- });
23593
- })
23594
- })]
23595
- })]
23596
- }, idx);
23597
- })
23598
- })]
23599
- }), widget.appOrigin && /*#__PURE__*/jsxRuntime.jsxs("div", {
23600
- className: "flex items-center gap-1.5 text-xs opacity-50",
23601
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23602
- icon: "laptop",
23603
- className: "h-3 w-3"
23604
- }), /*#__PURE__*/jsxRuntime.jsxs("span", {
23605
- children: ["Built for ", widget.appOrigin]
23606
- })]
23607
- }), widget.missingApis && widget.missingApis.length > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
23608
- className: "p-2 rounded bg-yellow-900/30 border border-yellow-700",
23609
- children: /*#__PURE__*/jsxRuntime.jsxs("p", {
23610
- className: "text-xs text-yellow-400",
23611
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23612
- icon: "triangle-exclamation",
23613
- className: "mr-1"
23614
- }), "Incompatible \u2014 requires ", widget.missingApis.join(", "), " API", widget.missingApis.length !== 1 ? "s" : ""]
23615
- })
23616
- }), widget.repository && /*#__PURE__*/jsxRuntime.jsxs("div", {
23617
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
23618
- className: "text-xs font-semibold opacity-50 mb-1 block",
23619
- children: "REPOSITORY"
23620
- }), /*#__PURE__*/jsxRuntime.jsx("button", {
23621
- type: "button",
23622
- onClick: function onClick() {
23623
- var _window$mainApi;
23624
- return (_window$mainApi = window.mainApi) === null || _window$mainApi === void 0 || (_window$mainApi = _window$mainApi.shell) === null || _window$mainApi === void 0 ? void 0 : _window$mainApi.openExternal(widget.repository);
23625
- },
23626
- className: "text-sm text-blue-400 hover:text-blue-300 hover:underline transition-colors break-all text-left",
23627
- children: widget.repository
23628
- })]
23629
- }), installError && /*#__PURE__*/jsxRuntime.jsx("div", {
23630
- className: "p-2 rounded bg-red-900/30 border border-red-700",
23631
- children: /*#__PURE__*/jsxRuntime.jsx("p", {
23632
- className: "text-xs text-red-400",
23633
- children: installError
23719
+ // Build widgetData for WidgetContext — hooks read from this
23720
+ var uuidString = DashReact.getUUID(params.uuid);
23721
+ var widgetData = _objectSpread$q(_objectSpread$q({}, params), {}, {
23722
+ uuidString: uuidString,
23723
+ providers: (config === null || config === void 0 ? void 0 : config.providers) || [],
23724
+ notifications: (config === null || config === void 0 ? void 0 : config.notifications) || []
23725
+ });
23726
+
23727
+ // need to set the electron api here.
23728
+ var w = WidgetApi;
23729
+ w.init({
23730
+ id: widgetKey,
23731
+ name: component
23732
+ });
23733
+ w.setElectronApi(dashApi);
23734
+ w.setPublisher(DashboardPublisher);
23735
+
23736
+ // init the helpers — pass WidgetApi (which has publishEvent/registerListeners
23737
+ // that delegate to DashboardPublisher), not the raw Electron dashApi
23738
+ var helpers = new WidgetHelpers(params, w);
23739
+
23740
+ // Memoize context value to prevent unnecessary re-renders
23741
+ var widgetContextValue = {
23742
+ widgetData: widgetData
23743
+ };
23744
+ var hasScheduledTasks = ((config === null || config === void 0 ? void 0 : config.scheduledTasks) || []).length > 0;
23745
+ var widgetElement = children === null ? /*#__PURE__*/jsxRuntime.jsx(WidgetComponent, _objectSpread$q(_objectSpread$q(_objectSpread$q({
23746
+ id: "widget-nokids-".concat(widgetKey),
23747
+ listen: function listen(listeners, handlers) {
23748
+ return helpers.listen(listeners, handlers);
23749
+ },
23750
+ publishEvent: function publishEvent(eventName, payload) {
23751
+ return helpers.publishEvent(eventName, payload);
23752
+ },
23753
+ api: w
23754
+ }, params), userPrefs), {}, {
23755
+ backgroundColor: bgColor,
23756
+ widgetConfig: helpers.config(),
23757
+ widgetEventNames: helpers.events()
23758
+ }), "widget-nokids-".concat(widgetKey)) : /*#__PURE__*/jsxRuntime.jsx(WidgetComponent, _objectSpread$q(_objectSpread$q(_objectSpread$q({
23759
+ listen: function listen(listeners, handlers) {
23760
+ return helpers.listen(listeners, handlers);
23761
+ },
23762
+ publishEvent: function publishEvent(eventName, payload) {
23763
+ return helpers.publishEvent(eventName, payload);
23764
+ },
23765
+ api: w,
23766
+ id: "widget-kids-".concat(widgetKey)
23767
+ }, params), userPrefs), {}, {
23768
+ backgroundColor: bgColor,
23769
+ children: children
23770
+ }), "widget-kids-".concat(widgetKey));
23771
+
23772
+ // Wrap widget rendering with WidgetContext + error boundary
23773
+ return /*#__PURE__*/jsxRuntime.jsx(WidgetContext.Provider, {
23774
+ value: widgetContextValue,
23775
+ children: /*#__PURE__*/jsxRuntime.jsx(WidgetErrorBoundary, {
23776
+ widgetName: component,
23777
+ children: hasScheduledTasks ? /*#__PURE__*/jsxRuntime.jsxs("div", {
23778
+ className: "flex flex-col w-full h-full min-h-0",
23779
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
23780
+ className: "flex-1 min-h-0 overflow-auto",
23781
+ children: widgetElement
23782
+ }), /*#__PURE__*/jsxRuntime.jsx(WidgetCardStatusBar, {
23783
+ item: params
23784
+ })]
23785
+ }) : widgetElement
23634
23786
  })
23635
- })]
23636
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
23637
- className: "flex items-center justify-end px-6 py-3 border-t ".concat(currentTheme["border-primary-medium"]),
23638
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
23639
- title: isInstalled ? "Installed" : isInstalling ? "Installing..." : "Install Package",
23640
- bgColor: isInstalled ? "bg-emerald-600/50" : "bg-blue-600",
23641
- hoverBackgroundColor: isInstalled || isInstalling ? "" : "hover:bg-blue-700",
23642
- textSize: "text-sm",
23643
- padding: "py-1.5 px-4",
23644
- onClick: onInstall,
23645
- disabled: isInstalling || isInstalled
23646
- })
23647
- }), /*#__PURE__*/jsxRuntime.jsx(RegistryAuthModal, {
23648
- isOpen: showAuth,
23649
- setIsOpen: function setIsOpen(open) {
23650
- if (!open && onAuthCancel) onAuthCancel();
23651
- },
23652
- onAuthenticated: onAuthSuccess,
23653
- onCancel: onAuthCancel,
23654
- message: "Sign in to install this widget from the Dash Registry."
23655
- })]
23787
+ });
23788
+ }
23789
+ } catch (e) {
23790
+ return /*#__PURE__*/jsxRuntime.jsx(WidgetNotFound, {
23791
+ component: component
23792
+ });
23793
+ }
23794
+ return /*#__PURE__*/jsxRuntime.jsx(WidgetNotFound, {
23795
+ component: component
23656
23796
  });
23657
23797
  };
23658
23798
 
23659
23799
  /**
23660
- * Extract a search query from a widget component key.
23661
- *
23662
- * Scoped IDs look like "scope.packageName.WidgetName" — we can do an exact
23663
- * package lookup with the middle segment. Plain names are just the widget
23664
- * class name, so we fall back to a search.
23665
- */
23666
- function getWidgetSearchQuery(componentKey) {
23667
- var parts = componentKey.split(".");
23668
- if (parts.length >= 3) {
23669
- return {
23670
- packageName: parts[1],
23671
- widgetName: parts[2],
23672
- scope: parts[0]
23673
- };
23674
- }
23675
- return {
23676
- packageName: null,
23677
- widgetName: componentKey,
23678
- scope: null
23679
- };
23680
- }
23681
-
23682
- /**
23683
- * Convert a raw registry package object into the flat widget shape
23684
- * expected by RegistryPackageDetail.
23800
+ * WidgetFactory
23801
+ * Get the "component" and params and dynamically generate the Component
23685
23802
  */
23686
- function packageToFlatWidget(pkg) {
23687
- return {
23688
- key: "".concat(pkg.name, "/0"),
23689
- name: pkg.displayName || pkg.name,
23690
- icon: pkg.icon || null,
23691
- isRegistry: true,
23692
- packageName: pkg.name,
23693
- packageScope: pkg.scope || null,
23694
- packageDisplayName: pkg.displayName || pkg.name,
23695
- packageVersion: pkg.version,
23696
- packageAuthor: pkg.author || "",
23697
- packageDescription: pkg.description || "",
23698
- packageTags: pkg.tags || [],
23699
- packageCategory: pkg.category || "",
23700
- downloadUrl: pkg.downloadUrl || "",
23701
- repository: pkg.repository || "",
23702
- publishedAt: pkg.publishedAt || "",
23703
- packageWidgets: pkg.widgets || [],
23704
- appOrigin: pkg.appOrigin || null,
23705
- packageProviders: pkg.providers || [],
23706
- missingApis: []
23707
- };
23708
- }
23709
-
23710
- var WidgetNotFound = function WidgetNotFound(_ref) {
23711
- var component = _ref.component;
23712
- var _useState = React.useState(false),
23713
- _useState2 = _slicedToArray(_useState, 2),
23714
- showModal = _useState2[0],
23715
- setShowModal = _useState2[1];
23716
- var _useState3 = React.useState(null),
23717
- _useState4 = _slicedToArray(_useState3, 2),
23718
- registryWidget = _useState4[0],
23719
- setRegistryWidget = _useState4[1];
23720
- var _useState5 = React.useState(false),
23721
- _useState6 = _slicedToArray(_useState5, 2),
23722
- isLoading = _useState6[0],
23723
- setIsLoading = _useState6[1];
23724
- var _useState7 = React.useState(false),
23725
- _useState8 = _slicedToArray(_useState7, 2),
23726
- notFound = _useState8[0],
23727
- setNotFound = _useState8[1];
23728
- var _useState9 = React.useState(false),
23729
- _useState0 = _slicedToArray(_useState9, 2),
23730
- isInstalling = _useState0[0],
23731
- setIsInstalling = _useState0[1];
23732
- var _useState1 = React.useState(null),
23733
- _useState10 = _slicedToArray(_useState1, 2),
23734
- installError = _useState10[0],
23735
- setInstallError = _useState10[1];
23736
- var _useState11 = React.useState(false),
23737
- _useState12 = _slicedToArray(_useState11, 2),
23738
- needsAuth = _useState12[0],
23739
- setNeedsAuth = _useState12[1];
23740
- var lookupWidget = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
23741
- var _getWidgetSearchQuery, packageName, widgetName, pkg, result;
23742
- return _regeneratorRuntime.wrap(function (_context) {
23743
- while (1) switch (_context.prev = _context.next) {
23744
- case 0:
23745
- setShowModal(true);
23746
- setIsLoading(true);
23747
- setNotFound(false);
23748
- setRegistryWidget(null);
23749
- setInstallError(null);
23750
- setNeedsAuth(false);
23751
- _getWidgetSearchQuery = getWidgetSearchQuery(component), packageName = _getWidgetSearchQuery.packageName, widgetName = _getWidgetSearchQuery.widgetName;
23752
- _context.prev = 1;
23753
- pkg = null; // Scoped ID — exact package lookup
23754
- if (!packageName) {
23755
- _context.next = 3;
23756
- break;
23757
- }
23758
- _context.next = 2;
23759
- return window.mainApi.registry.getPackage(packageName);
23760
- case 2:
23761
- pkg = _context.sent;
23762
- case 3:
23763
- if (pkg) {
23764
- _context.next = 5;
23765
- break;
23766
- }
23767
- _context.next = 4;
23768
- return window.mainApi.registry.search(widgetName);
23769
- case 4:
23770
- result = _context.sent;
23771
- pkg = (result.packages || []).find(function (p) {
23772
- return (p.widgets || []).some(function (w) {
23773
- return w.name === widgetName;
23774
- });
23775
- });
23776
- case 5:
23777
- if (pkg) {
23778
- setRegistryWidget(packageToFlatWidget(pkg));
23779
- } else {
23780
- setNotFound(true);
23781
- }
23782
- _context.next = 7;
23783
- break;
23784
- case 6:
23785
- _context.prev = 6;
23786
- _context["catch"](1);
23787
- setNotFound(true);
23788
- case 7:
23789
- setIsLoading(false);
23790
- case 8:
23791
- case "end":
23792
- return _context.stop();
23803
+ var WidgetFactory = {
23804
+ getComponent: function getComponent(component) {
23805
+ try {
23806
+ return ComponentManager.getComponent(component);
23807
+ } catch (e) {
23808
+ return null;
23809
+ }
23810
+ },
23811
+ render: function render(component, key) {
23812
+ var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
23813
+ var children = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
23814
+ return /*#__PURE__*/jsxRuntime.jsx(WidgetRenderer, {
23815
+ component: component,
23816
+ widgetKey: key,
23817
+ params: params,
23818
+ children: children
23819
+ });
23820
+ },
23821
+ renderChildren: function renderChildren(children) {
23822
+ return React.Children.map(children, function (el) {
23823
+ return el;
23824
+ // const clonedComponent = React.cloneElement(el);
23825
+ // return clonedComponent;
23826
+ });
23827
+ },
23828
+ /**
23829
+ * config
23830
+ * Get the developer's component configuration and enhance that configuration with
23831
+ * required fields if they are not present
23832
+ *
23833
+ * @param {object} component
23834
+ * @returns
23835
+ */
23836
+ config: function config(component) {
23837
+ if (component) {
23838
+ var requiredFields = {
23839
+ type: {
23840
+ value: "text"
23841
+ },
23842
+ required: {
23843
+ value: false
23844
+ },
23845
+ options: {
23846
+ value: []
23847
+ },
23848
+ defaultValue: {
23849
+ value: ""
23850
+ },
23851
+ events: [] // events that will be published
23852
+ };
23853
+
23854
+ // get the component configuration from the map
23855
+ var components = ComponentManager.map();
23856
+
23857
+ // let c = deepCopy(components['component']);
23858
+ var c = JSON.parse(JSON.stringify(components[component]));
23859
+ c["component"] = component;
23860
+ if ("userConfig" in c === false) {
23861
+ c["userConfig"] = {};
23862
+ return c;
23793
23863
  }
23794
- }, _callee, null, [[1, 6]]);
23795
- })), [component]);
23796
- var handleInstall = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
23797
- var _window$mainApi, status, packageName, packageScope, downloadUrl, packageVersion, scopedId, resolvedUrl, msg, _t3;
23798
- return _regeneratorRuntime.wrap(function (_context2) {
23799
- while (1) switch (_context2.prev = _context2.next) {
23800
- case 0:
23801
- if (registryWidget) {
23802
- _context2.next = 1;
23803
- break;
23804
- }
23805
- return _context2.abrupt("return");
23806
- case 1:
23807
- setIsInstalling(true);
23808
- setInstallError(null);
23809
- setNeedsAuth(false);
23810
- _context2.prev = 2;
23811
- _context2.prev = 3;
23812
- _context2.next = 4;
23813
- 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();
23814
- case 4:
23815
- status = _context2.sent;
23816
- if (status !== null && status !== void 0 && status.authenticated) {
23817
- _context2.next = 5;
23818
- break;
23864
+ var userPrefs = {};
23865
+ // now we can make sure the configuration is "complete"
23866
+ Object.keys(c["userConfig"]).forEach(function (key) {
23867
+ // check the required fields!
23868
+ Object.keys(requiredFields).forEach(function (k) {
23869
+ if (k in c["userConfig"][key] === false) {
23870
+ c["userConfig"][key][k] = requiredFields[k]["value"];
23819
23871
  }
23820
- setNeedsAuth(true);
23821
- setIsInstalling(false);
23822
- return _context2.abrupt("return");
23823
- case 5:
23824
- _context2.next = 7;
23825
- break;
23826
- case 6:
23827
- _context2.prev = 6;
23828
- _context2["catch"](3);
23829
- case 7:
23830
- packageName = registryWidget.packageName, packageScope = registryWidget.packageScope, downloadUrl = registryWidget.downloadUrl, packageVersion = registryWidget.packageVersion;
23831
- scopedId = packageScope ? "@".concat(packageScope.replace(/^@/, ""), "/").concat(packageName) : packageName;
23832
- resolvedUrl = downloadUrl.replace(/\{version\}/g, packageVersion).replace(/\{name\}/g, packageName);
23833
- _context2.next = 8;
23834
- return window.mainApi.widgets.install(scopedId, resolvedUrl);
23835
- case 8:
23836
- setShowModal(false);
23837
- _context2.next = 10;
23838
- break;
23839
- case 9:
23840
- _context2.prev = 9;
23841
- _t3 = _context2["catch"](2);
23842
- msg = _t3.message || "Failed to install package";
23843
- if (msg.toLowerCase().includes("unauthorized")) {
23844
- setNeedsAuth(true);
23845
- } else {
23846
- setInstallError(msg);
23872
+ });
23873
+ // tack on the user preferences
23874
+ userPrefs[key] = WidgetFactory.userPrefsForItem(c, key, c["userConfig"][key]);
23875
+ });
23876
+ c["userPrefs"] = userPrefs;
23877
+ return c;
23878
+ }
23879
+ return null;
23880
+ },
23881
+ workspace: function workspace(component) {
23882
+ var components = WidgetFactory.map();
23883
+ if (component !== undefined && components) {
23884
+ if (component in components) {
23885
+ var c = components[component];
23886
+ if ("workspace" in c) {
23887
+ return c["workspace"];
23888
+ }
23889
+ }
23890
+ }
23891
+ return null;
23892
+ },
23893
+ map: function map() {
23894
+ return ComponentManager.map();
23895
+ },
23896
+ /**
23897
+ * userConfig
23898
+ * We want to make sure all of the keys are available, and if not, set defaults...
23899
+ * @param {object} config the current configuration object
23900
+ * @returns
23901
+ */
23902
+ userPrefsForItem: function userPrefsForItem(item, key, config) {
23903
+ try {
23904
+ // console.log('value: ', item['userPrefs'][key]);
23905
+ // console.log('user prefs config item ', item, key, config);
23906
+
23907
+ var prefsForItem = {};
23908
+ if ("userPrefs" in item) {
23909
+ if (key in item["userPrefs"]) {
23910
+ prefsForItem = _defineProperty({}, key, item["userPrefs"][key]);
23911
+ } else {
23912
+ if ("defaultValue" in config) {
23913
+ prefsForItem = _defineProperty({}, key, config["defaultValue"]);
23847
23914
  }
23848
- case 10:
23849
- setIsInstalling(false);
23850
- case 11:
23851
- case "end":
23852
- return _context2.stop();
23915
+ }
23916
+ } else {
23917
+ // no user preferences in the item yet so we can try and set the defaults.
23918
+ // console.log('config item ', config);
23919
+ prefsForItem[key] = "defaultValue" in config ? config["defaultValue"] : "";
23853
23920
  }
23854
- }, _callee2, null, [[2, 9], [3, 6]]);
23855
- })), [registryWidget]);
23856
- var handleAuthSuccess = React.useCallback(function () {
23857
- setNeedsAuth(false);
23858
- handleInstall();
23859
- }, [handleInstall]);
23860
- var handleClose = React.useCallback(function () {
23861
- setShowModal(false);
23862
- }, []);
23863
- return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
23864
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
23865
- className: "flex flex-col h-full justify-center items-center w-full z-10 gap-2 p-4 text-center",
23921
+
23922
+ // console.log('config item prefs ', prefsForItem);
23923
+ return prefsForItem;
23924
+ } catch (e) {
23925
+ return {};
23926
+ }
23927
+ }
23928
+ };
23929
+
23930
+ var _excluded$3 = ["title", "description", "icon"];
23931
+ var ExternalWidget = function ExternalWidget(_ref) {
23932
+ var title = _ref.title,
23933
+ description = _ref.description,
23934
+ icon = _ref.icon;
23935
+ _objectWithoutProperties(_ref, _excluded$3);
23936
+ return /*#__PURE__*/jsxRuntime.jsx(DashReact.Panel, {
23937
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
23938
+ className: "flex flex-col items-center justify-center gap-2 py-6 text-center opacity-70",
23866
23939
  children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23867
- icon: "triangle-exclamation",
23868
- className: "h-6 w-6 text-amber-500"
23869
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
23870
- className: "text-sm font-semibold text-gray-300",
23871
- children: "Widget Not Found"
23872
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
23873
- className: "text-xs text-gray-500 font-mono",
23874
- children: component
23875
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
23876
- className: "text-xs text-gray-600 mt-1",
23877
- children: "This widget may have been uninstalled or renamed."
23878
- }), /*#__PURE__*/jsxRuntime.jsxs("button", {
23879
- type: "button",
23880
- className: "flex items-center gap-1.5 text-xs text-blue-400 hover:text-blue-300 transition-colors mt-2",
23881
- onClick: lookupWidget,
23882
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23883
- icon: "magnifying-glass",
23884
- className: "h-3 w-3"
23885
- }), "Find in Registry"]
23940
+ icon: icon || "puzzle-piece",
23941
+ className: "h-6 w-6 opacity-50"
23942
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Heading, {
23943
+ title: title || "External Widget",
23944
+ padding: false
23945
+ }), description && /*#__PURE__*/jsxRuntime.jsx("p", {
23946
+ className: "text-sm text-gray-400 max-w-xs",
23947
+ children: description
23886
23948
  })]
23887
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Modal, {
23888
- isOpen: showModal,
23889
- setIsOpen: setShowModal,
23890
- width: "w-1/3",
23891
- height: "auto",
23892
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
23893
- className: "relative",
23894
- children: [/*#__PURE__*/jsxRuntime.jsx("button", {
23895
- type: "button",
23896
- className: "absolute top-3 right-3 z-10 text-gray-500 hover:text-gray-300 transition-colors",
23897
- onClick: handleClose,
23898
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23899
- icon: "xmark",
23900
- className: "h-4 w-4"
23901
- })
23902
- }), isLoading && /*#__PURE__*/jsxRuntime.jsx("div", {
23903
- className: "flex items-center justify-center p-12",
23904
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23905
- icon: "spinner",
23906
- className: "h-5 w-5 text-gray-400 animate-spin"
23907
- })
23908
- }), !isLoading && registryWidget && /*#__PURE__*/jsxRuntime.jsx(RegistryPackageDetail, {
23909
- widget: registryWidget,
23910
- onInstall: handleInstall,
23911
- isInstalling: isInstalling,
23912
- installError: installError
23913
- }), !isLoading && notFound && /*#__PURE__*/jsxRuntime.jsxs("div", {
23914
- className: "flex flex-col items-center justify-center gap-3 p-12 text-center",
23915
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
23916
- icon: "triangle-exclamation",
23917
- className: "h-6 w-6 text-amber-500"
23918
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
23919
- className: "text-sm text-gray-400",
23920
- children: "This widget is not available in the registry."
23921
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
23922
- title: "Close",
23923
- bgColor: "bg-gray-600",
23924
- hoverBackgroundColor: "hover:bg-gray-700",
23925
- textSize: "text-sm",
23926
- padding: "py-1.5 px-4",
23927
- onClick: handleClose
23928
- })]
23929
- })]
23930
- })
23931
- }), /*#__PURE__*/jsxRuntime.jsx(RegistryAuthModal, {
23932
- isOpen: needsAuth && !!registryWidget,
23933
- setIsOpen: function setIsOpen(open) {
23934
- if (!open) setNeedsAuth(false);
23935
- },
23936
- onAuthenticated: handleAuthSuccess,
23937
- onCancel: function onCancel() {
23938
- return setNeedsAuth(false);
23939
- },
23940
- message: "Sign in to install this widget from the Dash Registry."
23941
- })]
23949
+ })
23942
23950
  });
23943
23951
  };
23944
23952
 
@@ -25081,7 +25089,7 @@ var LayoutGridContainer = /*#__PURE__*/React.memo(function (_ref3) {
25081
25089
  onDelete: cellComponent ? function () {
25082
25090
  if (onClickRemove) onClickRemove(cellComponent.id);
25083
25091
  } : undefined
25084
- }), cellComponent && isWidgetResolvable(cellComponent.component) ? /*#__PURE__*/jsxRuntime.jsx(DraggableDroppableCellBody, {
25092
+ }), cellComponent && ComponentManager.config(cellComponent.component, cellComponent) ? /*#__PURE__*/jsxRuntime.jsx(DraggableDroppableCellBody, {
25085
25093
  cellNumber: cellNumber,
25086
25094
  gridContainerId: id,
25087
25095
  onMoveWidgetToCell: onMoveWidgetToCell,
@@ -25095,7 +25103,9 @@ var LayoutGridContainer = /*#__PURE__*/React.memo(function (_ref3) {
25095
25103
  onDropWidgetFromSidebar: onDropWidgetFromSidebar,
25096
25104
  children: cellComponent ? /*#__PURE__*/jsxRuntime.jsx("div", {
25097
25105
  className: "flex-1 flex flex-col min-h-[120px]",
25098
- children: renderedWidget
25106
+ children: /*#__PURE__*/jsxRuntime.jsx(WidgetNotFound, {
25107
+ component: cellComponent.component
25108
+ })
25099
25109
  }) : /*#__PURE__*/jsxRuntime.jsx(WidgetCard.Body, {
25100
25110
  padding: "p-0",
25101
25111
  children: renderEmptyCellContent(cellNumber)