@trops/dash-core 0.1.269 → 0.1.271

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