@kwirthmagnify/kwirth-homepage-matrix 0.1.2 → 0.1.4

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 (2) hide show
  1. package/front.js +163 -68
  2. package/package.json +1 -1
package/front.js CHANGED
@@ -57,17 +57,73 @@
57
57
  });
58
58
 
59
59
  // src/front/Matrix.tsx
60
+ var import_react2 = __toESM(require_react(), 1);
61
+ var import_material2 = __toESM(require_material(), 1);
62
+ var import_icons_material = __toESM(require_icons_material(), 1);
63
+
64
+ // src/front/MatrixSetup.tsx
60
65
  var import_react = __toESM(require_react(), 1);
61
66
  var import_material = __toESM(require_material(), 1);
62
- var import_icons_material = __toESM(require_icons_material(), 1);
63
67
  var MATRIX_GREEN = "#00ff41";
64
68
  var MATRIX_DIM = "#006620";
69
+ var MatrixSetup = ({ config, onSave, onClose }) => {
70
+ const [showQuickAccess, setShowQuickAccess] = (0, import_react.useState)(config.showQuickAccess ?? true);
71
+ const [showRain, setShowRain] = (0, import_react.useState)(config.showRain ?? true);
72
+ const [rainSpeed, setRainSpeed] = (0, import_react.useState)(config.rainSpeed ?? 12);
73
+ const [rainActiveLines, setRainActiveLines] = (0, import_react.useState)(config.rainActiveLines ?? 50);
74
+ const checkSx = { color: MATRIX_DIM, "&.Mui-checked": { color: MATRIX_GREEN } };
75
+ const labelSx = { fontFamily: "monospace", fontSize: "0.85rem", color: MATRIX_GREEN };
76
+ const sliderSx = { color: MATRIX_GREEN, "& .MuiSlider-thumb": { bgcolor: MATRIX_GREEN }, "& .MuiSlider-rail": { bgcolor: MATRIX_DIM } };
77
+ return /* @__PURE__ */ import_react.default.createElement(import_material.Dialog, { open: true, PaperProps: { sx: { bgcolor: "#000", border: `1px solid ${MATRIX_GREEN}`, boxShadow: `0 0 20px rgba(0,255,65,0.3)`, color: MATRIX_GREEN, minWidth: 360 } } }, /* @__PURE__ */ import_react.default.createElement(import_material.DialogTitle, { sx: { fontFamily: "monospace", fontSize: "1rem", color: MATRIX_GREEN, borderBottom: `1px solid ${MATRIX_DIM}`, pb: 1 } }, "// matrix setup"), /* @__PURE__ */ import_react.default.createElement(import_material.DialogContent, null, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column", spacing: 2.5, sx: { pt: 2 } }, /* @__PURE__ */ import_react.default.createElement(
78
+ import_material.FormControlLabel,
79
+ {
80
+ control: /* @__PURE__ */ import_react.default.createElement(import_material.Checkbox, { checked: showQuickAccess, onChange: (e) => setShowQuickAccess(e.target.checked), sx: checkSx }),
81
+ label: /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: labelSx }, "Show tabs / workspaces card")
82
+ }
83
+ ), /* @__PURE__ */ import_react.default.createElement(
84
+ import_material.FormControlLabel,
85
+ {
86
+ control: /* @__PURE__ */ import_react.default.createElement(import_material.Checkbox, { checked: showRain, onChange: (e) => setShowRain(e.target.checked), sx: checkSx }),
87
+ label: /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: labelSx }, "Falling code")
88
+ }
89
+ ), /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column", spacing: 0.5, sx: { opacity: showRain ? 1 : 0.3, pointerEvents: showRain ? "auto" : "none" } }, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", justifyContent: "space-between" }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.75rem", color: MATRIX_DIM } }, "Speed"), /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.75rem", color: MATRIX_GREEN } }, rainSpeed <= 5 ? "fast" : rainSpeed <= 12 ? "normal" : "slow")), /* @__PURE__ */ import_react.default.createElement(
90
+ import_material.Slider,
91
+ {
92
+ value: 21 - rainSpeed,
93
+ min: 1,
94
+ max: 20,
95
+ onChange: (_, v) => setRainSpeed(21 - v),
96
+ sx: sliderSx
97
+ }
98
+ ), /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", justifyContent: "space-between" }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.6rem", color: MATRIX_DIM } }, "slow"), /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.6rem", color: MATRIX_DIM } }, "fast"))), /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column", spacing: 0.5, sx: { opacity: showRain ? 1 : 0.3, pointerEvents: showRain ? "auto" : "none" } }, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", justifyContent: "space-between" }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.75rem", color: MATRIX_DIM } }, "Active lines"), /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.75rem", color: MATRIX_GREEN } }, rainActiveLines)), /* @__PURE__ */ import_react.default.createElement(
99
+ import_material.Slider,
100
+ {
101
+ value: rainActiveLines,
102
+ min: 5,
103
+ max: 100,
104
+ onChange: (_, v) => setRainActiveLines(v),
105
+ sx: sliderSx
106
+ }
107
+ ), /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", justifyContent: "space-between" }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.6rem", color: MATRIX_DIM } }, "5"), /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.6rem", color: MATRIX_DIM } }, "100"))))), /* @__PURE__ */ import_react.default.createElement(import_material.DialogActions, { sx: { borderTop: `1px solid ${MATRIX_DIM}`, pt: 1 } }, /* @__PURE__ */ import_react.default.createElement(
108
+ import_material.Button,
109
+ {
110
+ onClick: () => onSave({ showQuickAccess, showRain, rainSpeed, rainActiveLines }),
111
+ variant: "contained",
112
+ sx: { bgcolor: MATRIX_GREEN, color: "#000", fontFamily: "monospace", fontWeight: "bold", "&:hover": { bgcolor: "#00cc33" } }
113
+ },
114
+ "Save"
115
+ ), /* @__PURE__ */ import_react.default.createElement(import_material.Button, { onClick: onClose, sx: { color: MATRIX_DIM, fontFamily: "monospace" } }, "Cancel")));
116
+ };
117
+
118
+ // src/front/Matrix.tsx
119
+ var MATRIX_GREEN2 = "#00ff41";
120
+ var MATRIX_DIM2 = "#006620";
65
121
  var MATRIX_GLOW = "rgba(0,255,65,0.3)";
66
122
  var EVENTS_LIMIT = 25;
67
123
  var POLL_INTERVAL_MS = 1e4;
68
- var MatrixRain = () => {
69
- const canvasRef = (0, import_react.useRef)(null);
70
- (0, import_react.useEffect)(() => {
124
+ var MatrixRain = ({ speed, activeLines }) => {
125
+ const canvasRef = (0, import_react2.useRef)(null);
126
+ (0, import_react2.useEffect)(() => {
71
127
  const canvas = canvasRef.current;
72
128
  if (!canvas) return;
73
129
  const ctx = canvas.getContext("2d");
@@ -75,25 +131,44 @@
75
131
  const fontSize = 22;
76
132
  const chars = "\u30A2\u30A4\u30A6\u30A8\u30AA\u30AB\u30AD\u30AF\u30B1\u30B3\u30B5\u30B7\u30B9\u30BB\u30BD\u30BF\u30C1\u30C4\u30C6\u30C8\u30CA\u30CB\u30CC\u30CD\u30CE\u30CF\u30D2\u30D5\u30D8\u30DB\u30DE\u30DF\u30E0\u30E1\u30E2\u30E4\u30E6\u30E8\u30E9\u30EA\u30EB\u30EC\u30ED\u30EF\u30F2\u30F30123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
77
133
  let drops = [];
134
+ let active = [];
78
135
  let animId;
79
136
  let frame = 0;
80
- const SPEED = 12;
137
+ const activateDrops = (cols, h, count) => {
138
+ const indices = Array.from({ length: cols }, (_, i) => i);
139
+ for (let i = indices.length - 1; i > 0; i--) {
140
+ const j = Math.floor(Math.random() * (i + 1));
141
+ [indices[i], indices[j]] = [indices[j], indices[i]];
142
+ }
143
+ const n = Math.min(count, cols);
144
+ indices.slice(0, n).forEach((i) => {
145
+ active[i] = true;
146
+ drops[i] = -Math.floor(Math.random() * (h / fontSize) * 2);
147
+ });
148
+ indices.slice(n).forEach((i) => {
149
+ active[i] = false;
150
+ drops[i] = -99999;
151
+ });
152
+ };
81
153
  const resize = (w, h) => {
82
154
  canvas.width = w;
83
155
  canvas.height = h;
84
156
  const cols = Math.floor(w / fontSize);
85
- drops = Array.from({ length: cols }, () => -Math.floor(Math.random() * (h / fontSize) * 4));
157
+ drops = new Array(cols).fill(0);
158
+ active = new Array(cols).fill(false);
159
+ activateDrops(cols, h, activeLines);
86
160
  };
87
161
  const draw = () => {
88
162
  frame++;
89
163
  ctx.fillStyle = "rgba(0,0,0,0.02)";
90
164
  ctx.fillRect(0, 0, canvas.width, canvas.height);
91
165
  ctx.font = `${fontSize}px monospace`;
92
- if (frame % SPEED === 0) {
166
+ if (frame % speed === 0) {
93
167
  for (let i = 0; i < drops.length; i++) {
168
+ if (!active[i]) continue;
94
169
  if (drops[i] > 0) {
95
170
  const bright = Math.random() > 0.97;
96
- ctx.fillStyle = bright ? "#ccffcc" : MATRIX_GREEN;
171
+ ctx.fillStyle = bright ? "#ccffcc" : MATRIX_GREEN2;
97
172
  ctx.fillText(chars[Math.floor(Math.random() * chars.length)], i * fontSize, drops[i] * fontSize);
98
173
  }
99
174
  if (drops[i] * fontSize > canvas.height) {
@@ -114,8 +189,8 @@
114
189
  cancelAnimationFrame(animId);
115
190
  observer.disconnect();
116
191
  };
117
- }, []);
118
- return /* @__PURE__ */ import_react.default.createElement(
192
+ }, [speed, activeLines]);
193
+ return /* @__PURE__ */ import_react2.default.createElement(
119
194
  "canvas",
120
195
  {
121
196
  ref: canvasRef,
@@ -126,9 +201,9 @@
126
201
  var StatusLight = ({ online, events, animationDelay }) => {
127
202
  const hasError = online && (events ?? []).some((e) => e.type !== "Normal" && e.type !== "Warning");
128
203
  const hasWarning = online && !hasError && (events ?? []).some((e) => e.type === "Warning");
129
- const color = !online ? "#ff3333" : hasError ? "#ff3333" : hasWarning ? "#ff9800" : MATRIX_GREEN;
204
+ const color = !online ? "#ff3333" : hasError ? "#ff3333" : hasWarning ? "#ff9800" : MATRIX_GREEN2;
130
205
  const label = !online ? "Offline" : hasError ? "Errors detected" : hasWarning ? "Warnings detected" : "Online";
131
- return /* @__PURE__ */ import_react.default.createElement(import_material.Tooltip, { title: label }, /* @__PURE__ */ import_react.default.createElement(import_material.Box, { sx: {
206
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.Tooltip, { title: label }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: {
132
207
  width: 12,
133
208
  height: 12,
134
209
  borderRadius: "50%",
@@ -141,9 +216,9 @@
141
216
  } }));
142
217
  };
143
218
  var MetricBar = ({ label, value }) => {
144
- const barRef = (0, import_react.useRef)(null);
145
- const [cols, setCols] = (0, import_react.useState)(10);
146
- (0, import_react.useEffect)(() => {
219
+ const barRef = (0, import_react2.useRef)(null);
220
+ const [cols, setCols] = (0, import_react2.useState)(10);
221
+ (0, import_react2.useEffect)(() => {
147
222
  if (!barRef.current) return;
148
223
  const obs = new ResizeObserver(() => {
149
224
  if (barRef.current) setCols(Math.max(5, Math.floor(barRef.current.offsetWidth / 6)));
@@ -153,11 +228,11 @@
153
228
  }, []);
154
229
  const filled = Math.round(value * cols / 100);
155
230
  const bar = "\u2588".repeat(filled) + "\u2591".repeat(cols - filled);
156
- const color = value > 90 ? "#ff3333" : value > 80 ? "#b36200" : MATRIX_GREEN;
157
- return /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", alignItems: "center", spacing: 0 }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.65rem", color: MATRIX_DIM, width: 28, flexShrink: 0 } }, label), /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { ref: barRef, sx: { fontFamily: "monospace", fontSize: "0.65rem", color, letterSpacing: "-0.5px", flex: 1, overflow: "hidden", whiteSpace: "nowrap" } }, bar), /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.65rem", color, flexShrink: 0, pl: 0.5, width: 32, textAlign: "right" } }, Math.round(value), "%"));
231
+ const color = value > 90 ? "#ff3333" : value > 80 ? "#b36200" : MATRIX_GREEN2;
232
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "row", alignItems: "center", spacing: 0 }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { sx: { fontFamily: "monospace", fontSize: "0.65rem", color: MATRIX_DIM2, width: 28, flexShrink: 0 } }, label), /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { ref: barRef, sx: { fontFamily: "monospace", fontSize: "0.65rem", color, letterSpacing: "-0.5px", flex: 1, overflow: "hidden", whiteSpace: "nowrap" } }, bar), /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { sx: { fontFamily: "monospace", fontSize: "0.65rem", color, flexShrink: 0, pl: 0.5, width: 32, textAlign: "right" } }, Math.round(value), "%"));
158
233
  };
159
- var MiniInfoCard = ({ label, value, stretch }) => /* @__PURE__ */ import_react.default.createElement(import_material.Box, { sx: {
160
- border: `1px solid ${MATRIX_DIM}`,
234
+ var MiniInfoCard = ({ label, value, stretch }) => /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: {
235
+ border: `1px solid ${MATRIX_DIM2}`,
161
236
  borderRadius: 1,
162
237
  px: 1,
163
238
  display: "flex",
@@ -166,51 +241,51 @@
166
241
  justifyContent: "center",
167
242
  minWidth: 70,
168
243
  ...stretch ? { height: "100%" } : { py: 0.75 }
169
- } }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "1rem", color: MATRIX_GREEN, lineHeight: 1.2 } }, value), /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.78rem", color: MATRIX_DIM, lineHeight: 1.2 } }, label));
244
+ } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { sx: { fontFamily: "monospace", fontSize: "1rem", color: MATRIX_GREEN2, lineHeight: 1.2 } }, value), /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { sx: { fontFamily: "monospace", fontSize: "0.78rem", color: MATRIX_DIM2, lineHeight: 1.2 } }, label));
170
245
  var EventLog = ({ events }) => {
171
- const boxRef = (0, import_react.useRef)(null);
172
- (0, import_react.useEffect)(() => {
246
+ const boxRef = (0, import_react2.useRef)(null);
247
+ (0, import_react2.useEffect)(() => {
173
248
  if (boxRef.current) boxRef.current.scrollTop = boxRef.current.scrollHeight;
174
249
  }, [events]);
175
- return /* @__PURE__ */ import_react.default.createElement(import_material.Box, { ref: boxRef, sx: {
250
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { ref: boxRef, sx: {
176
251
  flex: 1,
177
252
  overflowY: "auto",
178
253
  overflowX: "auto",
179
254
  fontFamily: "monospace",
180
255
  fontSize: "0.55rem",
181
256
  lineHeight: 1.9,
182
- color: MATRIX_DIM,
257
+ color: MATRIX_DIM2,
183
258
  bgcolor: "rgba(0,18,6,0.92)",
184
- border: `1px solid ${MATRIX_DIM}`,
259
+ border: `1px solid ${MATRIX_DIM2}`,
185
260
  borderRadius: 1,
186
261
  p: 1,
187
262
  whiteSpace: "nowrap",
188
263
  "&::-webkit-scrollbar": { width: 4, height: 4 },
189
- "&::-webkit-scrollbar-thumb": { bgcolor: MATRIX_DIM, borderRadius: 2 }
190
- } }, events.length === 0 ? /* @__PURE__ */ import_react.default.createElement(import_material.Box, { sx: { color: MATRIX_GREEN, opacity: 0.4 } }, "// follow the white rabbit") : [...events].reverse().map((e, i) => {
264
+ "&::-webkit-scrollbar-thumb": { bgcolor: MATRIX_DIM2, borderRadius: 2 }
265
+ } }, events.length === 0 ? /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: { color: MATRIX_GREEN2, opacity: 0.4 } }, "// follow the white rabbit") : [...events].reverse().map((e, i) => {
191
266
  const d = new Date(e.time);
192
267
  const t = [d.getHours(), d.getMinutes(), d.getSeconds()].map((n) => String(n).padStart(2, "0")).join(":");
193
- return /* @__PURE__ */ import_react.default.createElement(import_material.Box, { key: i, sx: { color: e.type === "Warning" ? "#ff9800" : MATRIX_GREEN, mb: 0.2 } }, /* @__PURE__ */ import_react.default.createElement(import_material.Box, { component: "span", sx: { color: MATRIX_DIM, mr: 0.5 } }, t), /* @__PURE__ */ import_react.default.createElement(import_material.Box, { component: "span", sx: { mr: 0.5 } }, "[", e.reason, "]"), /* @__PURE__ */ import_react.default.createElement(import_material.Box, { component: "span", sx: { color: MATRIX_DIM, mr: 0.5 } }, e.object), e.message);
268
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { key: i, sx: { color: e.type === "Warning" ? "#ff9800" : MATRIX_GREEN2, mb: 0.2 } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { component: "span", sx: { color: MATRIX_DIM2, mr: 0.5 } }, t), /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { component: "span", sx: { mr: 0.5 } }, "[", e.reason, "]"), /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { component: "span", sx: { color: MATRIX_DIM2, mr: 0.5 } }, e.object), e.message);
194
269
  }));
195
270
  };
196
271
  var matrixCardSx = {
197
272
  bgcolor: "rgba(0,0,0,0.80)",
198
- border: `1px solid ${MATRIX_GREEN}`,
273
+ border: `1px solid ${MATRIX_GREEN2}`,
199
274
  boxShadow: `0 0 10px ${MATRIX_GLOW}, inset 0 0 10px rgba(0,255,65,0.05)`,
200
- color: MATRIX_GREEN,
275
+ color: MATRIX_GREEN2,
201
276
  backdropFilter: "blur(2px)"
202
277
  };
203
278
  var matrixIconBtnSx = {
204
- color: MATRIX_DIM,
279
+ color: MATRIX_DIM2,
205
280
  p: 0.25,
206
281
  borderRadius: 0.5,
207
282
  fontSize: "0.6rem",
208
283
  fontFamily: "monospace",
209
284
  lineHeight: 1,
210
- "&:hover": { color: MATRIX_GREEN, bgcolor: "rgba(0,255,65,0.1)" }
285
+ "&:hover": { color: MATRIX_GREEN2, bgcolor: "rgba(0,255,65,0.1)" }
211
286
  };
212
287
  function QuickColumn({ label, items, getKey, getName, getSub, onLaunch, onDelete }) {
213
- return /* @__PURE__ */ import_react.default.createElement(import_material.Box, { sx: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 0.5, alignSelf: "stretch" } }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.75rem", color: MATRIX_DIM, letterSpacing: 1, mb: 0.25 } }, "// ", label), /* @__PURE__ */ import_react.default.createElement(import_material.Box, { sx: { borderTop: `1px solid ${MATRIX_DIM}`, mb: 0.5 } }), items.length === 0 ? /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.7rem", color: MATRIX_DIM, opacity: 0.5 } }, "// empty") : items.map((item) => /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { key: getKey(item), direction: "row", alignItems: "center", sx: { minWidth: 0, gap: 0.5 } }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", fontSize: "0.75rem", flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, /* @__PURE__ */ import_react.default.createElement("span", { style: { color: MATRIX_GREEN } }, getName(item)), getSub(item) && /* @__PURE__ */ import_react.default.createElement("span", { style: { color: MATRIX_DIM, paddingLeft: "20px" } }, getSub(item))), /* @__PURE__ */ import_react.default.createElement(import_material.Tooltip, { title: "Launch" }, /* @__PURE__ */ import_react.default.createElement(import_material.IconButton, { size: "small", sx: matrixIconBtnSx, onClick: () => onLaunch(item) }, "\u25B6")), /* @__PURE__ */ import_react.default.createElement(import_material.Tooltip, { title: "Remove" }, /* @__PURE__ */ import_react.default.createElement(import_material.IconButton, { size: "small", sx: matrixIconBtnSx, onClick: () => onDelete(item) }, "\u2715")))));
288
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 0.5, alignSelf: "stretch" } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { sx: { fontFamily: "monospace", fontSize: "0.75rem", color: MATRIX_DIM2, letterSpacing: 1, mb: 0.25 } }, "// ", label), /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: { borderTop: `1px solid ${MATRIX_DIM2}`, mb: 0.5 } }), items.length === 0 ? /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { sx: { fontFamily: "monospace", fontSize: "0.7rem", color: MATRIX_DIM2, opacity: 0.5 } }, "// empty") : items.map((item) => /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { key: getKey(item), direction: "row", alignItems: "center", sx: { minWidth: 0, gap: 0.5 } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { sx: { fontFamily: "monospace", fontSize: "0.75rem", flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, /* @__PURE__ */ import_react2.default.createElement("span", { style: { color: MATRIX_GREEN2 } }, getName(item)), getSub(item) && /* @__PURE__ */ import_react2.default.createElement("span", { style: { color: MATRIX_DIM2, paddingLeft: "20px" } }, getSub(item))), /* @__PURE__ */ import_react2.default.createElement(import_material2.Tooltip, { title: "Launch" }, /* @__PURE__ */ import_react2.default.createElement(import_material2.IconButton, { size: "small", sx: matrixIconBtnSx, onClick: () => onLaunch(item) }, "\u25B6")), /* @__PURE__ */ import_react2.default.createElement(import_material2.Tooltip, { title: "Remove" }, /* @__PURE__ */ import_react2.default.createElement(import_material2.IconButton, { size: "small", sx: matrixIconBtnSx, onClick: () => onDelete(item) }, "\u2715")))));
214
289
  }
215
290
  var QuickAccessCard = (props) => {
216
291
  const delLastTab = (tab) => props.onUpdateTabs(props.lastTabs.filter((t) => t.name !== tab.name || t.channel !== tab.channel), props.favTabs);
@@ -219,7 +294,7 @@
219
294
  const delFavWs = (ws) => props.onUpdateWorkspaces(props.lastWorkspaces, props.favWorkspaces.filter((w) => w.name !== ws.name));
220
295
  const allEmpty = props.lastTabs.length === 0 && props.favTabs.length === 0 && props.lastWorkspaces.length === 0 && props.favWorkspaces.length === 0;
221
296
  if (allEmpty) return null;
222
- return /* @__PURE__ */ import_react.default.createElement(import_material.Card, { variant: "outlined", sx: { ...matrixCardSx, gridColumn: "1 / -1", minHeight: 160 } }, /* @__PURE__ */ import_react.default.createElement(import_material.CardContent, { sx: { py: 1.5, px: 2, height: "100%", boxSizing: "border-box", "&:last-child": { pb: 1.5 } } }, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", spacing: 2, alignItems: "flex-start", sx: { minWidth: 0 } }, /* @__PURE__ */ import_react.default.createElement(
297
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.Card, { variant: "outlined", sx: { ...matrixCardSx, gridColumn: "1 / -1", minHeight: 160 } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.CardContent, { sx: { py: 1.5, px: 2, height: "100%", boxSizing: "border-box", "&:last-child": { pb: 1.5 } } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "row", spacing: 2, alignItems: "flex-start", sx: { minWidth: 0 } }, /* @__PURE__ */ import_react2.default.createElement(
223
298
  QuickColumn,
224
299
  {
225
300
  label: "LAST TABS",
@@ -230,7 +305,7 @@
230
305
  onLaunch: (t) => props.onHomepageSelectTab(t),
231
306
  onDelete: delLastTab
232
307
  }
233
- ), /* @__PURE__ */ import_react.default.createElement(import_material.Divider, { orientation: "vertical", flexItem: true, sx: { borderColor: MATRIX_DIM, opacity: 0.4 } }), /* @__PURE__ */ import_react.default.createElement(
308
+ ), /* @__PURE__ */ import_react2.default.createElement(import_material2.Divider, { orientation: "vertical", flexItem: true, sx: { borderColor: MATRIX_DIM2, opacity: 0.4 } }), /* @__PURE__ */ import_react2.default.createElement(
234
309
  QuickColumn,
235
310
  {
236
311
  label: "FAV TABS",
@@ -241,7 +316,7 @@
241
316
  onLaunch: (t) => props.onHomepageSelectTab(t),
242
317
  onDelete: delFavTab
243
318
  }
244
- ), /* @__PURE__ */ import_react.default.createElement(import_material.Divider, { orientation: "vertical", flexItem: true, sx: { borderColor: MATRIX_DIM, opacity: 0.4 } }), /* @__PURE__ */ import_react.default.createElement(
319
+ ), /* @__PURE__ */ import_react2.default.createElement(import_material2.Divider, { orientation: "vertical", flexItem: true, sx: { borderColor: MATRIX_DIM2, opacity: 0.4 } }), /* @__PURE__ */ import_react2.default.createElement(
245
320
  QuickColumn,
246
321
  {
247
322
  label: "LAST WORKSPACES",
@@ -252,7 +327,7 @@
252
327
  onLaunch: (w) => props.onSelectWorkspace(w),
253
328
  onDelete: delLastWs
254
329
  }
255
- ), /* @__PURE__ */ import_react.default.createElement(import_material.Divider, { orientation: "vertical", flexItem: true, sx: { borderColor: MATRIX_DIM, opacity: 0.4 } }), /* @__PURE__ */ import_react.default.createElement(
330
+ ), /* @__PURE__ */ import_react2.default.createElement(import_material2.Divider, { orientation: "vertical", flexItem: true, sx: { borderColor: MATRIX_DIM2, opacity: 0.4 } }), /* @__PURE__ */ import_react2.default.createElement(
256
331
  QuickColumn,
257
332
  {
258
333
  label: "FAV WORKSPACES",
@@ -266,14 +341,14 @@
266
341
  ))));
267
342
  };
268
343
  var Matrix = (props) => {
269
- (0, import_react.useEffect)(() => {
344
+ (0, import_react2.useEffect)(() => {
270
345
  const id = "matrix-keyframes";
271
346
  if (!document.getElementById(id)) {
272
347
  const style = document.createElement("style");
273
348
  style.id = id;
274
349
  style.textContent = `@keyframes matrix-status-pulse {
275
350
  0%, 100% { opacity: 0.25; box-shadow: none; }
276
- 50% { opacity: 0.85; box-shadow: 0 0 7px 2px ${MATRIX_GREEN}; }
351
+ 50% { opacity: 0.85; box-shadow: 0 0 7px 2px ${MATRIX_GREEN2}; }
277
352
  }`;
278
353
  document.head.appendChild(style);
279
354
  }
@@ -281,9 +356,9 @@
281
356
  document.getElementById("matrix-keyframes")?.remove();
282
357
  };
283
358
  }, []);
284
- const containerRef = (0, import_react.useRef)(null);
285
- const [containerHeight, setContainerHeight] = import_react.default.useState(0);
286
- (0, import_react.useEffect)(() => {
359
+ const containerRef = (0, import_react2.useRef)(null);
360
+ const [containerHeight, setContainerHeight] = import_react2.default.useState(0);
361
+ (0, import_react2.useEffect)(() => {
287
362
  const observer = new ResizeObserver(() => {
288
363
  if (!containerRef.current) return;
289
364
  const { top } = containerRef.current.getBoundingClientRect();
@@ -292,8 +367,8 @@
292
367
  observer.observe(document.body);
293
368
  return () => observer.disconnect();
294
369
  }, [containerRef.current]);
295
- const [clusterMetrics, setClusterMetrics] = (0, import_react.useState)({});
296
- (0, import_react.useEffect)(() => {
370
+ const [clusterMetrics, setClusterMetrics] = (0, import_react2.useState)({});
371
+ (0, import_react2.useEffect)(() => {
297
372
  if (!props.getClusterMetrics) return;
298
373
  const fetchAll = () => {
299
374
  props.clusters.forEach((cluster) => {
@@ -306,8 +381,8 @@
306
381
  const timer = setInterval(fetchAll, POLL_INTERVAL_MS);
307
382
  return () => clearInterval(timer);
308
383
  }, [props.clusters, props.getClusterMetrics]);
309
- const [clusterEvents, setClusterEvents] = (0, import_react.useState)({});
310
- (0, import_react.useEffect)(() => {
384
+ const [clusterEvents, setClusterEvents] = (0, import_react2.useState)({});
385
+ (0, import_react2.useEffect)(() => {
311
386
  if (!props.getClusterEvents) return;
312
387
  const fetchAll = () => {
313
388
  props.clusters.forEach((cluster) => {
@@ -336,22 +411,40 @@
336
411
  channelObject: { clusterName, view: "cluster", namespace: "", group: "", pod: "", container: "" }
337
412
  });
338
413
  };
414
+ const [localConfig, setLocalConfig] = (0, import_react2.useState)(props.config ?? {});
415
+ const [showSetup, setShowSetup] = (0, import_react2.useState)(false);
416
+ const showQuickAccess = localConfig.showQuickAccess ?? true;
417
+ const showRain = localConfig.showRain ?? true;
418
+ const rainSpeed = localConfig.rainSpeed ?? 12;
419
+ const rainActiveLines = localConfig.rainActiveLines ?? 50;
420
+ const saveConfig = (cfg) => {
421
+ localStorage.setItem("kwirth.homepage.config.matrix", JSON.stringify(cfg));
422
+ setLocalConfig(cfg);
423
+ setShowSetup(false);
424
+ };
339
425
  const hasMagnify = props.frontChannels.has("magnify");
340
426
  const hasTopology = props.frontChannels.has("topology");
341
427
  const magnifyClass = props.frontChannels.get("magnify");
342
428
  const magnifyIcon = magnifyClass ? new magnifyClass().getChannelIcon() : null;
343
429
  const topologyClass = props.frontChannels.get("topology");
344
- const topologyIcon = topologyClass ? new topologyClass().getChannelIcon() : /* @__PURE__ */ import_react.default.createElement(import_icons_material.AccountTree, null);
430
+ const topologyIcon = topologyClass ? new topologyClass().getChannelIcon() : /* @__PURE__ */ import_react2.default.createElement(import_icons_material.AccountTree, null);
345
431
  const matrixButtonSx = {
346
432
  fontFamily: "monospace",
347
- "&:not(.Mui-disabled)": { color: MATRIX_GREEN, borderColor: MATRIX_GREEN },
433
+ "&:not(.Mui-disabled)": { color: MATRIX_GREEN2, borderColor: MATRIX_GREEN2 },
348
434
  "&:hover:not(.Mui-disabled)": {
349
- borderColor: MATRIX_GREEN,
435
+ borderColor: MATRIX_GREEN2,
350
436
  bgcolor: "rgba(0,255,65,0.1)",
351
437
  boxShadow: `0 0 8px ${MATRIX_GLOW}`
352
438
  }
353
439
  };
354
- return /* @__PURE__ */ import_react.default.createElement(import_material.Box, { ref: containerRef, sx: { position: "relative", width: "100%", height: `${containerHeight}px`, overflow: "hidden", bgcolor: "#000" } }, /* @__PURE__ */ import_react.default.createElement(MatrixRain, null), /* @__PURE__ */ import_react.default.createElement(import_material.Box, { sx: {
440
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { ref: containerRef, sx: { position: "relative", width: "100%", height: `${containerHeight}px`, overflow: "hidden", bgcolor: "#000" } }, showRain && /* @__PURE__ */ import_react2.default.createElement(MatrixRain, { speed: rainSpeed, activeLines: rainActiveLines }), /* @__PURE__ */ import_react2.default.createElement(import_material2.IconButton, { onClick: () => setShowSetup(true), size: "small", sx: {
441
+ position: "absolute",
442
+ top: 8,
443
+ right: 8,
444
+ zIndex: 3,
445
+ color: MATRIX_DIM2,
446
+ "&:hover": { color: MATRIX_GREEN2, bgcolor: "rgba(0,255,65,0.1)" }
447
+ } }, /* @__PURE__ */ import_react2.default.createElement(import_icons_material.Settings, { fontSize: "small" })), /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: {
355
448
  position: "relative",
356
449
  zIndex: 1,
357
450
  p: 3,
@@ -361,40 +454,40 @@
361
454
  gridTemplateColumns: "repeat(2, 1fr)",
362
455
  gap: 4,
363
456
  alignContent: "start"
364
- } }, /* @__PURE__ */ import_react.default.createElement(QuickAccessCard, { ...props }), props.clusters.map((cluster, idx) => {
457
+ } }, showQuickAccess && /* @__PURE__ */ import_react2.default.createElement(QuickAccessCard, { ...props }), props.clusters.map((cluster, idx) => {
365
458
  const clusterChannelIds = new Set((cluster.kwirthData?.channels ?? []).map((ch) => ch.id));
366
459
  const clusterHasMagnify = hasMagnify && clusterChannelIds.has("magnify");
367
460
  const clusterHasTopology = hasTopology && clusterChannelIds.has("topology");
368
- return /* @__PURE__ */ import_react.default.createElement(import_material.Card, { key: cluster.name, variant: "outlined", sx: {
461
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.Card, { key: cluster.name, variant: "outlined", sx: {
369
462
  bgcolor: "rgba(0,0,0,0.80)",
370
- border: `1px solid ${MATRIX_GREEN}`,
463
+ border: `1px solid ${MATRIX_GREEN2}`,
371
464
  boxShadow: `0 0 10px ${MATRIX_GLOW}, inset 0 0 10px rgba(0,255,65,0.05)`,
372
- color: MATRIX_GREEN,
465
+ color: MATRIX_GREEN2,
373
466
  backdropFilter: "blur(2px)",
374
467
  height: `${Math.floor((containerHeight - 24 * 2 - 24) / 2) - 4}px`,
375
468
  overflow: "hidden"
376
- } }, /* @__PURE__ */ import_react.default.createElement(import_material.CardContent, { sx: { height: "100%", display: "flex", flexDirection: "row", gap: 2, py: 2, "&:last-child": { pb: 2 } } }, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column", justifyContent: "space-between", sx: { flex: "0 0 40%", minWidth: 0 } }, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column", spacing: 1 }, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", alignItems: "center", spacing: 1 }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { variant: "h6", sx: {
469
+ } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.CardContent, { sx: { height: "100%", display: "flex", flexDirection: "row", gap: 2, py: 2, "&:last-child": { pb: 2 } } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "column", justifyContent: "space-between", sx: { flex: "0 0 40%", minWidth: 0 } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "column", spacing: 1 }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "row", alignItems: "center", spacing: 1 }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { variant: "h6", sx: {
377
470
  fontFamily: "monospace",
378
- color: MATRIX_GREEN,
471
+ color: MATRIX_GREEN2,
379
472
  lineHeight: 1.3,
380
- textShadow: `0 0 8px ${MATRIX_GREEN}`,
473
+ textShadow: `0 0 8px ${MATRIX_GREEN2}`,
381
474
  overflow: "hidden",
382
475
  textOverflow: "ellipsis",
383
476
  whiteSpace: "nowrap",
384
477
  m: 0
385
- } }, cluster.name), /* @__PURE__ */ import_react.default.createElement(StatusLight, { online: !!clusterMetrics[cluster.name], events: clusterEvents[cluster.name], animationDelay: `${idx * 0.7 % 2.5}s` })), /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { variant: "body2", sx: {
478
+ } }, cluster.name), /* @__PURE__ */ import_react2.default.createElement(StatusLight, { online: !!clusterMetrics[cluster.name], events: clusterEvents[cluster.name], animationDelay: `${idx * 0.7 % 2.5}s` })), /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { variant: "body2", sx: {
386
479
  fontFamily: "monospace",
387
- color: MATRIX_DIM,
480
+ color: MATRIX_DIM2,
388
481
  overflow: "hidden",
389
482
  textOverflow: "ellipsis",
390
483
  whiteSpace: "nowrap"
391
- } }, cluster.url), clusterMetrics[cluster.name] && /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column", spacing: 0.25 }, /* @__PURE__ */ import_react.default.createElement(MetricBar, { label: "CPU", value: clusterMetrics[cluster.name].cpu }), /* @__PURE__ */ import_react.default.createElement(MetricBar, { label: "MEM", value: clusterMetrics[cluster.name].memory }), /* @__PURE__ */ import_react.default.createElement(MetricBar, { label: "POD", value: clusterMetrics[cluster.name].maxPods > 0 ? clusterMetrics[cluster.name].pods / clusterMetrics[cluster.name].maxPods * 100 : 0 }))), clusterMetrics[cluster.name] && /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", spacing: 1.5, sx: { justifyContent: "center" } }, /* @__PURE__ */ import_react.default.createElement(MiniInfoCard, { label: "vCPUs", value: clusterMetrics[cluster.name].vcpus != null ? String(clusterMetrics[cluster.name].vcpus) : "--" }), /* @__PURE__ */ import_react.default.createElement(MiniInfoCard, { label: "RAM", value: clusterMetrics[cluster.name].totalMemoryBytes != null ? `${(clusterMetrics[cluster.name].totalMemoryBytes / 1073741824).toFixed(0)}G` : "--" }), /* @__PURE__ */ import_react.default.createElement(MiniInfoCard, { label: "Pods", value: clusterMetrics[cluster.name].pods ? String(clusterMetrics[cluster.name].pods) : "--" }), /* @__PURE__ */ import_react.default.createElement(MiniInfoCard, { label: "Nodes", value: cluster.clusterInfo?.nodes?.length != null ? String(cluster.clusterInfo.nodes.length) : "--" })), /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column", spacing: 0.75 }, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", spacing: 0.5, alignItems: "center" }, (cluster.kwirthData?.channels ?? []).map((ch) => {
484
+ } }, cluster.url), clusterMetrics[cluster.name] && /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "column", spacing: 0.25 }, /* @__PURE__ */ import_react2.default.createElement(MetricBar, { label: "CPU", value: clusterMetrics[cluster.name].cpu }), /* @__PURE__ */ import_react2.default.createElement(MetricBar, { label: "MEM", value: clusterMetrics[cluster.name].memory }), /* @__PURE__ */ import_react2.default.createElement(MetricBar, { label: "POD", value: clusterMetrics[cluster.name].maxPods > 0 ? clusterMetrics[cluster.name].pods / clusterMetrics[cluster.name].maxPods * 100 : 0 }))), clusterMetrics[cluster.name] && /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "row", spacing: 1.5, sx: { justifyContent: "center" } }, /* @__PURE__ */ import_react2.default.createElement(MiniInfoCard, { label: "vCPUs", value: clusterMetrics[cluster.name].vcpus != null ? String(clusterMetrics[cluster.name].vcpus) : "--" }), /* @__PURE__ */ import_react2.default.createElement(MiniInfoCard, { label: "RAM", value: clusterMetrics[cluster.name].totalMemoryBytes != null ? `${(clusterMetrics[cluster.name].totalMemoryBytes / 1073741824).toFixed(0)}G` : "--" }), /* @__PURE__ */ import_react2.default.createElement(MiniInfoCard, { label: "Pods", value: clusterMetrics[cluster.name].pods ? String(clusterMetrics[cluster.name].pods) : "--" }), /* @__PURE__ */ import_react2.default.createElement(MiniInfoCard, { label: "Nodes", value: cluster.clusterInfo?.nodes?.length != null ? String(cluster.clusterInfo.nodes.length) : "--" })), /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "column", spacing: 0.75 }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "row", spacing: 0.5, alignItems: "center" }, (cluster.kwirthData?.channels ?? []).map((ch) => {
392
485
  const channelClass = props.frontChannels.get(ch.id);
393
486
  if (!channelClass) return null;
394
487
  const icon = new channelClass().getChannelIcon();
395
- return /* @__PURE__ */ import_react.default.createElement(import_material.Tooltip, { key: ch.id, title: ch.id }, import_react.default.cloneElement(icon, { fontSize: "small", sx: { color: MATRIX_GREEN, opacity: 0.6 } }));
396
- })), /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", spacing: 1, justifyContent: "flex-start" }, /* @__PURE__ */ import_react.default.createElement(
397
- import_material.Button,
488
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.Tooltip, { key: ch.id, title: ch.id }, import_react2.default.cloneElement(icon, { fontSize: "small", sx: { color: MATRIX_GREEN2, opacity: 0.6 } }));
489
+ })), /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "row", spacing: 1, justifyContent: "flex-start" }, /* @__PURE__ */ import_react2.default.createElement(
490
+ import_material2.Button,
398
491
  {
399
492
  variant: "outlined",
400
493
  size: "small",
@@ -404,8 +497,8 @@
404
497
  sx: matrixButtonSx
405
498
  },
406
499
  "Topology"
407
- ), /* @__PURE__ */ import_react.default.createElement(
408
- import_material.Button,
500
+ ), /* @__PURE__ */ import_react2.default.createElement(
501
+ import_material2.Button,
409
502
  {
410
503
  variant: "outlined",
411
504
  size: "small",
@@ -415,14 +508,16 @@
415
508
  sx: matrixButtonSx
416
509
  },
417
510
  "Magnify"
418
- )))), /* @__PURE__ */ import_react.default.createElement(EventLog, { events: clusterEvents[cluster.name] ?? [] })));
419
- }), props.clusters.length === 0 && /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { sx: { fontFamily: "monospace", color: MATRIX_GREEN, p: 2, textShadow: `0 0 8px ${MATRIX_GREEN}` } }, "// Entering the matrix...")));
511
+ )))), /* @__PURE__ */ import_react2.default.createElement(EventLog, { events: clusterEvents[cluster.name] ?? [] })));
512
+ }), props.clusters.length === 0 && /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { sx: { fontFamily: "monospace", color: MATRIX_GREEN2, p: 2, textShadow: `0 0 8px ${MATRIX_GREEN2}` } }, "// Entering the matrix...")), showSetup && /* @__PURE__ */ import_react2.default.createElement(MatrixSetup, { config: localConfig, onSave: saveConfig, onClose: () => setShowSetup(false) }));
420
513
  };
421
514
 
422
515
  // src/front/index.ts
423
516
  window.__kwirth_homepages__["matrix"] = {
424
517
  homepageId: "matrix",
425
518
  displayName: "Matrix",
426
- Component: Matrix
519
+ Component: Matrix,
520
+ SetupDialog: MatrixSetup,
521
+ defaultConfig: { showQuickAccess: true, showRain: true, rainSpeed: 12, rainActiveLines: 50 }
427
522
  };
428
523
  })();
package/package.json CHANGED
@@ -2,6 +2,6 @@
2
2
  "id": "matrix",
3
3
  "name": "@kwirthmagnify/kwirth-homepage-matrix",
4
4
  "displayName": "Matrix",
5
- "version": "0.1.2",
5
+ "version": "0.1.4",
6
6
  "description": "Matrix-style cluster overview homepage for Kwirth"
7
7
  }