@viasoftbr/shared-ui 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -123,6 +123,7 @@ __export(src_exports, {
123
123
  Accordion: () => Accordion_default,
124
124
  AddNetwork: () => AddNetwork_default,
125
125
  AudioGroup: () => AudioGroup_default,
126
+ AuthContext: () => AuthContext,
126
127
  AuthProvider: () => AuthProvider,
127
128
  CheckboxField: () => CheckboxField_default,
128
129
  ColorField: () => ColorField_default,
@@ -140,7 +141,6 @@ __export(src_exports, {
140
141
  InterfacesTable: () => InterfacesTable_default,
141
142
  InterfacesTimeseries: () => InterfacesTimeseries_default,
142
143
  Livecast: () => Livecast_default,
143
- MetadataLoader: () => MetadataLoader,
144
144
  MetricBar: () => Metrics_default,
145
145
  MiddlewareAuthGroup: () => Auth_default,
146
146
  MiddlewareChannelsGroup: () => Channels_default,
@@ -154,7 +154,6 @@ __export(src_exports, {
154
154
  Protocol: () => Protocol_default,
155
155
  ProtocolGroup: () => ProtocolGroup_default,
156
156
  RangeField: () => RangeField_default,
157
- RemoteModule: () => RemoteModule,
158
157
  RequireAuth: () => RequireAuth_default,
159
158
  Role: () => Role,
160
159
  SaveDiscard: () => SaveDiscard_default,
@@ -165,6 +164,7 @@ __export(src_exports, {
165
164
  SliderField: () => SliderField_default,
166
165
  StreamControl: () => StreamControl_default,
167
166
  SwitchField: () => SwitchField_default,
167
+ ThemeContext: () => ThemeContext,
168
168
  ThemeProvider: () => ThemeProvider,
169
169
  VUBar: () => VUMeter_default,
170
170
  ValidationItem: () => Validation_default,
@@ -186,8 +186,8 @@ __export(src_exports, {
186
186
  getRefreshToken: () => getRefreshToken,
187
187
  hostConfigLoader: () => hostConfigLoader,
188
188
  isFirstRun: () => isFirstRun,
189
- loadRemoteModule: () => loadRemoteModule,
190
- metadataLoader: () => metadataLoader,
189
+ isValidIPv4: () => isValidIPv4,
190
+ isValidIPv6: () => isValidIPv6,
191
191
  registry: () => registry,
192
192
  saveConfig: () => saveConfig,
193
193
  setAccessToken: () => setAccessToken,
@@ -3040,6 +3040,35 @@ function buildWsUrl(path = "/") {
3040
3040
  return `${proto}://${host}${path.startsWith("/") ? path : "/" + path}`;
3041
3041
  }
3042
3042
  }
3043
+ function extractBearerToken(headers, explicitToken) {
3044
+ if (explicitToken)
3045
+ return explicitToken;
3046
+ if (!headers)
3047
+ return null;
3048
+ const authHeader = headers.Authorization || headers.authorization;
3049
+ if (!authHeader)
3050
+ return null;
3051
+ const match = authHeader.match(/^Bearer\s+(.+)$/i);
3052
+ return match ? match[1] : null;
3053
+ }
3054
+ function appendWsQueryParam(url, key, value) {
3055
+ try {
3056
+ const parsed = new URL(
3057
+ url,
3058
+ typeof window !== "undefined" ? window.location.href : void 0
3059
+ );
3060
+ parsed.searchParams.set(key, value);
3061
+ return parsed.toString();
3062
+ } catch {
3063
+ const separator = url.includes("?") ? "&" : "?";
3064
+ return `${url}${separator}${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
3065
+ }
3066
+ }
3067
+ function normalizeProtocols(protocols) {
3068
+ if (!protocols)
3069
+ return void 0;
3070
+ return Array.isArray(protocols) ? protocols.filter(Boolean) : [protocols];
3071
+ }
3043
3072
  async function encodeFfurl(settings) {
3044
3073
  const { ffurl } = await fetchApi.postJson("/auth/protocols/ffurl/encode", settings);
3045
3074
  return ffurl;
@@ -3048,8 +3077,28 @@ async function decodeFfurl(ffurl) {
3048
3077
  const { settings } = await fetchApi.postJson("/auth/protocols/ffurl/decode", { ffurl });
3049
3078
  return settings;
3050
3079
  }
3051
- function subscribeToWebsocket(url, onMessage) {
3052
- const socket = new WebSocket(url);
3080
+ function subscribeToWebsocket(url, onMessage, options = {}) {
3081
+ const bearerToken = extractBearerToken(options.headers, options.bearerToken);
3082
+ const bearerStrategy = options.bearerStrategy ?? "query";
3083
+ let resolvedUrl = url;
3084
+ const protocols = normalizeProtocols(options.protocols) ?? [];
3085
+ if (options.headers && Object.keys(options.headers).length > 0) {
3086
+ console.warn(
3087
+ "WebSocket connections in browsers do not support custom HTTP headers. shared-ui will derive bearer auth from Authorization and forward it using query string or subprotocol."
3088
+ );
3089
+ }
3090
+ if (bearerToken) {
3091
+ if (bearerStrategy === "protocol") {
3092
+ protocols.push("bearer", bearerToken);
3093
+ } else {
3094
+ resolvedUrl = appendWsQueryParam(
3095
+ url,
3096
+ options.bearerQueryParam ?? "access_token",
3097
+ bearerToken
3098
+ );
3099
+ }
3100
+ }
3101
+ const socket = protocols.length > 0 ? new WebSocket(resolvedUrl, protocols) : new WebSocket(resolvedUrl);
3053
3102
  socket.onmessage = (event) => {
3054
3103
  try {
3055
3104
  const data = JSON.parse(event.data);
@@ -3100,140 +3149,6 @@ var authService = {
3100
3149
  }
3101
3150
  };
3102
3151
 
3103
- // src/services/loadRemoteModule.ts
3104
- var React = __toESM(require("react"), 1);
3105
- var ReactDOM = __toESM(require("react-dom"), 1);
3106
- var sharedScopeInitialized = false;
3107
- function getSharedScope() {
3108
- if (!globalThis.__federation_shared__) {
3109
- globalThis.__federation_shared__ = {};
3110
- }
3111
- if (!sharedScopeInitialized) {
3112
- globalThis.__federation_shared__["react"] = {
3113
- "18.3.1": {
3114
- get: () => Promise.resolve(() => React),
3115
- loaded: true,
3116
- from: "core",
3117
- scope: "default"
3118
- }
3119
- };
3120
- globalThis.__federation_shared__["react-dom"] = {
3121
- "18.3.1": {
3122
- get: () => Promise.resolve(() => ReactDOM),
3123
- loaded: true,
3124
- from: "core",
3125
- scope: "default"
3126
- }
3127
- };
3128
- sharedScopeInitialized = true;
3129
- }
3130
- return globalThis.__federation_shared__;
3131
- }
3132
- var loadedContainers = /* @__PURE__ */ new Map();
3133
- var initializedContainers = /* @__PURE__ */ new Set();
3134
- async function loadContainer(url) {
3135
- if (loadedContainers.has(url)) {
3136
- return loadedContainers.get(url);
3137
- }
3138
- const loadPromise = (async () => {
3139
- try {
3140
- const container = await import(
3141
- /* @vite-ignore */
3142
- url
3143
- );
3144
- if (container.init && !initializedContainers.has(url)) {
3145
- await container.init(getSharedScope());
3146
- initializedContainers.add(url);
3147
- }
3148
- return container;
3149
- } catch (error2) {
3150
- loadedContainers.delete(url);
3151
- initializedContainers.delete(url);
3152
- throw error2;
3153
- }
3154
- })();
3155
- loadedContainers.set(url, loadPromise);
3156
- return loadPromise;
3157
- }
3158
- async function loadRemoteModule(config) {
3159
- const container = await loadContainer(config.url);
3160
- if (!container || typeof container.get !== "function") {
3161
- throw new Error(`Container inv\xE1lido ou sem m\xE9todo get: ${config.scope}`);
3162
- }
3163
- if (typeof container.dynamicLoadingCss === "function") {
3164
- try {
3165
- await container.dynamicLoadingCss([]);
3166
- } catch (err) {
3167
- console.warn(`Aviso: Falha ao carregar CSS global do remote ${config.scope}`, err);
3168
- }
3169
- }
3170
- const factory2 = await container.get(config.module);
3171
- const moduleExports = await factory2();
3172
- if (moduleExports && typeof moduleExports === "object" && "default" in moduleExports) {
3173
- return moduleExports.default;
3174
- }
3175
- return moduleExports;
3176
- }
3177
-
3178
- // src/services/metadataLoader.ts
3179
- var MetadataLoader = class {
3180
- constructor() {
3181
- __publicField(this, "metadataCache", /* @__PURE__ */ new Map());
3182
- }
3183
- async loadMetadata(metadataUrl) {
3184
- if (this.metadataCache.has(metadataUrl)) {
3185
- return this.metadataCache.get(metadataUrl) || [];
3186
- }
3187
- try {
3188
- const response = await fetch(metadataUrl);
3189
- console.log(response);
3190
- if (!response.ok) {
3191
- throw new Error(`Failed to fetch metadata: ${response.statusText}`);
3192
- }
3193
- const data = await response.json();
3194
- let metadata;
3195
- if (Array.isArray(data)) {
3196
- metadata = data;
3197
- } else if (data.pages && Array.isArray(data.pages)) {
3198
- metadata = data.pages;
3199
- } else {
3200
- throw new Error(
3201
- "Invalid metadata format: expected array or object with pages property"
3202
- );
3203
- }
3204
- metadata.forEach((page, index3) => {
3205
- if (!page.id || !page.name || !page.path || !page.url) {
3206
- throw new Error(
3207
- `Invalid page metadata at index ${index3}: missing required fields`
3208
- );
3209
- }
3210
- });
3211
- this.metadataCache.set(metadataUrl, metadata);
3212
- return metadata;
3213
- } catch (error2) {
3214
- console.warn(`Failed to load metadata from ${metadataUrl}:`, error2);
3215
- return [];
3216
- }
3217
- }
3218
- async loadFromDirectory(directoryUrl) {
3219
- try {
3220
- const manifestUrl = `${directoryUrl}/manifest.json`;
3221
- return await this.loadMetadata(manifestUrl);
3222
- } catch (error2) {
3223
- throw new Error(
3224
- `Directory manifest not found at ${directoryUrl}/manifest.json: ${error2}`
3225
- );
3226
- }
3227
- }
3228
- clearCache() {
3229
- this.metadataCache.clear();
3230
- }
3231
- getCachedMetadata(metadataUrl) {
3232
- return this.metadataCache.get(metadataUrl);
3233
- }
3234
- };
3235
- var metadataLoader = new MetadataLoader();
3236
-
3237
3152
  // src/services/registry.ts
3238
3153
  var PluginRegistryImpl = class {
3239
3154
  constructor() {
@@ -26029,20 +25944,27 @@ var import_react5 = require("react");
26029
25944
  var import_react4 = require("react");
26030
25945
  var import_jsx_runtime2 = require("react/jsx-runtime");
26031
25946
  var AuthContext = (0, import_react4.createContext)(void 0);
26032
- var AuthProvider = ({ children, onNavigate }) => {
26033
- const [user, setUser] = (0, import_react4.useState)(null);
26034
- const [accessToken, setToken] = (0, import_react4.useState)(null);
25947
+ var AuthProvider = ({
25948
+ children,
25949
+ onNavigate,
25950
+ storage = typeof window !== "undefined" ? window.localStorage : null,
25951
+ authService: authService2 = authService,
25952
+ initialUser = null,
25953
+ initialAccessToken = null
25954
+ }) => {
25955
+ const [user, setUser] = (0, import_react4.useState)(initialUser);
25956
+ const [accessToken, setToken] = (0, import_react4.useState)(initialAccessToken ?? null);
26035
25957
  const [loading, setLoading] = (0, import_react4.useState)(true);
26036
25958
  (0, import_react4.useEffect)(() => {
26037
25959
  try {
26038
- const storedUser = localStorage.getItem("user");
25960
+ const storedUser = storage?.getItem("user");
26039
25961
  if (storedUser)
26040
25962
  setUser(JSON.parse(storedUser));
26041
25963
  } catch {
26042
25964
  }
26043
25965
  try {
26044
- const savedAccess = localStorage.getItem("accessToken");
26045
- const savedRefresh = localStorage.getItem("refreshToken");
25966
+ const savedAccess = storage?.getItem("accessToken");
25967
+ const savedRefresh = storage?.getItem("refreshToken");
26046
25968
  if (savedAccess) {
26047
25969
  setToken(savedAccess);
26048
25970
  setAccessToken(savedAccess);
@@ -26053,15 +25975,17 @@ var AuthProvider = ({ children, onNavigate }) => {
26053
25975
  } catch {
26054
25976
  }
26055
25977
  setLoading(false);
26056
- }, []);
25978
+ }, [storage]);
26057
25979
  const login = async (username, password, options) => {
26058
- const resp = await authService.login(username, password);
25980
+ const resp = await authService2.login(username, password);
26059
25981
  setToken(resp.accessToken);
26060
25982
  setAccessToken(resp.accessToken);
26061
25983
  setRefreshToken(resp.refreshToken);
26062
25984
  setUser(resp.user);
26063
25985
  try {
26064
- localStorage.setItem("user", JSON.stringify(resp.user));
25986
+ storage?.setItem("user", JSON.stringify(resp.user));
25987
+ storage?.setItem("accessToken", resp.accessToken);
25988
+ storage?.setItem("refreshToken", resp.refreshToken);
26065
25989
  } catch {
26066
25990
  }
26067
25991
  if (options?.redirect !== false)
@@ -26069,13 +25993,15 @@ var AuthProvider = ({ children, onNavigate }) => {
26069
25993
  };
26070
25994
  const logout = async () => {
26071
25995
  try {
26072
- await authService.logout();
25996
+ await authService2.logout();
26073
25997
  } finally {
26074
25998
  setToken(null);
26075
25999
  clearTokens();
26076
26000
  setUser(null);
26077
26001
  try {
26078
- localStorage.removeItem("user");
26002
+ storage?.removeItem("user");
26003
+ storage?.removeItem("accessToken");
26004
+ storage?.removeItem("refreshToken");
26079
26005
  } catch {
26080
26006
  }
26081
26007
  onNavigate?.("/login");
@@ -26087,10 +26013,10 @@ var AuthProvider = ({ children, onNavigate }) => {
26087
26013
  const want = Array.isArray(roles) ? roles : [roles];
26088
26014
  return want.some((r17) => user.role === r17);
26089
26015
  };
26090
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AuthContext.Provider, { value: { user, accessToken, loading, login, logout, hasRole }, children });
26016
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AuthContext, { value: { user, accessToken, loading, login, logout, hasRole }, children });
26091
26017
  };
26092
26018
  function useAuth() {
26093
- const ctx = (0, import_react4.useContext)(AuthContext);
26019
+ const ctx = (0, import_react4.use)(AuthContext);
26094
26020
  if (!ctx)
26095
26021
  throw new Error("useAuth must be used within AuthProvider");
26096
26022
  return ctx;
@@ -26139,7 +26065,7 @@ var SkeletonBlock = ({ lines = 3, className = "" }) => {
26139
26065
  var import_jsx_runtime4 = require("react/jsx-runtime");
26140
26066
  var SectionContext = (0, import_react5.createContext)(void 0);
26141
26067
  function useSection() {
26142
- const ctx = (0, import_react5.useContext)(SectionContext);
26068
+ const ctx = (0, import_react5.use)(SectionContext);
26143
26069
  return ctx ?? { readonly: false };
26144
26070
  }
26145
26071
  var Section2 = ({ id, title, icon, expanded, onToggle, children, readonly, loading = false }) => {
@@ -26184,7 +26110,7 @@ var Section2 = ({ id, title, icon, expanded, onToggle, children, readonly, loadi
26184
26110
  overflow-hidden
26185
26111
  ${expanded ? "max-h-fit opacity-100" : "max-h-0 opacity-0"}
26186
26112
  `,
26187
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "px-6 py-4 border-t transition-all transition-discrete border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900/50", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SectionContext.Provider, { value: { readonly: !!effectiveReadonly }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SkeletonBlock, { lines: 5 }) : children }) })
26113
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "px-6 py-4 border-t transition-all transition-discrete border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900/50", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SectionContext, { value: { readonly: !!effectiveReadonly }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SkeletonBlock, { lines: 5 }) : children }) })
26188
26114
  }
26189
26115
  )
26190
26116
  ] });
@@ -28343,7 +28269,7 @@ function m6(u16, t15) {
28343
28269
  }
28344
28270
 
28345
28271
  // node_modules/.pnpm/@floating-ui+react@0.26.28_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@floating-ui/react/dist/floating-ui.react.mjs
28346
- var React6 = __toESM(require("react"), 1);
28272
+ var React5 = __toESM(require("react"), 1);
28347
28273
  var import_react48 = require("react");
28348
28274
 
28349
28275
  // node_modules/.pnpm/@floating-ui+utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs
@@ -28648,7 +28574,7 @@ function rectToClientRect(rect) {
28648
28574
  }
28649
28575
 
28650
28576
  // node_modules/.pnpm/@floating-ui+react@0.26.28_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@floating-ui/react/dist/floating-ui.react.mjs
28651
- var ReactDOM3 = __toESM(require("react-dom"), 1);
28577
+ var ReactDOM2 = __toESM(require("react-dom"), 1);
28652
28578
 
28653
28579
  // node_modules/.pnpm/@floating-ui+core@1.7.4/node_modules/@floating-ui/core/dist/floating-ui.core.mjs
28654
28580
  function computeCoordsFromPlacement(_ref, placement, rtl) {
@@ -29851,9 +29777,9 @@ var computePosition2 = (reference, floating, options) => {
29851
29777
  };
29852
29778
 
29853
29779
  // node_modules/.pnpm/@floating-ui+react-dom@2.1.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.mjs
29854
- var React5 = __toESM(require("react"), 1);
29780
+ var React4 = __toESM(require("react"), 1);
29855
29781
  var import_react47 = require("react");
29856
- var ReactDOM2 = __toESM(require("react-dom"), 1);
29782
+ var ReactDOM = __toESM(require("react-dom"), 1);
29857
29783
  var isClient = typeof document !== "undefined";
29858
29784
  var noop2 = function noop3() {
29859
29785
  };
@@ -29918,7 +29844,7 @@ function roundByDPR(element, value) {
29918
29844
  return Math.round(value * dpr) / dpr;
29919
29845
  }
29920
29846
  function useLatestRef(value) {
29921
- const ref = React5.useRef(value);
29847
+ const ref = React4.useRef(value);
29922
29848
  index(() => {
29923
29849
  ref.current = value;
29924
29850
  });
@@ -29941,7 +29867,7 @@ function useFloating(options) {
29941
29867
  whileElementsMounted,
29942
29868
  open
29943
29869
  } = options;
29944
- const [data, setData] = React5.useState({
29870
+ const [data, setData] = React4.useState({
29945
29871
  x: 0,
29946
29872
  y: 0,
29947
29873
  strategy,
@@ -29949,19 +29875,19 @@ function useFloating(options) {
29949
29875
  middlewareData: {},
29950
29876
  isPositioned: false
29951
29877
  });
29952
- const [latestMiddleware, setLatestMiddleware] = React5.useState(middleware);
29878
+ const [latestMiddleware, setLatestMiddleware] = React4.useState(middleware);
29953
29879
  if (!deepEqual(latestMiddleware, middleware)) {
29954
29880
  setLatestMiddleware(middleware);
29955
29881
  }
29956
- const [_reference, _setReference] = React5.useState(null);
29957
- const [_floating, _setFloating] = React5.useState(null);
29958
- const setReference = React5.useCallback((node) => {
29882
+ const [_reference, _setReference] = React4.useState(null);
29883
+ const [_floating, _setFloating] = React4.useState(null);
29884
+ const setReference = React4.useCallback((node) => {
29959
29885
  if (node !== referenceRef.current) {
29960
29886
  referenceRef.current = node;
29961
29887
  _setReference(node);
29962
29888
  }
29963
29889
  }, []);
29964
- const setFloating = React5.useCallback((node) => {
29890
+ const setFloating = React4.useCallback((node) => {
29965
29891
  if (node !== floatingRef.current) {
29966
29892
  floatingRef.current = node;
29967
29893
  _setFloating(node);
@@ -29969,14 +29895,14 @@ function useFloating(options) {
29969
29895
  }, []);
29970
29896
  const referenceEl = externalReference || _reference;
29971
29897
  const floatingEl = externalFloating || _floating;
29972
- const referenceRef = React5.useRef(null);
29973
- const floatingRef = React5.useRef(null);
29974
- const dataRef = React5.useRef(data);
29898
+ const referenceRef = React4.useRef(null);
29899
+ const floatingRef = React4.useRef(null);
29900
+ const dataRef = React4.useRef(data);
29975
29901
  const hasWhileElementsMounted = whileElementsMounted != null;
29976
29902
  const whileElementsMountedRef = useLatestRef(whileElementsMounted);
29977
29903
  const platformRef = useLatestRef(platform2);
29978
29904
  const openRef = useLatestRef(open);
29979
- const update = React5.useCallback(() => {
29905
+ const update = React4.useCallback(() => {
29980
29906
  if (!referenceRef.current || !floatingRef.current) {
29981
29907
  return;
29982
29908
  }
@@ -29999,7 +29925,7 @@ function useFloating(options) {
29999
29925
  };
30000
29926
  if (isMountedRef.current && !deepEqual(dataRef.current, fullData)) {
30001
29927
  dataRef.current = fullData;
30002
- ReactDOM2.flushSync(() => {
29928
+ ReactDOM.flushSync(() => {
30003
29929
  setData(fullData);
30004
29930
  });
30005
29931
  }
@@ -30014,7 +29940,7 @@ function useFloating(options) {
30014
29940
  }));
30015
29941
  }
30016
29942
  }, [open]);
30017
- const isMountedRef = React5.useRef(false);
29943
+ const isMountedRef = React4.useRef(false);
30018
29944
  index(() => {
30019
29945
  isMountedRef.current = true;
30020
29946
  return () => {
@@ -30033,17 +29959,17 @@ function useFloating(options) {
30033
29959
  update();
30034
29960
  }
30035
29961
  }, [referenceEl, floatingEl, update, whileElementsMountedRef, hasWhileElementsMounted]);
30036
- const refs = React5.useMemo(() => ({
29962
+ const refs = React4.useMemo(() => ({
30037
29963
  reference: referenceRef,
30038
29964
  floating: floatingRef,
30039
29965
  setReference,
30040
29966
  setFloating
30041
29967
  }), [setReference, setFloating]);
30042
- const elements = React5.useMemo(() => ({
29968
+ const elements = React4.useMemo(() => ({
30043
29969
  reference: referenceEl,
30044
29970
  floating: floatingEl
30045
29971
  }), [referenceEl, floatingEl]);
30046
- const floatingStyles = React5.useMemo(() => {
29972
+ const floatingStyles = React4.useMemo(() => {
30047
29973
  const initialStyles = {
30048
29974
  position: strategy,
30049
29975
  left: 0,
@@ -30069,7 +29995,7 @@ function useFloating(options) {
30069
29995
  top: y8
30070
29996
  };
30071
29997
  }, [strategy, transform, elements.floating, data.x, data.y]);
30072
- return React5.useMemo(() => ({
29998
+ return React4.useMemo(() => ({
30073
29999
  ...data,
30074
30000
  update,
30075
30001
  refs,
@@ -30096,12 +30022,12 @@ var size3 = (options, deps) => ({
30096
30022
 
30097
30023
  // node_modules/.pnpm/@floating-ui+react@0.26.28_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@floating-ui/react/dist/floating-ui.react.mjs
30098
30024
  var SafeReact = {
30099
- ...React6
30025
+ ...React5
30100
30026
  };
30101
30027
  var useInsertionEffect = SafeReact.useInsertionEffect;
30102
30028
  var useSafeInsertionEffect = useInsertionEffect || ((fn) => fn());
30103
30029
  function useEffectEvent(callback) {
30104
- const ref = React6.useRef(() => {
30030
+ const ref = React5.useRef(() => {
30105
30031
  if (true) {
30106
30032
  throw new Error("Cannot call an event handler while rendering.");
30107
30033
  }
@@ -30109,7 +30035,7 @@ function useEffectEvent(callback) {
30109
30035
  useSafeInsertionEffect(() => {
30110
30036
  ref.current = callback;
30111
30037
  });
30112
- return React6.useCallback(function() {
30038
+ return React5.useCallback(function() {
30113
30039
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
30114
30040
  args[_key] = arguments[_key];
30115
30041
  }
@@ -30132,13 +30058,13 @@ var genId = () => (
30132
30058
  "floating-ui-" + Math.random().toString(36).slice(2, 6) + count++
30133
30059
  );
30134
30060
  function useFloatingId() {
30135
- const [id, setId] = React6.useState(() => serverHandoffComplete ? genId() : void 0);
30061
+ const [id, setId] = React5.useState(() => serverHandoffComplete ? genId() : void 0);
30136
30062
  index2(() => {
30137
30063
  if (id == null) {
30138
30064
  setId(genId());
30139
30065
  }
30140
30066
  }, []);
30141
- React6.useEffect(() => {
30067
+ React5.useEffect(() => {
30142
30068
  serverHandoffComplete = true;
30143
30069
  }, []);
30144
30070
  return id;
@@ -30189,13 +30115,13 @@ function createPubSub() {
30189
30115
  }
30190
30116
  };
30191
30117
  }
30192
- var FloatingNodeContext = /* @__PURE__ */ React6.createContext(null);
30193
- var FloatingTreeContext = /* @__PURE__ */ React6.createContext(null);
30118
+ var FloatingNodeContext = /* @__PURE__ */ React5.createContext(null);
30119
+ var FloatingTreeContext = /* @__PURE__ */ React5.createContext(null);
30194
30120
  var useFloatingParentNodeId = () => {
30195
30121
  var _React$useContext;
30196
- return ((_React$useContext = React6.useContext(FloatingNodeContext)) == null ? void 0 : _React$useContext.id) || null;
30122
+ return ((_React$useContext = React5.useContext(FloatingNodeContext)) == null ? void 0 : _React$useContext.id) || null;
30197
30123
  };
30198
- var useFloatingTree = () => React6.useContext(FloatingTreeContext);
30124
+ var useFloatingTree = () => React5.useContext(FloatingTreeContext);
30199
30125
  var FOCUSABLE_ATTRIBUTE = "data-floating-ui-focusable";
30200
30126
  function useFloatingRootContext(options) {
30201
30127
  const {
@@ -30204,8 +30130,8 @@ function useFloatingRootContext(options) {
30204
30130
  elements: elementsProp
30205
30131
  } = options;
30206
30132
  const floatingId = useId();
30207
- const dataRef = React6.useRef({});
30208
- const [events] = React6.useState(() => createPubSub());
30133
+ const dataRef = React5.useRef({});
30134
+ const [events] = React5.useState(() => createPubSub());
30209
30135
  const nested = useFloatingParentNodeId() != null;
30210
30136
  if (true) {
30211
30137
  const optionDomReference = elementsProp.reference;
@@ -30213,7 +30139,7 @@ function useFloatingRootContext(options) {
30213
30139
  error("Cannot pass a virtual element to the `elements.reference` option,", "as it must be a real DOM element. Use `refs.setPositionReference()`", "instead.");
30214
30140
  }
30215
30141
  }
30216
- const [positionReference, setPositionReference] = React6.useState(elementsProp.reference);
30142
+ const [positionReference, setPositionReference] = React5.useState(elementsProp.reference);
30217
30143
  const onOpenChange = useEffectEvent((open2, event, reason) => {
30218
30144
  dataRef.current.openEvent = open2 ? event : void 0;
30219
30145
  events.emit("openchange", {
@@ -30224,15 +30150,15 @@ function useFloatingRootContext(options) {
30224
30150
  });
30225
30151
  onOpenChangeProp == null || onOpenChangeProp(open2, event, reason);
30226
30152
  });
30227
- const refs = React6.useMemo(() => ({
30153
+ const refs = React5.useMemo(() => ({
30228
30154
  setPositionReference
30229
30155
  }), []);
30230
- const elements = React6.useMemo(() => ({
30156
+ const elements = React5.useMemo(() => ({
30231
30157
  reference: positionReference || elementsProp.reference || null,
30232
30158
  floating: elementsProp.floating || null,
30233
30159
  domReference: elementsProp.reference
30234
30160
  }), [positionReference, elementsProp.reference, elementsProp.floating]);
30235
- return React6.useMemo(() => ({
30161
+ return React5.useMemo(() => ({
30236
30162
  dataRef,
30237
30163
  open,
30238
30164
  onOpenChange,
@@ -30259,11 +30185,11 @@ function useFloating2(options) {
30259
30185
  });
30260
30186
  const rootContext = options.rootContext || internalRootContext;
30261
30187
  const computedElements = rootContext.elements;
30262
- const [_domReference, setDomReference] = React6.useState(null);
30263
- const [positionReference, _setPositionReference] = React6.useState(null);
30188
+ const [_domReference, setDomReference] = React5.useState(null);
30189
+ const [positionReference, _setPositionReference] = React5.useState(null);
30264
30190
  const optionDomReference = computedElements == null ? void 0 : computedElements.domReference;
30265
30191
  const domReference = optionDomReference || _domReference;
30266
- const domReferenceRef = React6.useRef(null);
30192
+ const domReferenceRef = React5.useRef(null);
30267
30193
  const tree = useFloatingTree();
30268
30194
  index2(() => {
30269
30195
  if (domReference) {
@@ -30279,7 +30205,7 @@ function useFloating2(options) {
30279
30205
  }
30280
30206
  }
30281
30207
  });
30282
- const setPositionReference = React6.useCallback((node) => {
30208
+ const setPositionReference = React5.useCallback((node) => {
30283
30209
  const computedPositionReference = isElement(node) ? {
30284
30210
  getBoundingClientRect: () => node.getBoundingClientRect(),
30285
30211
  contextElement: node
@@ -30287,7 +30213,7 @@ function useFloating2(options) {
30287
30213
  _setPositionReference(computedPositionReference);
30288
30214
  position.refs.setReference(computedPositionReference);
30289
30215
  }, [position.refs]);
30290
- const setReference = React6.useCallback((node) => {
30216
+ const setReference = React5.useCallback((node) => {
30291
30217
  if (isElement(node) || node === null) {
30292
30218
  domReferenceRef.current = node;
30293
30219
  setDomReference(node);
@@ -30299,17 +30225,17 @@ function useFloating2(options) {
30299
30225
  position.refs.setReference(node);
30300
30226
  }
30301
30227
  }, [position.refs]);
30302
- const refs = React6.useMemo(() => ({
30228
+ const refs = React5.useMemo(() => ({
30303
30229
  ...position.refs,
30304
30230
  setReference,
30305
30231
  setPositionReference,
30306
30232
  domReference: domReferenceRef
30307
30233
  }), [position.refs, setReference, setPositionReference]);
30308
- const elements = React6.useMemo(() => ({
30234
+ const elements = React5.useMemo(() => ({
30309
30235
  ...position.elements,
30310
30236
  domReference
30311
30237
  }), [position.elements, domReference]);
30312
- const context = React6.useMemo(() => ({
30238
+ const context = React5.useMemo(() => ({
30313
30239
  ...position,
30314
30240
  ...rootContext,
30315
30241
  refs,
@@ -30323,7 +30249,7 @@ function useFloating2(options) {
30323
30249
  node.context = context;
30324
30250
  }
30325
30251
  });
30326
- return React6.useMemo(() => ({
30252
+ return React5.useMemo(() => ({
30327
30253
  ...position,
30328
30254
  context,
30329
30255
  refs,
@@ -30395,22 +30321,22 @@ function useInteractions(propsList) {
30395
30321
  const referenceDeps = propsList.map((key) => key == null ? void 0 : key.reference);
30396
30322
  const floatingDeps = propsList.map((key) => key == null ? void 0 : key.floating);
30397
30323
  const itemDeps = propsList.map((key) => key == null ? void 0 : key.item);
30398
- const getReferenceProps = React6.useCallback(
30324
+ const getReferenceProps = React5.useCallback(
30399
30325
  (userProps) => mergeProps(userProps, propsList, "reference"),
30400
30326
  // eslint-disable-next-line react-hooks/exhaustive-deps
30401
30327
  referenceDeps
30402
30328
  );
30403
- const getFloatingProps = React6.useCallback(
30329
+ const getFloatingProps = React5.useCallback(
30404
30330
  (userProps) => mergeProps(userProps, propsList, "floating"),
30405
30331
  // eslint-disable-next-line react-hooks/exhaustive-deps
30406
30332
  floatingDeps
30407
30333
  );
30408
- const getItemProps = React6.useCallback(
30334
+ const getItemProps = React5.useCallback(
30409
30335
  (userProps) => mergeProps(userProps, propsList, "item"),
30410
30336
  // eslint-disable-next-line react-hooks/exhaustive-deps
30411
30337
  itemDeps
30412
30338
  );
30413
- return React6.useMemo(() => ({
30339
+ return React5.useMemo(() => ({
30414
30340
  getReferenceProps,
30415
30341
  getFloatingProps,
30416
30342
  getItemProps
@@ -30481,7 +30407,7 @@ var inner = (props) => ({
30481
30407
  scrollEl.scrollTop = diffY;
30482
30408
  if (onFallbackChange) {
30483
30409
  const shouldFallback = scrollEl.offsetHeight < item.offsetHeight * min(minItemsVisible, listRef.current.length) - 1 || refOverflow.top >= -referenceOverflowThreshold || refOverflow.bottom >= -referenceOverflowThreshold;
30484
- ReactDOM3.flushSync(() => onFallbackChange(shouldFallback));
30410
+ ReactDOM2.flushSync(() => onFallbackChange(shouldFallback));
30485
30411
  }
30486
30412
  if (overflowRef) {
30487
30413
  overflowRef.current = await detectOverflow2(getArgsWithCustomFloatingHeight({
@@ -30506,10 +30432,10 @@ function useInnerOffset(context, props) {
30506
30432
  onChange: unstable_onChange
30507
30433
  } = props;
30508
30434
  const onChange = useEffectEvent(unstable_onChange);
30509
- const controlledScrollingRef = React6.useRef(false);
30510
- const prevScrollTopRef = React6.useRef(null);
30511
- const initialOverflowRef = React6.useRef(null);
30512
- React6.useEffect(() => {
30435
+ const controlledScrollingRef = React5.useRef(false);
30436
+ const prevScrollTopRef = React5.useRef(null);
30437
+ const initialOverflowRef = React5.useRef(null);
30438
+ React5.useEffect(() => {
30513
30439
  if (!enabled)
30514
30440
  return;
30515
30441
  function onWheel(e10) {
@@ -30527,7 +30453,7 @@ function useInnerOffset(context, props) {
30527
30453
  }
30528
30454
  if (!isAtTop && dY > 0 || !isAtBottom && dY < 0) {
30529
30455
  e10.preventDefault();
30530
- ReactDOM3.flushSync(() => {
30456
+ ReactDOM2.flushSync(() => {
30531
30457
  onChange((d9) => d9 + Math[method](dY, remainingScroll * sign));
30532
30458
  });
30533
30459
  } else if (/firefox/i.test(getUserAgent())) {
@@ -30552,7 +30478,7 @@ function useInnerOffset(context, props) {
30552
30478
  };
30553
30479
  }
30554
30480
  }, [enabled, open, elements.floating, overflowRef, scrollRef, onChange]);
30555
- const floating = React6.useMemo(() => ({
30481
+ const floating = React5.useMemo(() => ({
30556
30482
  onKeyDown() {
30557
30483
  controlledScrollingRef.current = true;
30558
30484
  },
@@ -30570,7 +30496,7 @@ function useInnerOffset(context, props) {
30570
30496
  if (prevScrollTopRef.current !== null) {
30571
30497
  const scrollDiff = el.scrollTop - prevScrollTopRef.current;
30572
30498
  if (overflowRef.current.bottom < -0.5 && scrollDiff < -1 || overflowRef.current.top < -0.5 && scrollDiff > 1) {
30573
- ReactDOM3.flushSync(() => onChange((d9) => d9 + scrollDiff));
30499
+ ReactDOM2.flushSync(() => onChange((d9) => d9 + scrollDiff));
30574
30500
  }
30575
30501
  }
30576
30502
  requestAnimationFrame(() => {
@@ -30578,7 +30504,7 @@ function useInnerOffset(context, props) {
30578
30504
  });
30579
30505
  }
30580
30506
  }), [elements.floating, onChange, overflowRef, scrollRef]);
30581
- return React6.useMemo(() => enabled ? {
30507
+ return React5.useMemo(() => enabled ? {
30582
30508
  floating
30583
30509
  } : {}, [enabled, floating]);
30584
30510
  }
@@ -33081,7 +33007,8 @@ var normalizeDvBData = (data) => {
33081
33007
  protocol: parseProtocolUrl(data.output_url || defaultProtocolSettings.ffurl)
33082
33008
  };
33083
33009
  };
33084
- var DvB = (0, import_react74.forwardRef)(function DvB2({ settings, setSettings, encoderId, isLoading, setIsLoading }, ref) {
33010
+ var DvB = function DvB2(props) {
33011
+ const { settings, setSettings, encoderId, isLoading, setIsLoading, ref } = props;
33085
33012
  const [internalSettings, setInternalSettings] = (0, import_react74.useState)(defaultDvBSettings);
33086
33013
  const [expandedSections, setExpandedSections] = (0, import_react74.useState)({
33087
33014
  video: true,
@@ -33142,13 +33069,33 @@ var DvB = (0, import_react74.forwardRef)(function DvB2({ settings, setSettings,
33142
33069
  newTracks[idx] = { label: newTracks[idx].label, value: !newTracks[idx].value };
33143
33070
  setTracks(newTracks);
33144
33071
  };
33145
- (0, import_react74.useImperativeHandle)(ref, () => ({
33146
- getSettings: () => ({ ...effectiveSettings, output_url: buildProtocolUrl(effectiveSettings.protocol) }),
33147
- reset: () => {
33148
- effectiveSetSettings(savedSettings);
33149
- },
33150
- isDirty: () => JSON.stringify(effectiveSettings) !== JSON.stringify(savedSettings)
33151
- }));
33072
+ (0, import_react74.useEffect)(() => {
33073
+ if (!ref)
33074
+ return;
33075
+ const impl = {
33076
+ getSettings: () => ({ ...effectiveSettings, output_url: buildProtocolUrl(effectiveSettings.protocol) }),
33077
+ reset: () => {
33078
+ effectiveSetSettings(savedSettings);
33079
+ },
33080
+ isDirty: () => JSON.stringify(effectiveSettings) !== JSON.stringify(savedSettings)
33081
+ };
33082
+ try {
33083
+ if (typeof ref === "function")
33084
+ ref(impl);
33085
+ else if ("current" in ref)
33086
+ ref.current = impl;
33087
+ } catch {
33088
+ }
33089
+ return () => {
33090
+ try {
33091
+ if (typeof ref === "function")
33092
+ ref(null);
33093
+ else if ("current" in ref)
33094
+ ref.current = null;
33095
+ } catch {
33096
+ }
33097
+ };
33098
+ }, [ref, effectiveSettings, savedSettings, effectiveSetSettings]);
33152
33099
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-4 pl-4 border-l-[1px] border-gray-600 custom-scroll overflow-y-auto max-h-[670px]", children: [
33153
33100
  /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(VideoGroup_default, { expanded: expandedSections.video, onToggle: toggleSection, loading: isLoading ?? false, children: [
33154
33101
  /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { children: [
@@ -33495,7 +33442,7 @@ var DvB = (0, import_react74.forwardRef)(function DvB2({ settings, setSettings,
33495
33442
  }
33496
33443
  )
33497
33444
  ] });
33498
- });
33445
+ };
33499
33446
  var DvB_default = DvB;
33500
33447
 
33501
33448
  // src/components/encoder/Livecast.tsx
@@ -33623,7 +33570,8 @@ var normalizeLivecastData = (data) => {
33623
33570
  protocol: parsed
33624
33571
  };
33625
33572
  };
33626
- var Livecast = (0, import_react75.forwardRef)(function Livecast2({ settings, setSettings, encoderId, isLoading, setIsLoading }, ref) {
33573
+ var Livecast = function Livecast2(props) {
33574
+ const { settings, setSettings, encoderId, isLoading, setIsLoading, ref } = props;
33627
33575
  const [expandedSections, setExpandedSections] = (0, import_react75.useState)({
33628
33576
  video: true,
33629
33577
  audio: false,
@@ -33679,16 +33627,33 @@ var Livecast = (0, import_react75.forwardRef)(function Livecast2({ settings, set
33679
33627
  const next = { ...effectiveSettings, [key]: !effectiveSettings[key] };
33680
33628
  effectiveSetSettings(next);
33681
33629
  };
33682
- (0, import_react75.useImperativeHandle)(ref, () => ({
33683
- getSettings: () => ({
33684
- ...effectiveSettings,
33685
- send_url: buildProtocolUrl2(effectiveSettings.protocol)
33686
- }),
33687
- reset: () => {
33688
- effectiveSetSettings(savedSettings);
33689
- },
33690
- isDirty: () => JSON.stringify(effectiveSettings) !== JSON.stringify(savedSettings)
33691
- }));
33630
+ (0, import_react75.useEffect)(() => {
33631
+ if (!ref)
33632
+ return;
33633
+ const impl = {
33634
+ getSettings: () => ({ ...effectiveSettings, send_url: buildProtocolUrl2(effectiveSettings.protocol) }),
33635
+ reset: () => {
33636
+ effectiveSetSettings(savedSettings);
33637
+ },
33638
+ isDirty: () => JSON.stringify(effectiveSettings) !== JSON.stringify(savedSettings)
33639
+ };
33640
+ try {
33641
+ if (typeof ref === "function")
33642
+ ref(impl);
33643
+ else if ("current" in ref)
33644
+ ref.current = impl;
33645
+ } catch {
33646
+ }
33647
+ return () => {
33648
+ try {
33649
+ if (typeof ref === "function")
33650
+ ref(null);
33651
+ else if ("current" in ref)
33652
+ ref.current = null;
33653
+ } catch {
33654
+ }
33655
+ };
33656
+ }, [ref, effectiveSettings, savedSettings, effectiveSetSettings]);
33692
33657
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "space-y-4 px-4 border-x-[1px] border-gray-500 custom-scroll overflow-y-auto max-h-[670px]", children: [
33693
33658
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VideoGroup_default, { expanded: expandedSections.video, onToggle: toggleSection, loading: isLoading ?? false, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-4 gap-4", children: [
33694
33659
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
@@ -33839,7 +33804,7 @@ var Livecast = (0, import_react75.forwardRef)(function Livecast2({ settings, set
33839
33804
  }
33840
33805
  )
33841
33806
  ] });
33842
- });
33807
+ };
33843
33808
  var Livecast_default = Livecast;
33844
33809
 
33845
33810
  // src/components/encoder/ViewLog.tsx
@@ -34625,28 +34590,36 @@ var EditInPlaceField_default = EditInPlaceField;
34625
34590
  var import_react80 = require("react");
34626
34591
  var import_jsx_runtime25 = require("react/jsx-runtime");
34627
34592
  var ThemeContext = (0, import_react80.createContext)(void 0);
34628
- function ThemeProvider({ children }) {
34593
+ function ThemeProvider({ children, storage }) {
34594
+ const resolvedStorage = storage ?? (typeof window !== "undefined" ? window.localStorage : null);
34629
34595
  const [theme, setTheme] = (0, import_react80.useState)(() => {
34630
- const savedTheme = localStorage.getItem("theme");
34631
- const systemPreference = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
34632
- return savedTheme || systemPreference;
34596
+ try {
34597
+ if (!resolvedStorage)
34598
+ return "light";
34599
+ const savedTheme = resolvedStorage.getItem("theme");
34600
+ const systemPreference = typeof window !== "undefined" && window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
34601
+ return savedTheme ?? systemPreference;
34602
+ } catch {
34603
+ return "light";
34604
+ }
34633
34605
  });
34634
34606
  (0, import_react80.useEffect)(() => {
34635
- const root = document.documentElement;
34636
- if (theme === "dark") {
34637
- root.classList.add("dark");
34638
- } else {
34639
- root.classList.remove("dark");
34607
+ if (typeof document !== "undefined") {
34608
+ const root = document.documentElement;
34609
+ root.classList.toggle("dark", theme === "dark");
34610
+ }
34611
+ try {
34612
+ resolvedStorage?.setItem("theme", theme);
34613
+ } catch {
34640
34614
  }
34641
- localStorage.setItem("theme", theme);
34642
- }, [theme]);
34615
+ }, [theme, resolvedStorage]);
34643
34616
  const toggleTheme = () => {
34644
- setTheme((prevTheme) => prevTheme === "light" ? "dark" : "light");
34617
+ setTheme((prev) => prev === "light" ? "dark" : "light");
34645
34618
  };
34646
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ThemeContext.Provider, { value: { theme, toggleTheme }, children });
34619
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ThemeContext, { value: { theme, toggleTheme }, children });
34647
34620
  }
34648
34621
  function useTheme() {
34649
- const context = (0, import_react80.useContext)(ThemeContext);
34622
+ const context = (0, import_react80.use)(ThemeContext);
34650
34623
  if (context === void 0) {
34651
34624
  throw new Error("useTheme must be used within a ThemeProvider");
34652
34625
  }
@@ -35623,7 +35596,7 @@ var Footer = () => {
35623
35596
  var Footer_default = Footer;
35624
35597
 
35625
35598
  // src/components/main/Header.tsx
35626
- var import_react86 = __toESM(require("react"), 1);
35599
+ var import_react86 = __toESM(require("react"));
35627
35600
  var import_react_router_dom = require("react-router-dom");
35628
35601
  var import_jsx_runtime33 = require("react/jsx-runtime");
35629
35602
  function classNames(...classes) {
@@ -35993,7 +35966,7 @@ var Header = ({ isSidebarOpen, setSidebarOpen, onNavigate }) => {
35993
35966
  var Header_default = Header;
35994
35967
 
35995
35968
  // src/components/main/PageHeader.tsx
35996
- var import_react88 = __toESM(require("react"), 1);
35969
+ var import_react88 = __toESM(require("react"));
35997
35970
  var import_jsx_runtime34 = require("react/jsx-runtime");
35998
35971
  var PageHeader = ({
35999
35972
  icon,
@@ -36883,6 +36856,20 @@ var InterfacesTimeseries = ({
36883
36856
  };
36884
36857
  var InterfacesTimeseries_default = InterfacesTimeseries;
36885
36858
 
36859
+ // src/components/network/validators.ts
36860
+ var isValidIPv4 = (ip) => {
36861
+ if (!ip)
36862
+ return false;
36863
+ const ipv4Regex = /^(25[0-5]|2[0-4]\d|1?\d?\d)(\.(25[0-5]|2[0-4]\d|1?\d?\d)){3}$/;
36864
+ return ipv4Regex.test(ip.trim());
36865
+ };
36866
+ var isValidIPv6 = (ip) => {
36867
+ if (!ip)
36868
+ return false;
36869
+ const ipv6Regex = /^(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}$|^((?:[A-F0-9]{1,4}(?::|$)){1,8})$/i;
36870
+ return ipv6Regex.test(ip.trim());
36871
+ };
36872
+
36886
36873
  // src/components/system/RequireAuth.tsx
36887
36874
  var import_react_router_dom3 = require("react-router-dom");
36888
36875
  var import_jsx_runtime40 = require("react/jsx-runtime");
@@ -39315,7 +39302,7 @@ var dir = instance.dir;
39315
39302
  var init = instance.init;
39316
39303
  var loadResources = instance.loadResources;
39317
39304
  var reloadResources = instance.reloadResources;
39318
- var use = instance.use;
39305
+ var use4 = instance.use;
39319
39306
  var changeLanguage = instance.changeLanguage;
39320
39307
  var getFixedT = instance.getFixedT;
39321
39308
  var t14 = instance.t;
@@ -40356,11 +40343,14 @@ instance.use(initReactI18next).init({
40356
40343
  var i18n_default = instance;
40357
40344
 
40358
40345
  // src/context/SharedUiProvider.tsx
40359
- var import_react104 = __toESM(require("react"), 1);
40346
+ var import_react104 = __toESM(require("react"));
40360
40347
  var import_react_query2 = require("@tanstack/react-query");
40361
40348
  var import_jsx_runtime41 = require("react/jsx-runtime");
40362
40349
  function SharedUiProvider({ children, client }) {
40363
- const internal = import_react104.default.useMemo(() => client ?? new import_react_query2.QueryClient(), [client]);
40350
+ const ref = import_react104.default.useRef(null);
40351
+ if (!ref.current)
40352
+ ref.current = client ?? new import_react_query2.QueryClient();
40353
+ const internal = ref.current;
40364
40354
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_query2.QueryClientProvider, { client: internal, children });
40365
40355
  }
40366
40356
 
@@ -40603,48 +40593,13 @@ var ConfigWizard = ({ basePath = "./config-xcoder-wizard/php", onComplete }) =>
40603
40593
  };
40604
40594
  var Wizard_default = ConfigWizard;
40605
40595
 
40606
- // src/components/RemoteModule.tsx
40596
+ // src/components/xcoder/Fflog.tsx
40607
40597
  var import_react106 = require("react");
40608
40598
  var import_jsx_runtime43 = require("react/jsx-runtime");
40609
- function RemoteModule({ scope, url, module: module2, fallback }) {
40610
- const [Component2, setComponent] = (0, import_react106.useState)(null);
40611
- const [error2, setError] = (0, import_react106.useState)(null);
40612
- const [loading, setLoading] = (0, import_react106.useState)(true);
40613
- (0, import_react106.useEffect)(() => {
40614
- setLoading(true);
40615
- setError(null);
40616
- loadRemoteModule({ scope, url, module: module2 }).then((mod) => {
40617
- setComponent(() => mod);
40618
- }).catch((err) => {
40619
- console.error("Erro ao carregar m\xF3dulo:", err);
40620
- setError(err.message);
40621
- }).finally(() => {
40622
- setLoading(false);
40623
- });
40624
- }, [scope, url, module2]);
40625
- if (loading) {
40626
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "flex items-center justify-center h-64", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-primary dark:border-primary-purple" }) });
40627
- }
40628
- if (error2) {
40629
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "p-6 bg-red-50 dark:bg-red-950/30 border border-red-200 dark:border-red-800 rounded-lg", children: [
40630
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h3", { className: "text-lg font-semibold text-red-800 dark:text-red-300 mb-2", children: "Erro ao carregar m\xF3dulo" }),
40631
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-red-600 dark:text-red-400", children: error2 }),
40632
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-sm text-red-500 dark:text-red-500 mt-2", children: "Verifique se o m\xF3dulo est\xE1 instalado e o servidor est\xE1 rodando." })
40633
- ] });
40634
- }
40635
- if (!Component2) {
40636
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_jsx_runtime43.Fragment, { children: fallback || /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "p-4 text-neutral-500 dark:text-neutral-400", children: "M\xF3dulo n\xE3o encontrado" }) });
40637
- }
40638
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Component2, {});
40639
- }
40640
-
40641
- // src/components/xcoder/Fflog.tsx
40642
- var import_react107 = require("react");
40643
- var import_jsx_runtime44 = require("react/jsx-runtime");
40644
40599
  var Fflog = ({ index: index3 }) => {
40645
- const [message, setMessage] = (0, import_react107.useState)("");
40646
- const [tooltip, setTooltip] = (0, import_react107.useState)("Copy to Clipboard");
40647
- (0, import_react107.useEffect)(() => {
40600
+ const [message, setMessage] = (0, import_react106.useState)("");
40601
+ const [tooltip, setTooltip] = (0, import_react106.useState)("Copy to Clipboard");
40602
+ (0, import_react106.useEffect)(() => {
40648
40603
  const cleanupSocket = subscribeToWebsocket(buildWsUrl("/ws"), (data) => {
40649
40604
  const aux = data?.logs[index3 - 1];
40650
40605
  setMessage(aux.log);
@@ -40657,7 +40612,7 @@ var Fflog = ({ index: index3 }) => {
40657
40612
  cleanupSocket();
40658
40613
  };
40659
40614
  }, []);
40660
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
40615
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
40661
40616
  "div",
40662
40617
  {
40663
40618
  "data-tooltip-id": "tooltip",
@@ -40672,8 +40627,8 @@ var Fflog = ({ index: index3 }) => {
40672
40627
  },
40673
40628
  onMouseLeave: () => message == "" ? setTooltip("Copy to Clipboard") : "",
40674
40629
  children: [
40675
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(M10, { id: "tooltip" }),
40676
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "relative mt-[-10px] text-justify text-gray-900 dark:text-slate-200 font-mono", style: { overflow: "hidden", whiteSpace: "nowrap", textOverflow: "ellipsis" }, children: message })
40630
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(M10, { id: "tooltip" }),
40631
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "relative mt-[-10px] text-justify text-gray-900 dark:text-slate-200 font-mono", style: { overflow: "hidden", whiteSpace: "nowrap", textOverflow: "ellipsis" }, children: message })
40677
40632
  ]
40678
40633
  }
40679
40634
  );
@@ -40681,7 +40636,7 @@ var Fflog = ({ index: index3 }) => {
40681
40636
  var Fflog_default = Fflog;
40682
40637
 
40683
40638
  // src/components/xcoder/Metrics.tsx
40684
- var import_jsx_runtime45 = require("react/jsx-runtime");
40639
+ var import_jsx_runtime44 = require("react/jsx-runtime");
40685
40640
  var MetricBar = ({ label, value, suffix, color }) => {
40686
40641
  const colorClasses = {
40687
40642
  blue: "bg-blue-500",
@@ -40690,15 +40645,15 @@ var MetricBar = ({ label, value, suffix, color }) => {
40690
40645
  cyan: "bg-cyan-500",
40691
40646
  pink: "bg-pink-500"
40692
40647
  };
40693
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "space-y-1", children: [
40694
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center justify-between text-sm", children: [
40695
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "text-gray-900 dark:text-slate-400", children: label }),
40696
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "text-gray-900 dark:text-white font-mono", children: [
40648
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "space-y-1", children: [
40649
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center justify-between text-sm", children: [
40650
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-gray-900 dark:text-slate-400", children: label }),
40651
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "text-gray-900 dark:text-white font-mono", children: [
40697
40652
  Math.round(value),
40698
40653
  suffix
40699
40654
  ] })
40700
40655
  ] }),
40701
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "h-2 bg-slate-300 dark:bg-slate-800 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
40656
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "h-2 bg-slate-300 dark:bg-slate-800 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
40702
40657
  "div",
40703
40658
  {
40704
40659
  className: `h-full transition-all duration-300 ${colorClasses[color]}`,
@@ -40710,8 +40665,8 @@ var MetricBar = ({ label, value, suffix, color }) => {
40710
40665
  var Metrics_default = MetricBar;
40711
40666
 
40712
40667
  // src/components/xcoder/Panel.tsx
40713
- var import_react108 = require("react");
40714
- var import_jsx_runtime46 = require("react/jsx-runtime");
40668
+ var import_react107 = require("react");
40669
+ var import_jsx_runtime45 = require("react/jsx-runtime");
40715
40670
  var convertServiceToOption = (serviceString) => {
40716
40671
  const match = serviceString.match(/^([^@]+)@/);
40717
40672
  if (!match) {
@@ -40725,12 +40680,12 @@ var convertServiceToOption = (serviceString) => {
40725
40680
  return { label, value: rawValue };
40726
40681
  };
40727
40682
  var EncoderDecoderPanel = ({ index: index3 }) => {
40728
- const [status, setStatus] = (0, import_react108.useState)("idle");
40729
- const [modes, setModes] = (0, import_react108.useState)([]);
40730
- const [oldModes, setOldModes] = (0, import_react108.useState)(modes);
40731
- const [open, setOpen] = (0, import_react108.useState)(false);
40732
- const [optionsList, setOptionsList] = (0, import_react108.useState)([]);
40733
- (0, import_react108.useEffect)(() => {
40683
+ const [status, setStatus] = (0, import_react107.useState)("idle");
40684
+ const [modes, setModes] = (0, import_react107.useState)([]);
40685
+ const [oldModes, setOldModes] = (0, import_react107.useState)(modes);
40686
+ const [open, setOpen] = (0, import_react107.useState)(false);
40687
+ const [optionsList, setOptionsList] = (0, import_react107.useState)([]);
40688
+ (0, import_react107.useEffect)(() => {
40734
40689
  const cleanupSocket = subscribeToWebsocket(buildWsUrl("/"), (data) => {
40735
40690
  setStatus(data?.services[`xcoder_${index3}`].status);
40736
40691
  });
@@ -40764,52 +40719,52 @@ var EncoderDecoderPanel = ({ index: index3 }) => {
40764
40719
  m: state ? "stop" : "start"
40765
40720
  });
40766
40721
  };
40767
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "bg-gray-200 dark:bg-slate-900/50 border bg-gray-200 border-gray-400 dark:border-slate-800 rounded-lg", children: [
40768
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "px-6 py-3 border-b border-slate-800 flex items-center justify-between", children: [
40769
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-3", children: [
40770
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Radio, { className: "w-5 h-5 text-blue-500" }),
40771
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h1", { className: "text-base font-medium text-gray-800 dark:text-white hover:underline", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("a", { href: `/page/${modes[index3 - 1]?.split("@")[0] ?? "encoder-dvb"}?channel=${index3}`, children: [
40722
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "bg-gray-200 dark:bg-slate-900/50 border bg-gray-200 border-gray-400 dark:border-slate-800 rounded-lg", children: [
40723
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "px-6 py-3 border-b border-slate-800 flex items-center justify-between", children: [
40724
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center gap-3", children: [
40725
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Radio, { className: "w-5 h-5 text-blue-500" }),
40726
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("h1", { className: "text-base font-medium text-gray-800 dark:text-white hover:underline", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("a", { href: `/page/${modes[index3 - 1]?.split("@")[0] ?? "encoder-dvb"}?channel=${index3}`, children: [
40772
40727
  "Xcoder BMD Video Interface (",
40773
40728
  index3,
40774
40729
  ")"
40775
40730
  ] }) })
40776
40731
  ] }),
40777
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-4", children: [
40778
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
40732
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center gap-4", children: [
40733
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
40779
40734
  "button",
40780
40735
  {
40781
40736
  onClick: () => startStop(status == "running"),
40782
40737
  className: `flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-all ${status == "running" ? "bg-red-600 hover:bg-red-700 text-white" : "bg-blue-600 hover:bg-blue-700 text-white"}`,
40783
- children: status == "running" ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
40784
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Pause, { className: "w-4 h-4" }),
40738
+ children: status == "running" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
40739
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Pause, { className: "w-4 h-4" }),
40785
40740
  "Stop"
40786
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
40787
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Play, { className: "w-4 h-4" }),
40741
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
40742
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Play, { className: "w-4 h-4" }),
40788
40743
  "Start"
40789
40744
  ] })
40790
40745
  }
40791
40746
  ),
40792
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: `flex w-[100px] justify-center items-center gap-2 px-4 py-2 rounded-md ${status == "running" ? "bg-yellow-600" : "bg-slate-700"}`, children: [
40793
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: `w-2 h-2 rounded-full bg-white ${status == "running" ? "block" : "hidden"}` }),
40794
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "text-sm text-slate-100 font-mono font-bold", children: status == "running" ? "READY" : "STANDBY" })
40747
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: `flex w-[100px] justify-center items-center gap-2 px-4 py-2 rounded-md ${status == "running" ? "bg-yellow-600" : "bg-slate-700"}`, children: [
40748
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: `w-2 h-2 rounded-full bg-white ${status == "running" ? "block" : "hidden"}` }),
40749
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "text-sm text-slate-100 font-mono font-bold", children: status == "running" ? "READY" : "STANDBY" })
40795
40750
  ] }),
40796
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
40751
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
40797
40752
  "button",
40798
40753
  {
40799
40754
  onClick: () => setOpen(true),
40800
40755
  className: "p-2 rounded-md transition-colors",
40801
- children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Settings, { className: "w-5 h-5 text-slate-400 hover:text-blue-400" })
40756
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Settings, { className: "w-5 h-5 text-slate-400 hover:text-blue-400" })
40802
40757
  }
40803
40758
  )
40804
40759
  ] })
40805
40760
  ] }),
40806
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
40761
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
40807
40762
  Modal_default,
40808
40763
  {
40809
40764
  open,
40810
40765
  setOpen,
40811
40766
  title: "Switching Operation Mode",
40812
- element: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { children: optionsList[index3 - 1] && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "relative p-6", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
40767
+ element: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { children: optionsList[index3 - 1] && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "relative p-6", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
40813
40768
  SelectField_default,
40814
40769
  {
40815
40770
  label: "New Mode",
@@ -40830,15 +40785,15 @@ var EncoderDecoderPanel = ({ index: index3 }) => {
40830
40785
  }
40831
40786
  }
40832
40787
  ),
40833
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "p-6", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Preview_default, { index: index3, setVuPts: () => {
40788
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "p-6", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Preview_default, { index: index3, setVuPts: () => {
40834
40789
  } }) })
40835
40790
  ] });
40836
40791
  };
40837
40792
  var Panel_default = EncoderDecoderPanel;
40838
40793
 
40839
40794
  // src/components/xcoder/Preview.tsx
40840
- var import_react109 = require("react");
40841
- var import_jsx_runtime47 = require("react/jsx-runtime");
40795
+ var import_react108 = require("react");
40796
+ var import_jsx_runtime46 = require("react/jsx-runtime");
40842
40797
  var Preview = ({
40843
40798
  index: index3,
40844
40799
  setVuPts,
@@ -40847,9 +40802,9 @@ var Preview = ({
40847
40802
  showStreamControl = false,
40848
40803
  orientation = "horizontal"
40849
40804
  }) => {
40850
- const logEndRef = (0, import_react109.useRef)(null);
40851
- const [message, setMessage] = (0, import_react109.useState)([]);
40852
- (0, import_react109.useEffect)(() => {
40805
+ const logEndRef = (0, import_react108.useRef)(null);
40806
+ const [message, setMessage] = (0, import_react108.useState)([]);
40807
+ (0, import_react108.useEffect)(() => {
40853
40808
  const cleanupSocket = subscribeToWebsocket(buildWsUrl("/"), (data) => {
40854
40809
  const aux = data?.services[`xcoder_${index3}`];
40855
40810
  setMessage(aux.decklinkEvents.split("\n"));
@@ -40858,22 +40813,22 @@ var Preview = ({
40858
40813
  cleanupSocket();
40859
40814
  };
40860
40815
  }, []);
40861
- (0, import_react109.useEffect)(() => {
40816
+ (0, import_react108.useEffect)(() => {
40862
40817
  if (logEndRef.current) {
40863
40818
  logEndRef.current.scrollTop = logEndRef.current.scrollHeight;
40864
40819
  }
40865
40820
  }, [message]);
40866
- const [vuChannels, setVuChannels] = (0, import_react109.useState)(
40821
+ const [vuChannels, setVuChannels] = (0, import_react108.useState)(
40867
40822
  Array(8).fill({ left: 0, right: 0 })
40868
40823
  );
40869
40824
  const channelCount = 8;
40870
- const vuBars = (0, import_react109.useMemo)(() => {
40871
- return Array.from({ length: channelCount }, (_7, i14) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(VUMeter_default, { index: i14, volume: vuChannels }, `vu-bar-${i14}`));
40825
+ const vuBars = (0, import_react108.useMemo)(() => {
40826
+ return Array.from({ length: channelCount }, (_7, i14) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(VUMeter_default, { index: i14, volume: vuChannels }, `vu-bar-${i14}`));
40872
40827
  }, [channelCount, vuChannels]);
40873
- const playerRef = (0, import_react109.useRef)(null);
40874
- const vuRef = (0, import_react109.useRef)(null);
40875
- const [height, setHeight] = (0, import_react109.useState)("auto");
40876
- (0, import_react109.useLayoutEffect)(() => {
40828
+ const playerRef = (0, import_react108.useRef)(null);
40829
+ const vuRef = (0, import_react108.useRef)(null);
40830
+ const [height, setHeight] = (0, import_react108.useState)("auto");
40831
+ (0, import_react108.useLayoutEffect)(() => {
40877
40832
  const p8 = playerRef.current;
40878
40833
  const v6 = vuRef.current;
40879
40834
  if (p8 && p8 != null && v6 && v6 != null) {
@@ -40887,15 +40842,15 @@ var Preview = ({
40887
40842
  }
40888
40843
  ;
40889
40844
  }, []);
40890
- const [isOpen, setIsOpen] = (0, import_react109.useState)(false);
40891
- const logData = message.map((log, i14) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-slate-900 dark:text-slate-300 break-words", children: log }) }, i14));
40892
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: `"w-full h-full" ${orientation === "horizontal" ? "" : "py-6"}`, children: [
40893
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
40845
+ const [isOpen, setIsOpen] = (0, import_react108.useState)(false);
40846
+ const logData = message.map((log, i14) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "text-slate-900 dark:text-slate-300 break-words", children: log }) }, i14));
40847
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: `"w-full h-full" ${orientation === "horizontal" ? "" : "py-6"}`, children: [
40848
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
40894
40849
  "div",
40895
40850
  {
40896
40851
  className: `grid gap-6 mb-5 ${orientation === "horizontal" ? "grid-cols-[1fr_300px] items-start" : "grid-cols-1"}`,
40897
40852
  children: [
40898
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { ref: playerRef, className: "bg-black rounded-lg overflow-hidden aspect-video", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "w-full h-full relative flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
40853
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { ref: playerRef, className: "bg-black rounded-lg overflow-hidden aspect-video", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "w-full h-full relative flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
40899
40854
  VideoPlayer_default,
40900
40855
  {
40901
40856
  pgmIndex: index3,
@@ -40904,10 +40859,10 @@ var Preview = ({
40904
40859
  setVuChannels
40905
40860
  }
40906
40861
  ) }) }),
40907
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: `flex flex-col ${orientation === "horizontal" ? "h-full" : "h-[200px]"}`, children: [
40908
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { ref: vuRef, className: `bg-gray-100 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg p-4 ${showDlog || showStreamControl ? "mb-5" : "flex-1"}`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: `flex justify-between items-end ${showDlog || showStreamControl ? "h-32" : "h-full"}`, children: vuBars }) }),
40909
- showStreamControl && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(StreamControl_default, { index: index3 }),
40910
- showDlog && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "bg-gray-100 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg overflow-hidden flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
40862
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: `flex flex-col ${orientation === "horizontal" ? "h-full" : "h-[200px]"}`, children: [
40863
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { ref: vuRef, className: `bg-gray-100 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg p-4 ${showDlog || showStreamControl ? "mb-5" : "flex-1"}`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: `flex justify-between items-end ${showDlog || showStreamControl ? "h-32" : "h-full"}`, children: vuBars }) }),
40864
+ showStreamControl && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(StreamControl_default, { index: index3 }),
40865
+ showDlog && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "bg-gray-100 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg overflow-hidden flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
40911
40866
  "div",
40912
40867
  {
40913
40868
  ref: logEndRef,
@@ -40918,7 +40873,7 @@ var Preview = ({
40918
40873
  style: { height },
40919
40874
  onClick: () => setIsOpen(true),
40920
40875
  children: [
40921
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(M10, { id: "tooltip" }),
40876
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(M10, { id: "tooltip" }),
40922
40877
  logData
40923
40878
  ]
40924
40879
  }
@@ -40927,15 +40882,15 @@ var Preview = ({
40927
40882
  ]
40928
40883
  }
40929
40884
  ),
40930
- showFflog && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Fflog_default, { index: index3 }),
40931
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
40885
+ showFflog && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Fflog_default, { index: index3 }),
40886
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
40932
40887
  Modal_default,
40933
40888
  {
40934
40889
  open: isOpen,
40935
40890
  setOpen: () => setIsOpen(!isOpen),
40936
40891
  title: "Log Message",
40937
- element: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "custom-scroll overflow-y-auto p-3 h-[300px]", children: logData }),
40938
- icon: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(FileClock, { "aria-hidden": "true", className: "size-6 text-yellow-600" }),
40892
+ element: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "custom-scroll overflow-y-auto p-3 h-[300px]", children: logData }),
40893
+ icon: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(FileClock, { "aria-hidden": "true", className: "size-6 text-yellow-600" }),
40939
40894
  positiveLabel: "Copy",
40940
40895
  positiveCommand: () => {
40941
40896
  navigator.clipboard.writeText(message.join("\n"));
@@ -40947,11 +40902,11 @@ var Preview = ({
40947
40902
  var Preview_default = Preview;
40948
40903
 
40949
40904
  // src/components/xcoder/StreamControl.tsx
40950
- var import_react110 = require("react");
40951
- var import_jsx_runtime48 = require("react/jsx-runtime");
40905
+ var import_react109 = require("react");
40906
+ var import_jsx_runtime47 = require("react/jsx-runtime");
40952
40907
  var StreamControl = ({ index: index3 }) => {
40953
- const [bufferValue, setBufferValue] = (0, import_react110.useState)(0);
40954
- const [syncValue, setSyncValue] = (0, import_react110.useState)(0);
40908
+ const [bufferValue, setBufferValue] = (0, import_react109.useState)(0);
40909
+ const [syncValue, setSyncValue] = (0, import_react109.useState)(0);
40955
40910
  const minBuffer = 0;
40956
40911
  const maxBuffer = 100;
40957
40912
  const minSync = -30;
@@ -40964,45 +40919,45 @@ var StreamControl = ({ index: index3 }) => {
40964
40919
  true,
40965
40920
  1e3
40966
40921
  );
40967
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "w-80 space-y-3", children: [
40968
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "bg-gray-100 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg p-3 max-h-[300px] min-h-[100px] overflow-auto", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "text-xs space-y-2 text-gray-800 dark:text-slate-200", children: [
40969
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "space-y-1", children: [
40970
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex gap-2", children: [
40971
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: "Service Name:" }),
40972
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "truncate", children: data?.service_name ?? "\u2014" })
40922
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "w-80 space-y-3", children: [
40923
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "bg-gray-100 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg p-3 max-h-[300px] min-h-[100px] overflow-auto", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "text-xs space-y-2 text-gray-800 dark:text-slate-200", children: [
40924
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "space-y-1", children: [
40925
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex gap-2", children: [
40926
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "font-medium", children: "Service Name:" }),
40927
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "truncate", children: data?.service_name ?? "\u2014" })
40973
40928
  ] }),
40974
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex gap-2", children: [
40975
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: "Service Provider:" }),
40976
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "truncate", children: data?.service_provider ?? "\u2014" })
40929
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex gap-2", children: [
40930
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "font-medium", children: "Service Provider:" }),
40931
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "truncate", children: data?.service_provider ?? "\u2014" })
40977
40932
  ] })
40978
40933
  ] }),
40979
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "space-y-1.5 pt-2", children: [
40980
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex items-center gap-2", children: [
40981
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Video, { className: "w-4 h-4 text-sky-400" }),
40982
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "truncate", children: [
40934
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "space-y-1.5 pt-2", children: [
40935
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
40936
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Video, { className: "w-4 h-4 text-sky-400" }),
40937
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "truncate", children: [
40983
40938
  "Video 0: ",
40984
40939
  data?.input_streans[1].input_stream.type
40985
40940
  ] })
40986
40941
  ] }),
40987
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex items-center gap-2", children: [
40988
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Volume2, { className: "w-4 h-4 text-emerald-400" }),
40989
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "truncate", children: [
40942
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
40943
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Volume2, { className: "w-4 h-4 text-emerald-400" }),
40944
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "truncate", children: [
40990
40945
  "Audio 1: ",
40991
40946
  data?.input_streans[0].input_stream.type
40992
40947
  ] })
40993
40948
  ] })
40994
40949
  ] })
40995
40950
  ] }) }),
40996
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "bg-gray-100 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg p-3", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "space-y-3 text-slate-200 text-xs", children: [
40997
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(SliderField_default, { value: bufferValue, setValue: setBufferValue, label: "Fifo Size:", min: minBuffer, max: maxBuffer }),
40998
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(SliderField_default, { value: syncValue, setValue: setSyncValue, label: "A/V Sync:", min: minSync, max: maxSync, content: ["<", ">"], step: 10 }),
40999
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "pt-2 border-t border-slate-700 text-xs text-gray-700 dark:text-slate-300 flex justify-between", children: [
41000
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { children: [
40951
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "bg-gray-100 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg p-3", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "space-y-3 text-slate-200 text-xs", children: [
40952
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(SliderField_default, { value: bufferValue, setValue: setBufferValue, label: "Fifo Size:", min: minBuffer, max: maxBuffer }),
40953
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(SliderField_default, { value: syncValue, setValue: setSyncValue, label: "A/V Sync:", min: minSync, max: maxSync, content: ["<", ">"], step: 10 }),
40954
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "pt-2 border-t border-slate-700 text-xs text-gray-700 dark:text-slate-300 flex justify-between", children: [
40955
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { children: [
41001
40956
  "Buffer: ",
41002
40957
  bufferValue,
41003
40958
  " frames"
41004
40959
  ] }),
41005
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { children: [
40960
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { children: [
41006
40961
  "Sync: ",
41007
40962
  syncValue > 0 ? "+" : "",
41008
40963
  syncValue,
@@ -41015,8 +40970,8 @@ var StreamControl = ({ index: index3 }) => {
41015
40970
  var StreamControl_default = StreamControl;
41016
40971
 
41017
40972
  // src/components/xcoder/VideoPlayer.tsx
41018
- var import_react111 = require("react");
41019
- var import_jsx_runtime49 = require("react/jsx-runtime");
40973
+ var import_react110 = require("react");
40974
+ var import_jsx_runtime48 = require("react/jsx-runtime");
41020
40975
  var import_meta2 = {};
41021
40976
  var VideoPlayer = ({
41022
40977
  pgmIndex,
@@ -41024,11 +40979,11 @@ var VideoPlayer = ({
41024
40979
  setVuPts,
41025
40980
  setVuChannels
41026
40981
  }) => {
41027
- const dummyCanvas = (0, import_react111.useMemo)(() => document.createElement("canvas"), []);
41028
- const videoRef = (0, import_react111.useRef)(dummyCanvas);
41029
- const prevRawChannelsRef = (0, import_react111.useRef)(null);
41030
- const playerRef = (0, import_react111.useRef)(null);
41031
- (0, import_react111.useEffect)(() => {
40982
+ const dummyCanvas = (0, import_react110.useMemo)(() => document.createElement("canvas"), []);
40983
+ const videoRef = (0, import_react110.useRef)(dummyCanvas);
40984
+ const prevRawChannelsRef = (0, import_react110.useRef)(null);
40985
+ const playerRef = (0, import_react110.useRef)(null);
40986
+ (0, import_react110.useEffect)(() => {
41032
40987
  let cancelled = false;
41033
40988
  if (!videoRef.current) {
41034
40989
  console.warn("Video canvas not ready yet");
@@ -41149,7 +41104,7 @@ var VideoPlayer = ({
41149
41104
  initPlayer();
41150
41105
  }
41151
41106
  }, [pgmIndex]);
41152
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
41107
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
41153
41108
  "canvas",
41154
41109
  {
41155
41110
  ref: videoRef,
@@ -41160,21 +41115,21 @@ var VideoPlayer = ({
41160
41115
  var VideoPlayer_default = VideoPlayer;
41161
41116
 
41162
41117
  // src/components/xcoder/VUMeter.tsx
41163
- var import_react112 = require("react");
41164
- var import_jsx_runtime50 = require("react/jsx-runtime");
41118
+ var import_react111 = require("react");
41119
+ var import_jsx_runtime49 = require("react/jsx-runtime");
41165
41120
  var VUBar = ({ index: index3, volume, width = "15px", displayMarks = false }) => {
41166
- const [tickerTarget, setTickerTarget] = (0, import_react112.useState)({ left: 0, right: 0 });
41167
- const [tickerTransition, setTickerTransition] = (0, import_react112.useState)({
41121
+ const [tickerTarget, setTickerTarget] = (0, import_react111.useState)({ left: 0, right: 0 });
41122
+ const [tickerTransition, setTickerTransition] = (0, import_react111.useState)({
41168
41123
  left: 0,
41169
41124
  right: 0
41170
41125
  });
41171
- const [resetVUTimeout, setResetVUTimeout] = (0, import_react112.useState)(0);
41172
- const tickerLeftRef = (0, import_react112.useRef)(null);
41173
- const tickerRightRef = (0, import_react112.useRef)(null);
41174
- const blockerLeftRef = (0, import_react112.useRef)(null);
41175
- const blockerRightRef = (0, import_react112.useRef)(null);
41176
- const fillerRef = (0, import_react112.useRef)(null);
41177
- const calcVolume = (0, import_react112.useCallback)(() => {
41126
+ const [resetVUTimeout, setResetVUTimeout] = (0, import_react111.useState)(0);
41127
+ const tickerLeftRef = (0, import_react111.useRef)(null);
41128
+ const tickerRightRef = (0, import_react111.useRef)(null);
41129
+ const blockerLeftRef = (0, import_react111.useRef)(null);
41130
+ const blockerRightRef = (0, import_react111.useRef)(null);
41131
+ const fillerRef = (0, import_react111.useRef)(null);
41132
+ const calcVolume = (0, import_react111.useCallback)(() => {
41178
41133
  try {
41179
41134
  const fillerRect = fillerRef.current?.getBoundingClientRect();
41180
41135
  const blockerLeftRect = blockerLeftRef.current?.getBoundingClientRect();
@@ -41223,7 +41178,7 @@ var VUBar = ({ index: index3, volume, width = "15px", displayMarks = false }) =>
41223
41178
  } catch (e10) {
41224
41179
  }
41225
41180
  }, []);
41226
- (0, import_react112.useEffect)(() => {
41181
+ (0, import_react111.useEffect)(() => {
41227
41182
  calcVolume();
41228
41183
  if (resetVUTimeout) {
41229
41184
  clearTimeout(resetVUTimeout);
@@ -41238,9 +41193,9 @@ var VUBar = ({ index: index3, volume, width = "15px", displayMarks = false }) =>
41238
41193
  const MIN_DB = -70;
41239
41194
  const MAX_DB = 0;
41240
41195
  const measures = [0, -10, -20, -30, -40, -50, -60, -70];
41241
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex w-full h-full justify-center", children: [
41242
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: displayMarks ? "mt-[60px]" : "hidden", children: measures.map((db) => {
41243
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
41196
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex w-full h-full justify-center", children: [
41197
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: displayMarks ? "mt-[60px]" : "hidden", children: measures.map((db) => {
41198
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
41244
41199
  "div",
41245
41200
  {
41246
41201
  style: { marginBottom: `${(db - MIN_DB) / (MAX_DB - MIN_DB) * 100}px`, marginRight: "25px", textAlignLast: "center" },
@@ -41261,15 +41216,15 @@ var VUBar = ({ index: index3, volume, width = "15px", displayMarks = false }) =>
41261
41216
  db
41262
41217
  );
41263
41218
  }) }),
41264
- /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: `h-full w-full text-xs text-center text-white`, style: { maxWidth: `${width}` }, children: [
41265
- /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex border border-gray-400 w-full h-[96%] rotate-180 scale-x-[-1]", children: [
41266
- /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { ref: fillerRef, className: "w-1/2 h-full", style: { background: "linear-gradient(180deg, rgba(0, 187, 0, 1) 0%, rgba(255, 162, 0, 1) 50%, rgba(255, 0, 0, 1) 100%)", borderRadius: "inherit" }, children: [
41267
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { ref: blockerLeftRef, className: "absolute bg-gray-200 dark:bg-[#18191d] bottom-0 w-1/2", style: { height: `${100 - volume[index3].left}%`, transition: "height 0.1s ease-out" } }),
41268
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { ref: tickerLeftRef, className: "absolute h-[5px] w-1/2 bg-white border border-black", style: { top: `${tickerTarget.left}%`, transition: `top ${tickerTransition.left}s ease-out` } })
41219
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: `h-full w-full text-xs text-center text-white`, style: { maxWidth: `${width}` }, children: [
41220
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex border border-gray-400 w-full h-[96%] rotate-180 scale-x-[-1]", children: [
41221
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { ref: fillerRef, className: "w-1/2 h-full", style: { background: "linear-gradient(180deg, rgba(0, 187, 0, 1) 0%, rgba(255, 162, 0, 1) 50%, rgba(255, 0, 0, 1) 100%)", borderRadius: "inherit" }, children: [
41222
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { ref: blockerLeftRef, className: "absolute bg-gray-200 dark:bg-[#18191d] bottom-0 w-1/2", style: { height: `${100 - volume[index3].left}%`, transition: "height 0.1s ease-out" } }),
41223
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { ref: tickerLeftRef, className: "absolute h-[5px] w-1/2 bg-white border border-black", style: { top: `${tickerTarget.left}%`, transition: `top ${tickerTransition.left}s ease-out` } })
41269
41224
  ] }),
41270
- /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "w-1/2 h-full", style: { background: "linear-gradient(180deg, rgba(0, 187, 0, 1) 0%, rgba(255, 162, 0, 1) 50%, rgba(255, 0, 0, 1) 100%)", borderRadius: "inherit" }, children: [
41271
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { ref: blockerRightRef, className: "absolute bg-gray-200 dark:bg-[#18191d] bottom-0 w-1/2", style: { height: `${100 - volume[index3].right}%`, transition: "height 0.1s ease-out" } }),
41272
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { ref: tickerRightRef, className: "absolute h-[5px] w-1/2 bg-white border border-black", style: { top: `${tickerTarget.right}%`, transition: `top ${tickerTransition.right}s ease-out` } })
41225
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "w-1/2 h-full", style: { background: "linear-gradient(180deg, rgba(0, 187, 0, 1) 0%, rgba(255, 162, 0, 1) 50%, rgba(255, 0, 0, 1) 100%)", borderRadius: "inherit" }, children: [
41226
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { ref: blockerRightRef, className: "absolute bg-gray-200 dark:bg-[#18191d] bottom-0 w-1/2", style: { height: `${100 - volume[index3].right}%`, transition: "height 0.1s ease-out" } }),
41227
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { ref: tickerRightRef, className: "absolute h-[5px] w-1/2 bg-white border border-black", style: { top: `${tickerTarget.right}%`, transition: `top ${tickerTransition.right}s ease-out` } })
41273
41228
  ] })
41274
41229
  ] }),
41275
41230
  index3 + 1
@@ -41279,7 +41234,7 @@ var VUBar = ({ index: index3, volume, width = "15px", displayMarks = false }) =>
41279
41234
  var VUMeter_default = VUBar;
41280
41235
 
41281
41236
  // src/hooks/useSettings.ts
41282
- var import_react113 = require("react");
41237
+ var import_react112 = require("react");
41283
41238
  var import_react_query3 = require("@tanstack/react-query");
41284
41239
  function useSettings(defaultSettings4, options) {
41285
41240
  const {
@@ -41294,8 +41249,8 @@ function useSettings(defaultSettings4, options) {
41294
41249
  refetchInterval
41295
41250
  } = options;
41296
41251
  const queryClient = (0, import_react_query3.useQueryClient)();
41297
- const [settings, setSettings] = (0, import_react113.useState)(defaultSettings4);
41298
- const [savedSettings, setSavedSettings] = (0, import_react113.useState)(defaultSettings4);
41252
+ const [settings, setSettings] = (0, import_react112.useState)(defaultSettings4);
41253
+ const [savedSettings, setSavedSettings] = (0, import_react112.useState)(defaultSettings4);
41299
41254
  const {
41300
41255
  data,
41301
41256
  isLoading,
@@ -41310,7 +41265,7 @@ function useSettings(defaultSettings4, options) {
41310
41265
  enabled,
41311
41266
  refetchInterval
41312
41267
  });
41313
- (0, import_react113.useEffect)(() => {
41268
+ (0, import_react112.useEffect)(() => {
41314
41269
  if (data) {
41315
41270
  setSettings(data);
41316
41271
  setSavedSettings(data);
@@ -41332,20 +41287,20 @@ function useSettings(defaultSettings4, options) {
41332
41287
  queryClient.invalidateQueries({ queryKey });
41333
41288
  }
41334
41289
  });
41335
- const isDirty = (0, import_react113.useMemo)(
41290
+ const isDirty = (0, import_react112.useMemo)(
41336
41291
  () => JSON.stringify(settings) !== JSON.stringify(savedSettings),
41337
41292
  [settings, savedSettings]
41338
41293
  );
41339
- const updateField = (0, import_react113.useCallback)((key, value) => {
41294
+ const updateField = (0, import_react112.useCallback)((key, value) => {
41340
41295
  setSettings((prev) => ({ ...prev, [key]: value }));
41341
41296
  }, []);
41342
- const updateSettings = (0, import_react113.useCallback)((partial) => {
41297
+ const updateSettings = (0, import_react112.useCallback)((partial) => {
41343
41298
  setSettings((prev) => ({ ...prev, ...partial }));
41344
41299
  }, []);
41345
- const discard = (0, import_react113.useCallback)(() => {
41300
+ const discard = (0, import_react112.useCallback)(() => {
41346
41301
  setSettings(savedSettings);
41347
41302
  }, [savedSettings]);
41348
- const save = (0, import_react113.useCallback)(async () => {
41303
+ const save = (0, import_react112.useCallback)(async () => {
41349
41304
  const payload = toPayload(settings);
41350
41305
  await saveMutation.mutateAsync(payload);
41351
41306
  }, [settings, toPayload, saveMutation]);
@@ -41365,13 +41320,13 @@ function useSettings(defaultSettings4, options) {
41365
41320
  }
41366
41321
 
41367
41322
  // src/hooks/useAvailableSubservices.ts
41368
- var import_react114 = require("react");
41323
+ var import_react113 = require("react");
41369
41324
  function useAvailableSubservices(serviceKey, fallbackCount = 4) {
41370
- const [options, setOptions] = (0, import_react114.useState)(
41325
+ const [options, setOptions] = (0, import_react113.useState)(
41371
41326
  Array.from({ length: fallbackCount }).map((_7, i14) => ({ label: `Channel ${i14 + 1}`, value: `${i14}` }))
41372
41327
  );
41373
- const [loading, setLoading] = (0, import_react114.useState)(false);
41374
- (0, import_react114.useEffect)(() => {
41328
+ const [loading, setLoading] = (0, import_react113.useState)(false);
41329
+ (0, import_react113.useEffect)(() => {
41375
41330
  let mounted = true;
41376
41331
  (async () => {
41377
41332
  setLoading(true);