@64mb/freelens-power 2.1.0 → 2.2.0

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.
Files changed (106) hide show
  1. package/README.md +4 -4
  2. package/out/main/common/power-logs.js.map +1 -1
  3. package/out/main/common/resource-search.js.map +1 -1
  4. package/out/main/power-logs-child.js +3 -3
  5. package/out/main/power-logs-child.js.map +1 -1
  6. package/out/main/power-logs-database.js +165 -7
  7. package/out/main/power-logs-database.js.map +1 -1
  8. package/out/main/power-logs-ipc.js +12 -3
  9. package/out/main/power-logs-ipc.js.map +1 -1
  10. package/out/main/power-logs-worker.js +29 -7
  11. package/out/main/power-logs-worker.js.map +1 -1
  12. package/out/main/resource-search-database.js +3 -2
  13. package/out/main/resource-search-database.js.map +1 -1
  14. package/out/main/resource-search.js +2 -1
  15. package/out/main/resource-search.js.map +1 -1
  16. package/out/renderer/_virtual/_global-external_react.js +2 -1
  17. package/out/renderer/ai-context-mutations.js +14 -0
  18. package/out/renderer/ai-context-mutations.js.map +1 -0
  19. package/out/renderer/ai-copy-answer.js +18 -15
  20. package/out/renderer/ai-copy-answer.js.map +1 -1
  21. package/out/renderer/ai-diagnostic-handoff.js +2 -2
  22. package/out/renderer/ai-diagnostic-handoff.js.map +1 -1
  23. package/out/renderer/ai-extras.js +41 -38
  24. package/out/renderer/ai-extras.js.map +1 -1
  25. package/out/renderer/ai-message.js +50 -39
  26. package/out/renderer/ai-message.js.map +1 -1
  27. package/out/renderer/ai-provider-icon.js +39 -32
  28. package/out/renderer/ai-provider-icon.js.map +1 -1
  29. package/out/renderer/ai-resize.js +40 -37
  30. package/out/renderer/ai-resize.js.map +1 -1
  31. package/out/renderer/ai-shortcuts.js +20 -17
  32. package/out/renderer/ai-shortcuts.js.map +1 -1
  33. package/out/renderer/ai-terminal-context.js +42 -48
  34. package/out/renderer/ai-terminal-context.js.map +1 -1
  35. package/out/renderer/ai.js +137 -111
  36. package/out/renderer/ai.js.map +1 -1
  37. package/out/renderer/cluster-icon-colors.js +10 -7
  38. package/out/renderer/cluster-icon-colors.js.map +1 -1
  39. package/out/renderer/cluster-icons.js +47 -40
  40. package/out/renderer/cluster-icons.js.map +1 -1
  41. package/out/renderer/details/service-diagnostics-details.js +25 -23
  42. package/out/renderer/details/service-diagnostics-details.js.map +1 -1
  43. package/out/renderer/diagnostic-explain-button.js +7 -4
  44. package/out/renderer/diagnostic-explain-button.js.map +1 -1
  45. package/out/renderer/diagnostics-screen-finding.js +51 -0
  46. package/out/renderer/diagnostics-screen-finding.js.map +1 -0
  47. package/out/renderer/diagnostics.css.js +1 -1
  48. package/out/renderer/diagnostics.css.js.map +1 -1
  49. package/out/renderer/diagnostics.js +146 -107
  50. package/out/renderer/diagnostics.js.map +1 -1
  51. package/out/renderer/incident-copy-button.js +24 -21
  52. package/out/renderer/incident-copy-button.js.map +1 -1
  53. package/out/renderer/index.js +2 -0
  54. package/out/renderer/index.js.map +1 -1
  55. package/out/renderer/monitoring.js +19 -22
  56. package/out/renderer/monitoring.js.map +1 -1
  57. package/out/renderer/native-tooltip.js +22 -0
  58. package/out/renderer/native-tooltip.js.map +1 -0
  59. package/out/renderer/pod-details-enhancements.js +106 -0
  60. package/out/renderer/pod-details-enhancements.js.map +1 -0
  61. package/out/renderer/power-log-json-cell.js +44 -38
  62. package/out/renderer/power-log-json-cell.js.map +1 -1
  63. package/out/renderer/power-log-json.js +17 -10
  64. package/out/renderer/power-log-json.js.map +1 -1
  65. package/out/renderer/power-log-sql-editor.js +31 -2
  66. package/out/renderer/power-log-sql-editor.js.map +1 -1
  67. package/out/renderer/power-logs-client.js +5 -0
  68. package/out/renderer/power-logs-client.js.map +1 -1
  69. package/out/renderer/power-logs-entrypoints.js +10 -36
  70. package/out/renderer/power-logs-entrypoints.js.map +1 -1
  71. package/out/renderer/power-logs.css.js +9 -2
  72. package/out/renderer/power-logs.css.js.map +1 -1
  73. package/out/renderer/power-logs.js +376 -214
  74. package/out/renderer/power-logs.js.map +1 -1
  75. package/out/renderer/preferences/dashboard-preferences.js +42 -35
  76. package/out/renderer/preferences/dashboard-preferences.js.map +1 -1
  77. package/out/renderer/preferences/logs-preferences.js +1 -1
  78. package/out/renderer/preferences/logs-preferences.js.map +1 -1
  79. package/out/renderer/preferences/monitoring-preferences.js +7 -4
  80. package/out/renderer/preferences/monitoring-preferences.js.map +1 -1
  81. package/out/renderer/preferences/preferences.js +2 -2
  82. package/out/renderer/preferences/preferences.js.map +1 -1
  83. package/out/renderer/preferences/settings-icon-action.js +12 -11
  84. package/out/renderer/preferences/settings-icon-action.js.map +1 -1
  85. package/out/renderer/relationship-map-finding.js +53 -0
  86. package/out/renderer/relationship-map-finding.js.map +1 -0
  87. package/out/renderer/resource-relationships.css.js +6 -0
  88. package/out/renderer/resource-relationships.css.js.map +1 -1
  89. package/out/renderer/resource-relationships.js +94 -47
  90. package/out/renderer/resource-relationships.js.map +1 -1
  91. package/out/renderer/resource-search-client.js.map +1 -1
  92. package/out/renderer/resource-search.js +88 -35
  93. package/out/renderer/resource-search.js.map +1 -1
  94. package/out/renderer/src/common/gateway-relationships.js +8 -7
  95. package/out/renderer/src/common/gateway-relationships.js.map +1 -1
  96. package/out/renderer/src/common/power-log-json-filter-sql.js +12 -0
  97. package/out/renderer/src/common/power-log-json-filter-sql.js.map +1 -1
  98. package/out/renderer/src/common/power-log-json-preset.js +2 -2
  99. package/out/renderer/src/common/power-log-json-preset.js.map +1 -1
  100. package/out/renderer/src/common/power-logs.js.map +1 -1
  101. package/out/renderer/src/common/resource-relationships.js +10 -8
  102. package/out/renderer/src/common/resource-relationships.js.map +1 -1
  103. package/out/renderer/src/common/resource-search.js.map +1 -1
  104. package/out/renderer/welcome.js +16 -1
  105. package/out/renderer/welcome.js.map +1 -1
  106. package/package.json +1 -1
@@ -2,6 +2,7 @@ const require_extensions = require("./_virtual/_global-external_@freelensapp/ext
2
2
  const require__global_external_react = require("./_virtual/_global-external_react.js");
3
3
  const require_jsx_runtime = require("./_virtual/_global-external_react/jsx-runtime.js");
4
4
  const require_ai_icon = require("./ai-icon.js");
5
+ const require_native_tooltip = require("./native-tooltip.js");
5
6
  const require_incident_summary = require("./src/common/incident-summary.js");
6
7
  let electron = require("electron");
7
8
  //#region src/renderer/incident-copy-button.tsx
@@ -14,29 +15,31 @@ function IncidentCopyButton({ incident, clusterId }) {
14
15
  }, [feedback]);
15
16
  return /* @__PURE__ */ require_jsx_runtime.jsxs("span", {
16
17
  className: "incident-copy",
17
- children: [/* @__PURE__ */ require_jsx_runtime.jsx("button", {
18
- type: "button",
19
- "aria-label": "Copy incident summary",
18
+ children: [/* @__PURE__ */ require_jsx_runtime.jsx(require_native_tooltip.NativeTooltip, {
20
19
  title: feedback || "Copy incident summary",
21
- onClick: () => {
22
- try {
23
- const activeCluster = require_extensions.Renderer.Catalog.activeCluster.get();
24
- if (clusterId && activeCluster?.metadata.uid !== clusterId) {
25
- setFeedback("Cluster changed. Return to this finding before copying");
26
- return;
20
+ children: /* @__PURE__ */ require_jsx_runtime.jsx("button", {
21
+ type: "button",
22
+ "aria-label": "Copy incident summary",
23
+ onClick: () => {
24
+ try {
25
+ const activeCluster = require_extensions.Renderer.Catalog.activeCluster.get();
26
+ if (clusterId && activeCluster?.metadata.uid !== clusterId) {
27
+ setFeedback("Cluster changed. Return to this finding before copying");
28
+ return;
29
+ }
30
+ electron.clipboard.writeText(require_incident_summary.formatIncidentSummary({
31
+ ...incident,
32
+ ...clusterId ? { clusterName: activeCluster?.metadata.name ?? clusterId } : {}
33
+ }));
34
+ setFeedback("Copied");
35
+ } catch {
36
+ setFeedback("Unable to copy incident summary");
27
37
  }
28
- electron.clipboard.writeText(require_incident_summary.formatIncidentSummary({
29
- ...incident,
30
- ...clusterId ? { clusterName: activeCluster?.metadata.name ?? clusterId } : {}
31
- }));
32
- setFeedback("Copied");
33
- } catch {
34
- setFeedback("Unable to copy incident summary");
35
- }
36
- },
37
- children: /* @__PURE__ */ require_jsx_runtime.jsx(require_ai_icon.AiIcon, {
38
- material: feedback === "Copied" ? "check" : "content_copy",
39
- size: 14
38
+ },
39
+ children: /* @__PURE__ */ require_jsx_runtime.jsx(require_ai_icon.AiIcon, {
40
+ material: feedback === "Copied" ? "check" : "content_copy",
41
+ size: 14
42
+ })
40
43
  })
41
44
  }), feedback && /* @__PURE__ */ require_jsx_runtime.jsx("span", {
42
45
  role: "status",
@@ -1 +1 @@
1
- {"version":3,"file":"incident-copy-button.js","names":[],"sources":["../../src/renderer/incident-copy-button.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { clipboard } from \"electron\";\nimport { useEffect, useState } from \"react\";\nimport { formatIncidentSummary, type IncidentSummary } from \"../common/incident-summary\";\nimport { AiIcon } from \"./ai-icon\";\nexport function IncidentCopyButton({ incident, clusterId }: { incident: IncidentSummary; clusterId?: string }) {\n const [feedback, setFeedback] = useState(\"\");\n useEffect(() => {\n if (!feedback) return;\n const timer = window.setTimeout(() => setFeedback(\"\"), 2200);\n return () => window.clearTimeout(timer);\n }, [feedback]);\n return (\n <span className=\"incident-copy\">\n <button\n type=\"button\"\n aria-label=\"Copy incident summary\"\n title={feedback || \"Copy incident summary\"}\n onClick={() => {\n try {\n const activeCluster = Renderer.Catalog.activeCluster.get();\n if (clusterId && activeCluster?.metadata.uid !== clusterId) {\n setFeedback(\"Cluster changed. Return to this finding before copying\");\n return;\n }\n clipboard.writeText(\n formatIncidentSummary({\n ...incident,\n ...(clusterId ? { clusterName: activeCluster?.metadata.name ?? clusterId } : {}),\n }),\n );\n setFeedback(\"Copied\");\n } catch {\n setFeedback(\"Unable to copy incident summary\");\n }\n }}\n >\n <AiIcon material={feedback === \"Copied\" ? \"check\" : \"content_copy\"} size={14} />\n </button>\n {feedback && <span role=\"status\">{feedback}</span>}\n </span>\n );\n}\n"],"mappings":";;;;;;;AAKA,SAAgB,mBAAmB,EAAE,UAAU,aAAgE;CAC7G,MAAM,CAAC,UAAU,eAAe,+BAAA,SAAS,EAAE;CAC3C,+BAAA,gBAAgB;EACd,IAAI,CAAC,UAAU;EACf,MAAM,QAAQ,OAAO,iBAAiB,YAAY,EAAE,GAAG,IAAI;EAC3D,aAAa,OAAO,aAAa,KAAK;CACxC,GAAG,CAAC,QAAQ,CAAC;CACb,OACE,oCAAA,KAAC,QAAD;EAAM,WAAU;YAAhB,CACE,oCAAA,IAAC,UAAD;GACE,MAAK;GACL,cAAW;GACX,OAAO,YAAY;GACnB,eAAe;IACb,IAAI;KACF,MAAM,gBAAgB,mBAAA,SAAS,QAAQ,cAAc,IAAI;KACzD,IAAI,aAAa,eAAe,SAAS,QAAQ,WAAW;MAC1D,YAAY,wDAAwD;MACpE;KACF;KACA,SAAA,UAAU,UACR,yBAAA,sBAAsB;MACpB,GAAG;MACH,GAAI,YAAY,EAAE,aAAa,eAAe,SAAS,QAAQ,UAAU,IAAI,CAAC;KAChF,CAAC,CACH;KACA,YAAY,QAAQ;IACtB,QAAQ;KACN,YAAY,iCAAiC;IAC/C;GACF;aAEA,oCAAA,IAAC,gBAAA,QAAD;IAAQ,UAAU,aAAa,WAAW,UAAU;IAAgB,MAAM;GAAK,CAAA;EACzE,CAAA,GACP,YAAY,oCAAA,IAAC,QAAD;GAAM,MAAK;aAAU;EAAe,CAAA,CAC7C;;AAEV"}
1
+ {"version":3,"file":"incident-copy-button.js","names":[],"sources":["../../src/renderer/incident-copy-button.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { clipboard } from \"electron\";\nimport { useEffect, useState } from \"react\";\nimport { formatIncidentSummary, type IncidentSummary } from \"../common/incident-summary\";\nimport { AiIcon } from \"./ai-icon\";\nimport { NativeTooltip } from \"./native-tooltip\";\nexport function IncidentCopyButton({ incident, clusterId }: { incident: IncidentSummary; clusterId?: string }) {\n const [feedback, setFeedback] = useState(\"\");\n useEffect(() => {\n if (!feedback) return;\n const timer = window.setTimeout(() => setFeedback(\"\"), 2200);\n return () => window.clearTimeout(timer);\n }, [feedback]);\n return (\n <span className=\"incident-copy\">\n <NativeTooltip title={feedback || \"Copy incident summary\"}>\n <button\n type=\"button\"\n aria-label=\"Copy incident summary\"\n onClick={() => {\n try {\n const activeCluster = Renderer.Catalog.activeCluster.get();\n if (clusterId && activeCluster?.metadata.uid !== clusterId) {\n setFeedback(\"Cluster changed. Return to this finding before copying\");\n return;\n }\n clipboard.writeText(\n formatIncidentSummary({\n ...incident,\n ...(clusterId ? { clusterName: activeCluster?.metadata.name ?? clusterId } : {}),\n }),\n );\n setFeedback(\"Copied\");\n } catch {\n setFeedback(\"Unable to copy incident summary\");\n }\n }}\n >\n <AiIcon material={feedback === \"Copied\" ? \"check\" : \"content_copy\"} size={14} />\n </button>\n </NativeTooltip>\n {feedback && <span role=\"status\">{feedback}</span>}\n </span>\n );\n}\n"],"mappings":";;;;;;;;AAMA,SAAgB,mBAAmB,EAAE,UAAU,aAAgE;CAC7G,MAAM,CAAC,UAAU,eAAe,+BAAA,SAAS,EAAE;CAC3C,+BAAA,gBAAgB;EACd,IAAI,CAAC,UAAU;EACf,MAAM,QAAQ,OAAO,iBAAiB,YAAY,EAAE,GAAG,IAAI;EAC3D,aAAa,OAAO,aAAa,KAAK;CACxC,GAAG,CAAC,QAAQ,CAAC;CACb,OACE,oCAAA,KAAC,QAAD;EAAM,WAAU;YAAhB,CACE,oCAAA,IAAC,uBAAA,eAAD;GAAe,OAAO,YAAY;aAChC,oCAAA,IAAC,UAAD;IACE,MAAK;IACL,cAAW;IACX,eAAe;KACb,IAAI;MACF,MAAM,gBAAgB,mBAAA,SAAS,QAAQ,cAAc,IAAI;MACzD,IAAI,aAAa,eAAe,SAAS,QAAQ,WAAW;OAC1D,YAAY,wDAAwD;OACpE;MACF;MACA,SAAA,UAAU,UACR,yBAAA,sBAAsB;OACpB,GAAG;OACH,GAAI,YAAY,EAAE,aAAa,eAAe,SAAS,QAAQ,UAAU,IAAI,CAAC;MAChF,CAAC,CACH;MACA,YAAY,QAAQ;KACtB,QAAQ;MACN,YAAY,iCAAiC;KAC/C;IACF;cAEA,oCAAA,IAAC,gBAAA,QAAD;KAAQ,UAAU,aAAa,WAAW,UAAU;KAAgB,MAAM;IAAK,CAAA;GACzE,CAAA;EACK,CAAA,GACd,YAAY,oCAAA,IAAC,QAAD;GAAM,MAAK;aAAU;EAAe,CAAA,CAC7C;;AAEV"}
@@ -33,6 +33,7 @@ const require_secure_node_shell_menu = require("./menus/secure-node-shell-menu.j
33
33
  const require_monitoring = require("./monitoring.js");
34
34
  const require_monitoring_history_collection = require("./monitoring-history-collection.js");
35
35
  const require_node_monitoring = require("./node-monitoring.js");
36
+ const require_pod_details_enhancements = require("./pod-details-enhancements.js");
36
37
  const require_pod_monitoring = require("./pod-monitoring.js");
37
38
  const require_power_logs_entrypoints = require("./power-logs-entrypoints.js");
38
39
  const require_power_logs = require("./power-logs.js");
@@ -82,6 +83,7 @@ var FreelensPowerRenderer = class extends require_extensions.Renderer.LensExtens
82
83
  require_monitoring_history_collection.startMonitoringHistoryCollection,
83
84
  require_monitoring.startMonitoring,
84
85
  require_pod_monitoring.startPodMonitoring,
86
+ require_pod_details_enhancements.startPodDetailsEnhancements,
85
87
  require_button_styles.startPowerButtonStyles,
86
88
  require_appearance.startAppearanceOverride,
87
89
  require_welcome.startWelcomeOverride,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/renderer/index.tsx"],"sourcesContent":["/**\n * Copyright (c) Freelens Authors. All rights reserved.\n * Licensed under MIT License. See THIRD_PARTY_LICENSES for more information.\n */\n\nimport { Common, Renderer } from \"@freelensapp/extensions\";\nimport { computed, reaction } from \"mobx\";\nimport { observer } from \"mobx-react\";\nimport { EXTENSION_DISPLAY_NAME, EXTENSION_ID } from \"../common/extension-info\";\nimport { AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { AiShortcutsStore } from \"../common/store/ai-shortcuts-store\";\nimport { AppearancePreferencesStore } from \"../common/store/appearance-preferences-store\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\nimport { LogsPreferencesStore } from \"../common/store/logs-preferences-store\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { NodeShellPreferencesStore } from \"../common/store/node-shell-preferences-store\";\nimport { PowerPreferencesStore } from \"../common/store/power-preferences-store\";\nimport { ReadOnlyPreferencesStore } from \"../common/store/read-only-preferences-store\";\nimport { startAiChat } from \"./ai\";\nimport { startAppearanceOverride } from \"./appearance\";\nimport { startPowerButtonStyles } from \"./button-styles\";\nimport { ClusterIconsPage } from \"./cluster-icons\";\nimport { DashboardPage } from \"./dashboard\";\nimport { HpaDiagnosticsDetails } from \"./details/hpa-diagnostics-details\";\nimport { NamespaceHealthDetails } from \"./details/namespace-health-details\";\nimport { ResourceHealthDetails } from \"./details/resource-health-details\";\nimport { SecretCertificateDetails } from \"./details/secret-certificate-details\";\nimport { ServiceDiagnosticsDetails } from \"./details/service-diagnostics-details\";\nimport { DiagnosticsPage } from \"./diagnostics\";\nimport { type DiagnosticsResourceScope, focusDiagnosticsNamespace } from \"./diagnostics-state\";\nimport { SecureNodeShellMenu } from \"./menus/secure-node-shell-menu\";\nimport { startMonitoring } from \"./monitoring\";\nimport { startMonitoringCollector } from \"./monitoring-collector\";\nimport { startMonitoringHistoryCollection } from \"./monitoring-history-collection\";\nimport { NodeMonitoringDetails } from \"./node-monitoring\";\nimport { startPodMonitoring } from \"./pod-monitoring\";\nimport { PowerLogsPage } from \"./power-logs\";\nimport { PowerLogsMenu, startPowerLogsEntrypoints } from \"./power-logs-entrypoints\";\nimport { PowerPreferences } from \"./preferences/preferences\";\nimport { openPreferencesSection } from \"./preferences/section-navigation\";\nimport { startReadOnlyMode } from \"./read-only\";\nimport { ResourceRelationshipsPage } from \"./resource-relationships\";\nimport { startResourceSearch } from \"./resource-search\";\nimport { startWelcomeOverride } from \"./welcome\";\n\nimport type { ReactNode } from \"react\";\n\nconst PowerEnabled = observer(({ children }: { children: ReactNode }) =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled ? <>{children}</> : null,\n);\n\nconst RelationshipsPage = observer(() => (\n <PowerEnabled>\n <ResourceRelationshipsPage\n enabled={MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible}\n />\n </PowerEnabled>\n));\n\nexport default class FreelensPowerRenderer extends Renderer.LensExtension {\n get name() {\n return EXTENSION_DISPLAY_NAME;\n }\n get sanitizedExtensionId() {\n return EXTENSION_ID;\n }\n get storeName() {\n return this.manifest.storeName || EXTENSION_ID;\n }\n\n private stopFeatures?: () => void;\n\n onActivate() {\n const power = PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>();\n power.loadExtension(this);\n LogsPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiShortcutsStore.getInstanceOrCreate().loadExtension(this);\n ReadOnlyPreferencesStore.getInstanceOrCreate().loadExtension(this);\n NodeShellPreferencesStore.getInstanceOrCreate().loadExtension(this);\n MonitoringPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AppearancePreferencesStore.getInstanceOrCreate().loadExtension(this);\n DashboardPreferencesStore.getInstanceOrCreate().loadExtension(this);\n this.stopFeatures?.();\n let disposers: (() => void)[] = [];\n const stop = reaction(\n () => power.enabled,\n (enabled) => {\n for (const dispose of disposers) dispose();\n disposers = [];\n if (enabled) {\n for (const start of [\n startReadOnlyMode,\n startMonitoringCollector,\n startMonitoringHistoryCollection,\n startMonitoring,\n startPodMonitoring,\n startPowerButtonStyles,\n startAppearanceOverride,\n startWelcomeOverride,\n startAiChat,\n startResourceSearch,\n startPowerLogsEntrypoints,\n ]) {\n try {\n disposers.push(start());\n } catch {\n Common.logger.warn(\"[Freelens Power] feature could not start\", { feature: start.name });\n }\n }\n }\n },\n { fireImmediately: true },\n );\n this.stopFeatures = () => {\n stop();\n for (const dispose of disposers) dispose();\n disposers = [];\n };\n }\n\n onDeactivate() {\n this.stopFeatures?.();\n this.stopFeatures = undefined;\n }\n\n appPreferences = [\n {\n id: \"freelens-power-settings\",\n title: \"\",\n components: { Input: PowerPreferences, Hint: () => null },\n },\n ];\n\n globalPages = [\n {\n id: \"cluster-icons\",\n components: {\n Page: () => (\n <PowerEnabled>\n <ClusterIconsPage />\n </PowerEnabled>\n ),\n },\n },\n {\n id: \"dashboard\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DashboardPage\n onOpenPreferences={() => openPreferencesSection(\"dashboard\", () => this.navigateToPreferences())}\n />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPages = [\n {\n id: \"power-logs\",\n components: {\n Page: () => (\n <PowerEnabled>\n <PowerLogsPage />\n </PowerEnabled>\n ),\n },\n },\n { id: \"relationships\", components: { Page: () => <RelationshipsPage /> } },\n {\n id: \"diagnostics\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DiagnosticsPage />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPageMenus = [\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().diagnosticsVisible,\n ),\n target: { pageId: \"diagnostics\" },\n title: \"Diagnostics\",\n orderNumber: 5,\n components: { Icon: () => <Renderer.Component.Icon material=\"insights\" tooltip=\"Resource diagnostics\" /> },\n },\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible,\n ),\n id: \"relationships\",\n target: { pageId: \"relationships\" },\n title: \"Relationships\",\n orderNumber: 6,\n components: {\n Icon: () => <Renderer.Component.Icon material=\"account_tree\" tooltip=\"Resource relationships\" />,\n },\n },\n {\n id: \"power-logs\",\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n LogsPreferencesStore.getInstanceOrCreate<LogsPreferencesStore>().enabled,\n ),\n target: { pageId: \"power-logs\" },\n title: \"Power Logs\",\n orderNumber: 7,\n components: {\n Icon: () => <Renderer.Component.Icon material=\"subject\" tooltip=\"Workload logs and SQL captures\" />,\n },\n },\n ];\n\n topBarItems = [\n {\n components: {\n Item: () => (\n <PowerEnabled>\n <Renderer.Component.Icon\n material=\"battery_charging_full\"\n className=\"freelens-power-settings-icon\"\n tooltip=\"Freelens Power settings\"\n onClick={() => this.navigateToPreferences()}\n />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n private openDiagnostics = (namespace?: string, resourceScope?: DiagnosticsResourceScope) => {\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n if (clusterId && (namespace || resourceScope)) focusDiagnosticsNamespace(clusterId, namespace, resourceScope);\n void this.navigate(\"diagnostics\");\n };\n\n kubeObjectDetailItems: Renderer.LensExtension[\"kubeObjectDetailItems\"] = [\n ...[\"Pod\", \"Deployment\", \"StatefulSet\", \"DaemonSet\", \"Node\"].map((kind) => ({\n kind,\n apiVersions: kind === \"Pod\" || kind === \"Node\" ? [\"v1\"] : [\"apps/v1\"],\n priority: 320,\n components: {\n Details: (props: Renderer.Component.KubeObjectDetailsProps) => (\n <PowerEnabled>\n <ResourceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n })),\n {\n kind: \"Namespace\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NamespaceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Service\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <ServiceDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.Service} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"HorizontalPodAutoscaler\",\n apiVersions: [\"autoscaling/v1\", \"autoscaling/v2\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <HpaDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.HorizontalPodAutoscaler} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n // host order is [300 - priority], before native metrics at [-1]\n priority: 310,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NodeMonitoringDetails {...props} object={props.object as Renderer.K8sApi.Node} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Secret\",\n apiVersions: [\"v1\"],\n priority: 10,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <SecretCertificateDetails {...props} object={props.object as Renderer.K8sApi.Secret} />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n kubeObjectMenuItems = [\n ...([\"Pod\", \"Deployment\", \"DaemonSet\", \"StatefulSet\", \"ReplicaSet\", \"Job\", \"CronJob\"] as const).map((kind) => ({\n kind,\n apiVersions: kind === \"Pod\" ? [\"v1\"] : kind === \"Job\" || kind === \"CronJob\" ? [\"batch/v1\"] : [\"apps/v1\"],\n components: {\n MenuItem: (props: Renderer.Component.KubeObjectMenuProps<Renderer.K8sApi.KubeObject>) => (\n <PowerEnabled>\n <PowerLogsMenu {...props} />\n </PowerEnabled>\n ),\n },\n })),\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n components: {\n MenuItem: (props: Renderer.Component.KubeObjectMenuProps<Renderer.K8sApi.Node>) => (\n <PowerEnabled>\n <SecureNodeShellMenu {...props} />\n </PowerEnabled>\n ),\n },\n },\n ];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/renderer/index.tsx"],"sourcesContent":["/**\n * Copyright (c) Freelens Authors. All rights reserved.\n * Licensed under MIT License. See THIRD_PARTY_LICENSES for more information.\n */\n\nimport { Common, Renderer } from \"@freelensapp/extensions\";\nimport { computed, reaction } from \"mobx\";\nimport { observer } from \"mobx-react\";\nimport { EXTENSION_DISPLAY_NAME, EXTENSION_ID } from \"../common/extension-info\";\nimport { AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { AiShortcutsStore } from \"../common/store/ai-shortcuts-store\";\nimport { AppearancePreferencesStore } from \"../common/store/appearance-preferences-store\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\nimport { LogsPreferencesStore } from \"../common/store/logs-preferences-store\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { NodeShellPreferencesStore } from \"../common/store/node-shell-preferences-store\";\nimport { PowerPreferencesStore } from \"../common/store/power-preferences-store\";\nimport { ReadOnlyPreferencesStore } from \"../common/store/read-only-preferences-store\";\nimport { startAiChat } from \"./ai\";\nimport { startAppearanceOverride } from \"./appearance\";\nimport { startPowerButtonStyles } from \"./button-styles\";\nimport { ClusterIconsPage } from \"./cluster-icons\";\nimport { DashboardPage } from \"./dashboard\";\nimport { HpaDiagnosticsDetails } from \"./details/hpa-diagnostics-details\";\nimport { NamespaceHealthDetails } from \"./details/namespace-health-details\";\nimport { ResourceHealthDetails } from \"./details/resource-health-details\";\nimport { SecretCertificateDetails } from \"./details/secret-certificate-details\";\nimport { ServiceDiagnosticsDetails } from \"./details/service-diagnostics-details\";\nimport { DiagnosticsPage } from \"./diagnostics\";\nimport { type DiagnosticsResourceScope, focusDiagnosticsNamespace } from \"./diagnostics-state\";\nimport { SecureNodeShellMenu } from \"./menus/secure-node-shell-menu\";\nimport { startMonitoring } from \"./monitoring\";\nimport { startMonitoringCollector } from \"./monitoring-collector\";\nimport { startMonitoringHistoryCollection } from \"./monitoring-history-collection\";\nimport { NodeMonitoringDetails } from \"./node-monitoring\";\nimport { startPodDetailsEnhancements } from \"./pod-details-enhancements\";\nimport { startPodMonitoring } from \"./pod-monitoring\";\nimport { PowerLogsPage } from \"./power-logs\";\nimport { PowerLogsMenu, startPowerLogsEntrypoints } from \"./power-logs-entrypoints\";\nimport { PowerPreferences } from \"./preferences/preferences\";\nimport { openPreferencesSection } from \"./preferences/section-navigation\";\nimport { startReadOnlyMode } from \"./read-only\";\nimport { ResourceRelationshipsPage } from \"./resource-relationships\";\nimport { startResourceSearch } from \"./resource-search\";\nimport { startWelcomeOverride } from \"./welcome\";\n\nimport type { ReactNode } from \"react\";\n\nconst PowerEnabled = observer(({ children }: { children: ReactNode }) =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled ? <>{children}</> : null,\n);\n\nconst RelationshipsPage = observer(() => (\n <PowerEnabled>\n <ResourceRelationshipsPage\n enabled={MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible}\n />\n </PowerEnabled>\n));\n\nexport default class FreelensPowerRenderer extends Renderer.LensExtension {\n get name() {\n return EXTENSION_DISPLAY_NAME;\n }\n get sanitizedExtensionId() {\n return EXTENSION_ID;\n }\n get storeName() {\n return this.manifest.storeName || EXTENSION_ID;\n }\n\n private stopFeatures?: () => void;\n\n onActivate() {\n const power = PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>();\n power.loadExtension(this);\n LogsPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiShortcutsStore.getInstanceOrCreate().loadExtension(this);\n ReadOnlyPreferencesStore.getInstanceOrCreate().loadExtension(this);\n NodeShellPreferencesStore.getInstanceOrCreate().loadExtension(this);\n MonitoringPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AppearancePreferencesStore.getInstanceOrCreate().loadExtension(this);\n DashboardPreferencesStore.getInstanceOrCreate().loadExtension(this);\n this.stopFeatures?.();\n let disposers: (() => void)[] = [];\n const stop = reaction(\n () => power.enabled,\n (enabled) => {\n for (const dispose of disposers) dispose();\n disposers = [];\n if (enabled) {\n for (const start of [\n startReadOnlyMode,\n startMonitoringCollector,\n startMonitoringHistoryCollection,\n startMonitoring,\n startPodMonitoring,\n startPodDetailsEnhancements,\n startPowerButtonStyles,\n startAppearanceOverride,\n startWelcomeOverride,\n startAiChat,\n startResourceSearch,\n startPowerLogsEntrypoints,\n ]) {\n try {\n disposers.push(start());\n } catch {\n Common.logger.warn(\"[Freelens Power] feature could not start\", { feature: start.name });\n }\n }\n }\n },\n { fireImmediately: true },\n );\n this.stopFeatures = () => {\n stop();\n for (const dispose of disposers) dispose();\n disposers = [];\n };\n }\n\n onDeactivate() {\n this.stopFeatures?.();\n this.stopFeatures = undefined;\n }\n\n appPreferences = [\n {\n id: \"freelens-power-settings\",\n title: \"\",\n components: { Input: PowerPreferences, Hint: () => null },\n },\n ];\n\n globalPages = [\n {\n id: \"cluster-icons\",\n components: {\n Page: () => (\n <PowerEnabled>\n <ClusterIconsPage />\n </PowerEnabled>\n ),\n },\n },\n {\n id: \"dashboard\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DashboardPage\n onOpenPreferences={() => openPreferencesSection(\"dashboard\", () => this.navigateToPreferences())}\n />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPages = [\n {\n id: \"power-logs\",\n components: {\n Page: () => (\n <PowerEnabled>\n <PowerLogsPage />\n </PowerEnabled>\n ),\n },\n },\n { id: \"relationships\", components: { Page: () => <RelationshipsPage /> } },\n {\n id: \"diagnostics\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DiagnosticsPage />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPageMenus = [\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().diagnosticsVisible,\n ),\n target: { pageId: \"diagnostics\" },\n title: \"Diagnostics\",\n orderNumber: 5,\n components: { Icon: () => <Renderer.Component.Icon material=\"insights\" tooltip=\"Resource diagnostics\" /> },\n },\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible,\n ),\n id: \"relationships\",\n target: { pageId: \"relationships\" },\n title: \"Relationships\",\n orderNumber: 6,\n components: {\n Icon: () => <Renderer.Component.Icon material=\"account_tree\" tooltip=\"Resource relationships\" />,\n },\n },\n {\n id: \"power-logs\",\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n LogsPreferencesStore.getInstanceOrCreate<LogsPreferencesStore>().enabled,\n ),\n target: { pageId: \"power-logs\" },\n title: \"Power Logs\",\n orderNumber: 7,\n components: {\n Icon: () => <Renderer.Component.Icon material=\"subject\" tooltip=\"Workload logs and SQL captures\" />,\n },\n },\n ];\n\n topBarItems = [\n {\n components: {\n Item: () => (\n <PowerEnabled>\n <Renderer.Component.Icon\n material=\"battery_charging_full\"\n className=\"freelens-power-settings-icon\"\n tooltip=\"Freelens Power settings\"\n onClick={() => this.navigateToPreferences()}\n />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n private openDiagnostics = (namespace?: string, resourceScope?: DiagnosticsResourceScope) => {\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n if (clusterId && (namespace || resourceScope)) focusDiagnosticsNamespace(clusterId, namespace, resourceScope);\n void this.navigate(\"diagnostics\");\n };\n\n kubeObjectDetailItems: Renderer.LensExtension[\"kubeObjectDetailItems\"] = [\n ...[\"Pod\", \"Deployment\", \"StatefulSet\", \"DaemonSet\", \"Node\"].map((kind) => ({\n kind,\n apiVersions: kind === \"Pod\" || kind === \"Node\" ? [\"v1\"] : [\"apps/v1\"],\n priority: 320,\n components: {\n Details: (props: Renderer.Component.KubeObjectDetailsProps) => (\n <PowerEnabled>\n <ResourceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n })),\n {\n kind: \"Namespace\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NamespaceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Service\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <ServiceDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.Service} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"HorizontalPodAutoscaler\",\n apiVersions: [\"autoscaling/v1\", \"autoscaling/v2\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <HpaDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.HorizontalPodAutoscaler} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n // host order is [300 - priority], before native metrics at [-1]\n priority: 310,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NodeMonitoringDetails {...props} object={props.object as Renderer.K8sApi.Node} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Secret\",\n apiVersions: [\"v1\"],\n priority: 10,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <SecretCertificateDetails {...props} object={props.object as Renderer.K8sApi.Secret} />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n kubeObjectMenuItems = [\n ...([\"Pod\", \"Deployment\", \"DaemonSet\", \"StatefulSet\", \"ReplicaSet\", \"Job\", \"CronJob\"] as const).map((kind) => ({\n kind,\n apiVersions: kind === \"Pod\" ? [\"v1\"] : kind === \"Job\" || kind === \"CronJob\" ? [\"batch/v1\"] : [\"apps/v1\"],\n components: {\n MenuItem: (props: Renderer.Component.KubeObjectMenuProps<Renderer.K8sApi.KubeObject>) => (\n <PowerEnabled>\n <PowerLogsMenu {...props} />\n </PowerEnabled>\n ),\n },\n })),\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n components: {\n MenuItem: (props: Renderer.Component.KubeObjectMenuProps<Renderer.K8sApi.Node>) => (\n <PowerEnabled>\n <SecureNodeShellMenu {...props} />\n </PowerEnabled>\n ),\n },\n },\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,IAAM,eAAe,oCAAA,UAAU,EAAE,eAC/B,gCAAA,sBAAsB,oBAA2C,CAAC,CAAC,UAAU,oCAAA,IAAA,oBAAA,UAAA,EAAG,SAAW,CAAA,IAAI,IACjG;AAEA,IAAM,oBAAoB,oCAAA,eACxB,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,+BAAA,2BAAD,EACE,SAAS,qCAAA,2BAA2B,oBAAgD,CAAC,CAAC,qBACvF,CAAA,EACW,CAAA,CACf;AAED,IAAqB,wBAArB,cAAmD,mBAAA,SAAS,cAAc;CACxE,IAAI,OAAO;EACT,OAAO,uBAAA;CACT;CACA,IAAI,uBAAuB;EACzB,OAAO,uBAAA;CACT;CACA,IAAI,YAAY;EACd,OAAO,KAAK,SAAS,aAAA;CACvB;CAEA;CAEA,aAAa;EACX,MAAM,QAAQ,gCAAA,sBAAsB,oBAA2C;EAC/E,MAAM,cAAc,IAAI;EACxB,+BAAA,qBAAqB,oBAAoB,CAAC,CAAC,cAAc,IAAI;EAC7D,6BAAA,mBAAmB,oBAAoB,CAAC,CAAC,cAAc,IAAI;EAC3D,2BAAA,iBAAiB,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACzD,oCAAA,yBAAyB,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACjE,qCAAA,0BAA0B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EAClE,qCAAA,2BAA2B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACnE,qCAAA,2BAA2B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACnE,oCAAA,0BAA0B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EAClE,KAAK,eAAe;EACpB,IAAI,YAA4B,CAAC;EACjC,MAAM,OAAO,8BAAA,eACL,MAAM,UACX,YAAY;GACX,KAAK,MAAM,WAAW,WAAW,QAAQ;GACzC,YAAY,CAAC;GACb,IAAI,SACF,KAAK,MAAM,SAAS;IAClB,kBAAA;IACA,6BAAA;IACA,sCAAA;IACA,mBAAA;IACA,uBAAA;IACA,iCAAA;IACA,sBAAA;IACA,mBAAA;IACA,gBAAA;IACA,WAAA;IACA,wBAAA;IACA,+BAAA;GACF,GACE,IAAI;IACF,UAAU,KAAK,MAAM,CAAC;GACxB,QAAQ;IACN,mBAAA,OAAO,OAAO,KAAK,4CAA4C,EAAE,SAAS,MAAM,KAAK,CAAC;GACxF;EAGN,GACA,EAAE,iBAAiB,KAAK,CAC1B;EACA,KAAK,qBAAqB;GACxB,KAAK;GACL,KAAK,MAAM,WAAW,WAAW,QAAQ;GACzC,YAAY,CAAC;EACf;CACF;CAEA,eAAe;EACb,KAAK,eAAe;EACpB,KAAK,eAAe,KAAA;CACtB;CAEA,iBAAiB,CACf;EACE,IAAI;EACJ,OAAO;EACP,YAAY;GAAE,OAAO,oBAAA;GAAkB,YAAY;EAAK;CAC1D,CACF;CAEA,cAAc,CACZ;EACE,IAAI;EACJ,YAAY,EACV,YACE,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,sBAAA,kBAAD,CAAmB,CAAA,EACP,CAAA,EAElB;CACF,GACA;EACE,IAAI;EACJ,YAAY,EACV,YACE,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,kBAAA,eAAD,EACE,yBAAyB,2BAAA,uBAAuB,mBAAmB,KAAK,sBAAsB,CAAC,EAChG,CAAA,EACW,CAAA,EAElB;CACF,CACF;CAEA,eAAe;EACb;GACE,IAAI;GACJ,YAAY,EACV,YACE,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,mBAAA,eAAD,CAAgB,CAAA,EACJ,CAAA,EAElB;EACF;EACA;GAAE,IAAI;GAAiB,YAAY,EAAE,YAAY,oCAAA,IAAC,mBAAD,CAAoB,CAAA,EAAE;EAAE;EACzE;GACE,IAAI;GACJ,YAAY,EACV,YACE,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,oBAAA,iBAAD,CAAkB,CAAA,EACN,CAAA,EAElB;EACF;CACF;CAEA,mBAAmB;EACjB;GACE,SAAS,8BAAA,eAEL,gCAAA,sBAAsB,oBAA2C,CAAC,CAAC,WACnE,qCAAA,2BAA2B,oBAAgD,CAAC,CAAC,kBACjF;GACA,QAAQ,EAAE,QAAQ,cAAc;GAChC,OAAO;GACP,aAAa;GACb,YAAY,EAAE,YAAY,oCAAA,IAAC,mBAAA,SAAS,UAAU,MAApB;IAAyB,UAAS;IAAW,SAAQ;GAAwB,CAAA,EAAE;EAC3G;EACA;GACE,SAAS,8BAAA,eAEL,gCAAA,sBAAsB,oBAA2C,CAAC,CAAC,WACnE,qCAAA,2BAA2B,oBAAgD,CAAC,CAAC,oBACjF;GACA,IAAI;GACJ,QAAQ,EAAE,QAAQ,gBAAgB;GAClC,OAAO;GACP,aAAa;GACb,YAAY,EACV,YAAY,oCAAA,IAAC,mBAAA,SAAS,UAAU,MAApB;IAAyB,UAAS;IAAe,SAAQ;GAA0B,CAAA,EACjG;EACF;EACA;GACE,IAAI;GACJ,SAAS,8BAAA,eAEL,gCAAA,sBAAsB,oBAA2C,CAAC,CAAC,WACnE,+BAAA,qBAAqB,oBAA0C,CAAC,CAAC,OACrE;GACA,QAAQ,EAAE,QAAQ,aAAa;GAC/B,OAAO;GACP,aAAa;GACb,YAAY,EACV,YAAY,oCAAA,IAAC,mBAAA,SAAS,UAAU,MAApB;IAAyB,UAAS;IAAU,SAAQ;GAAkC,CAAA,EACpG;EACF;CACF;CAEA,cAAc,CACZ,EACE,YAAY,EACV,YACE,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,mBAAA,SAAS,UAAU,MAApB;EACE,UAAS;EACT,WAAU;EACV,SAAQ;EACR,eAAe,KAAK,sBAAsB;CAC3C,CAAA,EACW,CAAA,EAElB,EACF,CACF;CAEA,mBAA2B,WAAoB,kBAA6C;EAC1F,MAAM,YAAY,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS;EACjE,IAAI,cAAc,aAAa,gBAAgB,0BAAA,0BAA0B,WAAW,WAAW,aAAa;EAC5G,KAAU,SAAS,aAAa;CAClC;CAEA,wBAAyE;EACvE,GAAG;GAAC;GAAO;GAAc;GAAe;GAAa;EAAM,CAAC,CAAC,KAAK,UAAU;GAC1E;GACA,aAAa,SAAS,SAAS,SAAS,SAAS,CAAC,IAAI,IAAI,CAAC,SAAS;GACpE,UAAU;GACV,YAAY,EACV,UAAU,UACR,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,gCAAA,uBAAD;IAAuB,GAAI;IAAO,mBAAmB,KAAK;GAAkB,CAAA,EAChE,CAAA,EAElB;EACF,EAAE;EACF;GACE,MAAM;GACN,aAAa,CAAC,IAAI;GAClB,UAAU;GACV,YAAY,EACV,UAAU,UACR,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,iCAAA,wBAAD;IAAwB,GAAI;IAAO,mBAAmB,KAAK;GAAkB,CAAA,EACjE,CAAA,EAElB;EACF;EACA;GACE,MAAM;GACN,aAAa,CAAC,IAAI;GAClB,UAAU;GACV,YAAY,EACV,UAAU,UACR,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,oCAAA,2BAAD;IAA2B,GAAI;IAAO,QAAQ,MAAM;GAAoC,CAAA,EAC5E,CAAA,EAElB;EACF;EACA;GACE,MAAM;GACN,aAAa,CAAC,kBAAkB,gBAAgB;GAChD,UAAU;GACV,YAAY,EACV,UAAU,UACR,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,gCAAA,uBAAD;IAAuB,GAAI;IAAO,QAAQ,MAAM;GAAoD,CAAA,EACxF,CAAA,EAElB;EACF;EACA;GACE,MAAM;GACN,aAAa,CAAC,IAAI;GAElB,UAAU;GACV,YAAY,EACV,UAAU,UACR,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,wBAAA,uBAAD;IAAuB,GAAI;IAAO,QAAQ,MAAM;GAAiC,CAAA,EACrE,CAAA,EAElB;EACF;EACA;GACE,MAAM;GACN,aAAa,CAAC,IAAI;GAClB,UAAU;GACV,YAAY,EACV,UAAU,UACR,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,mCAAA,0BAAD;IAA0B,GAAI;IAAO,QAAQ,MAAM;GAAmC,CAAA,EAC1E,CAAA,EAElB;EACF;CACF;CAEA,sBAAsB,CACpB,GAAI;EAAC;EAAO;EAAc;EAAa;EAAe;EAAc;EAAO;CAAS,CAAC,CAAW,KAAK,UAAU;EAC7G;EACA,aAAa,SAAS,QAAQ,CAAC,IAAI,IAAI,SAAS,SAAS,SAAS,YAAY,CAAC,UAAU,IAAI,CAAC,SAAS;EACvG,YAAY,EACV,WAAW,UACT,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,+BAAA,eAAD,EAAe,GAAI,MAAQ,CAAA,EACf,CAAA,EAElB;CACF,EAAE,GACF;EACE,MAAM;EACN,aAAa,CAAC,IAAI;EAClB,YAAY,EACV,WAAW,UACT,oCAAA,IAAC,cAAD,EAAA,UACE,oCAAA,IAAC,+BAAA,qBAAD,EAAqB,GAAI,MAAQ,CAAA,EACrB,CAAA,EAElB;CACF,CACF;AACF"}
@@ -4,6 +4,7 @@ const require_monitoring_preferences_store = require("./src/common/store/monitor
4
4
  const require__global_external_react = require("./_virtual/_global-external_react.js");
5
5
  const require__global_external_react_dom = require("./_virtual/_global-external_react-dom.js");
6
6
  const require_jsx_runtime = require("./_virtual/_global-external_react/jsx-runtime.js");
7
+ const require_native_tooltip = require("./native-tooltip.js");
7
8
  const require_date_time = require("./src/common/date-time.js");
8
9
  const require_monitoring_math = require("./src/common/monitoring-math.js");
9
10
  const require_monitoring_collector = require("./monitoring-collector.js");
@@ -202,7 +203,6 @@ function MetricChart({ metric, samples, status, scope = "node", headerAction })
202
203
  display: "block"
203
204
  },
204
205
  children: [
205
- /* @__PURE__ */ require_jsx_runtime.jsx("title", { children: "Click to pin tooltip · click again or Escape to unpin" }),
206
206
  [
207
207
  0,
208
208
  .5,
@@ -263,27 +263,24 @@ function MetricChart({ metric, samples, status, scope = "node", headerAction })
263
263
  stroke: line.color,
264
264
  strokeWidth: "2",
265
265
  strokeDasharray: line.key === "capacity" || line.key === "allocatable" ? "5 3" : void 0
266
- }), gaps && /* @__PURE__ */ require_jsx_runtime.jsx("path", {
267
- "data-monitoring-gap": line.key,
268
- d: gaps,
269
- fill: "none",
270
- stroke: line.color,
271
- strokeWidth: "2",
272
- strokeDasharray: "3 4",
273
- opacity: ".65",
274
- children: /* @__PURE__ */ require_jsx_runtime.jsx("title", { children: "Dashed connections span missing measurements; intermediate values are unknown" })
266
+ }), gaps && /* @__PURE__ */ require_jsx_runtime.jsx(require_native_tooltip.NativeTooltip, {
267
+ title: "Dashed connections span missing measurements; intermediate values are unknown",
268
+ children: /* @__PURE__ */ require_jsx_runtime.jsx("path", {
269
+ "data-monitoring-gap": line.key,
270
+ d: gaps,
271
+ fill: "none",
272
+ stroke: line.color,
273
+ strokeWidth: "2",
274
+ strokeDasharray: "3 4",
275
+ opacity: ".65"
276
+ })
275
277
  })] }, line.key);
276
278
  }),
277
279
  samples.map((sample) => /* @__PURE__ */ require_jsx_runtime.jsx("circle", {
278
280
  cx: x(sample),
279
281
  cy: y(sample),
280
282
  r: "2",
281
- fill: "currentColor",
282
- children: /* @__PURE__ */ require_jsx_runtime.jsxs("title", { children: [
283
- require_date_time.formatDateTime(sample.time),
284
- ": ",
285
- format(sample[metric])
286
- ] })
283
+ fill: "currentColor"
287
284
  }, sample.time)),
288
285
  samples.length > 0 && [
289
286
  0,
@@ -554,9 +551,9 @@ function ResourceDonut({ metric, sample, status }) {
554
551
  gap: 6,
555
552
  fontSize: 12
556
553
  },
557
- children: [rings.map((ring) => /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
554
+ children: [rings.map((ring) => /* @__PURE__ */ require_jsx_runtime.jsx(require_native_tooltip.NativeTooltip, {
558
555
  title: `${ring.label} relative to allocatable capacity. ${ring.label === "Usage" ? `Unused allocatable (usage): ${unused}` : `Unrequested: ${unrequested}`}`,
559
- children: [
556
+ children: /* @__PURE__ */ require_jsx_runtime.jsxs("div", { children: [
560
557
  /* @__PURE__ */ require_jsx_runtime.jsx("span", {
561
558
  style: { color: ring.color },
562
559
  children: "●"
@@ -570,17 +567,17 @@ function ResourceDonut({ metric, sample, status }) {
570
567
  percentage(ring.value).toFixed(1),
571
568
  "%)"
572
569
  ] })
573
- ]
574
- }, ring.label)), /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
570
+ ] })
571
+ }, ring.label)), /* @__PURE__ */ require_jsx_runtime.jsx(require_native_tooltip.NativeTooltip, {
575
572
  title: allocationDetail,
576
- children: [
573
+ children: /* @__PURE__ */ require_jsx_runtime.jsxs("div", { children: [
577
574
  /* @__PURE__ */ require_jsx_runtime.jsx("span", {
578
575
  style: { color: "#5486b5" },
579
576
  children: "●"
580
577
  }),
581
578
  " Allocatable: ",
582
579
  available(denominator)
583
- ]
580
+ ] })
584
581
  })]
585
582
  }),
586
583
  (status || sample?.resourceStatus) && /* @__PURE__ */ require_jsx_runtime.jsx("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"monitoring.js","names":[],"sources":["../../src/renderer/monitoring.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { reaction } from \"mobx\";\nimport { type CSSProperties, type ReactNode, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { formatDateTime } from \"../common/date-time\";\nimport {\n aggregateMetrics,\n aggregateResources,\n MONITORING_INTERVAL as INTERVAL,\n MAX_SAMPLES,\n type MonitoringSample,\n} from \"../common/monitoring-math\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { getMonitoringSnapshot, retainMonitoringCollector } from \"./monitoring-collector\";\nimport { MonitoringHistoryRange, useMonitoringHistory } from \"./monitoring-history-view\";\n\nexport {\n aggregateMetrics,\n aggregateResources,\n effectivePodResource,\n MAX_SAMPLES,\n type MonitoringNode,\n type MonitoringPod,\n type MonitoringSample,\n parseQuantity,\n} from \"../common/monitoring-math\";\n\nexport function formatMonitoringTime(time: number): string {\n return new Date(time).toLocaleTimeString([], {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hourCycle: \"h23\",\n });\n}\n\nfunction ResourceTitle({ metric, label }: { metric: \"cpu\" | \"memory\"; label?: string }) {\n return (\n <strong style={{ display: \"inline-flex\", alignItems: \"center\", gap: 6 }}>\n <span className=\"Icon material\" aria-hidden=\"true\" style={{ \"--size\": \"18px\", fontWeight: 400 } as CSSProperties}>\n <span className=\"icon\">{metric === \"cpu\" ? \"developer_board\" : \"memory\"}</span>\n </span>\n {label ?? (metric === \"cpu\" ? \"CPU\" : \"Memory\")}\n </strong>\n );\n}\n\nexport function MetricChart({\n metric,\n samples,\n status,\n scope = \"node\",\n headerAction,\n}: {\n metric: \"cpu\" | \"memory\";\n samples: MonitoringSample[];\n status: string;\n scope?: \"node\" | \"pod\";\n headerAction?: ReactNode;\n}) {\n const [selectedTime, setSelectedTime] = useState<number>();\n const [pinned, setPinned] = useState(false);\n const previousMetric = useRef(metric);\n useEffect(() => {\n if (\n previousMetric.current !== metric ||\n (selectedTime !== undefined && !samples.some((sample) => sample.time === selectedTime))\n ) {\n setPinned(false);\n setSelectedTime(undefined);\n }\n previousMetric.current = metric;\n }, [metric, samples, selectedTime]);\n useEffect(() => {\n if (!pinned) return;\n const escape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n event.stopPropagation();\n setPinned(false);\n setSelectedTime(undefined);\n }\n };\n document.addEventListener(\"keydown\", escape, true);\n return () => document.removeEventListener(\"keydown\", escape, true);\n }, [pinned]);\n const chartRef = useRef<SVGSVGElement>(null);\n const [width, setWidth] = useState(600);\n useLayoutEffect(() => {\n const chart = chartRef.current;\n if (!chart) return;\n const measure = () => {\n const measured = chart.getBoundingClientRect().width;\n if (measured > 0) setWidth(measured);\n };\n measure();\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(measure);\n observer?.observe(chart);\n window.addEventListener(\"resize\", measure);\n return () => {\n observer?.disconnect();\n window.removeEventListener(\"resize\", measure);\n };\n }, []);\n const plotWidth = Math.max(1, width - 112);\n const last = samples.at(-1);\n const selected = samples.find((sample) => sample.time === selectedTime);\n const label = metric === \"cpu\" ? \"CPU\" : \"Memory\";\n const format = (value: number) =>\n metric === \"cpu\" ? `${value.toFixed(2)} cores` : `${(value / 1024 ** 3).toFixed(2)} GiB`;\n const series = [\n { key: \"usage\", label: \"Usage\", color: \"#c93dce\", value: (sample: MonitoringSample) => sample[metric] },\n ...([\"requests\", \"allocatable\", \"capacity\"] as const).map((key) => ({\n key,\n label: { requests: \"Requests\", allocatable: \"Allocatable Capacity\", capacity: \"Capacity\" }[key],\n color: { requests: \"#4caf50\", allocatable: \"#5486b5\", capacity: \"var(--textColorSecondary)\" }[key],\n value: (sample: MonitoringSample) => sample.resources?.[metric][key],\n })),\n ];\n const visibleSeries =\n scope === \"pod\" ? series.filter((line) => line.key === \"usage\" || line.key === \"requests\") : series;\n const max =\n Math.max(\n ...samples.flatMap((sample) => [\n ...visibleSeries.map((line) => line.value(sample) ?? 0),\n sample.historical?.[metric]?.max ?? 0,\n ]),\n 0.001,\n ) * 1.1;\n const end = last?.time ?? Date.now();\n const start = samples[0]?.time ?? end;\n const duration = Math.max(end - start, INTERVAL);\n const x = (sample: MonitoringSample) => 88 + ((sample.time - start) / duration) * plotWidth;\n const y = (sample: MonitoringSample) => 208 - (sample[metric] / max) * 184;\n const selectNearest = (event: React.MouseEvent<SVGSVGElement>) => {\n const bounds = event.currentTarget.getBoundingClientRect();\n if (!bounds.width || !samples.length) return;\n const scale = Math.min(bounds.width / width, (bounds.height || 250) / 250);\n const offset = (bounds.width - width * scale) / 2;\n const position = (event.clientX - bounds.left - offset) / scale;\n const time = start + ((position - 88) / plotWidth) * duration;\n const nearest = samples.reduce((nearest, sample) =>\n Math.abs(sample.time - time) < Math.abs(nearest.time - time) ? sample : nearest,\n ).time;\n setSelectedTime(nearest);\n return nearest;\n };\n return (\n <section\n aria-label={`${label} metrics-server usage`}\n style={{\n padding: \"var(--power-monitoring-trend-top, 16px) 16px 16px\",\n background: \"var(--contentColor)\",\n minWidth: 0,\n minHeight: 280,\n position: \"relative\",\n }}\n >\n {headerAction && <div className=\"power-monitoring-period-action\">{headerAction}</div>}\n <div\n data-monitoring-heading=\"\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n flexWrap: \"wrap\",\n gap: 12,\n paddingRight: headerAction ? 100 : 0,\n minHeight: headerAction ? 32 : undefined,\n }}\n >\n <ResourceTitle metric={metric} />\n <span>{status ? \"Unavailable\" : last ? format(last[metric]) : \"Collecting…\"}</span>\n </div>\n <svg\n ref={chartRef}\n data-monitoring-trend=\"\"\n viewBox={`0 0 ${width} 250`}\n role=\"img\"\n tabIndex={0}\n aria-label={`${label} usage over collected samples. Use arrow keys to inspect samples. Click or press Enter to pin the tooltip, Escape to dismiss`}\n onMouseMove={(event) => {\n if (!pinned) selectNearest(event);\n }}\n onClick={(event) => {\n if (pinned) setPinned(false);\n else if (samples.length) {\n if (selectNearest(event) === undefined && !selected) setSelectedTime(last?.time);\n setPinned(true);\n }\n }}\n onMouseLeave={() => {\n if (!pinned) setSelectedTime(undefined);\n }}\n onFocus={() => {\n if (!pinned) setSelectedTime(last?.time);\n }}\n onBlur={() => {\n if (!pinned) setSelectedTime(undefined);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n if (samples.length) {\n if (!selected) setSelectedTime(last?.time);\n setPinned(!pinned);\n }\n return;\n }\n if (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\") return;\n event.preventDefault();\n const index = samples.findIndex((sample) => sample.time === selectedTime);\n setSelectedTime(\n samples[\n Math.max(\n 0,\n Math.min(\n samples.length - 1,\n (index < 0 ? samples.length - 1 : index) + (event.key === \"ArrowLeft\" ? -1 : 1),\n ),\n )\n ]?.time,\n );\n }}\n style={{ width: \"100%\", height: 250, color: \"#c93dce\", display: \"block\" }}\n >\n <title>Click to pin tooltip · click again or Escape to unpin</title>\n {[0, 0.5, 1].map((fraction) => (\n <g key={fraction}>\n <line\n x1=\"88\"\n x2={width - 24}\n y1={208 - fraction * 184}\n y2={208 - fraction * 184}\n stroke=\"var(--borderFaintColor)\"\n />\n <text x=\"80\" y={212 - fraction * 184} textAnchor=\"end\" fill=\"var(--textColorSecondary)\" fontSize=\"11\">\n {format(max * fraction)}\n </text>\n </g>\n ))}\n {samples.map((sample) => {\n const summary = sample.historical?.[metric];\n if (!summary || summary.min === summary.max) return null;\n return (\n <line\n key={`range:${sample.time}`}\n data-monitoring-extrema=\"\"\n x1={x(sample)}\n x2={x(sample)}\n y1={208 - (summary.max / max) * 184}\n y2={208 - (summary.min / max) * 184}\n stroke=\"#c93dce\"\n strokeOpacity={0.35}\n strokeWidth={4}\n />\n );\n })}\n {visibleSeries.map((line) => {\n let path = \"\";\n let gaps = \"\";\n let previous: { sample: MonitoringSample; point: string } | undefined;\n let interrupted = false;\n for (const sample of samples) {\n const value = line.value(sample);\n if (value === undefined || !Number.isFinite(value)) {\n interrupted = true;\n continue;\n }\n const point = `${x(sample)},${208 - (value / max) * 184}`;\n const gap =\n previous &&\n (interrupted ||\n sample.breakBefore ||\n sample.time - previous.sample.time >\n 1.8 *\n Math.max(\n sample.historical?.[metric]?.resolution ?? INTERVAL,\n previous.sample.historical?.[metric]?.resolution ?? INTERVAL,\n ));\n path += ` ${!previous || gap ? \"M\" : \"L\"}${point}`;\n if (previous && gap) gaps += ` M${previous.point} L${point}`;\n previous = { sample, point };\n interrupted = false;\n }\n return (\n <g key={line.key}>\n <path\n data-monitoring-series={line.key}\n d={path}\n fill=\"none\"\n stroke={line.color}\n strokeWidth=\"2\"\n strokeDasharray={line.key === \"capacity\" || line.key === \"allocatable\" ? \"5 3\" : undefined}\n />\n {gaps && (\n <path\n data-monitoring-gap={line.key}\n d={gaps}\n fill=\"none\"\n stroke={line.color}\n strokeWidth=\"2\"\n strokeDasharray=\"3 4\"\n opacity=\".65\"\n >\n <title>Dashed connections span missing measurements; intermediate values are unknown</title>\n </path>\n )}\n </g>\n );\n })}\n {samples.map((sample) => (\n <circle key={sample.time} cx={x(sample)} cy={y(sample)} r=\"2\" fill=\"currentColor\">\n <title>\n {formatDateTime(sample.time)}: {format(sample[metric])}\n </title>\n </circle>\n ))}\n {samples.length > 0 &&\n [0, 0.5, 1].map((fraction) => (\n <text\n key={fraction}\n x={88 + fraction * plotWidth}\n y=\"235\"\n textAnchor={fraction === 0 ? \"start\" : fraction === 1 ? \"end\" : \"middle\"}\n fill=\"var(--textColorSecondary)\"\n fontSize=\"11\"\n >\n {formatMonitoringTime(start + fraction * duration)}\n </text>\n ))}\n {selected && (\n <line\n data-monitoring-crosshair=\"\"\n x1={x(selected)}\n x2={x(selected)}\n y1=\"24\"\n y2=\"208\"\n stroke=\"var(--textColorSecondary)\"\n strokeDasharray=\"4 3\"\n />\n )}\n </svg>\n <style>{`\n @keyframes freelens-power-metric-tooltip-enter { from { opacity:0; transform:translateY(2px) } to { opacity:1; transform:translateY(0) } }\n [data-monitoring-tooltip] { animation:freelens-power-metric-tooltip-enter 140ms ease-out }\n @media (prefers-reduced-motion:reduce) { [data-monitoring-tooltip] { animation:none } }\n `}</style>\n {selected && (\n <div\n data-monitoring-tooltip=\"\"\n role=\"tooltip\"\n style={{\n position: \"absolute\",\n top: 44,\n right: 24,\n padding: 8,\n background: \"var(--contentColor)\",\n border: \"1px solid var(--borderFaintColor)\",\n pointerEvents: \"none\",\n }}\n >\n <div style={{ whiteSpace: \"pre-wrap\" }}>\n {formatDateTime(selected.time)}\n {pinned ? \" · Pinned\" : \"\"}\n </div>\n {visibleSeries.map((line) => (\n <div key={line.key} style={{ color: line.color }}>\n {line.label}: {line.value(selected) === undefined ? \"Unavailable\" : format(line.value(selected)!)}\n </div>\n ))}\n {selected.historical?.[metric] && (\n <div>\n Min: {format(selected.historical[metric]!.min)} · Max: {format(selected.historical[metric]!.max)}\n <br />\n {selected.historical[metric]!.count} samples ·{\" \"}\n {Math.round(selected.historical[metric]!.resolution / 1000)}s bucket\n </div>\n )}\n <div style={{ color: \"var(--textColorSecondary)\", marginTop: 4, fontSize: 10 }}>\n {pinned ? \"Click chart or Escape to unpin\" : \"Click or Enter to pin\"}\n </div>\n </div>\n )}\n <div\n aria-label={`${label} chart legend`}\n style={{ display: \"flex\", flexWrap: \"wrap\", gap: \"6px 16px\", marginBottom: 8 }}\n >\n {visibleSeries.map((line) => (\n <span key={line.key}>\n <span style={{ color: line.color }}>●</span> {line.label}\n </span>\n ))}\n </div>\n {last?.resourceStatus && (\n <div role=\"status\" style={{ color: \"var(--textColorSecondary)\", marginBottom: 8 }}>\n {last.resourceStatus}\n </div>\n )}\n {(scope === \"node\" || status || !samples.length) && (\n <div\n style={{ fontSize: 11, color: \"var(--textColorSecondary)\", display: \"flex\", alignItems: \"center\", gap: 4 }}\n role=\"status\"\n aria-label={`${scope} metrics status`}\n >\n {scope === \"node\" && (\n <sup aria-hidden=\"true\" style={{ fontSize: 12 }}>\n *\n </sup>\n )}\n <span>{status || (samples.length ? \"metrics-server data\" : \"Waiting for metrics-server data\")}</span>\n </div>\n )}\n </section>\n );\n}\n\nfunction ResourceDonut({\n metric,\n sample,\n status,\n}: {\n metric: \"cpu\" | \"memory\";\n sample?: MonitoringSample;\n status: string;\n}) {\n const [activeRing, setActiveRing] = useState<number>();\n useEffect(() => {\n if (activeRing === undefined) return;\n const dismiss = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n event.preventDefault();\n event.stopPropagation();\n setActiveRing(undefined);\n };\n document.addEventListener(\"keydown\", dismiss, true);\n return () => document.removeEventListener(\"keydown\", dismiss, true);\n }, [activeRing]);\n const label = metric === \"cpu\" ? \"CPU\" : \"Memory\";\n const totals = sample?.resources?.[metric];\n const format = (value: number) =>\n metric === \"cpu\" ? `${value.toFixed(2)} cores` : `${(value / 1024 ** 3).toFixed(2)} GiB`;\n const available = (value?: number) => (value === undefined ? \"Unavailable\" : format(value));\n const denominator = totals?.allocatable;\n const rings = [\n { label: \"Usage\", color: \"#c93dce\", value: sample?.[metric] },\n { label: \"Requests\", color: \"#4caf50\", value: totals?.requests },\n ];\n const percentage = (value?: number) =>\n value !== undefined && denominator !== undefined && denominator > 0 ? (value / denominator) * 100 : undefined;\n const usagePercent = percentage(sample?.[metric]);\n const unused =\n sample?.completeUsage && denominator !== undefined ? format(denominator - sample[metric]) : \"Unavailable\";\n const unrequested =\n denominator !== undefined && totals?.requests !== undefined ? format(denominator - totals.requests) : \"Unavailable\";\n const allocationDetail = `Allocatable: ${available(denominator)}. Schedulable capacity after system reservations, used as the denominator for both rings. Physical Capacity: ${available(totals?.capacity)}. Unused allocatable (usage): ${unused}. Unrequested: ${unrequested}`;\n const hovered = activeRing === undefined ? undefined : rings[activeRing];\n const tooltipId = `power-monitoring-${metric}-donut-tooltip`;\n return (\n <section\n aria-label={`${label} resource summary`}\n style={{\n padding: \"var(--power-monitoring-summary-top, 16px) 16px 16px\",\n minWidth: 0,\n background: \"var(--contentColor)\",\n position: \"relative\",\n overflow: \"visible\",\n }}\n >\n <ResourceTitle metric={metric} label={metric === \"memory\" ? \"RAM\" : \"CPU\"} />\n <svg\n data-monitoring-donut=\"\"\n viewBox=\"0 0 200 200\"\n role=\"img\"\n aria-label={`${label} usage and requests relative to allocatable capacity`}\n style={{ display: \"block\", width: \"100%\", height: 200 }}\n >\n {rings.map((ring, index) => {\n const radius = 76 - index * 18;\n const percent = percentage(ring.value);\n const detail = `${ring.label}: ${available(ring.value)}${percent === undefined ? \"\" : ` (${percent.toFixed(1)}% of allocatable${percent > 100 ? \", over allocatable\" : \"\"})`}`;\n return (\n <g\n key={ring.label}\n tabIndex={0}\n role=\"img\"\n aria-label={detail}\n aria-describedby={activeRing === index ? tooltipId : undefined}\n onMouseEnter={() => setActiveRing(index)}\n onMouseMove={() => setActiveRing(index)}\n onMouseLeave={() => setActiveRing(undefined)}\n onFocus={() => setActiveRing(index)}\n onBlur={() => setActiveRing(undefined)}\n >\n <circle cx=\"100\" cy=\"100\" r={radius} fill=\"none\" stroke=\"var(--borderFaintColor)\" strokeWidth=\"12\" />\n {percent !== undefined && (\n <circle\n data-monitoring-ring={ring.label}\n cx=\"100\"\n cy=\"100\"\n r={radius}\n fill=\"none\"\n stroke={ring.color}\n strokeWidth=\"12\"\n pathLength=\"100\"\n strokeDasharray={`${Math.min(100, Math.max(0, percent))} 100`}\n transform=\"rotate(-90 100 100)\"\n />\n )}\n </g>\n );\n })}\n <text\n data-monitoring-usage-percentage=\"\"\n x=\"100\"\n y=\"100\"\n textAnchor=\"middle\"\n fill=\"var(--textColorPrimary)\"\n fontSize=\"26\"\n fontWeight=\"600\"\n >\n {usagePercent === undefined ? \"N/A\" : `${usagePercent.toFixed(1)}%`}\n </text>\n <text x=\"100\" y=\"120\" textAnchor=\"middle\" fill=\"var(--textColorPrimary)\" fontSize=\"12\">\n Usage\n </text>\n </svg>\n {hovered && (\n <div\n id={tooltipId}\n data-monitoring-tooltip=\"\"\n role=\"tooltip\"\n style={{\n position: \"absolute\",\n top: 48,\n left: 8,\n right: 8,\n zIndex: 20,\n padding: 8,\n border: \"1px solid var(--borderFaintColor)\",\n background: \"var(--contentColor)\",\n pointerEvents: \"none\",\n overflowWrap: \"anywhere\",\n boxShadow: \"0 3px 12px #0003\",\n }}\n >\n <div style={{ color: hovered.color }}>\n {hovered.label}: {available(hovered.value)}\n </div>\n <div>\n {percentage(hovered.value) === undefined\n ? \"Percentage unavailable\"\n : `${percentage(hovered.value)!.toFixed(1)}% of allocatable${percentage(hovered.value)! > 100 ? \" (over allocatable)\" : \"\"}`}\n </div>\n <div>Allocatable: {available(denominator)}</div>\n </div>\n )}\n <div aria-label={`${label} resource totals`} style={{ display: \"grid\", gap: 6, fontSize: 12 }}>\n {rings.map((ring) => (\n <div\n key={ring.label}\n title={`${ring.label} relative to allocatable capacity. ${ring.label === \"Usage\" ? `Unused allocatable (usage): ${unused}` : `Unrequested: ${unrequested}`}`}\n >\n <span style={{ color: ring.color }}>●</span> {ring.label}: {available(ring.value)}\n {percentage(ring.value) !== undefined && <span> ({percentage(ring.value)!.toFixed(1)}%)</span>}\n </div>\n ))}\n <div title={allocationDetail}>\n <span style={{ color: \"#5486b5\" }}>●</span> Allocatable: {available(denominator)}\n </div>\n </div>\n {(status || sample?.resourceStatus) && (\n <div role=\"status\" style={{ color: \"var(--textColorSecondary)\", fontSize: 11, marginTop: 8 }}>\n {status || sample?.resourceStatus}\n </div>\n )}\n </section>\n );\n}\n\nfunction MonitoringCharts({ samples, status }: { samples: MonitoringSample[]; status: string }) {\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n const history = useMonitoringHistory(\n clusterId ? { clusterId, scope: \"cluster\", uid: clusterId } : undefined,\n samples,\n );\n return (\n <div style={{ containerType: \"inline-size\" }}>\n <style>{`\n [data-monitoring-layout] { display:grid; grid-template-columns:minmax(0,1.6fr) minmax(0,1.6fr) minmax(0,1fr) minmax(0,1fr); gap:16px; align-items:stretch }\n [data-monitoring-trends], [data-monitoring-summaries] { display:contents }\n .power-monitoring-period-action { position:absolute;right:16px;top:19px }\n @container (min-width: 961px) {\n [data-monitoring-summaries] > section { --power-monitoring-summary-top:16px }\n }\n @container (max-width: 960px) {\n [data-monitoring-layout] { grid-template-columns:repeat(2,minmax(0,1fr)) }\n .power-ai-overview-actions + [data-testid=\"cluster-overview-page\"] [data-monitoring-trends] > section { --power-monitoring-trend-top:56px }\n }\n @container (max-width: 580px) {\n [data-monitoring-layout] { grid-template-columns:minmax(0,1fr) }\n .power-monitoring-period-action { left:16px;right:auto;top:15px }\n [data-monitoring-trends] > section:first-child { --power-monitoring-trend-top:56px }\n .power-ai-overview-actions + [data-testid=\"cluster-overview-page\"] [data-monitoring-trends] > section:not(:first-child) { --power-monitoring-trend-top:16px }\n }\n `}</style>\n {history.status && (\n <small role=\"status\" style={{ display: \"block\", color: \"var(--textColorSecondary)\", marginBottom: 8 }}>\n {history.status}\n </small>\n )}\n <div data-monitoring-layout=\"\">\n <div data-monitoring-trends=\"\">\n {([\"cpu\", \"memory\"] as const).map((metric) => (\n <MetricChart\n key={metric}\n metric={metric}\n samples={history.samples}\n status={status}\n headerAction={\n metric === \"cpu\" ? (\n <MonitoringHistoryRange compact range={history.range} onChange={history.setRange} />\n ) : undefined\n }\n />\n ))}\n </div>\n <div data-monitoring-summaries=\"\">\n {([\"cpu\", \"memory\"] as const).map((metric) => (\n <ResourceDonut key={metric} metric={metric} sample={samples.at(-1)} status={status} />\n ))}\n </div>\n </div>\n </div>\n );\n}\n\nexport function startMonitoring(): () => void {\n const release = retainMonitoringCollector();\n const preferences = MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>();\n let stopCurrent: (() => void) | undefined;\n const stop = reaction(\n () => preferences.enabled,\n (enabled) => {\n stopCurrent?.();\n stopCurrent = enabled ? mountMonitoring() : undefined;\n },\n { fireImmediately: true },\n );\n return () => {\n stop();\n stopCurrent?.();\n release();\n };\n}\n\nfunction mountMonitoring(): () => void {\n const suppression = document.createElement(\"style\");\n suppression.setAttribute(\"data-freelens-power-native-metrics-suppression\", \"\");\n suppression.textContent = `\n .Nodes .TableCell:is(.cpu, .memory) .LineProgress:has(> .line.secondary) {\n overflow:hidden;\n }\n .Nodes .TableCell:is(.cpu, .memory) .LineProgress:has(> .line.secondary) > .line {\n border-radius:0;\n }\n .Nodes .TableCell:is(.cpu, .memory) .LineProgress:has(> .line.secondary) > .line:not(.secondary) {\n height:60%;\n }\n .Nodes .TableCell:is(.cpu, .memory) .LineProgress > .line.secondary {\n top:60%;\n height:40%;\n opacity:1;\n background:color-mix(in srgb, currentColor 65%, var(--mainBackground));\n }\n [data-testid=\"cluster-overview-page\"] > [class*=\"ClusterMetrics\"],\n [data-testid=\"cluster-overview-page\"] > :has([class*=\"ClusterMetrics\"]),\n [data-testid=\"cluster-overview-page\"] > :is([class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"]):not(:has(.PieChart)),\n [data-testid=\"cluster-overview-page\"] > :has([class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"], [class*=\"cluster-pie-charts\"][class*=\"empty\"]):not(:has(.PieChart)) {\n display:none !important;\n }\n `;\n document.head.append(suppression);\n let host: HTMLElement | undefined;\n let overview: Element | null = null;\n let samples: MonitoringSample[] = [];\n let status = \"\";\n let renderedSamples: MonitoringSample[] | undefined;\n let renderedStatus: string | undefined;\n let cluster: string | undefined;\n let stopped = false;\n let pendingGeneration: number | undefined;\n let generation = 0;\n let nextSample = 0;\n const hidden = new Map<HTMLElement, string | null>();\n const restore = () => {\n for (const [element, original] of hidden) {\n if (original === null) element.removeAttribute(\"style\");\n else element.setAttribute(\"style\", original);\n }\n hidden.clear();\n if (host) {\n ReactDOM.unmountComponentAtNode(host);\n host.remove();\n host = undefined;\n renderedSamples = undefined;\n renderedStatus = undefined;\n }\n };\n const update = async () => {\n const currentCluster = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n const currentOverview = document.querySelector('[data-testid=\"cluster-overview-page\"]');\n if (cluster !== currentCluster || overview !== currentOverview) {\n generation++;\n restore();\n samples = [];\n status = \"\";\n nextSample = 0;\n cluster = currentCluster;\n overview = currentOverview;\n }\n const cutoff = Date.now() - MAX_SAMPLES * INTERVAL;\n if (samples.length && samples[0].time < cutoff) samples = samples.filter((sample) => sample.time >= cutoff);\n if (!overview || !cluster || document.visibilityState === \"hidden\") return;\n if (!host) {\n host = document.createElement(\"div\");\n host.setAttribute(\"data-freelens-power-monitoring\", \"\");\n host.style.gridColumn = \"1 / -1\";\n hidden.set(overview as HTMLElement, overview.getAttribute(\"style\"));\n Object.assign((overview as HTMLElement).style, {\n gridTemplateAreas: \"none\",\n gridTemplateColumns: \"minmax(0, 1fr)\",\n gridTemplateRows: \"none\",\n height: \"auto\",\n });\n overview.prepend(host);\n }\n for (const title of overview.querySelectorAll<HTMLElement>(\".PieChart > .chart-title\")) {\n if (title.textContent !== \"CPU\" && title.textContent !== \"Memory\") continue;\n const panel = title.closest(\".PieChart\")?.parentElement;\n if (panel && panel.style.display !== \"none\") {\n if (!hidden.has(panel)) hidden.set(panel, panel.getAttribute(\"style\"));\n panel.style.display = \"none\";\n }\n }\n // native CSS modules retain [ClusterMetrics] in the generated class name\n for (const child of overview.children) {\n if (!(child instanceof HTMLElement) || child === host) continue;\n const nativeMetrics =\n child.matches('[class*=\"ClusterMetrics\"]') || child.querySelector('[class*=\"ClusterMetrics\"]');\n const unavailablePies =\n (child.matches('[class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"]') ||\n child.querySelector(\n '[class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"], [class*=\"cluster-pie-charts\"][class*=\"empty\"]',\n )) &&\n !child.querySelector(\".PieChart\");\n if ((nativeMetrics || unavailablePies) && child.style.display !== \"none\") {\n if (!hidden.has(child)) hidden.set(child, child.getAttribute(\"style\"));\n child.style.display = \"none\";\n }\n if (!hidden.has(child)) hidden.set(child, child.getAttribute(\"style\"));\n child.style.gridArea = \"auto\";\n }\n const render = () => {\n if (host && (renderedSamples !== samples || renderedStatus !== status)) {\n ReactDOM.render(<MonitoringCharts samples={samples} status={status} />, host);\n renderedSamples = samples;\n renderedStatus = status;\n }\n };\n render();\n if (pendingGeneration === generation || Date.now() < nextSample) return;\n pendingGeneration = generation;\n nextSample = Date.now() + INTERVAL;\n const requestGeneration = generation;\n const isCurrent = () =>\n !stopped &&\n requestGeneration === generation &&\n document.visibilityState !== \"hidden\" &&\n overview?.isConnected === true &&\n Renderer.Catalog.activeCluster.get()?.metadata.uid === cluster;\n try {\n const collected = await getMonitoringSnapshot();\n const metrics =\n collected.nodeMetrics === undefined\n ? { status: \"rejected\" as const }\n : { status: \"fulfilled\" as const, value: collected.nodeMetrics };\n const inventory =\n collected.nodes === undefined\n ? { status: \"rejected\" as const }\n : { status: \"fulfilled\" as const, value: collected.nodes };\n const pods =\n collected.pods === undefined\n ? { status: \"rejected\" as const }\n : { status: \"fulfilled\" as const, value: collected.pods };\n if (!isCurrent()) return;\n if (metrics.status !== \"fulfilled\") throw new Error(\"Metrics unavailable\");\n const sample = aggregateMetrics(metrics.value ?? []);\n sample.time = Math.min(...metrics.value.map((item) => Date.parse(item.timestamp)));\n const warnings: string[] = [];\n if (inventory.status === \"fulfilled\") {\n try {\n sample.resources = aggregateResources(\n inventory.value ?? [],\n pods.status === \"fulfilled\" ? (pods.value ?? undefined) : undefined,\n );\n const expected = new Set((inventory.value ?? []).map((node) => node.metadata.name));\n const observed = new Set((metrics.value ?? []).map((node) => node.metadata.name));\n sample.completeUsage =\n expected.size > 0 && expected.size === observed.size && [...expected].every((name) => observed.has(name));\n if (!sample.completeUsage)\n warnings.push(\n \"Partial node metrics coverage: usage is the reported subset; unused allocatable unavailable\",\n );\n } catch {\n warnings.push(\"Resource totals unavailable: incomplete or invalid node/pod data\");\n }\n } else\n warnings.push(\"Node inventory unavailable or access denied; usage coverage unverified, capacity unavailable\");\n if (pods.status !== \"fulfilled\")\n warnings.push(\"Cluster-wide Pods unavailable or access denied; requests unavailable\");\n sample.resourceStatus = warnings.join(\". \");\n samples = [...samples.filter((entry) => entry.time !== sample.time), sample]\n .sort((a, b) => a.time - b.time)\n .slice(-MAX_SAMPLES);\n status = \"\";\n } catch {\n if (!isCurrent()) return;\n status = \"Node metrics unavailable, stale or access denied. Last collected samples remain visible.\";\n } finally {\n if (pendingGeneration === requestGeneration) pendingGeneration = undefined;\n }\n if (!stopped && requestGeneration === generation) render();\n };\n const observer = new MutationObserver(() => {\n void update();\n });\n observer.observe(document.body, { childList: true, subtree: true });\n const timer = window.setInterval(() => {\n void update();\n }, 1000);\n void update();\n return () => {\n stopped = true;\n generation++;\n window.clearInterval(timer);\n observer.disconnect();\n suppression.remove();\n restore();\n samples = [];\n };\n}\n"],"mappings":";;;;;;;;;;;AA2BA,SAAgB,qBAAqB,MAAsB;CACzD,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,mBAAmB,CAAC,GAAG;EAC3C,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,WAAW;CACb,CAAC;AACH;AAEA,SAAS,cAAc,EAAE,QAAQ,SAAuD;CACtF,OACE,oCAAA,KAAC,UAAD;EAAQ,OAAO;GAAE,SAAS;GAAe,YAAY;GAAU,KAAK;EAAE;YAAtE,CACE,oCAAA,IAAC,QAAD;GAAM,WAAU;GAAgB,eAAY;GAAO,OAAO;IAAE,UAAU;IAAQ,YAAY;GAAI;aAC5F,oCAAA,IAAC,QAAD;IAAM,WAAU;cAAQ,WAAW,QAAQ,oBAAoB;GAAe,CAAA;EAC1E,CAAA,GACL,UAAU,WAAW,QAAQ,QAAQ,SAChC;;AAEZ;AAEA,SAAgB,YAAY,EAC1B,QACA,SACA,QACA,QAAQ,QACR,gBAOC;CACD,MAAM,CAAC,cAAc,mBAAmB,+BAAA,SAAiB;CACzD,MAAM,CAAC,QAAQ,aAAa,+BAAA,SAAS,KAAK;CAC1C,MAAM,iBAAiB,+BAAA,OAAO,MAAM;CACpC,+BAAA,gBAAgB;EACd,IACE,eAAe,YAAY,UAC1B,iBAAiB,KAAA,KAAa,CAAC,QAAQ,MAAM,WAAW,OAAO,SAAS,YAAY,GACrF;GACA,UAAU,KAAK;GACf,gBAAgB,KAAA,CAAS;EAC3B;EACA,eAAe,UAAU;CAC3B,GAAG;EAAC;EAAQ;EAAS;CAAY,CAAC;CAClC,+BAAA,gBAAgB;EACd,IAAI,CAAC,QAAQ;EACb,MAAM,UAAU,UAAyB;GACvC,IAAI,MAAM,QAAQ,UAAU;IAC1B,MAAM,eAAe;IACrB,MAAM,gBAAgB;IACtB,UAAU,KAAK;IACf,gBAAgB,KAAA,CAAS;GAC3B;EACF;EACA,SAAS,iBAAiB,WAAW,QAAQ,IAAI;EACjD,aAAa,SAAS,oBAAoB,WAAW,QAAQ,IAAI;CACnE,GAAG,CAAC,MAAM,CAAC;CACX,MAAM,WAAW,+BAAA,OAAsB,IAAI;CAC3C,MAAM,CAAC,OAAO,YAAY,+BAAA,SAAS,GAAG;CACtC,+BAAA,sBAAsB;EACpB,MAAM,QAAQ,SAAS;EACvB,IAAI,CAAC,OAAO;EACZ,MAAM,gBAAgB;GACpB,MAAM,WAAW,MAAM,sBAAsB,CAAC,CAAC;GAC/C,IAAI,WAAW,GAAG,SAAS,QAAQ;EACrC;EACA,QAAQ;EACR,MAAM,WAAW,OAAO,mBAAmB,cAAc,KAAA,IAAY,IAAI,eAAe,OAAO;EAC/F,UAAU,QAAQ,KAAK;EACvB,OAAO,iBAAiB,UAAU,OAAO;EACzC,aAAa;GACX,UAAU,WAAW;GACrB,OAAO,oBAAoB,UAAU,OAAO;EAC9C;CACF,GAAG,CAAC,CAAC;CACL,MAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,GAAG;CACzC,MAAM,OAAO,QAAQ,GAAG,EAAE;CAC1B,MAAM,WAAW,QAAQ,MAAM,WAAW,OAAO,SAAS,YAAY;CACtE,MAAM,QAAQ,WAAW,QAAQ,QAAQ;CACzC,MAAM,UAAU,UACd,WAAW,QAAQ,GAAG,MAAM,QAAQ,CAAC,EAAE,UAAU,IAAI,QAAQ,QAAQ,EAAA,CAAG,QAAQ,CAAC,EAAE;CACrF,MAAM,SAAS,CACb;EAAE,KAAK;EAAS,OAAO;EAAS,OAAO;EAAW,QAAQ,WAA6B,OAAO;CAAQ,GACtG,GAAI;EAAC;EAAY;EAAe;CAAU,CAAC,CAAW,KAAK,SAAS;EAClE;EACA,OAAO;GAAE,UAAU;GAAY,aAAa;GAAwB,UAAU;EAAW,EAAE;EAC3F,OAAO;GAAE,UAAU;GAAW,aAAa;GAAW,UAAU;EAA4B,EAAE;EAC9F,QAAQ,WAA6B,OAAO,YAAY,OAAO,CAAC;CAClE,EAAE,CACJ;CACA,MAAM,gBACJ,UAAU,QAAQ,OAAO,QAAQ,SAAS,KAAK,QAAQ,WAAW,KAAK,QAAQ,UAAU,IAAI;CAC/F,MAAM,MACJ,KAAK,IACH,GAAG,QAAQ,SAAS,WAAW,CAC7B,GAAG,cAAc,KAAK,SAAS,KAAK,MAAM,MAAM,KAAK,CAAC,GACtD,OAAO,aAAa,OAAO,EAAE,OAAO,CACtC,CAAC,GACD,IACF,IAAI;CACN,MAAM,MAAM,MAAM,QAAQ,KAAK,IAAI;CACnC,MAAM,QAAQ,QAAQ,EAAE,EAAE,QAAQ;CAClC,MAAM,WAAW,KAAK,IAAI,MAAM,OAAO,wBAAA,mBAAQ;CAC/C,MAAM,KAAK,WAA6B,MAAO,OAAO,OAAO,SAAS,WAAY;CAClF,MAAM,KAAK,WAA6B,MAAO,OAAO,UAAU,MAAO;CACvE,MAAM,iBAAiB,UAA2C;EAChE,MAAM,SAAS,MAAM,cAAc,sBAAsB;EACzD,IAAI,CAAC,OAAO,SAAS,CAAC,QAAQ,QAAQ;EACtC,MAAM,QAAQ,KAAK,IAAI,OAAO,QAAQ,QAAQ,OAAO,UAAU,OAAO,GAAG;EACzE,MAAM,UAAU,OAAO,QAAQ,QAAQ,SAAS;EAEhD,MAAM,OAAO,UADK,MAAM,UAAU,OAAO,OAAO,UAAU,QACxB,MAAM,YAAa;EACrD,MAAM,UAAU,QAAQ,QAAQ,SAAS,WACvC,KAAK,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,IAAI,QAAQ,OAAO,IAAI,IAAI,SAAS,OAC1E,CAAC,CAAC;EACF,gBAAgB,OAAO;EACvB,OAAO;CACT;CACA,OACE,oCAAA,KAAC,WAAD;EACE,cAAY,GAAG,MAAM;EACrB,OAAO;GACL,SAAS;GACT,YAAY;GACZ,UAAU;GACV,WAAW;GACX,UAAU;EACZ;YARF;GAUG,gBAAgB,oCAAA,IAAC,OAAD;IAAK,WAAU;cAAkC;GAAkB,CAAA;GACpF,oCAAA,KAAC,OAAD;IACE,2BAAwB;IACxB,OAAO;KACL,SAAS;KACT,YAAY;KACZ,UAAU;KACV,KAAK;KACL,cAAc,eAAe,MAAM;KACnC,WAAW,eAAe,KAAK,KAAA;IACjC;cATF,CAWE,oCAAA,IAAC,eAAD,EAAuB,OAAS,CAAA,GAChC,oCAAA,IAAC,QAAD,EAAA,UAAO,SAAS,gBAAgB,OAAO,OAAO,KAAK,OAAO,IAAI,cAAoB,CAAA,CAC/E;;GACL,oCAAA,KAAC,OAAD;IACE,KAAK;IACL,yBAAsB;IACtB,SAAS,OAAO,MAAM;IACtB,MAAK;IACL,UAAU;IACV,cAAY,GAAG,MAAM;IACrB,cAAc,UAAU;KACtB,IAAI,CAAC,QAAQ,cAAc,KAAK;IAClC;IACA,UAAU,UAAU;KAClB,IAAI,QAAQ,UAAU,KAAK;UACtB,IAAI,QAAQ,QAAQ;MACvB,IAAI,cAAc,KAAK,MAAM,KAAA,KAAa,CAAC,UAAU,gBAAgB,MAAM,IAAI;MAC/E,UAAU,IAAI;KAChB;IACF;IACA,oBAAoB;KAClB,IAAI,CAAC,QAAQ,gBAAgB,KAAA,CAAS;IACxC;IACA,eAAe;KACb,IAAI,CAAC,QAAQ,gBAAgB,MAAM,IAAI;IACzC;IACA,cAAc;KACZ,IAAI,CAAC,QAAQ,gBAAgB,KAAA,CAAS;IACxC;IACA,YAAY,UAAU;KACpB,IAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;MAC9C,MAAM,eAAe;MACrB,IAAI,QAAQ,QAAQ;OAClB,IAAI,CAAC,UAAU,gBAAgB,MAAM,IAAI;OACzC,UAAU,CAAC,MAAM;MACnB;MACA;KACF;KACA,IAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,cAAc;KAC7D,MAAM,eAAe;KACrB,MAAM,QAAQ,QAAQ,WAAW,WAAW,OAAO,SAAS,YAAY;KACxE,gBACE,QACE,KAAK,IACH,GACA,KAAK,IACH,QAAQ,SAAS,IAChB,QAAQ,IAAI,QAAQ,SAAS,IAAI,UAAU,MAAM,QAAQ,cAAc,KAAK,EAC/E,CACF,EACD,EAAE,IACL;IACF;IACA,OAAO;KAAE,OAAO;KAAQ,QAAQ;KAAK,OAAO;KAAW,SAAS;IAAQ;cAlD1E;KAoDE,oCAAA,IAAC,SAAD,EAAA,UAAO,wDAA4D,CAAA;KAClE;MAAC;MAAG;MAAK;KAAC,CAAC,CAAC,KAAK,aAChB,oCAAA,KAAC,KAAD,EAAA,UAAA,CACE,oCAAA,IAAC,QAAD;MACE,IAAG;MACH,IAAI,QAAQ;MACZ,IAAI,MAAM,WAAW;MACrB,IAAI,MAAM,WAAW;MACrB,QAAO;KACR,CAAA,GACD,oCAAA,IAAC,QAAD;MAAM,GAAE;MAAK,GAAG,MAAM,WAAW;MAAK,YAAW;MAAM,MAAK;MAA4B,UAAS;gBAC9F,OAAO,MAAM,QAAQ;KAClB,CAAA,CACL,EAAA,GAXK,QAWL,CACJ;KACA,QAAQ,KAAK,WAAW;MACvB,MAAM,UAAU,OAAO,aAAa;MACpC,IAAI,CAAC,WAAW,QAAQ,QAAQ,QAAQ,KAAK,OAAO;MACpD,OACE,oCAAA,IAAC,QAAD;OAEE,2BAAwB;OACxB,IAAI,EAAE,MAAM;OACZ,IAAI,EAAE,MAAM;OACZ,IAAI,MAAO,QAAQ,MAAM,MAAO;OAChC,IAAI,MAAO,QAAQ,MAAM,MAAO;OAChC,QAAO;OACP,eAAe;OACf,aAAa;MACd,GATM,SAAS,OAAO,MAStB;KAEL,CAAC;KACA,cAAc,KAAK,SAAS;MAC3B,IAAI,OAAO;MACX,IAAI,OAAO;MACX,IAAI;MACJ,IAAI,cAAc;MAClB,KAAK,MAAM,UAAU,SAAS;OAC5B,MAAM,QAAQ,KAAK,MAAM,MAAM;OAC/B,IAAI,UAAU,KAAA,KAAa,CAAC,OAAO,SAAS,KAAK,GAAG;QAClD,cAAc;QACd;OACF;OACA,MAAM,QAAQ,GAAG,EAAE,MAAM,EAAE,GAAG,MAAO,QAAQ,MAAO;OACpD,MAAM,MACJ,aACC,eACC,OAAO,eACP,OAAO,OAAO,SAAS,OAAO,OAC5B,MACE,KAAK,IACH,OAAO,aAAa,OAAO,EAAE,cAAA,KAC7B,SAAS,OAAO,aAAa,OAAO,EAAE,cAAA,GACxC;OACR,QAAQ,IAAI,CAAC,YAAY,MAAM,MAAM,MAAM;OAC3C,IAAI,YAAY,KAAK,QAAQ,KAAK,SAAS,MAAM,IAAI;OACrD,WAAW;QAAE;QAAQ;OAAM;OAC3B,cAAc;MAChB;MACA,OACE,oCAAA,KAAC,KAAD,EAAA,UAAA,CACE,oCAAA,IAAC,QAAD;OACE,0BAAwB,KAAK;OAC7B,GAAG;OACH,MAAK;OACL,QAAQ,KAAK;OACb,aAAY;OACZ,iBAAiB,KAAK,QAAQ,cAAc,KAAK,QAAQ,gBAAgB,QAAQ,KAAA;MAClF,CAAA,GACA,QACC,oCAAA,IAAC,QAAD;OACE,uBAAqB,KAAK;OAC1B,GAAG;OACH,MAAK;OACL,QAAQ,KAAK;OACb,aAAY;OACZ,iBAAgB;OAChB,SAAQ;iBAER,oCAAA,IAAC,SAAD,EAAA,UAAO,gFAAoF,CAAA;MACvF,CAAA,CAEP,EAAA,GAtBK,KAAK,GAsBV;KAEP,CAAC;KACA,QAAQ,KAAK,WACZ,oCAAA,IAAC,UAAD;MAA0B,IAAI,EAAE,MAAM;MAAG,IAAI,EAAE,MAAM;MAAG,GAAE;MAAI,MAAK;gBACjE,oCAAA,KAAC,SAAD,EAAA,UAAA;OACG,kBAAA,eAAe,OAAO,IAAI;OAAE;OAAG,OAAO,OAAO,OAAO;MAChD,EAAA,CAAA;KACD,GAJK,OAAO,IAIZ,CACT;KACA,QAAQ,SAAS,KAChB;MAAC;MAAG;MAAK;KAAC,CAAC,CAAC,KAAK,aACf,oCAAA,IAAC,QAAD;MAEE,GAAG,KAAK,WAAW;MACnB,GAAE;MACF,YAAY,aAAa,IAAI,UAAU,aAAa,IAAI,QAAQ;MAChE,MAAK;MACL,UAAS;gBAER,qBAAqB,QAAQ,WAAW,QAAQ;KAC7C,GARC,QAQD,CACP;KACF,YACC,oCAAA,IAAC,QAAD;MACE,6BAA0B;MAC1B,IAAI,EAAE,QAAQ;MACd,IAAI,EAAE,QAAQ;MACd,IAAG;MACH,IAAG;MACH,QAAO;MACP,iBAAgB;KACjB,CAAA;IAEA;;GACL,oCAAA,IAAC,SAAD,EAAA,UAAQ;;;;QAIC,CAAA;GACR,YACC,oCAAA,KAAC,OAAD;IACE,2BAAwB;IACxB,MAAK;IACL,OAAO;KACL,UAAU;KACV,KAAK;KACL,OAAO;KACP,SAAS;KACT,YAAY;KACZ,QAAQ;KACR,eAAe;IACjB;cAXF;KAaE,oCAAA,KAAC,OAAD;MAAK,OAAO,EAAE,YAAY,WAAW;gBAArC,CACG,kBAAA,eAAe,SAAS,IAAI,GAC5B,SAAS,cAAc,EACrB;;KACJ,cAAc,KAAK,SAClB,oCAAA,KAAC,OAAD;MAAoB,OAAO,EAAE,OAAO,KAAK,MAAM;gBAA/C;OACG,KAAK;OAAM;OAAG,KAAK,MAAM,QAAQ,MAAM,KAAA,IAAY,gBAAgB,OAAO,KAAK,MAAM,QAAQ,CAAE;MAC7F;QAFK,KAAK,GAEV,CACN;KACA,SAAS,aAAa,WACrB,oCAAA,KAAC,OAAD,EAAA,UAAA;MAAK;MACG,OAAO,SAAS,WAAW,OAAO,CAAE,GAAG;MAAE;MAAS,OAAO,SAAS,WAAW,OAAO,CAAE,GAAG;MAC/F,oCAAA,IAAC,MAAD,CAAK,CAAA;MACJ,SAAS,WAAW,OAAO,CAAE;MAAM;MAAW;MAC9C,KAAK,MAAM,SAAS,WAAW,OAAO,CAAE,aAAa,GAAI;MAAE;KACzD,EAAA,CAAA;KAEP,oCAAA,IAAC,OAAD;MAAK,OAAO;OAAE,OAAO;OAA6B,WAAW;OAAG,UAAU;MAAG;gBAC1E,SAAS,mCAAmC;KAC1C,CAAA;IACF;;GAEP,oCAAA,IAAC,OAAD;IACE,cAAY,GAAG,MAAM;IACrB,OAAO;KAAE,SAAS;KAAQ,UAAU;KAAQ,KAAK;KAAY,cAAc;IAAE;cAE5E,cAAc,KAAK,SAClB,oCAAA,KAAC,QAAD,EAAA,UAAA;KACE,oCAAA,IAAC,QAAD;MAAM,OAAO,EAAE,OAAO,KAAK,MAAM;gBAAG;KAAO,CAAA;KAAC;KAAE,KAAK;IAC/C,EAAA,GAFK,KAAK,GAEV,CACP;GACE,CAAA;GACJ,MAAM,kBACL,oCAAA,IAAC,OAAD;IAAK,MAAK;IAAS,OAAO;KAAE,OAAO;KAA6B,cAAc;IAAE;cAC7E,KAAK;GACH,CAAA;IAEL,UAAU,UAAU,UAAU,CAAC,QAAQ,WACvC,oCAAA,KAAC,OAAD;IACE,OAAO;KAAE,UAAU;KAAI,OAAO;KAA6B,SAAS;KAAQ,YAAY;KAAU,KAAK;IAAE;IACzG,MAAK;IACL,cAAY,GAAG,MAAM;cAHvB,CAKG,UAAU,UACT,oCAAA,IAAC,OAAD;KAAK,eAAY;KAAO,OAAO,EAAE,UAAU,GAAG;eAAG;IAE5C,CAAA,GAEP,oCAAA,IAAC,QAAD,EAAA,UAAO,WAAW,QAAQ,SAAS,wBAAwB,mCAAyC,CAAA,CACjG;;EAEA;;AAEb;AAEA,SAAS,cAAc,EACrB,QACA,QACA,UAKC;CACD,MAAM,CAAC,YAAY,iBAAiB,+BAAA,SAAiB;CACrD,+BAAA,gBAAgB;EACd,IAAI,eAAe,KAAA,GAAW;EAC9B,MAAM,WAAW,UAAyB;GACxC,IAAI,MAAM,QAAQ,UAAU;GAC5B,MAAM,eAAe;GACrB,MAAM,gBAAgB;GACtB,cAAc,KAAA,CAAS;EACzB;EACA,SAAS,iBAAiB,WAAW,SAAS,IAAI;EAClD,aAAa,SAAS,oBAAoB,WAAW,SAAS,IAAI;CACpE,GAAG,CAAC,UAAU,CAAC;CACf,MAAM,QAAQ,WAAW,QAAQ,QAAQ;CACzC,MAAM,SAAS,QAAQ,YAAY;CACnC,MAAM,UAAU,UACd,WAAW,QAAQ,GAAG,MAAM,QAAQ,CAAC,EAAE,UAAU,IAAI,QAAQ,QAAQ,EAAA,CAAG,QAAQ,CAAC,EAAE;CACrF,MAAM,aAAa,UAAoB,UAAU,KAAA,IAAY,gBAAgB,OAAO,KAAK;CACzF,MAAM,cAAc,QAAQ;CAC5B,MAAM,QAAQ,CACZ;EAAE,OAAO;EAAS,OAAO;EAAW,OAAO,SAAS;CAAQ,GAC5D;EAAE,OAAO;EAAY,OAAO;EAAW,OAAO,QAAQ;CAAS,CACjE;CACA,MAAM,cAAc,UAClB,UAAU,KAAA,KAAa,gBAAgB,KAAA,KAAa,cAAc,IAAK,QAAQ,cAAe,MAAM,KAAA;CACtG,MAAM,eAAe,WAAW,SAAS,OAAO;CAChD,MAAM,SACJ,QAAQ,iBAAiB,gBAAgB,KAAA,IAAY,OAAO,cAAc,OAAO,OAAO,IAAI;CAC9F,MAAM,cACJ,gBAAgB,KAAA,KAAa,QAAQ,aAAa,KAAA,IAAY,OAAO,cAAc,OAAO,QAAQ,IAAI;CACxG,MAAM,mBAAmB,gBAAgB,UAAU,WAAW,EAAE,+GAA+G,UAAU,QAAQ,QAAQ,EAAE,gCAAgC,OAAO,iBAAiB;CACnQ,MAAM,UAAU,eAAe,KAAA,IAAY,KAAA,IAAY,MAAM;CAC7D,MAAM,YAAY,oBAAoB,OAAO;CAC7C,OACE,oCAAA,KAAC,WAAD;EACE,cAAY,GAAG,MAAM;EACrB,OAAO;GACL,SAAS;GACT,UAAU;GACV,YAAY;GACZ,UAAU;GACV,UAAU;EACZ;YARF;GAUE,oCAAA,IAAC,eAAD;IAAuB;IAAQ,OAAO,WAAW,WAAW,QAAQ;GAAQ,CAAA;GAC5E,oCAAA,KAAC,OAAD;IACE,yBAAsB;IACtB,SAAQ;IACR,MAAK;IACL,cAAY,GAAG,MAAM;IACrB,OAAO;KAAE,SAAS;KAAS,OAAO;KAAQ,QAAQ;IAAI;cALxD;KAOG,MAAM,KAAK,MAAM,UAAU;MAC1B,MAAM,SAAS,KAAK,QAAQ;MAC5B,MAAM,UAAU,WAAW,KAAK,KAAK;MAErC,OACE,oCAAA,KAAC,KAAD;OAEE,UAAU;OACV,MAAK;OACL,cAAY,GANE,KAAK,MAAM,IAAI,UAAU,KAAK,KAAK,IAAI,YAAY,KAAA,IAAY,KAAK,KAAK,QAAQ,QAAQ,CAAC,EAAE,kBAAkB,UAAU,MAAM,uBAAuB,GAAG;OAOtK,oBAAkB,eAAe,QAAQ,YAAY,KAAA;OACrD,oBAAoB,cAAc,KAAK;OACvC,mBAAmB,cAAc,KAAK;OACtC,oBAAoB,cAAc,KAAA,CAAS;OAC3C,eAAe,cAAc,KAAK;OAClC,cAAc,cAAc,KAAA,CAAS;iBAVvC,CAYE,oCAAA,IAAC,UAAD;QAAQ,IAAG;QAAM,IAAG;QAAM,GAAG;QAAQ,MAAK;QAAO,QAAO;QAA0B,aAAY;OAAM,CAAA,GACnG,YAAY,KAAA,KACX,oCAAA,IAAC,UAAD;QACE,wBAAsB,KAAK;QAC3B,IAAG;QACH,IAAG;QACH,GAAG;QACH,MAAK;QACL,QAAQ,KAAK;QACb,aAAY;QACZ,YAAW;QACX,iBAAiB,GAAG,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,EAAE;QACxD,WAAU;OACX,CAAA,CAEF;SA1BI,KAAK,KA0BT;KAEP,CAAC;KACD,oCAAA,IAAC,QAAD;MACE,oCAAiC;MACjC,GAAE;MACF,GAAE;MACF,YAAW;MACX,MAAK;MACL,UAAS;MACT,YAAW;gBAEV,iBAAiB,KAAA,IAAY,QAAQ,GAAG,aAAa,QAAQ,CAAC,EAAE;KAC7D,CAAA;KACN,oCAAA,IAAC,QAAD;MAAM,GAAE;MAAM,GAAE;MAAM,YAAW;MAAS,MAAK;MAA0B,UAAS;gBAAK;KAEjF,CAAA;IACH;;GACJ,WACC,oCAAA,KAAC,OAAD;IACE,IAAI;IACJ,2BAAwB;IACxB,MAAK;IACL,OAAO;KACL,UAAU;KACV,KAAK;KACL,MAAM;KACN,OAAO;KACP,QAAQ;KACR,SAAS;KACT,QAAQ;KACR,YAAY;KACZ,eAAe;KACf,cAAc;KACd,WAAW;IACb;cAhBF;KAkBE,oCAAA,KAAC,OAAD;MAAK,OAAO,EAAE,OAAO,QAAQ,MAAM;gBAAnC;OACG,QAAQ;OAAM;OAAG,UAAU,QAAQ,KAAK;MACtC;;KACL,oCAAA,IAAC,OAAD,EAAA,UACG,WAAW,QAAQ,KAAK,MAAM,KAAA,IAC3B,2BACA,GAAG,WAAW,QAAQ,KAAK,CAAC,CAAE,QAAQ,CAAC,EAAE,kBAAkB,WAAW,QAAQ,KAAK,IAAK,MAAM,wBAAwB,KACvH,CAAA;KACL,oCAAA,KAAC,OAAD,EAAA,UAAA,CAAK,iBAAc,UAAU,WAAW,CAAO,EAAA,CAAA;IAC5C;;GAEP,oCAAA,KAAC,OAAD;IAAK,cAAY,GAAG,MAAM;IAAmB,OAAO;KAAE,SAAS;KAAQ,KAAK;KAAG,UAAU;IAAG;cAA5F,CACG,MAAM,KAAK,SACV,oCAAA,KAAC,OAAD;KAEE,OAAO,GAAG,KAAK,MAAM,qCAAqC,KAAK,UAAU,UAAU,+BAA+B,WAAW,gBAAgB;eAF/I;MAIE,oCAAA,IAAC,QAAD;OAAM,OAAO,EAAE,OAAO,KAAK,MAAM;iBAAG;MAAO,CAAA;MAAC;MAAE,KAAK;MAAM;MAAG,UAAU,KAAK,KAAK;MAC/E,WAAW,KAAK,KAAK,MAAM,KAAA,KAAa,oCAAA,KAAC,QAAD,EAAA,UAAA;OAAM;OAAG,WAAW,KAAK,KAAK,CAAC,CAAE,QAAQ,CAAC;OAAE;MAAQ,EAAA,CAAA;KAC1F;OALE,KAAK,KAKP,CACN,GACD,oCAAA,KAAC,OAAD;KAAK,OAAO;eAAZ;MACE,oCAAA,IAAC,QAAD;OAAM,OAAO,EAAE,OAAO,UAAU;iBAAG;MAAO,CAAA;MAAC;MAAe,UAAU,WAAW;KAC5E;MACF;;IACH,UAAU,QAAQ,mBAClB,oCAAA,IAAC,OAAD;IAAK,MAAK;IAAS,OAAO;KAAE,OAAO;KAA6B,UAAU;KAAI,WAAW;IAAE;cACxF,UAAU,QAAQ;GAChB,CAAA;EAEA;;AAEb;AAEA,SAAS,iBAAiB,EAAE,SAAS,UAA2D;CAC9F,MAAM,YAAY,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS;CACjE,MAAM,UAAU,gCAAA,qBACd,YAAY;EAAE;EAAW,OAAO;EAAW,KAAK;CAAU,IAAI,KAAA,GAC9D,OACF;CACA,OACE,oCAAA,KAAC,OAAD;EAAK,OAAO,EAAE,eAAe,cAAc;YAA3C;GACE,oCAAA,IAAC,SAAD,EAAA,UAAQ;;;;;;;;;;;;;;;;;MAiBD,CAAA;GACN,QAAQ,UACP,oCAAA,IAAC,SAAD;IAAO,MAAK;IAAS,OAAO;KAAE,SAAS;KAAS,OAAO;KAA6B,cAAc;IAAE;cACjG,QAAQ;GACJ,CAAA;GAET,oCAAA,KAAC,OAAD;IAAK,0BAAuB;cAA5B,CACE,oCAAA,IAAC,OAAD;KAAK,0BAAuB;eACxB,CAAC,OAAO,QAAQ,CAAC,CAAW,KAAK,WACjC,oCAAA,IAAC,aAAD;MAEU;MACR,SAAS,QAAQ;MACT;MACR,cACE,WAAW,QACT,oCAAA,IAAC,gCAAA,wBAAD;OAAwB,SAAA;OAAQ,OAAO,QAAQ;OAAO,UAAU,QAAQ;MAAW,CAAA,IACjF,KAAA;KAEP,GATM,MASN,CACF;IACE,CAAA,GACL,oCAAA,IAAC,OAAD;KAAK,6BAA0B;eAC3B,CAAC,OAAO,QAAQ,CAAC,CAAW,KAAK,WACjC,oCAAA,IAAC,eAAD;MAAoC;MAAQ,QAAQ,QAAQ,GAAG,EAAE;MAAW;KAAS,GAAjE,MAAiE,CACtF;IACE,CAAA,CACF;;EACF;;AAET;AAEA,SAAgB,kBAA8B;CAC5C,MAAM,UAAU,6BAAA,0BAA0B;CAC1C,MAAM,cAAc,qCAAA,2BAA2B,oBAAgD;CAC/F,IAAI;CACJ,MAAM,OAAO,8BAAA,eACL,YAAY,UACjB,YAAY;EACX,cAAc;EACd,cAAc,UAAU,gBAAgB,IAAI,KAAA;CAC9C,GACA,EAAE,iBAAiB,KAAK,CAC1B;CACA,aAAa;EACX,KAAK;EACL,cAAc;EACd,QAAQ;CACV;AACF;AAEA,SAAS,kBAA8B;CACrC,MAAM,cAAc,SAAS,cAAc,OAAO;CAClD,YAAY,aAAa,kDAAkD,EAAE;CAC7E,YAAY,cAAc;;;;;;;;;;;;;;;;;;;;;;;CAuB1B,SAAS,KAAK,OAAO,WAAW;CAChC,IAAI;CACJ,IAAI,WAA2B;CAC/B,IAAI,UAA8B,CAAC;CACnC,IAAI,SAAS;CACb,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI,UAAU;CACd,IAAI;CACJ,IAAI,aAAa;CACjB,IAAI,aAAa;CACjB,MAAM,yBAAS,IAAI,IAAgC;CACnD,MAAM,gBAAgB;EACpB,KAAK,MAAM,CAAC,SAAS,aAAa,QAChC,IAAI,aAAa,MAAM,QAAQ,gBAAgB,OAAO;OACjD,QAAQ,aAAa,SAAS,QAAQ;EAE7C,OAAO,MAAM;EACb,IAAI,MAAM;GACR,mCAAA,QAAS,uBAAuB,IAAI;GACpC,KAAK,OAAO;GACZ,OAAO,KAAA;GACP,kBAAkB,KAAA;GAClB,iBAAiB,KAAA;EACnB;CACF;CACA,MAAM,SAAS,YAAY;EACzB,MAAM,iBAAiB,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS;EACtE,MAAM,kBAAkB,SAAS,cAAc,yCAAuC;EACtF,IAAI,YAAY,kBAAkB,aAAa,iBAAiB;GAC9D;GACA,QAAQ;GACR,UAAU,CAAC;GACX,SAAS;GACT,aAAa;GACb,UAAU;GACV,WAAW;EACb;EACA,MAAM,SAAS,KAAK,IAAI,IAAA,KAAkB,wBAAA;EAC1C,IAAI,QAAQ,UAAU,QAAQ,EAAE,CAAC,OAAO,QAAQ,UAAU,QAAQ,QAAQ,WAAW,OAAO,QAAQ,MAAM;EAC1G,IAAI,CAAC,YAAY,CAAC,WAAW,SAAS,oBAAoB,UAAU;EACpE,IAAI,CAAC,MAAM;GACT,OAAO,SAAS,cAAc,KAAK;GACnC,KAAK,aAAa,kCAAkC,EAAE;GACtD,KAAK,MAAM,aAAa;GACxB,OAAO,IAAI,UAAyB,SAAS,aAAa,OAAO,CAAC;GAClE,OAAO,OAAQ,SAAyB,OAAO;IAC7C,mBAAmB;IACnB,qBAAqB;IACrB,kBAAkB;IAClB,QAAQ;GACV,CAAC;GACD,SAAS,QAAQ,IAAI;EACvB;EACA,KAAK,MAAM,SAAS,SAAS,iBAA8B,0BAA0B,GAAG;GACtF,IAAI,MAAM,gBAAgB,SAAS,MAAM,gBAAgB,UAAU;GACnE,MAAM,QAAQ,MAAM,QAAQ,WAAW,CAAC,EAAE;GAC1C,IAAI,SAAS,MAAM,MAAM,YAAY,QAAQ;IAC3C,IAAI,CAAC,OAAO,IAAI,KAAK,GAAG,OAAO,IAAI,OAAO,MAAM,aAAa,OAAO,CAAC;IACrE,MAAM,MAAM,UAAU;GACxB;EACF;EAEA,KAAK,MAAM,SAAS,SAAS,UAAU;GACrC,IAAI,EAAE,iBAAiB,gBAAgB,UAAU,MAAM;GACvD,MAAM,gBACJ,MAAM,QAAQ,6BAA2B,KAAK,MAAM,cAAc,6BAA2B;GAC/F,MAAM,mBACH,MAAM,QAAQ,8DAA0D,KACvE,MAAM,cACJ,iHACF,MACF,CAAC,MAAM,cAAc,WAAW;GAClC,KAAK,iBAAiB,oBAAoB,MAAM,MAAM,YAAY,QAAQ;IACxE,IAAI,CAAC,OAAO,IAAI,KAAK,GAAG,OAAO,IAAI,OAAO,MAAM,aAAa,OAAO,CAAC;IACrE,MAAM,MAAM,UAAU;GACxB;GACA,IAAI,CAAC,OAAO,IAAI,KAAK,GAAG,OAAO,IAAI,OAAO,MAAM,aAAa,OAAO,CAAC;GACrE,MAAM,MAAM,WAAW;EACzB;EACA,MAAM,eAAe;GACnB,IAAI,SAAS,oBAAoB,WAAW,mBAAmB,SAAS;IACtE,mCAAA,QAAS,OAAO,oCAAA,IAAC,kBAAD;KAA2B;KAAiB;IAAS,CAAA,GAAG,IAAI;IAC5E,kBAAkB;IAClB,iBAAiB;GACnB;EACF;EACA,OAAO;EACP,IAAI,sBAAsB,cAAc,KAAK,IAAI,IAAI,YAAY;EACjE,oBAAoB;EACpB,aAAa,KAAK,IAAI,IAAI,wBAAA;EAC1B,MAAM,oBAAoB;EAC1B,MAAM,kBACJ,CAAC,WACD,sBAAsB,cACtB,SAAS,oBAAoB,YAC7B,UAAU,gBAAgB,QAC1B,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS,QAAQ;EACzD,IAAI;GACF,MAAM,YAAY,MAAM,6BAAA,sBAAsB;GAC9C,MAAM,UACJ,UAAU,gBAAgB,KAAA,IACtB,EAAE,QAAQ,WAAoB,IAC9B;IAAE,QAAQ;IAAsB,OAAO,UAAU;GAAY;GACnE,MAAM,YACJ,UAAU,UAAU,KAAA,IAChB,EAAE,QAAQ,WAAoB,IAC9B;IAAE,QAAQ;IAAsB,OAAO,UAAU;GAAM;GAC7D,MAAM,OACJ,UAAU,SAAS,KAAA,IACf,EAAE,QAAQ,WAAoB,IAC9B;IAAE,QAAQ;IAAsB,OAAO,UAAU;GAAK;GAC5D,IAAI,CAAC,UAAU,GAAG;GAClB,IAAI,QAAQ,WAAW,aAAa,MAAM,IAAI,MAAM,qBAAqB;GACzE,MAAM,SAAS,wBAAA,iBAAiB,QAAQ,SAAS,CAAC,CAAC;GACnD,OAAO,OAAO,KAAK,IAAI,GAAG,QAAQ,MAAM,KAAK,SAAS,KAAK,MAAM,KAAK,SAAS,CAAC,CAAC;GACjF,MAAM,WAAqB,CAAC;GAC5B,IAAI,UAAU,WAAW,aACvB,IAAI;IACF,OAAO,YAAY,wBAAA,mBACjB,UAAU,SAAS,CAAC,GACpB,KAAK,WAAW,cAAe,KAAK,SAAS,KAAA,IAAa,KAAA,CAC5D;IACA,MAAM,WAAW,IAAI,KAAK,UAAU,SAAS,CAAC,EAAA,CAAG,KAAK,SAAS,KAAK,SAAS,IAAI,CAAC;IAClF,MAAM,WAAW,IAAI,KAAK,QAAQ,SAAS,CAAC,EAAA,CAAG,KAAK,SAAS,KAAK,SAAS,IAAI,CAAC;IAChF,OAAO,gBACL,SAAS,OAAO,KAAK,SAAS,SAAS,SAAS,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,OAAO,SAAS,SAAS,IAAI,IAAI,CAAC;IAC1G,IAAI,CAAC,OAAO,eACV,SAAS,KACP,6FACF;GACJ,QAAQ;IACN,SAAS,KAAK,kEAAkE;GAClF;QAEA,SAAS,KAAK,8FAA8F;GAC9G,IAAI,KAAK,WAAW,aAClB,SAAS,KAAK,sEAAsE;GACtF,OAAO,iBAAiB,SAAS,KAAK,IAAI;GAC1C,UAAU,CAAC,GAAG,QAAQ,QAAQ,UAAU,MAAM,SAAS,OAAO,IAAI,GAAG,MAAM,CAAC,CACzE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAC/B,MAAM,GAAY;GACrB,SAAS;EACX,QAAQ;GACN,IAAI,CAAC,UAAU,GAAG;GAClB,SAAS;EACX,UAAU;GACR,IAAI,sBAAsB,mBAAmB,oBAAoB,KAAA;EACnE;EACA,IAAI,CAAC,WAAW,sBAAsB,YAAY,OAAO;CAC3D;CACA,MAAM,WAAW,IAAI,uBAAuB;EAC1C,OAAY;CACd,CAAC;CACD,SAAS,QAAQ,SAAS,MAAM;EAAE,WAAW;EAAM,SAAS;CAAK,CAAC;CAClE,MAAM,QAAQ,OAAO,kBAAkB;EACrC,OAAY;CACd,GAAG,GAAI;CACP,OAAY;CACZ,aAAa;EACX,UAAU;EACV;EACA,OAAO,cAAc,KAAK;EAC1B,SAAS,WAAW;EACpB,YAAY,OAAO;EACnB,QAAQ;EACR,UAAU,CAAC;CACb;AACF"}
1
+ {"version":3,"file":"monitoring.js","names":[],"sources":["../../src/renderer/monitoring.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { reaction } from \"mobx\";\nimport { type CSSProperties, type ReactNode, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { formatDateTime } from \"../common/date-time\";\nimport {\n aggregateMetrics,\n aggregateResources,\n MONITORING_INTERVAL as INTERVAL,\n MAX_SAMPLES,\n type MonitoringSample,\n} from \"../common/monitoring-math\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { getMonitoringSnapshot, retainMonitoringCollector } from \"./monitoring-collector\";\nimport { MonitoringHistoryRange, useMonitoringHistory } from \"./monitoring-history-view\";\nimport { NativeTooltip } from \"./native-tooltip\";\n\nexport {\n aggregateMetrics,\n aggregateResources,\n effectivePodResource,\n MAX_SAMPLES,\n type MonitoringNode,\n type MonitoringPod,\n type MonitoringSample,\n parseQuantity,\n} from \"../common/monitoring-math\";\n\nexport function formatMonitoringTime(time: number): string {\n return new Date(time).toLocaleTimeString([], {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hourCycle: \"h23\",\n });\n}\n\nfunction ResourceTitle({ metric, label }: { metric: \"cpu\" | \"memory\"; label?: string }) {\n return (\n <strong style={{ display: \"inline-flex\", alignItems: \"center\", gap: 6 }}>\n <span className=\"Icon material\" aria-hidden=\"true\" style={{ \"--size\": \"18px\", fontWeight: 400 } as CSSProperties}>\n <span className=\"icon\">{metric === \"cpu\" ? \"developer_board\" : \"memory\"}</span>\n </span>\n {label ?? (metric === \"cpu\" ? \"CPU\" : \"Memory\")}\n </strong>\n );\n}\n\nexport function MetricChart({\n metric,\n samples,\n status,\n scope = \"node\",\n headerAction,\n}: {\n metric: \"cpu\" | \"memory\";\n samples: MonitoringSample[];\n status: string;\n scope?: \"node\" | \"pod\";\n headerAction?: ReactNode;\n}) {\n const [selectedTime, setSelectedTime] = useState<number>();\n const [pinned, setPinned] = useState(false);\n const previousMetric = useRef(metric);\n useEffect(() => {\n if (\n previousMetric.current !== metric ||\n (selectedTime !== undefined && !samples.some((sample) => sample.time === selectedTime))\n ) {\n setPinned(false);\n setSelectedTime(undefined);\n }\n previousMetric.current = metric;\n }, [metric, samples, selectedTime]);\n useEffect(() => {\n if (!pinned) return;\n const escape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n event.stopPropagation();\n setPinned(false);\n setSelectedTime(undefined);\n }\n };\n document.addEventListener(\"keydown\", escape, true);\n return () => document.removeEventListener(\"keydown\", escape, true);\n }, [pinned]);\n const chartRef = useRef<SVGSVGElement>(null);\n const [width, setWidth] = useState(600);\n useLayoutEffect(() => {\n const chart = chartRef.current;\n if (!chart) return;\n const measure = () => {\n const measured = chart.getBoundingClientRect().width;\n if (measured > 0) setWidth(measured);\n };\n measure();\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(measure);\n observer?.observe(chart);\n window.addEventListener(\"resize\", measure);\n return () => {\n observer?.disconnect();\n window.removeEventListener(\"resize\", measure);\n };\n }, []);\n const plotWidth = Math.max(1, width - 112);\n const last = samples.at(-1);\n const selected = samples.find((sample) => sample.time === selectedTime);\n const label = metric === \"cpu\" ? \"CPU\" : \"Memory\";\n const format = (value: number) =>\n metric === \"cpu\" ? `${value.toFixed(2)} cores` : `${(value / 1024 ** 3).toFixed(2)} GiB`;\n const series = [\n { key: \"usage\", label: \"Usage\", color: \"#c93dce\", value: (sample: MonitoringSample) => sample[metric] },\n ...([\"requests\", \"allocatable\", \"capacity\"] as const).map((key) => ({\n key,\n label: { requests: \"Requests\", allocatable: \"Allocatable Capacity\", capacity: \"Capacity\" }[key],\n color: { requests: \"#4caf50\", allocatable: \"#5486b5\", capacity: \"var(--textColorSecondary)\" }[key],\n value: (sample: MonitoringSample) => sample.resources?.[metric][key],\n })),\n ];\n const visibleSeries =\n scope === \"pod\" ? series.filter((line) => line.key === \"usage\" || line.key === \"requests\") : series;\n const max =\n Math.max(\n ...samples.flatMap((sample) => [\n ...visibleSeries.map((line) => line.value(sample) ?? 0),\n sample.historical?.[metric]?.max ?? 0,\n ]),\n 0.001,\n ) * 1.1;\n const end = last?.time ?? Date.now();\n const start = samples[0]?.time ?? end;\n const duration = Math.max(end - start, INTERVAL);\n const x = (sample: MonitoringSample) => 88 + ((sample.time - start) / duration) * plotWidth;\n const y = (sample: MonitoringSample) => 208 - (sample[metric] / max) * 184;\n const selectNearest = (event: React.MouseEvent<SVGSVGElement>) => {\n const bounds = event.currentTarget.getBoundingClientRect();\n if (!bounds.width || !samples.length) return;\n const scale = Math.min(bounds.width / width, (bounds.height || 250) / 250);\n const offset = (bounds.width - width * scale) / 2;\n const position = (event.clientX - bounds.left - offset) / scale;\n const time = start + ((position - 88) / plotWidth) * duration;\n const nearest = samples.reduce((nearest, sample) =>\n Math.abs(sample.time - time) < Math.abs(nearest.time - time) ? sample : nearest,\n ).time;\n setSelectedTime(nearest);\n return nearest;\n };\n return (\n <section\n aria-label={`${label} metrics-server usage`}\n style={{\n padding: \"var(--power-monitoring-trend-top, 16px) 16px 16px\",\n background: \"var(--contentColor)\",\n minWidth: 0,\n minHeight: 280,\n position: \"relative\",\n }}\n >\n {headerAction && <div className=\"power-monitoring-period-action\">{headerAction}</div>}\n <div\n data-monitoring-heading=\"\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n flexWrap: \"wrap\",\n gap: 12,\n paddingRight: headerAction ? 100 : 0,\n minHeight: headerAction ? 32 : undefined,\n }}\n >\n <ResourceTitle metric={metric} />\n <span>{status ? \"Unavailable\" : last ? format(last[metric]) : \"Collecting…\"}</span>\n </div>\n <svg\n ref={chartRef}\n data-monitoring-trend=\"\"\n viewBox={`0 0 ${width} 250`}\n role=\"img\"\n tabIndex={0}\n aria-label={`${label} usage over collected samples. Use arrow keys to inspect samples. Click or press Enter to pin the tooltip, Escape to dismiss`}\n onMouseMove={(event) => {\n if (!pinned) selectNearest(event);\n }}\n onClick={(event) => {\n if (pinned) setPinned(false);\n else if (samples.length) {\n if (selectNearest(event) === undefined && !selected) setSelectedTime(last?.time);\n setPinned(true);\n }\n }}\n onMouseLeave={() => {\n if (!pinned) setSelectedTime(undefined);\n }}\n onFocus={() => {\n if (!pinned) setSelectedTime(last?.time);\n }}\n onBlur={() => {\n if (!pinned) setSelectedTime(undefined);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n if (samples.length) {\n if (!selected) setSelectedTime(last?.time);\n setPinned(!pinned);\n }\n return;\n }\n if (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\") return;\n event.preventDefault();\n const index = samples.findIndex((sample) => sample.time === selectedTime);\n setSelectedTime(\n samples[\n Math.max(\n 0,\n Math.min(\n samples.length - 1,\n (index < 0 ? samples.length - 1 : index) + (event.key === \"ArrowLeft\" ? -1 : 1),\n ),\n )\n ]?.time,\n );\n }}\n style={{ width: \"100%\", height: 250, color: \"#c93dce\", display: \"block\" }}\n >\n {[0, 0.5, 1].map((fraction) => (\n <g key={fraction}>\n <line\n x1=\"88\"\n x2={width - 24}\n y1={208 - fraction * 184}\n y2={208 - fraction * 184}\n stroke=\"var(--borderFaintColor)\"\n />\n <text x=\"80\" y={212 - fraction * 184} textAnchor=\"end\" fill=\"var(--textColorSecondary)\" fontSize=\"11\">\n {format(max * fraction)}\n </text>\n </g>\n ))}\n {samples.map((sample) => {\n const summary = sample.historical?.[metric];\n if (!summary || summary.min === summary.max) return null;\n return (\n <line\n key={`range:${sample.time}`}\n data-monitoring-extrema=\"\"\n x1={x(sample)}\n x2={x(sample)}\n y1={208 - (summary.max / max) * 184}\n y2={208 - (summary.min / max) * 184}\n stroke=\"#c93dce\"\n strokeOpacity={0.35}\n strokeWidth={4}\n />\n );\n })}\n {visibleSeries.map((line) => {\n let path = \"\";\n let gaps = \"\";\n let previous: { sample: MonitoringSample; point: string } | undefined;\n let interrupted = false;\n for (const sample of samples) {\n const value = line.value(sample);\n if (value === undefined || !Number.isFinite(value)) {\n interrupted = true;\n continue;\n }\n const point = `${x(sample)},${208 - (value / max) * 184}`;\n const gap =\n previous &&\n (interrupted ||\n sample.breakBefore ||\n sample.time - previous.sample.time >\n 1.8 *\n Math.max(\n sample.historical?.[metric]?.resolution ?? INTERVAL,\n previous.sample.historical?.[metric]?.resolution ?? INTERVAL,\n ));\n path += ` ${!previous || gap ? \"M\" : \"L\"}${point}`;\n if (previous && gap) gaps += ` M${previous.point} L${point}`;\n previous = { sample, point };\n interrupted = false;\n }\n return (\n <g key={line.key}>\n <path\n data-monitoring-series={line.key}\n d={path}\n fill=\"none\"\n stroke={line.color}\n strokeWidth=\"2\"\n strokeDasharray={line.key === \"capacity\" || line.key === \"allocatable\" ? \"5 3\" : undefined}\n />\n {gaps && (\n <NativeTooltip title=\"Dashed connections span missing measurements; intermediate values are unknown\">\n <path\n data-monitoring-gap={line.key}\n d={gaps}\n fill=\"none\"\n stroke={line.color}\n strokeWidth=\"2\"\n strokeDasharray=\"3 4\"\n opacity=\".65\"\n />\n </NativeTooltip>\n )}\n </g>\n );\n })}\n {samples.map((sample) => (\n <circle key={sample.time} cx={x(sample)} cy={y(sample)} r=\"2\" fill=\"currentColor\" />\n ))}\n {samples.length > 0 &&\n [0, 0.5, 1].map((fraction) => (\n <text\n key={fraction}\n x={88 + fraction * plotWidth}\n y=\"235\"\n textAnchor={fraction === 0 ? \"start\" : fraction === 1 ? \"end\" : \"middle\"}\n fill=\"var(--textColorSecondary)\"\n fontSize=\"11\"\n >\n {formatMonitoringTime(start + fraction * duration)}\n </text>\n ))}\n {selected && (\n <line\n data-monitoring-crosshair=\"\"\n x1={x(selected)}\n x2={x(selected)}\n y1=\"24\"\n y2=\"208\"\n stroke=\"var(--textColorSecondary)\"\n strokeDasharray=\"4 3\"\n />\n )}\n </svg>\n <style>{`\n @keyframes freelens-power-metric-tooltip-enter { from { opacity:0; transform:translateY(2px) } to { opacity:1; transform:translateY(0) } }\n [data-monitoring-tooltip] { animation:freelens-power-metric-tooltip-enter 140ms ease-out }\n @media (prefers-reduced-motion:reduce) { [data-monitoring-tooltip] { animation:none } }\n `}</style>\n {selected && (\n <div\n data-monitoring-tooltip=\"\"\n role=\"tooltip\"\n style={{\n position: \"absolute\",\n top: 44,\n right: 24,\n padding: 8,\n background: \"var(--contentColor)\",\n border: \"1px solid var(--borderFaintColor)\",\n pointerEvents: \"none\",\n }}\n >\n <div style={{ whiteSpace: \"pre-wrap\" }}>\n {formatDateTime(selected.time)}\n {pinned ? \" · Pinned\" : \"\"}\n </div>\n {visibleSeries.map((line) => (\n <div key={line.key} style={{ color: line.color }}>\n {line.label}: {line.value(selected) === undefined ? \"Unavailable\" : format(line.value(selected)!)}\n </div>\n ))}\n {selected.historical?.[metric] && (\n <div>\n Min: {format(selected.historical[metric]!.min)} · Max: {format(selected.historical[metric]!.max)}\n <br />\n {selected.historical[metric]!.count} samples ·{\" \"}\n {Math.round(selected.historical[metric]!.resolution / 1000)}s bucket\n </div>\n )}\n <div style={{ color: \"var(--textColorSecondary)\", marginTop: 4, fontSize: 10 }}>\n {pinned ? \"Click chart or Escape to unpin\" : \"Click or Enter to pin\"}\n </div>\n </div>\n )}\n <div\n aria-label={`${label} chart legend`}\n style={{ display: \"flex\", flexWrap: \"wrap\", gap: \"6px 16px\", marginBottom: 8 }}\n >\n {visibleSeries.map((line) => (\n <span key={line.key}>\n <span style={{ color: line.color }}>●</span> {line.label}\n </span>\n ))}\n </div>\n {last?.resourceStatus && (\n <div role=\"status\" style={{ color: \"var(--textColorSecondary)\", marginBottom: 8 }}>\n {last.resourceStatus}\n </div>\n )}\n {(scope === \"node\" || status || !samples.length) && (\n <div\n style={{ fontSize: 11, color: \"var(--textColorSecondary)\", display: \"flex\", alignItems: \"center\", gap: 4 }}\n role=\"status\"\n aria-label={`${scope} metrics status`}\n >\n {scope === \"node\" && (\n <sup aria-hidden=\"true\" style={{ fontSize: 12 }}>\n *\n </sup>\n )}\n <span>{status || (samples.length ? \"metrics-server data\" : \"Waiting for metrics-server data\")}</span>\n </div>\n )}\n </section>\n );\n}\n\nfunction ResourceDonut({\n metric,\n sample,\n status,\n}: {\n metric: \"cpu\" | \"memory\";\n sample?: MonitoringSample;\n status: string;\n}) {\n const [activeRing, setActiveRing] = useState<number>();\n useEffect(() => {\n if (activeRing === undefined) return;\n const dismiss = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n event.preventDefault();\n event.stopPropagation();\n setActiveRing(undefined);\n };\n document.addEventListener(\"keydown\", dismiss, true);\n return () => document.removeEventListener(\"keydown\", dismiss, true);\n }, [activeRing]);\n const label = metric === \"cpu\" ? \"CPU\" : \"Memory\";\n const totals = sample?.resources?.[metric];\n const format = (value: number) =>\n metric === \"cpu\" ? `${value.toFixed(2)} cores` : `${(value / 1024 ** 3).toFixed(2)} GiB`;\n const available = (value?: number) => (value === undefined ? \"Unavailable\" : format(value));\n const denominator = totals?.allocatable;\n const rings = [\n { label: \"Usage\", color: \"#c93dce\", value: sample?.[metric] },\n { label: \"Requests\", color: \"#4caf50\", value: totals?.requests },\n ];\n const percentage = (value?: number) =>\n value !== undefined && denominator !== undefined && denominator > 0 ? (value / denominator) * 100 : undefined;\n const usagePercent = percentage(sample?.[metric]);\n const unused =\n sample?.completeUsage && denominator !== undefined ? format(denominator - sample[metric]) : \"Unavailable\";\n const unrequested =\n denominator !== undefined && totals?.requests !== undefined ? format(denominator - totals.requests) : \"Unavailable\";\n const allocationDetail = `Allocatable: ${available(denominator)}. Schedulable capacity after system reservations, used as the denominator for both rings. Physical Capacity: ${available(totals?.capacity)}. Unused allocatable (usage): ${unused}. Unrequested: ${unrequested}`;\n const hovered = activeRing === undefined ? undefined : rings[activeRing];\n const tooltipId = `power-monitoring-${metric}-donut-tooltip`;\n return (\n <section\n aria-label={`${label} resource summary`}\n style={{\n padding: \"var(--power-monitoring-summary-top, 16px) 16px 16px\",\n minWidth: 0,\n background: \"var(--contentColor)\",\n position: \"relative\",\n overflow: \"visible\",\n }}\n >\n <ResourceTitle metric={metric} label={metric === \"memory\" ? \"RAM\" : \"CPU\"} />\n <svg\n data-monitoring-donut=\"\"\n viewBox=\"0 0 200 200\"\n role=\"img\"\n aria-label={`${label} usage and requests relative to allocatable capacity`}\n style={{ display: \"block\", width: \"100%\", height: 200 }}\n >\n {rings.map((ring, index) => {\n const radius = 76 - index * 18;\n const percent = percentage(ring.value);\n const detail = `${ring.label}: ${available(ring.value)}${percent === undefined ? \"\" : ` (${percent.toFixed(1)}% of allocatable${percent > 100 ? \", over allocatable\" : \"\"})`}`;\n return (\n <g\n key={ring.label}\n tabIndex={0}\n role=\"img\"\n aria-label={detail}\n aria-describedby={activeRing === index ? tooltipId : undefined}\n onMouseEnter={() => setActiveRing(index)}\n onMouseMove={() => setActiveRing(index)}\n onMouseLeave={() => setActiveRing(undefined)}\n onFocus={() => setActiveRing(index)}\n onBlur={() => setActiveRing(undefined)}\n >\n <circle cx=\"100\" cy=\"100\" r={radius} fill=\"none\" stroke=\"var(--borderFaintColor)\" strokeWidth=\"12\" />\n {percent !== undefined && (\n <circle\n data-monitoring-ring={ring.label}\n cx=\"100\"\n cy=\"100\"\n r={radius}\n fill=\"none\"\n stroke={ring.color}\n strokeWidth=\"12\"\n pathLength=\"100\"\n strokeDasharray={`${Math.min(100, Math.max(0, percent))} 100`}\n transform=\"rotate(-90 100 100)\"\n />\n )}\n </g>\n );\n })}\n <text\n data-monitoring-usage-percentage=\"\"\n x=\"100\"\n y=\"100\"\n textAnchor=\"middle\"\n fill=\"var(--textColorPrimary)\"\n fontSize=\"26\"\n fontWeight=\"600\"\n >\n {usagePercent === undefined ? \"N/A\" : `${usagePercent.toFixed(1)}%`}\n </text>\n <text x=\"100\" y=\"120\" textAnchor=\"middle\" fill=\"var(--textColorPrimary)\" fontSize=\"12\">\n Usage\n </text>\n </svg>\n {hovered && (\n <div\n id={tooltipId}\n data-monitoring-tooltip=\"\"\n role=\"tooltip\"\n style={{\n position: \"absolute\",\n top: 48,\n left: 8,\n right: 8,\n zIndex: 20,\n padding: 8,\n border: \"1px solid var(--borderFaintColor)\",\n background: \"var(--contentColor)\",\n pointerEvents: \"none\",\n overflowWrap: \"anywhere\",\n boxShadow: \"0 3px 12px #0003\",\n }}\n >\n <div style={{ color: hovered.color }}>\n {hovered.label}: {available(hovered.value)}\n </div>\n <div>\n {percentage(hovered.value) === undefined\n ? \"Percentage unavailable\"\n : `${percentage(hovered.value)!.toFixed(1)}% of allocatable${percentage(hovered.value)! > 100 ? \" (over allocatable)\" : \"\"}`}\n </div>\n <div>Allocatable: {available(denominator)}</div>\n </div>\n )}\n <div aria-label={`${label} resource totals`} style={{ display: \"grid\", gap: 6, fontSize: 12 }}>\n {rings.map((ring) => (\n <NativeTooltip\n key={ring.label}\n title={`${ring.label} relative to allocatable capacity. ${ring.label === \"Usage\" ? `Unused allocatable (usage): ${unused}` : `Unrequested: ${unrequested}`}`}\n >\n <div>\n <span style={{ color: ring.color }}>●</span> {ring.label}: {available(ring.value)}\n {percentage(ring.value) !== undefined && <span> ({percentage(ring.value)!.toFixed(1)}%)</span>}\n </div>\n </NativeTooltip>\n ))}\n <NativeTooltip title={allocationDetail}>\n <div>\n <span style={{ color: \"#5486b5\" }}>●</span> Allocatable: {available(denominator)}\n </div>\n </NativeTooltip>\n </div>\n {(status || sample?.resourceStatus) && (\n <div role=\"status\" style={{ color: \"var(--textColorSecondary)\", fontSize: 11, marginTop: 8 }}>\n {status || sample?.resourceStatus}\n </div>\n )}\n </section>\n );\n}\n\nfunction MonitoringCharts({ samples, status }: { samples: MonitoringSample[]; status: string }) {\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n const history = useMonitoringHistory(\n clusterId ? { clusterId, scope: \"cluster\", uid: clusterId } : undefined,\n samples,\n );\n return (\n <div style={{ containerType: \"inline-size\" }}>\n <style>{`\n [data-monitoring-layout] { display:grid; grid-template-columns:minmax(0,1.6fr) minmax(0,1.6fr) minmax(0,1fr) minmax(0,1fr); gap:16px; align-items:stretch }\n [data-monitoring-trends], [data-monitoring-summaries] { display:contents }\n .power-monitoring-period-action { position:absolute;right:16px;top:19px }\n @container (min-width: 961px) {\n [data-monitoring-summaries] > section { --power-monitoring-summary-top:16px }\n }\n @container (max-width: 960px) {\n [data-monitoring-layout] { grid-template-columns:repeat(2,minmax(0,1fr)) }\n .power-ai-overview-actions + [data-testid=\"cluster-overview-page\"] [data-monitoring-trends] > section { --power-monitoring-trend-top:56px }\n }\n @container (max-width: 580px) {\n [data-monitoring-layout] { grid-template-columns:minmax(0,1fr) }\n .power-monitoring-period-action { left:16px;right:auto;top:15px }\n [data-monitoring-trends] > section:first-child { --power-monitoring-trend-top:56px }\n .power-ai-overview-actions + [data-testid=\"cluster-overview-page\"] [data-monitoring-trends] > section:not(:first-child) { --power-monitoring-trend-top:16px }\n }\n `}</style>\n {history.status && (\n <small role=\"status\" style={{ display: \"block\", color: \"var(--textColorSecondary)\", marginBottom: 8 }}>\n {history.status}\n </small>\n )}\n <div data-monitoring-layout=\"\">\n <div data-monitoring-trends=\"\">\n {([\"cpu\", \"memory\"] as const).map((metric) => (\n <MetricChart\n key={metric}\n metric={metric}\n samples={history.samples}\n status={status}\n headerAction={\n metric === \"cpu\" ? (\n <MonitoringHistoryRange compact range={history.range} onChange={history.setRange} />\n ) : undefined\n }\n />\n ))}\n </div>\n <div data-monitoring-summaries=\"\">\n {([\"cpu\", \"memory\"] as const).map((metric) => (\n <ResourceDonut key={metric} metric={metric} sample={samples.at(-1)} status={status} />\n ))}\n </div>\n </div>\n </div>\n );\n}\n\nexport function startMonitoring(): () => void {\n const release = retainMonitoringCollector();\n const preferences = MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>();\n let stopCurrent: (() => void) | undefined;\n const stop = reaction(\n () => preferences.enabled,\n (enabled) => {\n stopCurrent?.();\n stopCurrent = enabled ? mountMonitoring() : undefined;\n },\n { fireImmediately: true },\n );\n return () => {\n stop();\n stopCurrent?.();\n release();\n };\n}\n\nfunction mountMonitoring(): () => void {\n const suppression = document.createElement(\"style\");\n suppression.setAttribute(\"data-freelens-power-native-metrics-suppression\", \"\");\n suppression.textContent = `\n .Nodes .TableCell:is(.cpu, .memory) .LineProgress:has(> .line.secondary) {\n overflow:hidden;\n }\n .Nodes .TableCell:is(.cpu, .memory) .LineProgress:has(> .line.secondary) > .line {\n border-radius:0;\n }\n .Nodes .TableCell:is(.cpu, .memory) .LineProgress:has(> .line.secondary) > .line:not(.secondary) {\n height:60%;\n }\n .Nodes .TableCell:is(.cpu, .memory) .LineProgress > .line.secondary {\n top:60%;\n height:40%;\n opacity:1;\n background:color-mix(in srgb, currentColor 65%, var(--mainBackground));\n }\n [data-testid=\"cluster-overview-page\"] > [class*=\"ClusterMetrics\"],\n [data-testid=\"cluster-overview-page\"] > :has([class*=\"ClusterMetrics\"]),\n [data-testid=\"cluster-overview-page\"] > :is([class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"]):not(:has(.PieChart)),\n [data-testid=\"cluster-overview-page\"] > :has([class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"], [class*=\"cluster-pie-charts\"][class*=\"empty\"]):not(:has(.PieChart)) {\n display:none !important;\n }\n `;\n document.head.append(suppression);\n let host: HTMLElement | undefined;\n let overview: Element | null = null;\n let samples: MonitoringSample[] = [];\n let status = \"\";\n let renderedSamples: MonitoringSample[] | undefined;\n let renderedStatus: string | undefined;\n let cluster: string | undefined;\n let stopped = false;\n let pendingGeneration: number | undefined;\n let generation = 0;\n let nextSample = 0;\n const hidden = new Map<HTMLElement, string | null>();\n const restore = () => {\n for (const [element, original] of hidden) {\n if (original === null) element.removeAttribute(\"style\");\n else element.setAttribute(\"style\", original);\n }\n hidden.clear();\n if (host) {\n ReactDOM.unmountComponentAtNode(host);\n host.remove();\n host = undefined;\n renderedSamples = undefined;\n renderedStatus = undefined;\n }\n };\n const update = async () => {\n const currentCluster = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n const currentOverview = document.querySelector('[data-testid=\"cluster-overview-page\"]');\n if (cluster !== currentCluster || overview !== currentOverview) {\n generation++;\n restore();\n samples = [];\n status = \"\";\n nextSample = 0;\n cluster = currentCluster;\n overview = currentOverview;\n }\n const cutoff = Date.now() - MAX_SAMPLES * INTERVAL;\n if (samples.length && samples[0].time < cutoff) samples = samples.filter((sample) => sample.time >= cutoff);\n if (!overview || !cluster || document.visibilityState === \"hidden\") return;\n if (!host) {\n host = document.createElement(\"div\");\n host.setAttribute(\"data-freelens-power-monitoring\", \"\");\n host.style.gridColumn = \"1 / -1\";\n hidden.set(overview as HTMLElement, overview.getAttribute(\"style\"));\n Object.assign((overview as HTMLElement).style, {\n gridTemplateAreas: \"none\",\n gridTemplateColumns: \"minmax(0, 1fr)\",\n gridTemplateRows: \"none\",\n height: \"auto\",\n });\n overview.prepend(host);\n }\n for (const title of overview.querySelectorAll<HTMLElement>(\".PieChart > .chart-title\")) {\n if (title.textContent !== \"CPU\" && title.textContent !== \"Memory\") continue;\n const panel = title.closest(\".PieChart\")?.parentElement;\n if (panel && panel.style.display !== \"none\") {\n if (!hidden.has(panel)) hidden.set(panel, panel.getAttribute(\"style\"));\n panel.style.display = \"none\";\n }\n }\n // native CSS modules retain [ClusterMetrics] in the generated class name\n for (const child of overview.children) {\n if (!(child instanceof HTMLElement) || child === host) continue;\n const nativeMetrics =\n child.matches('[class*=\"ClusterMetrics\"]') || child.querySelector('[class*=\"ClusterMetrics\"]');\n const unavailablePies =\n (child.matches('[class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"]') ||\n child.querySelector(\n '[class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"], [class*=\"cluster-pie-charts\"][class*=\"empty\"]',\n )) &&\n !child.querySelector(\".PieChart\");\n if ((nativeMetrics || unavailablePies) && child.style.display !== \"none\") {\n if (!hidden.has(child)) hidden.set(child, child.getAttribute(\"style\"));\n child.style.display = \"none\";\n }\n if (!hidden.has(child)) hidden.set(child, child.getAttribute(\"style\"));\n child.style.gridArea = \"auto\";\n }\n const render = () => {\n if (host && (renderedSamples !== samples || renderedStatus !== status)) {\n ReactDOM.render(<MonitoringCharts samples={samples} status={status} />, host);\n renderedSamples = samples;\n renderedStatus = status;\n }\n };\n render();\n if (pendingGeneration === generation || Date.now() < nextSample) return;\n pendingGeneration = generation;\n nextSample = Date.now() + INTERVAL;\n const requestGeneration = generation;\n const isCurrent = () =>\n !stopped &&\n requestGeneration === generation &&\n document.visibilityState !== \"hidden\" &&\n overview?.isConnected === true &&\n Renderer.Catalog.activeCluster.get()?.metadata.uid === cluster;\n try {\n const collected = await getMonitoringSnapshot();\n const metrics =\n collected.nodeMetrics === undefined\n ? { status: \"rejected\" as const }\n : { status: \"fulfilled\" as const, value: collected.nodeMetrics };\n const inventory =\n collected.nodes === undefined\n ? { status: \"rejected\" as const }\n : { status: \"fulfilled\" as const, value: collected.nodes };\n const pods =\n collected.pods === undefined\n ? { status: \"rejected\" as const }\n : { status: \"fulfilled\" as const, value: collected.pods };\n if (!isCurrent()) return;\n if (metrics.status !== \"fulfilled\") throw new Error(\"Metrics unavailable\");\n const sample = aggregateMetrics(metrics.value ?? []);\n sample.time = Math.min(...metrics.value.map((item) => Date.parse(item.timestamp)));\n const warnings: string[] = [];\n if (inventory.status === \"fulfilled\") {\n try {\n sample.resources = aggregateResources(\n inventory.value ?? [],\n pods.status === \"fulfilled\" ? (pods.value ?? undefined) : undefined,\n );\n const expected = new Set((inventory.value ?? []).map((node) => node.metadata.name));\n const observed = new Set((metrics.value ?? []).map((node) => node.metadata.name));\n sample.completeUsage =\n expected.size > 0 && expected.size === observed.size && [...expected].every((name) => observed.has(name));\n if (!sample.completeUsage)\n warnings.push(\n \"Partial node metrics coverage: usage is the reported subset; unused allocatable unavailable\",\n );\n } catch {\n warnings.push(\"Resource totals unavailable: incomplete or invalid node/pod data\");\n }\n } else\n warnings.push(\"Node inventory unavailable or access denied; usage coverage unverified, capacity unavailable\");\n if (pods.status !== \"fulfilled\")\n warnings.push(\"Cluster-wide Pods unavailable or access denied; requests unavailable\");\n sample.resourceStatus = warnings.join(\". \");\n samples = [...samples.filter((entry) => entry.time !== sample.time), sample]\n .sort((a, b) => a.time - b.time)\n .slice(-MAX_SAMPLES);\n status = \"\";\n } catch {\n if (!isCurrent()) return;\n status = \"Node metrics unavailable, stale or access denied. Last collected samples remain visible.\";\n } finally {\n if (pendingGeneration === requestGeneration) pendingGeneration = undefined;\n }\n if (!stopped && requestGeneration === generation) render();\n };\n const observer = new MutationObserver(() => {\n void update();\n });\n observer.observe(document.body, { childList: true, subtree: true });\n const timer = window.setInterval(() => {\n void update();\n }, 1000);\n void update();\n return () => {\n stopped = true;\n generation++;\n window.clearInterval(timer);\n observer.disconnect();\n suppression.remove();\n restore();\n samples = [];\n };\n}\n"],"mappings":";;;;;;;;;;;;AA4BA,SAAgB,qBAAqB,MAAsB;CACzD,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,mBAAmB,CAAC,GAAG;EAC3C,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,WAAW;CACb,CAAC;AACH;AAEA,SAAS,cAAc,EAAE,QAAQ,SAAuD;CACtF,OACE,oCAAA,KAAC,UAAD;EAAQ,OAAO;GAAE,SAAS;GAAe,YAAY;GAAU,KAAK;EAAE;YAAtE,CACE,oCAAA,IAAC,QAAD;GAAM,WAAU;GAAgB,eAAY;GAAO,OAAO;IAAE,UAAU;IAAQ,YAAY;GAAI;aAC5F,oCAAA,IAAC,QAAD;IAAM,WAAU;cAAQ,WAAW,QAAQ,oBAAoB;GAAe,CAAA;EAC1E,CAAA,GACL,UAAU,WAAW,QAAQ,QAAQ,SAChC;;AAEZ;AAEA,SAAgB,YAAY,EAC1B,QACA,SACA,QACA,QAAQ,QACR,gBAOC;CACD,MAAM,CAAC,cAAc,mBAAmB,+BAAA,SAAiB;CACzD,MAAM,CAAC,QAAQ,aAAa,+BAAA,SAAS,KAAK;CAC1C,MAAM,iBAAiB,+BAAA,OAAO,MAAM;CACpC,+BAAA,gBAAgB;EACd,IACE,eAAe,YAAY,UAC1B,iBAAiB,KAAA,KAAa,CAAC,QAAQ,MAAM,WAAW,OAAO,SAAS,YAAY,GACrF;GACA,UAAU,KAAK;GACf,gBAAgB,KAAA,CAAS;EAC3B;EACA,eAAe,UAAU;CAC3B,GAAG;EAAC;EAAQ;EAAS;CAAY,CAAC;CAClC,+BAAA,gBAAgB;EACd,IAAI,CAAC,QAAQ;EACb,MAAM,UAAU,UAAyB;GACvC,IAAI,MAAM,QAAQ,UAAU;IAC1B,MAAM,eAAe;IACrB,MAAM,gBAAgB;IACtB,UAAU,KAAK;IACf,gBAAgB,KAAA,CAAS;GAC3B;EACF;EACA,SAAS,iBAAiB,WAAW,QAAQ,IAAI;EACjD,aAAa,SAAS,oBAAoB,WAAW,QAAQ,IAAI;CACnE,GAAG,CAAC,MAAM,CAAC;CACX,MAAM,WAAW,+BAAA,OAAsB,IAAI;CAC3C,MAAM,CAAC,OAAO,YAAY,+BAAA,SAAS,GAAG;CACtC,+BAAA,sBAAsB;EACpB,MAAM,QAAQ,SAAS;EACvB,IAAI,CAAC,OAAO;EACZ,MAAM,gBAAgB;GACpB,MAAM,WAAW,MAAM,sBAAsB,CAAC,CAAC;GAC/C,IAAI,WAAW,GAAG,SAAS,QAAQ;EACrC;EACA,QAAQ;EACR,MAAM,WAAW,OAAO,mBAAmB,cAAc,KAAA,IAAY,IAAI,eAAe,OAAO;EAC/F,UAAU,QAAQ,KAAK;EACvB,OAAO,iBAAiB,UAAU,OAAO;EACzC,aAAa;GACX,UAAU,WAAW;GACrB,OAAO,oBAAoB,UAAU,OAAO;EAC9C;CACF,GAAG,CAAC,CAAC;CACL,MAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,GAAG;CACzC,MAAM,OAAO,QAAQ,GAAG,EAAE;CAC1B,MAAM,WAAW,QAAQ,MAAM,WAAW,OAAO,SAAS,YAAY;CACtE,MAAM,QAAQ,WAAW,QAAQ,QAAQ;CACzC,MAAM,UAAU,UACd,WAAW,QAAQ,GAAG,MAAM,QAAQ,CAAC,EAAE,UAAU,IAAI,QAAQ,QAAQ,EAAA,CAAG,QAAQ,CAAC,EAAE;CACrF,MAAM,SAAS,CACb;EAAE,KAAK;EAAS,OAAO;EAAS,OAAO;EAAW,QAAQ,WAA6B,OAAO;CAAQ,GACtG,GAAI;EAAC;EAAY;EAAe;CAAU,CAAC,CAAW,KAAK,SAAS;EAClE;EACA,OAAO;GAAE,UAAU;GAAY,aAAa;GAAwB,UAAU;EAAW,EAAE;EAC3F,OAAO;GAAE,UAAU;GAAW,aAAa;GAAW,UAAU;EAA4B,EAAE;EAC9F,QAAQ,WAA6B,OAAO,YAAY,OAAO,CAAC;CAClE,EAAE,CACJ;CACA,MAAM,gBACJ,UAAU,QAAQ,OAAO,QAAQ,SAAS,KAAK,QAAQ,WAAW,KAAK,QAAQ,UAAU,IAAI;CAC/F,MAAM,MACJ,KAAK,IACH,GAAG,QAAQ,SAAS,WAAW,CAC7B,GAAG,cAAc,KAAK,SAAS,KAAK,MAAM,MAAM,KAAK,CAAC,GACtD,OAAO,aAAa,OAAO,EAAE,OAAO,CACtC,CAAC,GACD,IACF,IAAI;CACN,MAAM,MAAM,MAAM,QAAQ,KAAK,IAAI;CACnC,MAAM,QAAQ,QAAQ,EAAE,EAAE,QAAQ;CAClC,MAAM,WAAW,KAAK,IAAI,MAAM,OAAO,wBAAA,mBAAQ;CAC/C,MAAM,KAAK,WAA6B,MAAO,OAAO,OAAO,SAAS,WAAY;CAClF,MAAM,KAAK,WAA6B,MAAO,OAAO,UAAU,MAAO;CACvE,MAAM,iBAAiB,UAA2C;EAChE,MAAM,SAAS,MAAM,cAAc,sBAAsB;EACzD,IAAI,CAAC,OAAO,SAAS,CAAC,QAAQ,QAAQ;EACtC,MAAM,QAAQ,KAAK,IAAI,OAAO,QAAQ,QAAQ,OAAO,UAAU,OAAO,GAAG;EACzE,MAAM,UAAU,OAAO,QAAQ,QAAQ,SAAS;EAEhD,MAAM,OAAO,UADK,MAAM,UAAU,OAAO,OAAO,UAAU,QACxB,MAAM,YAAa;EACrD,MAAM,UAAU,QAAQ,QAAQ,SAAS,WACvC,KAAK,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,IAAI,QAAQ,OAAO,IAAI,IAAI,SAAS,OAC1E,CAAC,CAAC;EACF,gBAAgB,OAAO;EACvB,OAAO;CACT;CACA,OACE,oCAAA,KAAC,WAAD;EACE,cAAY,GAAG,MAAM;EACrB,OAAO;GACL,SAAS;GACT,YAAY;GACZ,UAAU;GACV,WAAW;GACX,UAAU;EACZ;YARF;GAUG,gBAAgB,oCAAA,IAAC,OAAD;IAAK,WAAU;cAAkC;GAAkB,CAAA;GACpF,oCAAA,KAAC,OAAD;IACE,2BAAwB;IACxB,OAAO;KACL,SAAS;KACT,YAAY;KACZ,UAAU;KACV,KAAK;KACL,cAAc,eAAe,MAAM;KACnC,WAAW,eAAe,KAAK,KAAA;IACjC;cATF,CAWE,oCAAA,IAAC,eAAD,EAAuB,OAAS,CAAA,GAChC,oCAAA,IAAC,QAAD,EAAA,UAAO,SAAS,gBAAgB,OAAO,OAAO,KAAK,OAAO,IAAI,cAAoB,CAAA,CAC/E;;GACL,oCAAA,KAAC,OAAD;IACE,KAAK;IACL,yBAAsB;IACtB,SAAS,OAAO,MAAM;IACtB,MAAK;IACL,UAAU;IACV,cAAY,GAAG,MAAM;IACrB,cAAc,UAAU;KACtB,IAAI,CAAC,QAAQ,cAAc,KAAK;IAClC;IACA,UAAU,UAAU;KAClB,IAAI,QAAQ,UAAU,KAAK;UACtB,IAAI,QAAQ,QAAQ;MACvB,IAAI,cAAc,KAAK,MAAM,KAAA,KAAa,CAAC,UAAU,gBAAgB,MAAM,IAAI;MAC/E,UAAU,IAAI;KAChB;IACF;IACA,oBAAoB;KAClB,IAAI,CAAC,QAAQ,gBAAgB,KAAA,CAAS;IACxC;IACA,eAAe;KACb,IAAI,CAAC,QAAQ,gBAAgB,MAAM,IAAI;IACzC;IACA,cAAc;KACZ,IAAI,CAAC,QAAQ,gBAAgB,KAAA,CAAS;IACxC;IACA,YAAY,UAAU;KACpB,IAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;MAC9C,MAAM,eAAe;MACrB,IAAI,QAAQ,QAAQ;OAClB,IAAI,CAAC,UAAU,gBAAgB,MAAM,IAAI;OACzC,UAAU,CAAC,MAAM;MACnB;MACA;KACF;KACA,IAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,cAAc;KAC7D,MAAM,eAAe;KACrB,MAAM,QAAQ,QAAQ,WAAW,WAAW,OAAO,SAAS,YAAY;KACxE,gBACE,QACE,KAAK,IACH,GACA,KAAK,IACH,QAAQ,SAAS,IAChB,QAAQ,IAAI,QAAQ,SAAS,IAAI,UAAU,MAAM,QAAQ,cAAc,KAAK,EAC/E,CACF,EACD,EAAE,IACL;IACF;IACA,OAAO;KAAE,OAAO;KAAQ,QAAQ;KAAK,OAAO;KAAW,SAAS;IAAQ;cAlD1E;KAoDG;MAAC;MAAG;MAAK;KAAC,CAAC,CAAC,KAAK,aAChB,oCAAA,KAAC,KAAD,EAAA,UAAA,CACE,oCAAA,IAAC,QAAD;MACE,IAAG;MACH,IAAI,QAAQ;MACZ,IAAI,MAAM,WAAW;MACrB,IAAI,MAAM,WAAW;MACrB,QAAO;KACR,CAAA,GACD,oCAAA,IAAC,QAAD;MAAM,GAAE;MAAK,GAAG,MAAM,WAAW;MAAK,YAAW;MAAM,MAAK;MAA4B,UAAS;gBAC9F,OAAO,MAAM,QAAQ;KAClB,CAAA,CACL,EAAA,GAXK,QAWL,CACJ;KACA,QAAQ,KAAK,WAAW;MACvB,MAAM,UAAU,OAAO,aAAa;MACpC,IAAI,CAAC,WAAW,QAAQ,QAAQ,QAAQ,KAAK,OAAO;MACpD,OACE,oCAAA,IAAC,QAAD;OAEE,2BAAwB;OACxB,IAAI,EAAE,MAAM;OACZ,IAAI,EAAE,MAAM;OACZ,IAAI,MAAO,QAAQ,MAAM,MAAO;OAChC,IAAI,MAAO,QAAQ,MAAM,MAAO;OAChC,QAAO;OACP,eAAe;OACf,aAAa;MACd,GATM,SAAS,OAAO,MAStB;KAEL,CAAC;KACA,cAAc,KAAK,SAAS;MAC3B,IAAI,OAAO;MACX,IAAI,OAAO;MACX,IAAI;MACJ,IAAI,cAAc;MAClB,KAAK,MAAM,UAAU,SAAS;OAC5B,MAAM,QAAQ,KAAK,MAAM,MAAM;OAC/B,IAAI,UAAU,KAAA,KAAa,CAAC,OAAO,SAAS,KAAK,GAAG;QAClD,cAAc;QACd;OACF;OACA,MAAM,QAAQ,GAAG,EAAE,MAAM,EAAE,GAAG,MAAO,QAAQ,MAAO;OACpD,MAAM,MACJ,aACC,eACC,OAAO,eACP,OAAO,OAAO,SAAS,OAAO,OAC5B,MACE,KAAK,IACH,OAAO,aAAa,OAAO,EAAE,cAAA,KAC7B,SAAS,OAAO,aAAa,OAAO,EAAE,cAAA,GACxC;OACR,QAAQ,IAAI,CAAC,YAAY,MAAM,MAAM,MAAM;OAC3C,IAAI,YAAY,KAAK,QAAQ,KAAK,SAAS,MAAM,IAAI;OACrD,WAAW;QAAE;QAAQ;OAAM;OAC3B,cAAc;MAChB;MACA,OACE,oCAAA,KAAC,KAAD,EAAA,UAAA,CACE,oCAAA,IAAC,QAAD;OACE,0BAAwB,KAAK;OAC7B,GAAG;OACH,MAAK;OACL,QAAQ,KAAK;OACb,aAAY;OACZ,iBAAiB,KAAK,QAAQ,cAAc,KAAK,QAAQ,gBAAgB,QAAQ,KAAA;MAClF,CAAA,GACA,QACC,oCAAA,IAAC,uBAAA,eAAD;OAAe,OAAM;iBACnB,oCAAA,IAAC,QAAD;QACE,uBAAqB,KAAK;QAC1B,GAAG;QACH,MAAK;QACL,QAAQ,KAAK;QACb,aAAY;QACZ,iBAAgB;QAChB,SAAQ;OACT,CAAA;MACY,CAAA,CAEhB,EAAA,GAtBK,KAAK,GAsBV;KAEP,CAAC;KACA,QAAQ,KAAK,WACZ,oCAAA,IAAC,UAAD;MAA0B,IAAI,EAAE,MAAM;MAAG,IAAI,EAAE,MAAM;MAAG,GAAE;MAAI,MAAK;KAAgB,GAAtE,OAAO,IAA+D,CACpF;KACA,QAAQ,SAAS,KAChB;MAAC;MAAG;MAAK;KAAC,CAAC,CAAC,KAAK,aACf,oCAAA,IAAC,QAAD;MAEE,GAAG,KAAK,WAAW;MACnB,GAAE;MACF,YAAY,aAAa,IAAI,UAAU,aAAa,IAAI,QAAQ;MAChE,MAAK;MACL,UAAS;gBAER,qBAAqB,QAAQ,WAAW,QAAQ;KAC7C,GARC,QAQD,CACP;KACF,YACC,oCAAA,IAAC,QAAD;MACE,6BAA0B;MAC1B,IAAI,EAAE,QAAQ;MACd,IAAI,EAAE,QAAQ;MACd,IAAG;MACH,IAAG;MACH,QAAO;MACP,iBAAgB;KACjB,CAAA;IAEA;;GACL,oCAAA,IAAC,SAAD,EAAA,UAAQ;;;;QAIC,CAAA;GACR,YACC,oCAAA,KAAC,OAAD;IACE,2BAAwB;IACxB,MAAK;IACL,OAAO;KACL,UAAU;KACV,KAAK;KACL,OAAO;KACP,SAAS;KACT,YAAY;KACZ,QAAQ;KACR,eAAe;IACjB;cAXF;KAaE,oCAAA,KAAC,OAAD;MAAK,OAAO,EAAE,YAAY,WAAW;gBAArC,CACG,kBAAA,eAAe,SAAS,IAAI,GAC5B,SAAS,cAAc,EACrB;;KACJ,cAAc,KAAK,SAClB,oCAAA,KAAC,OAAD;MAAoB,OAAO,EAAE,OAAO,KAAK,MAAM;gBAA/C;OACG,KAAK;OAAM;OAAG,KAAK,MAAM,QAAQ,MAAM,KAAA,IAAY,gBAAgB,OAAO,KAAK,MAAM,QAAQ,CAAE;MAC7F;QAFK,KAAK,GAEV,CACN;KACA,SAAS,aAAa,WACrB,oCAAA,KAAC,OAAD,EAAA,UAAA;MAAK;MACG,OAAO,SAAS,WAAW,OAAO,CAAE,GAAG;MAAE;MAAS,OAAO,SAAS,WAAW,OAAO,CAAE,GAAG;MAC/F,oCAAA,IAAC,MAAD,CAAK,CAAA;MACJ,SAAS,WAAW,OAAO,CAAE;MAAM;MAAW;MAC9C,KAAK,MAAM,SAAS,WAAW,OAAO,CAAE,aAAa,GAAI;MAAE;KACzD,EAAA,CAAA;KAEP,oCAAA,IAAC,OAAD;MAAK,OAAO;OAAE,OAAO;OAA6B,WAAW;OAAG,UAAU;MAAG;gBAC1E,SAAS,mCAAmC;KAC1C,CAAA;IACF;;GAEP,oCAAA,IAAC,OAAD;IACE,cAAY,GAAG,MAAM;IACrB,OAAO;KAAE,SAAS;KAAQ,UAAU;KAAQ,KAAK;KAAY,cAAc;IAAE;cAE5E,cAAc,KAAK,SAClB,oCAAA,KAAC,QAAD,EAAA,UAAA;KACE,oCAAA,IAAC,QAAD;MAAM,OAAO,EAAE,OAAO,KAAK,MAAM;gBAAG;KAAO,CAAA;KAAC;KAAE,KAAK;IAC/C,EAAA,GAFK,KAAK,GAEV,CACP;GACE,CAAA;GACJ,MAAM,kBACL,oCAAA,IAAC,OAAD;IAAK,MAAK;IAAS,OAAO;KAAE,OAAO;KAA6B,cAAc;IAAE;cAC7E,KAAK;GACH,CAAA;IAEL,UAAU,UAAU,UAAU,CAAC,QAAQ,WACvC,oCAAA,KAAC,OAAD;IACE,OAAO;KAAE,UAAU;KAAI,OAAO;KAA6B,SAAS;KAAQ,YAAY;KAAU,KAAK;IAAE;IACzG,MAAK;IACL,cAAY,GAAG,MAAM;cAHvB,CAKG,UAAU,UACT,oCAAA,IAAC,OAAD;KAAK,eAAY;KAAO,OAAO,EAAE,UAAU,GAAG;eAAG;IAE5C,CAAA,GAEP,oCAAA,IAAC,QAAD,EAAA,UAAO,WAAW,QAAQ,SAAS,wBAAwB,mCAAyC,CAAA,CACjG;;EAEA;;AAEb;AAEA,SAAS,cAAc,EACrB,QACA,QACA,UAKC;CACD,MAAM,CAAC,YAAY,iBAAiB,+BAAA,SAAiB;CACrD,+BAAA,gBAAgB;EACd,IAAI,eAAe,KAAA,GAAW;EAC9B,MAAM,WAAW,UAAyB;GACxC,IAAI,MAAM,QAAQ,UAAU;GAC5B,MAAM,eAAe;GACrB,MAAM,gBAAgB;GACtB,cAAc,KAAA,CAAS;EACzB;EACA,SAAS,iBAAiB,WAAW,SAAS,IAAI;EAClD,aAAa,SAAS,oBAAoB,WAAW,SAAS,IAAI;CACpE,GAAG,CAAC,UAAU,CAAC;CACf,MAAM,QAAQ,WAAW,QAAQ,QAAQ;CACzC,MAAM,SAAS,QAAQ,YAAY;CACnC,MAAM,UAAU,UACd,WAAW,QAAQ,GAAG,MAAM,QAAQ,CAAC,EAAE,UAAU,IAAI,QAAQ,QAAQ,EAAA,CAAG,QAAQ,CAAC,EAAE;CACrF,MAAM,aAAa,UAAoB,UAAU,KAAA,IAAY,gBAAgB,OAAO,KAAK;CACzF,MAAM,cAAc,QAAQ;CAC5B,MAAM,QAAQ,CACZ;EAAE,OAAO;EAAS,OAAO;EAAW,OAAO,SAAS;CAAQ,GAC5D;EAAE,OAAO;EAAY,OAAO;EAAW,OAAO,QAAQ;CAAS,CACjE;CACA,MAAM,cAAc,UAClB,UAAU,KAAA,KAAa,gBAAgB,KAAA,KAAa,cAAc,IAAK,QAAQ,cAAe,MAAM,KAAA;CACtG,MAAM,eAAe,WAAW,SAAS,OAAO;CAChD,MAAM,SACJ,QAAQ,iBAAiB,gBAAgB,KAAA,IAAY,OAAO,cAAc,OAAO,OAAO,IAAI;CAC9F,MAAM,cACJ,gBAAgB,KAAA,KAAa,QAAQ,aAAa,KAAA,IAAY,OAAO,cAAc,OAAO,QAAQ,IAAI;CACxG,MAAM,mBAAmB,gBAAgB,UAAU,WAAW,EAAE,+GAA+G,UAAU,QAAQ,QAAQ,EAAE,gCAAgC,OAAO,iBAAiB;CACnQ,MAAM,UAAU,eAAe,KAAA,IAAY,KAAA,IAAY,MAAM;CAC7D,MAAM,YAAY,oBAAoB,OAAO;CAC7C,OACE,oCAAA,KAAC,WAAD;EACE,cAAY,GAAG,MAAM;EACrB,OAAO;GACL,SAAS;GACT,UAAU;GACV,YAAY;GACZ,UAAU;GACV,UAAU;EACZ;YARF;GAUE,oCAAA,IAAC,eAAD;IAAuB;IAAQ,OAAO,WAAW,WAAW,QAAQ;GAAQ,CAAA;GAC5E,oCAAA,KAAC,OAAD;IACE,yBAAsB;IACtB,SAAQ;IACR,MAAK;IACL,cAAY,GAAG,MAAM;IACrB,OAAO;KAAE,SAAS;KAAS,OAAO;KAAQ,QAAQ;IAAI;cALxD;KAOG,MAAM,KAAK,MAAM,UAAU;MAC1B,MAAM,SAAS,KAAK,QAAQ;MAC5B,MAAM,UAAU,WAAW,KAAK,KAAK;MAErC,OACE,oCAAA,KAAC,KAAD;OAEE,UAAU;OACV,MAAK;OACL,cAAY,GANE,KAAK,MAAM,IAAI,UAAU,KAAK,KAAK,IAAI,YAAY,KAAA,IAAY,KAAK,KAAK,QAAQ,QAAQ,CAAC,EAAE,kBAAkB,UAAU,MAAM,uBAAuB,GAAG;OAOtK,oBAAkB,eAAe,QAAQ,YAAY,KAAA;OACrD,oBAAoB,cAAc,KAAK;OACvC,mBAAmB,cAAc,KAAK;OACtC,oBAAoB,cAAc,KAAA,CAAS;OAC3C,eAAe,cAAc,KAAK;OAClC,cAAc,cAAc,KAAA,CAAS;iBAVvC,CAYE,oCAAA,IAAC,UAAD;QAAQ,IAAG;QAAM,IAAG;QAAM,GAAG;QAAQ,MAAK;QAAO,QAAO;QAA0B,aAAY;OAAM,CAAA,GACnG,YAAY,KAAA,KACX,oCAAA,IAAC,UAAD;QACE,wBAAsB,KAAK;QAC3B,IAAG;QACH,IAAG;QACH,GAAG;QACH,MAAK;QACL,QAAQ,KAAK;QACb,aAAY;QACZ,YAAW;QACX,iBAAiB,GAAG,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,EAAE;QACxD,WAAU;OACX,CAAA,CAEF;SA1BI,KAAK,KA0BT;KAEP,CAAC;KACD,oCAAA,IAAC,QAAD;MACE,oCAAiC;MACjC,GAAE;MACF,GAAE;MACF,YAAW;MACX,MAAK;MACL,UAAS;MACT,YAAW;gBAEV,iBAAiB,KAAA,IAAY,QAAQ,GAAG,aAAa,QAAQ,CAAC,EAAE;KAC7D,CAAA;KACN,oCAAA,IAAC,QAAD;MAAM,GAAE;MAAM,GAAE;MAAM,YAAW;MAAS,MAAK;MAA0B,UAAS;gBAAK;KAEjF,CAAA;IACH;;GACJ,WACC,oCAAA,KAAC,OAAD;IACE,IAAI;IACJ,2BAAwB;IACxB,MAAK;IACL,OAAO;KACL,UAAU;KACV,KAAK;KACL,MAAM;KACN,OAAO;KACP,QAAQ;KACR,SAAS;KACT,QAAQ;KACR,YAAY;KACZ,eAAe;KACf,cAAc;KACd,WAAW;IACb;cAhBF;KAkBE,oCAAA,KAAC,OAAD;MAAK,OAAO,EAAE,OAAO,QAAQ,MAAM;gBAAnC;OACG,QAAQ;OAAM;OAAG,UAAU,QAAQ,KAAK;MACtC;;KACL,oCAAA,IAAC,OAAD,EAAA,UACG,WAAW,QAAQ,KAAK,MAAM,KAAA,IAC3B,2BACA,GAAG,WAAW,QAAQ,KAAK,CAAC,CAAE,QAAQ,CAAC,EAAE,kBAAkB,WAAW,QAAQ,KAAK,IAAK,MAAM,wBAAwB,KACvH,CAAA;KACL,oCAAA,KAAC,OAAD,EAAA,UAAA,CAAK,iBAAc,UAAU,WAAW,CAAO,EAAA,CAAA;IAC5C;;GAEP,oCAAA,KAAC,OAAD;IAAK,cAAY,GAAG,MAAM;IAAmB,OAAO;KAAE,SAAS;KAAQ,KAAK;KAAG,UAAU;IAAG;cAA5F,CACG,MAAM,KAAK,SACV,oCAAA,IAAC,uBAAA,eAAD;KAEE,OAAO,GAAG,KAAK,MAAM,qCAAqC,KAAK,UAAU,UAAU,+BAA+B,WAAW,gBAAgB;eAE7I,oCAAA,KAAC,OAAD,EAAA,UAAA;MACE,oCAAA,IAAC,QAAD;OAAM,OAAO,EAAE,OAAO,KAAK,MAAM;iBAAG;MAAO,CAAA;MAAC;MAAE,KAAK;MAAM;MAAG,UAAU,KAAK,KAAK;MAC/E,WAAW,KAAK,KAAK,MAAM,KAAA,KAAa,oCAAA,KAAC,QAAD,EAAA,UAAA;OAAM;OAAG,WAAW,KAAK,KAAK,CAAC,CAAE,QAAQ,CAAC;OAAE;MAAQ,EAAA,CAAA;KAC1F,EAAA,CAAA;IACQ,GAPR,KAAK,KAOG,CAChB,GACD,oCAAA,IAAC,uBAAA,eAAD;KAAe,OAAO;eACpB,oCAAA,KAAC,OAAD,EAAA,UAAA;MACE,oCAAA,IAAC,QAAD;OAAM,OAAO,EAAE,OAAO,UAAU;iBAAG;MAAO,CAAA;MAAC;MAAe,UAAU,WAAW;KAC5E,EAAA,CAAA;IACQ,CAAA,CACZ;;IACH,UAAU,QAAQ,mBAClB,oCAAA,IAAC,OAAD;IAAK,MAAK;IAAS,OAAO;KAAE,OAAO;KAA6B,UAAU;KAAI,WAAW;IAAE;cACxF,UAAU,QAAQ;GAChB,CAAA;EAEA;;AAEb;AAEA,SAAS,iBAAiB,EAAE,SAAS,UAA2D;CAC9F,MAAM,YAAY,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS;CACjE,MAAM,UAAU,gCAAA,qBACd,YAAY;EAAE;EAAW,OAAO;EAAW,KAAK;CAAU,IAAI,KAAA,GAC9D,OACF;CACA,OACE,oCAAA,KAAC,OAAD;EAAK,OAAO,EAAE,eAAe,cAAc;YAA3C;GACE,oCAAA,IAAC,SAAD,EAAA,UAAQ;;;;;;;;;;;;;;;;;MAiBD,CAAA;GACN,QAAQ,UACP,oCAAA,IAAC,SAAD;IAAO,MAAK;IAAS,OAAO;KAAE,SAAS;KAAS,OAAO;KAA6B,cAAc;IAAE;cACjG,QAAQ;GACJ,CAAA;GAET,oCAAA,KAAC,OAAD;IAAK,0BAAuB;cAA5B,CACE,oCAAA,IAAC,OAAD;KAAK,0BAAuB;eACxB,CAAC,OAAO,QAAQ,CAAC,CAAW,KAAK,WACjC,oCAAA,IAAC,aAAD;MAEU;MACR,SAAS,QAAQ;MACT;MACR,cACE,WAAW,QACT,oCAAA,IAAC,gCAAA,wBAAD;OAAwB,SAAA;OAAQ,OAAO,QAAQ;OAAO,UAAU,QAAQ;MAAW,CAAA,IACjF,KAAA;KAEP,GATM,MASN,CACF;IACE,CAAA,GACL,oCAAA,IAAC,OAAD;KAAK,6BAA0B;eAC3B,CAAC,OAAO,QAAQ,CAAC,CAAW,KAAK,WACjC,oCAAA,IAAC,eAAD;MAAoC;MAAQ,QAAQ,QAAQ,GAAG,EAAE;MAAW;KAAS,GAAjE,MAAiE,CACtF;IACE,CAAA,CACF;;EACF;;AAET;AAEA,SAAgB,kBAA8B;CAC5C,MAAM,UAAU,6BAAA,0BAA0B;CAC1C,MAAM,cAAc,qCAAA,2BAA2B,oBAAgD;CAC/F,IAAI;CACJ,MAAM,OAAO,8BAAA,eACL,YAAY,UACjB,YAAY;EACX,cAAc;EACd,cAAc,UAAU,gBAAgB,IAAI,KAAA;CAC9C,GACA,EAAE,iBAAiB,KAAK,CAC1B;CACA,aAAa;EACX,KAAK;EACL,cAAc;EACd,QAAQ;CACV;AACF;AAEA,SAAS,kBAA8B;CACrC,MAAM,cAAc,SAAS,cAAc,OAAO;CAClD,YAAY,aAAa,kDAAkD,EAAE;CAC7E,YAAY,cAAc;;;;;;;;;;;;;;;;;;;;;;;CAuB1B,SAAS,KAAK,OAAO,WAAW;CAChC,IAAI;CACJ,IAAI,WAA2B;CAC/B,IAAI,UAA8B,CAAC;CACnC,IAAI,SAAS;CACb,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI,UAAU;CACd,IAAI;CACJ,IAAI,aAAa;CACjB,IAAI,aAAa;CACjB,MAAM,yBAAS,IAAI,IAAgC;CACnD,MAAM,gBAAgB;EACpB,KAAK,MAAM,CAAC,SAAS,aAAa,QAChC,IAAI,aAAa,MAAM,QAAQ,gBAAgB,OAAO;OACjD,QAAQ,aAAa,SAAS,QAAQ;EAE7C,OAAO,MAAM;EACb,IAAI,MAAM;GACR,mCAAA,QAAS,uBAAuB,IAAI;GACpC,KAAK,OAAO;GACZ,OAAO,KAAA;GACP,kBAAkB,KAAA;GAClB,iBAAiB,KAAA;EACnB;CACF;CACA,MAAM,SAAS,YAAY;EACzB,MAAM,iBAAiB,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS;EACtE,MAAM,kBAAkB,SAAS,cAAc,yCAAuC;EACtF,IAAI,YAAY,kBAAkB,aAAa,iBAAiB;GAC9D;GACA,QAAQ;GACR,UAAU,CAAC;GACX,SAAS;GACT,aAAa;GACb,UAAU;GACV,WAAW;EACb;EACA,MAAM,SAAS,KAAK,IAAI,IAAA,KAAkB,wBAAA;EAC1C,IAAI,QAAQ,UAAU,QAAQ,EAAE,CAAC,OAAO,QAAQ,UAAU,QAAQ,QAAQ,WAAW,OAAO,QAAQ,MAAM;EAC1G,IAAI,CAAC,YAAY,CAAC,WAAW,SAAS,oBAAoB,UAAU;EACpE,IAAI,CAAC,MAAM;GACT,OAAO,SAAS,cAAc,KAAK;GACnC,KAAK,aAAa,kCAAkC,EAAE;GACtD,KAAK,MAAM,aAAa;GACxB,OAAO,IAAI,UAAyB,SAAS,aAAa,OAAO,CAAC;GAClE,OAAO,OAAQ,SAAyB,OAAO;IAC7C,mBAAmB;IACnB,qBAAqB;IACrB,kBAAkB;IAClB,QAAQ;GACV,CAAC;GACD,SAAS,QAAQ,IAAI;EACvB;EACA,KAAK,MAAM,SAAS,SAAS,iBAA8B,0BAA0B,GAAG;GACtF,IAAI,MAAM,gBAAgB,SAAS,MAAM,gBAAgB,UAAU;GACnE,MAAM,QAAQ,MAAM,QAAQ,WAAW,CAAC,EAAE;GAC1C,IAAI,SAAS,MAAM,MAAM,YAAY,QAAQ;IAC3C,IAAI,CAAC,OAAO,IAAI,KAAK,GAAG,OAAO,IAAI,OAAO,MAAM,aAAa,OAAO,CAAC;IACrE,MAAM,MAAM,UAAU;GACxB;EACF;EAEA,KAAK,MAAM,SAAS,SAAS,UAAU;GACrC,IAAI,EAAE,iBAAiB,gBAAgB,UAAU,MAAM;GACvD,MAAM,gBACJ,MAAM,QAAQ,6BAA2B,KAAK,MAAM,cAAc,6BAA2B;GAC/F,MAAM,mBACH,MAAM,QAAQ,8DAA0D,KACvE,MAAM,cACJ,iHACF,MACF,CAAC,MAAM,cAAc,WAAW;GAClC,KAAK,iBAAiB,oBAAoB,MAAM,MAAM,YAAY,QAAQ;IACxE,IAAI,CAAC,OAAO,IAAI,KAAK,GAAG,OAAO,IAAI,OAAO,MAAM,aAAa,OAAO,CAAC;IACrE,MAAM,MAAM,UAAU;GACxB;GACA,IAAI,CAAC,OAAO,IAAI,KAAK,GAAG,OAAO,IAAI,OAAO,MAAM,aAAa,OAAO,CAAC;GACrE,MAAM,MAAM,WAAW;EACzB;EACA,MAAM,eAAe;GACnB,IAAI,SAAS,oBAAoB,WAAW,mBAAmB,SAAS;IACtE,mCAAA,QAAS,OAAO,oCAAA,IAAC,kBAAD;KAA2B;KAAiB;IAAS,CAAA,GAAG,IAAI;IAC5E,kBAAkB;IAClB,iBAAiB;GACnB;EACF;EACA,OAAO;EACP,IAAI,sBAAsB,cAAc,KAAK,IAAI,IAAI,YAAY;EACjE,oBAAoB;EACpB,aAAa,KAAK,IAAI,IAAI,wBAAA;EAC1B,MAAM,oBAAoB;EAC1B,MAAM,kBACJ,CAAC,WACD,sBAAsB,cACtB,SAAS,oBAAoB,YAC7B,UAAU,gBAAgB,QAC1B,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS,QAAQ;EACzD,IAAI;GACF,MAAM,YAAY,MAAM,6BAAA,sBAAsB;GAC9C,MAAM,UACJ,UAAU,gBAAgB,KAAA,IACtB,EAAE,QAAQ,WAAoB,IAC9B;IAAE,QAAQ;IAAsB,OAAO,UAAU;GAAY;GACnE,MAAM,YACJ,UAAU,UAAU,KAAA,IAChB,EAAE,QAAQ,WAAoB,IAC9B;IAAE,QAAQ;IAAsB,OAAO,UAAU;GAAM;GAC7D,MAAM,OACJ,UAAU,SAAS,KAAA,IACf,EAAE,QAAQ,WAAoB,IAC9B;IAAE,QAAQ;IAAsB,OAAO,UAAU;GAAK;GAC5D,IAAI,CAAC,UAAU,GAAG;GAClB,IAAI,QAAQ,WAAW,aAAa,MAAM,IAAI,MAAM,qBAAqB;GACzE,MAAM,SAAS,wBAAA,iBAAiB,QAAQ,SAAS,CAAC,CAAC;GACnD,OAAO,OAAO,KAAK,IAAI,GAAG,QAAQ,MAAM,KAAK,SAAS,KAAK,MAAM,KAAK,SAAS,CAAC,CAAC;GACjF,MAAM,WAAqB,CAAC;GAC5B,IAAI,UAAU,WAAW,aACvB,IAAI;IACF,OAAO,YAAY,wBAAA,mBACjB,UAAU,SAAS,CAAC,GACpB,KAAK,WAAW,cAAe,KAAK,SAAS,KAAA,IAAa,KAAA,CAC5D;IACA,MAAM,WAAW,IAAI,KAAK,UAAU,SAAS,CAAC,EAAA,CAAG,KAAK,SAAS,KAAK,SAAS,IAAI,CAAC;IAClF,MAAM,WAAW,IAAI,KAAK,QAAQ,SAAS,CAAC,EAAA,CAAG,KAAK,SAAS,KAAK,SAAS,IAAI,CAAC;IAChF,OAAO,gBACL,SAAS,OAAO,KAAK,SAAS,SAAS,SAAS,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,OAAO,SAAS,SAAS,IAAI,IAAI,CAAC;IAC1G,IAAI,CAAC,OAAO,eACV,SAAS,KACP,6FACF;GACJ,QAAQ;IACN,SAAS,KAAK,kEAAkE;GAClF;QAEA,SAAS,KAAK,8FAA8F;GAC9G,IAAI,KAAK,WAAW,aAClB,SAAS,KAAK,sEAAsE;GACtF,OAAO,iBAAiB,SAAS,KAAK,IAAI;GAC1C,UAAU,CAAC,GAAG,QAAQ,QAAQ,UAAU,MAAM,SAAS,OAAO,IAAI,GAAG,MAAM,CAAC,CACzE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAC/B,MAAM,GAAY;GACrB,SAAS;EACX,QAAQ;GACN,IAAI,CAAC,UAAU,GAAG;GAClB,SAAS;EACX,UAAU;GACR,IAAI,sBAAsB,mBAAmB,oBAAoB,KAAA;EACnE;EACA,IAAI,CAAC,WAAW,sBAAsB,YAAY,OAAO;CAC3D;CACA,MAAM,WAAW,IAAI,uBAAuB;EAC1C,OAAY;CACd,CAAC;CACD,SAAS,QAAQ,SAAS,MAAM;EAAE,WAAW;EAAM,SAAS;CAAK,CAAC;CAClE,MAAM,QAAQ,OAAO,kBAAkB;EACrC,OAAY;CACd,GAAG,GAAI;CACP,OAAY;CACZ,aAAa;EACX,UAAU;EACV;EACA,OAAO,cAAc,KAAK;EAC1B,SAAS,WAAW;EACpB,YAAY,OAAO;EACnB,QAAQ;EACR,UAAU,CAAC;CACb;AACF"}
@@ -0,0 +1,22 @@
1
+ const require_extensions = require("./_virtual/_global-external_@freelensapp/extensions.js");
2
+ const require__global_external_react = require("./_virtual/_global-external_react.js");
3
+ const require_jsx_runtime = require("./_virtual/_global-external_react/jsx-runtime.js");
4
+ //#region src/renderer/native-tooltip.tsx
5
+ var nextTooltipId = 0;
6
+ function NativeTooltip({ children, title }) {
7
+ const [generatedId] = require__global_external_react.useState(() => `power-tooltip-${++nextTooltipId}`);
8
+ const targetId = children.props.id || generatedId;
9
+ const Tooltip = require_extensions.Renderer.Component?.Tooltip;
10
+ return /* @__PURE__ */ require_jsx_runtime.jsxs(require_jsx_runtime.Fragment, { children: [require__global_external_react.cloneElement(children, {
11
+ id: targetId,
12
+ title: void 0
13
+ }), title != null && title !== "" && Tooltip ? /* @__PURE__ */ require_jsx_runtime.jsx(Tooltip, {
14
+ targetId,
15
+ formatters: { narrow: true },
16
+ children: title
17
+ }, `${targetId}:${String(children.type)}:${children.key ?? ""}`) : null] });
18
+ }
19
+ //#endregion
20
+ exports.NativeTooltip = NativeTooltip;
21
+
22
+ //# sourceMappingURL=native-tooltip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-tooltip.js","names":[],"sources":["../../src/renderer/native-tooltip.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { cloneElement, type ReactElement, type ReactNode, useState } from \"react\";\n\nlet nextTooltipId = 0;\n\nexport function NativeTooltip({ children, title }: { children: ReactElement; title?: ReactNode }) {\n const [generatedId] = useState(() => `power-tooltip-${++nextTooltipId}`);\n const targetId = children.props.id || generatedId;\n const Tooltip = Renderer.Component?.Tooltip;\n return (\n <>\n {cloneElement(children, { id: targetId, title: undefined })}\n {title != null && title !== \"\" && Tooltip ? (\n <Tooltip\n key={`${targetId}:${String(children.type)}:${children.key ?? \"\"}`}\n targetId={targetId}\n formatters={{ narrow: true }}\n >\n {title}\n </Tooltip>\n ) : null}\n </>\n );\n}\n"],"mappings":";;;;AAGA,IAAI,gBAAgB;AAEpB,SAAgB,cAAc,EAAE,UAAU,SAAwD;CAChG,MAAM,CAAC,eAAe,+BAAA,eAAe,iBAAiB,EAAE,eAAe;CACvE,MAAM,WAAW,SAAS,MAAM,MAAM;CACtC,MAAM,UAAU,mBAAA,SAAS,WAAW;CACpC,OACE,oCAAA,KAAA,oBAAA,UAAA,EAAA,UAAA,CACG,+BAAA,aAAa,UAAU;EAAE,IAAI;EAAU,OAAO,KAAA;CAAU,CAAC,GACzD,SAAS,QAAQ,UAAU,MAAM,UAChC,oCAAA,IAAC,SAAD;EAEY;EACV,YAAY,EAAE,QAAQ,KAAK;YAE1B;CACM,GALF,GAAG,SAAS,GAAG,OAAO,SAAS,IAAI,EAAE,GAAG,SAAS,OAAO,IAKtD,IACP,IACJ,EAAA,CAAA;AAEN"}