@viasoftbr/shared-ui 0.0.1 → 0.0.3

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 (96) hide show
  1. package/README.md +89 -106
  2. package/dist/components/RemoteModule.d.ts +8 -0
  3. package/dist/components/display/Accordion.d.ts +8 -0
  4. package/dist/components/display/Section.d.ts +19 -0
  5. package/dist/components/display/Skeleton.d.ts +21 -0
  6. package/dist/components/display/index.d.ts +4 -0
  7. package/dist/components/encoder/DvB.d.ts +53 -0
  8. package/dist/components/encoder/Livecast.d.ts +37 -0
  9. package/dist/components/encoder/ViewLog.d.ts +5 -0
  10. package/dist/components/encoder/index.d.ts +4 -0
  11. package/dist/components/general/Copy2Clipboard.d.ts +4 -0
  12. package/dist/components/general/GridSelectionModal.d.ts +24 -0
  13. package/dist/components/general/Modal.d.ts +17 -0
  14. package/dist/components/general/Validation.d.ts +6 -0
  15. package/dist/components/general/index.d.ts +5 -0
  16. package/dist/components/groups/AudioGroup.d.ts +26 -0
  17. package/dist/components/groups/FilterGroup.d.ts +3 -0
  18. package/dist/components/groups/Middleware/Auth.d.ts +14 -0
  19. package/dist/components/groups/Middleware/Channels.d.ts +26 -0
  20. package/dist/components/groups/Middleware/MOS.d.ts +24 -0
  21. package/dist/components/groups/Middleware/Service.d.ts +16 -0
  22. package/dist/components/groups/Middleware/index.d.ts +5 -0
  23. package/dist/components/groups/PreviewGroup.d.ts +3 -0
  24. package/dist/components/groups/ProtocolGroup.d.ts +10 -0
  25. package/dist/components/groups/VideoGroup.d.ts +3 -0
  26. package/dist/components/groups/index.d.ts +7 -0
  27. package/dist/components/index.d.ts +11 -0
  28. package/dist/components/input/CheckboxField.d.ts +9 -0
  29. package/dist/components/input/ColorField.d.ts +9 -0
  30. package/dist/components/input/DatePicker.d.ts +12 -0
  31. package/dist/components/input/EditInPlaceField.d.ts +7 -0
  32. package/dist/components/input/InputField.d.ts +15 -0
  33. package/dist/components/input/Protocol.d.ts +10 -0
  34. package/dist/components/input/RangeField.d.ts +13 -0
  35. package/dist/components/input/SelectField.d.ts +13 -0
  36. package/dist/components/input/SliderField.d.ts +15 -0
  37. package/dist/components/input/SwitchField.d.ts +11 -0
  38. package/dist/components/input/index.d.ts +11 -0
  39. package/dist/components/main/Footer.d.ts +2 -0
  40. package/dist/components/main/Header.d.ts +7 -0
  41. package/dist/components/main/PageHeader.d.ts +14 -0
  42. package/dist/components/main/SaveDiscard.d.ts +13 -0
  43. package/dist/components/main/Sidebar.d.ts +10 -0
  44. package/dist/components/main/index.d.ts +6 -0
  45. package/dist/components/network/AddNetwork.d.ts +6 -0
  46. package/dist/components/network/InterfacesTable.d.ts +19 -0
  47. package/dist/components/network/InterfacesTimeseries.d.ts +21 -0
  48. package/dist/components/network/index.d.ts +4 -0
  49. package/dist/components/network/validators.d.ts +7 -0
  50. package/dist/components/system/RequireAuth.d.ts +8 -0
  51. package/dist/components/system/Wizard.d.ts +6 -0
  52. package/dist/components/system/index.d.ts +3 -0
  53. package/dist/components/xcoder/Fflog.d.ts +5 -0
  54. package/dist/components/xcoder/LiveLog.d.ts +5 -0
  55. package/dist/components/xcoder/Metrics.d.ts +8 -0
  56. package/dist/components/xcoder/Panel.d.ts +6 -0
  57. package/dist/components/xcoder/Preview.d.ts +11 -0
  58. package/dist/components/xcoder/StreamControl.d.ts +5 -0
  59. package/dist/components/xcoder/VUMeter.d.ts +8 -0
  60. package/dist/components/xcoder/VideoPlayer.d.ts +13 -0
  61. package/dist/components/xcoder/index.d.ts +8 -0
  62. package/dist/components.js +182 -118
  63. package/dist/context/AuthContext.d.ts +17 -0
  64. package/dist/context/ThemeContext.d.ts +11 -0
  65. package/dist/context/index.d.ts +3 -0
  66. package/dist/context.js +25 -9
  67. package/dist/hooks/index.d.ts +3 -0
  68. package/dist/hooks/useApi.d.ts +1 -0
  69. package/dist/hooks/useAvailableSubservices.d.ts +13 -0
  70. package/dist/hooks/useSettings.d.ts +45 -0
  71. package/dist/hooks.js +25 -9
  72. package/dist/i18n.d.ts +2 -0
  73. package/dist/index.d.ts +6 -0
  74. package/dist/index.js +55895 -0
  75. package/dist/package.json +111 -0
  76. package/dist/services/api.d.ts +22 -0
  77. package/dist/services/auth.d.ts +15 -0
  78. package/dist/services/discovery.d.ts +12 -0
  79. package/dist/services/hostConfig.d.ts +20 -0
  80. package/dist/services/index.d.ts +9 -0
  81. package/dist/services/loadRemoteModule.d.ts +9 -0
  82. package/dist/services/metadataLoader.d.ts +9 -0
  83. package/dist/services/registry.d.ts +42 -0
  84. package/dist/services/users.d.ts +18 -0
  85. package/dist/services/wizard.d.ts +3 -0
  86. package/dist/services.js +61 -28
  87. package/dist/types/alarm.d.ts +21 -0
  88. package/dist/types/auth.d.ts +18 -0
  89. package/dist/types/group.d.ts +32 -0
  90. package/dist/types/index.d.ts +6 -0
  91. package/dist/types/module.d.ts +13 -0
  92. package/dist/types/plugin.types.d.ts +30 -0
  93. package/dist/types/protocol.d.ts +12 -0
  94. package/dist/types/websocket.d.ts +27 -0
  95. package/dist/types/wizard.d.ts +12 -0
  96. package/package.json +35 -4
@@ -26178,19 +26178,36 @@ var {
26178
26178
  } = axios_default;
26179
26179
 
26180
26180
  // src/services/api.ts
26181
- var getApiBaseUrl = () => {
26182
- if (typeof import.meta !== "undefined" && import.meta.env?.VITE_API_BASE_URL) {
26183
- return import.meta.env.VITE_API_BASE_URL;
26181
+ var normalizeOrigin = (raw) => {
26182
+ if (!raw)
26183
+ return "";
26184
+ if (/^https?:\/\//i.test(raw) || /^wss?:\/\//i.test(raw))
26185
+ return raw.replace(/\/$/, "");
26186
+ return `http://${raw.replace(/\/$/, "")}`;
26187
+ };
26188
+ var getApiOrigin = () => {
26189
+ try {
26190
+ if (typeof import.meta !== "undefined" && import.meta.env?.VITE_API_BASE_URL) {
26191
+ return normalizeOrigin(import.meta.env.VITE_API_BASE_URL);
26192
+ }
26193
+ } catch (e10) {
26184
26194
  }
26185
- return "192.168.100.9:3000";
26195
+ if (typeof window !== "undefined") {
26196
+ const win = window;
26197
+ if (win.__VIASOFT_API_BASE_URL)
26198
+ return normalizeOrigin(win.__VIASOFT_API_BASE_URL);
26199
+ if (window.location && window.location.origin)
26200
+ return window.location.origin.replace(/\/$/, "");
26201
+ }
26202
+ return "http://localhost:3000";
26186
26203
  };
26187
- var serverUrl = getApiBaseUrl();
26204
+ var apiOrigin = getApiOrigin();
26188
26205
  var api = axios_default.create({
26189
- baseURL: `http://${serverUrl}`,
26206
+ baseURL: apiOrigin,
26190
26207
  timeout: 1e4
26191
26208
  });
26192
26209
  var authApi = axios_default.create({
26193
- baseURL: `http://${serverUrl}`,
26210
+ baseURL: apiOrigin,
26194
26211
  timeout: 1e4
26195
26212
  });
26196
26213
  function getAccessToken() {
@@ -26354,18 +26371,18 @@ var fetchApi = {
26354
26371
  }
26355
26372
  }
26356
26373
  };
26357
- var serverOrigin = `http://${serverUrl}`;
26358
26374
  function buildWsUrl(path = "/") {
26359
26375
  try {
26360
- const origin2 = new URL(serverOrigin);
26376
+ const origin2 = new URL(apiOrigin);
26361
26377
  origin2.protocol = origin2.protocol === "https:" ? "wss:" : "ws:";
26362
26378
  if (!path.startsWith("/"))
26363
26379
  path = "/" + path;
26364
26380
  origin2.pathname = path;
26365
26381
  return origin2.toString();
26366
26382
  } catch (e10) {
26367
- const proto = serverOrigin.startsWith("https") ? "wss" : "ws";
26368
- return `${proto}://${serverUrl}${path.startsWith("/") ? path : "/" + path}`;
26383
+ const proto = apiOrigin.startsWith("https") ? "wss" : "ws";
26384
+ const host = apiOrigin.replace(/^https?:\/\//, "").replace(/\/$/, "");
26385
+ return `${proto}://${host}${path.startsWith("/") ? path : "/" + path}`;
26369
26386
  }
26370
26387
  }
26371
26388
  async function decodeFfurl(ffurl) {
@@ -26391,7 +26408,6 @@ function subscribeToWebsocket(url, onMessage) {
26391
26408
  // src/services/loadRemoteModule.ts
26392
26409
  import * as React4 from "react";
26393
26410
  import * as ReactDOM2 from "react-dom";
26394
- var loadedContainers = /* @__PURE__ */ new Map();
26395
26411
  var sharedScopeInitialized = false;
26396
26412
  function getSharedScope() {
26397
26413
  if (!globalThis.__federation_shared__) {
@@ -26418,28 +26434,46 @@ function getSharedScope() {
26418
26434
  }
26419
26435
  return globalThis.__federation_shared__;
26420
26436
  }
26437
+ var loadedContainers = /* @__PURE__ */ new Map();
26438
+ var initializedContainers = /* @__PURE__ */ new Set();
26421
26439
  async function loadContainer(url) {
26422
26440
  if (loadedContainers.has(url)) {
26423
- const cached = loadedContainers.get(url);
26424
- if (cached)
26425
- return cached;
26441
+ return loadedContainers.get(url);
26426
26442
  }
26427
- const promise = import(
26428
- /* @vite-ignore */
26429
- url
26430
- );
26431
- loadedContainers.set(url, promise);
26432
- return promise;
26443
+ const loadPromise = (async () => {
26444
+ try {
26445
+ const container = await import(
26446
+ /* @vite-ignore */
26447
+ url
26448
+ );
26449
+ if (container.init && !initializedContainers.has(url)) {
26450
+ await container.init(getSharedScope());
26451
+ initializedContainers.add(url);
26452
+ }
26453
+ return container;
26454
+ } catch (error) {
26455
+ loadedContainers.delete(url);
26456
+ initializedContainers.delete(url);
26457
+ throw error;
26458
+ }
26459
+ })();
26460
+ loadedContainers.set(url, loadPromise);
26461
+ return loadPromise;
26433
26462
  }
26434
26463
  async function loadRemoteModule(config) {
26435
26464
  const container = await loadContainer(config.url);
26436
- if (!container || typeof container.init !== "function") {
26437
- throw new Error(`Container inv\xE1lido: ${config.scope}`);
26465
+ if (!container || typeof container.get !== "function") {
26466
+ throw new Error(`Container inv\xE1lido ou sem m\xE9todo get: ${config.scope}`);
26467
+ }
26468
+ if (typeof container.dynamicLoadingCss === "function") {
26469
+ try {
26470
+ await container.dynamicLoadingCss([]);
26471
+ } catch (err) {
26472
+ console.warn(`Aviso: Falha ao carregar CSS global do remote ${config.scope}`, err);
26473
+ }
26438
26474
  }
26439
- const shareScope = getSharedScope();
26440
- container.init(shareScope);
26441
26475
  const factory2 = await container.get(config.module);
26442
- const moduleExports = factory2();
26476
+ const moduleExports = await factory2();
26443
26477
  if (moduleExports && typeof moduleExports === "object" && "default" in moduleExports) {
26444
26478
  return moduleExports.default;
26445
26479
  }
@@ -26473,7 +26507,7 @@ var MetadataLoader = class {
26473
26507
  );
26474
26508
  }
26475
26509
  metadata.forEach((page, index3) => {
26476
- if (!page.id || !page.name || !page.path || !page.bundleUrl) {
26510
+ if (!page.id || !page.name || !page.path || !page.url) {
26477
26511
  throw new Error(
26478
26512
  `Invalid page metadata at index ${index3}: missing required fields`
26479
26513
  );
@@ -37661,9 +37695,9 @@ function buildSidebarItems(pages, modules) {
37661
37695
  isModule: false
37662
37696
  }));
37663
37697
  const fromModules = modules.map((m8) => ({
37664
- id: `mod:${m8.name}`,
37665
- label: m8.label,
37666
- to: `/page/${m8.name}`,
37698
+ id: `mod:${m8.id}`,
37699
+ label: m8.label ?? m8.name,
37700
+ to: `/page/${m8.id}`,
37667
37701
  group: m8.group || "Other",
37668
37702
  version: m8.module,
37669
37703
  iconName: m8.icon,
@@ -37699,13 +37733,29 @@ var Sidebar = ({ pages = [], modules = [], isOpen, setIsOpen }) => {
37699
37733
  };
37700
37734
  const isItemActive = (item) => location2.pathname === item.to;
37701
37735
  useEffect21(() => {
37702
- const all3 = {};
37703
- for (const groupName of Object.keys(itemGroups)) {
37704
- const hasActive = itemGroups[groupName].some((i14) => isItemActive(i14));
37705
- all3[groupName] = hasActive;
37706
- }
37707
- setExpandedGroups(all3);
37708
- }, [open, location2.pathname, allItems]);
37736
+ setExpandedGroups((prev) => {
37737
+ const next = { ...prev };
37738
+ let changed = false;
37739
+ for (const groupName of Object.keys(itemGroups)) {
37740
+ const hasActive = itemGroups[groupName].some((i14) => isItemActive(i14));
37741
+ if (prev[groupName] === void 0) {
37742
+ next[groupName] = hasActive;
37743
+ if (prev[groupName] !== next[groupName])
37744
+ changed = true;
37745
+ }
37746
+ }
37747
+ for (const groupName of Object.keys(itemGroups)) {
37748
+ const hasActive = itemGroups[groupName].some((i14) => isItemActive(i14));
37749
+ if (hasActive && !next[groupName]) {
37750
+ next[groupName] = true;
37751
+ changed = true;
37752
+ }
37753
+ }
37754
+ if (!changed)
37755
+ return prev;
37756
+ return next;
37757
+ });
37758
+ }, [location2.pathname, itemGroups]);
37709
37759
  const groupOrder = ["Encoder", "Decoder", "Network", "Playout", "Audio", "System", "Other"];
37710
37760
  const sortedGroupNames = Object.keys(itemGroups).sort((a23, b9) => {
37711
37761
  const ai = groupOrder.indexOf(a23);
@@ -37724,7 +37774,6 @@ var Sidebar = ({ pages = [], modules = [], isOpen, setIsOpen }) => {
37724
37774
  }
37725
37775
  return true;
37726
37776
  });
37727
- const totalModules = allItems.length;
37728
37777
  return /* @__PURE__ */ jsxs32(Fragment7, { children: [
37729
37778
  /* @__PURE__ */ jsx38(
37730
37779
  "button",
@@ -37735,7 +37784,7 @@ var Sidebar = ({ pages = [], modules = [], isOpen, setIsOpen }) => {
37735
37784
  children: open ? /* @__PURE__ */ jsx38(X, { className: "w-6 h-6" }) : /* @__PURE__ */ jsx38(Menu, { className: "w-6 h-6" })
37736
37785
  }
37737
37786
  ),
37738
- /* @__PURE__ */ jsxs32(
37787
+ /* @__PURE__ */ jsx38(
37739
37788
  "div",
37740
37789
  {
37741
37790
  className: [
@@ -37745,90 +37794,81 @@ var Sidebar = ({ pages = [], modules = [], isOpen, setIsOpen }) => {
37745
37794
  "transform transition-transform duration-300 ease-in-out",
37746
37795
  open ? "translate-x-0" : "-translate-x-full"
37747
37796
  ].join(" "),
37748
- children: [
37749
- /* @__PURE__ */ jsxs32("nav", { className: "flex-1 px-4 py-4 my-12 overflow-y-auto custom-scroll h-[calc(100%-90px)]", children: [
37750
- /* @__PURE__ */ jsxs32(
37751
- Link3,
37752
- {
37753
- to: "/",
37754
- className: `flex items-center px-3 py-2 mb-4 text-sm font-medium rounded-md transition-colors hover:bg-purple-700
37797
+ children: /* @__PURE__ */ jsxs32("nav", { className: "flex-1 px-4 py-4 my-12 overflow-y-auto custom-scroll h-[calc(100%-90px)]", children: [
37798
+ /* @__PURE__ */ jsxs32(
37799
+ Link3,
37800
+ {
37801
+ to: "/",
37802
+ className: `flex items-center px-3 py-2 mb-4 text-sm font-medium rounded-md transition-colors hover:bg-purple-700
37755
37803
  ${theme === "dark" || location2.pathname === "/" ? "text-neutral-50" : "text-primary hover:text-neutral-50"}
37756
37804
  ${location2.pathname === "/" ? "bg-purple-700" : ""}
37757
37805
  `,
37758
- onClick: () => setIsOpen?.(false),
37759
- children: [
37760
- /* @__PURE__ */ jsx38(House, { className: "w-5 h-5 mr-3" }),
37761
- "Home"
37762
- ]
37763
- }
37764
- ),
37765
- /* @__PURE__ */ jsx38("div", { className: "space-y-2", children: filteredGroupNames.map((groupName) => {
37766
- const items = itemGroups[groupName];
37767
- const isExpanded = expandedGroups[groupName];
37768
- return /* @__PURE__ */ jsxs32("div", { className: "space-y-1", children: [
37769
- /* @__PURE__ */ jsxs32(
37770
- "button",
37806
+ onClick: () => setIsOpen?.(false),
37807
+ children: [
37808
+ /* @__PURE__ */ jsx38(House, { className: "w-5 h-5 mr-3" }),
37809
+ "Home"
37810
+ ]
37811
+ }
37812
+ ),
37813
+ /* @__PURE__ */ jsx38("div", { className: "space-y-2", children: filteredGroupNames.map((groupName) => {
37814
+ const items = itemGroups[groupName];
37815
+ const isExpanded = expandedGroups[groupName];
37816
+ return /* @__PURE__ */ jsxs32("div", { className: "space-y-1", children: [
37817
+ /* @__PURE__ */ jsxs32(
37818
+ "button",
37819
+ {
37820
+ type: "button",
37821
+ onClick: () => toggleGroup(groupName),
37822
+ className: `flex items-center justify-between w-full px-3 py-2 text-sm font-medium rounded-md transition-colors ${theme === "dark" ? "text-neutral-300 hover:text-neutral-100 hover:bg-neutral-800" : "text-neutral-600 hover:text-neutral-800 hover:bg-neutral-100"}`,
37823
+ "aria-expanded": isExpanded,
37824
+ "aria-controls": `group-${groupName}`,
37825
+ children: [
37826
+ /* @__PURE__ */ jsxs32("div", { className: "flex items-center", children: [
37827
+ /* @__PURE__ */ jsx38(GroupIcon, { groupName }),
37828
+ /* @__PURE__ */ jsx38("span", { className: "ml-2", children: groupName }),
37829
+ /* @__PURE__ */ jsx38("span", { className: `ml-2 px-2 py-0.5 text-xs rounded-full ${theme === "dark" ? "bg-neutral-800 text-neutral-400" : "bg-neutral-200 text-neutral-600"}`, children: items.length })
37830
+ ] }),
37831
+ /* @__PURE__ */ jsx38(
37832
+ "svg",
37833
+ {
37834
+ className: `w-4 h-4 transition-transform ${isExpanded ? "rotate-90" : ""}`,
37835
+ fill: "none",
37836
+ stroke: "currentColor",
37837
+ viewBox: "0 0 24 24",
37838
+ "aria-hidden": "true",
37839
+ children: /* @__PURE__ */ jsx38("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" })
37840
+ }
37841
+ )
37842
+ ]
37843
+ }
37844
+ ),
37845
+ isExpanded && /* @__PURE__ */ jsx38("div", { id: `group-${groupName}`, className: "ml-4 space-y-1", children: items.filter((item) => !(item.id === "authentication" && user?.role === "operator" /* Operator */)).filter((item) => !(item.id === "mod:authentication" && user?.role === "operator" /* Operator */)).map((item) => {
37846
+ const isActive = isItemActive(item);
37847
+ return /* @__PURE__ */ jsxs32(
37848
+ Link3,
37771
37849
  {
37772
- type: "button",
37773
- onClick: () => toggleGroup(groupName),
37774
- className: `flex items-center justify-between w-full px-3 py-2 text-sm font-medium rounded-md transition-colors ${theme === "dark" ? "text-neutral-300 hover:text-neutral-100 hover:bg-neutral-800" : "text-neutral-600 hover:text-neutral-800 hover:bg-neutral-100"}`,
37775
- "aria-expanded": isExpanded,
37776
- "aria-controls": `group-${groupName}`,
37850
+ to: item.to,
37851
+ onClick: () => setIsOpen?.(false),
37852
+ className: `flex items-center px-3 py-2 text-sm rounded-md transition-colors hover:text-purple-400 ${isActive ? "bg-purple-700 bg-opacity-20 text-purple-400 border-l-4 border-purple-900" : theme === "dark" ? "text-neutral-400 hover:bg-neutral-800" : "text-neutral-600 hover:bg-neutral-100"}`,
37853
+ title: item.description,
37777
37854
  children: [
37778
- /* @__PURE__ */ jsxs32("div", { className: "flex items-center", children: [
37779
- /* @__PURE__ */ jsx38(GroupIcon, { groupName }),
37780
- /* @__PURE__ */ jsx38("span", { className: "ml-2", children: groupName }),
37781
- /* @__PURE__ */ jsx38("span", { className: `ml-2 px-2 py-0.5 text-xs rounded-full ${theme === "dark" ? "bg-neutral-800 text-neutral-400" : "bg-neutral-200 text-neutral-600"}`, children: items.length })
37855
+ /* @__PURE__ */ jsx38(ItemIcon, { item }),
37856
+ /* @__PURE__ */ jsxs32("div", { className: "ml-2 flex-1", children: [
37857
+ /* @__PURE__ */ jsx38("div", { className: "font-medium", children: item.label }),
37858
+ item.description && /* @__PURE__ */ jsx38("div", { className: `text-xs truncate w-28 ${theme === "dark" ? "text-neutral-500" : "text-neutral-600"}`, children: item.description })
37782
37859
  ] }),
37783
- /* @__PURE__ */ jsx38(
37784
- "svg",
37785
- {
37786
- className: `w-4 h-4 transition-transform ${isExpanded ? "rotate-90" : ""}`,
37787
- fill: "none",
37788
- stroke: "currentColor",
37789
- viewBox: "0 0 24 24",
37790
- "aria-hidden": "true",
37791
- children: /* @__PURE__ */ jsx38("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" })
37792
- }
37793
- )
37860
+ item.version && /* @__PURE__ */ jsxs32("span", { className: `text-xs px-1.5 py-0.5 rounded ${theme === "dark" ? "text-primary-purple bg-neutral-800" : "text-primary bg-neutral-100"}`, children: [
37861
+ "v",
37862
+ item.version
37863
+ ] })
37794
37864
  ]
37795
- }
37796
- ),
37797
- isExpanded && /* @__PURE__ */ jsx38("div", { id: `group-${groupName}`, className: "ml-4 space-y-1", children: items.filter((item) => !(item.id === "authentication" && user?.role === "operator" /* Operator */)).filter((item) => !(item.id === "mod:authentication" && user?.role === "operator" /* Operator */)).map((item) => {
37798
- const isActive = isItemActive(item);
37799
- return /* @__PURE__ */ jsxs32(
37800
- Link3,
37801
- {
37802
- to: item.to,
37803
- onClick: () => setIsOpen?.(false),
37804
- className: `flex items-center px-3 py-2 text-sm rounded-md transition-colors hover:text-purple-400 ${isActive ? "bg-purple-700 bg-opacity-20 text-purple-400 border-l-4 border-purple-900" : theme === "dark" ? "text-neutral-400 hover:bg-neutral-800" : "text-neutral-600 hover:bg-neutral-100"}`,
37805
- title: item.description,
37806
- children: [
37807
- /* @__PURE__ */ jsx38(ItemIcon, { item }),
37808
- /* @__PURE__ */ jsxs32("div", { className: "ml-2 flex-1", children: [
37809
- /* @__PURE__ */ jsx38("div", { className: "font-medium", children: item.label }),
37810
- item.description && /* @__PURE__ */ jsx38("div", { className: `text-xs truncate w-28 ${theme === "dark" ? "text-neutral-500" : "text-neutral-600"}`, children: item.description })
37811
- ] }),
37812
- item.version && /* @__PURE__ */ jsxs32("span", { className: `text-xs px-1.5 py-0.5 rounded ${theme === "dark" ? "text-primary-purple bg-neutral-800" : "text-primary bg-neutral-100"}`, children: [
37813
- "v",
37814
- item.version
37815
- ] })
37816
- ]
37817
- },
37818
- item.id
37819
- );
37820
- }) })
37821
- ] }, groupName);
37822
- }) })
37823
- ] }),
37824
- totalModules > 0 && /* @__PURE__ */ jsx38("div", { className: `absolute bottom-0 left-0 right-0 p-4 border-t ${theme === "dark" ? "border-neutral-800" : "border-neutral-200"}`, children: /* @__PURE__ */ jsxs32("p", { className: `text-xs text-center ${theme === "dark" ? "text-neutral-400" : "text-neutral-500"}`, children: [
37825
- totalModules,
37826
- " m\xF3dulo",
37827
- totalModules !== 1 ? "s" : "",
37828
- " carregado",
37829
- totalModules !== 1 ? "s" : ""
37830
- ] }) })
37831
- ]
37865
+ },
37866
+ item.id
37867
+ );
37868
+ }) })
37869
+ ] }, groupName);
37870
+ }) })
37871
+ ] })
37832
37872
  }
37833
37873
  )
37834
37874
  ] });
@@ -42571,9 +42611,33 @@ var VideoPlayer = ({
42571
42611
  }
42572
42612
  try {
42573
42613
  console.log("Initializing JSMpeg player url");
42574
- const apiBaseUrl = typeof import.meta !== "undefined" && import.meta.env?.VITE_API_BASE_URL ? import.meta.env.VITE_API_BASE_URL : "localhost:3000";
42614
+ const resolveWsOrigin = () => {
42615
+ try {
42616
+ if (typeof import.meta !== "undefined" && import.meta.env?.VITE_API_BASE_URL) {
42617
+ const raw = import.meta.env.VITE_API_BASE_URL;
42618
+ const pref = /^https?:\/\//i.test(raw) ? raw : `http://${raw}`;
42619
+ const u16 = new URL(pref);
42620
+ return u16.protocol === "https:" ? `wss://${u16.host}` : `ws://${u16.host}`;
42621
+ }
42622
+ } catch (e10) {
42623
+ }
42624
+ if (typeof window !== "undefined") {
42625
+ const win = window;
42626
+ if (win.__VIASOFT_API_BASE_URL) {
42627
+ const raw = win.__VIASOFT_API_BASE_URL;
42628
+ const pref = /^https?:\/\//i.test(raw) ? raw : `http://${raw}`;
42629
+ const u16 = new URL(pref);
42630
+ return u16.protocol === "https:" ? `wss://${u16.host}` : `ws://${u16.host}`;
42631
+ }
42632
+ if (window.location && window.location.host) {
42633
+ return window.location.protocol === "https:" ? `wss://${window.location.host}` : `ws://${window.location.host}`;
42634
+ }
42635
+ }
42636
+ return `ws://localhost:3000`;
42637
+ };
42638
+ const wsOrigin = resolveWsOrigin();
42575
42639
  playerRef.current = new window.JSMpeg.Player(
42576
- `ws://${apiBaseUrl}/ws/preview-xcoder_${pgmIndex}`,
42640
+ `${wsOrigin}/ws/preview-xcoder_${pgmIndex}`,
42577
42641
  {
42578
42642
  canvas: videoRef.current,
42579
42643
  disableWebAssembly: false,
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { User, Role } from '../types';
3
+ interface AuthContextType {
4
+ user: User | null;
5
+ accessToken: string | null;
6
+ loading: boolean;
7
+ login: (username: string, password: string, options?: {
8
+ redirect?: boolean;
9
+ }) => Promise<void>;
10
+ logout: () => Promise<void>;
11
+ hasRole: (roles: Role | Role[]) => boolean;
12
+ }
13
+ export declare const AuthProvider: React.FC<{
14
+ children: React.ReactNode;
15
+ }>;
16
+ export declare function useAuth(): AuthContextType;
17
+ export {};
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ type Theme = 'light' | 'dark';
3
+ interface ThemeContextType {
4
+ theme: Theme;
5
+ toggleTheme: () => void;
6
+ }
7
+ export declare function ThemeProvider({ children }: {
8
+ children: React.ReactNode;
9
+ }): import("react/jsx-runtime").JSX.Element;
10
+ export declare function useTheme(): ThemeContextType;
11
+ export {};
@@ -0,0 +1,3 @@
1
+ import { ThemeProvider } from './ThemeContext';
2
+ import { AuthProvider, useAuth } from './AuthContext';
3
+ export { ThemeProvider, AuthProvider, useAuth, };
package/dist/context.js CHANGED
@@ -3072,19 +3072,36 @@ var {
3072
3072
  } = axios_default;
3073
3073
 
3074
3074
  // src/services/api.ts
3075
- var getApiBaseUrl = () => {
3076
- if (typeof import.meta !== "undefined" && import.meta.env?.VITE_API_BASE_URL) {
3077
- return import.meta.env.VITE_API_BASE_URL;
3075
+ var normalizeOrigin = (raw) => {
3076
+ if (!raw)
3077
+ return "";
3078
+ if (/^https?:\/\//i.test(raw) || /^wss?:\/\//i.test(raw))
3079
+ return raw.replace(/\/$/, "");
3080
+ return `http://${raw.replace(/\/$/, "")}`;
3081
+ };
3082
+ var getApiOrigin = () => {
3083
+ try {
3084
+ if (typeof import.meta !== "undefined" && import.meta.env?.VITE_API_BASE_URL) {
3085
+ return normalizeOrigin(import.meta.env.VITE_API_BASE_URL);
3086
+ }
3087
+ } catch (e) {
3088
+ }
3089
+ if (typeof window !== "undefined") {
3090
+ const win = window;
3091
+ if (win.__VIASOFT_API_BASE_URL)
3092
+ return normalizeOrigin(win.__VIASOFT_API_BASE_URL);
3093
+ if (window.location && window.location.origin)
3094
+ return window.location.origin.replace(/\/$/, "");
3078
3095
  }
3079
- return "192.168.100.9:3000";
3096
+ return "http://localhost:3000";
3080
3097
  };
3081
- var serverUrl = getApiBaseUrl();
3098
+ var apiOrigin = getApiOrigin();
3082
3099
  var api = axios_default.create({
3083
- baseURL: `http://${serverUrl}`,
3100
+ baseURL: apiOrigin,
3084
3101
  timeout: 1e4
3085
3102
  });
3086
3103
  var authApi = axios_default.create({
3087
- baseURL: `http://${serverUrl}`,
3104
+ baseURL: apiOrigin,
3088
3105
  timeout: 1e4
3089
3106
  });
3090
3107
  function getAccessToken() {
@@ -3170,7 +3187,6 @@ authApi.interceptors.response.use(
3170
3187
  return Promise.reject(err);
3171
3188
  }
3172
3189
  );
3173
- var serverOrigin = `http://${serverUrl}`;
3174
3190
 
3175
3191
  // src/services/auth.ts
3176
3192
  var authService = {
@@ -3239,7 +3255,7 @@ var MetadataLoader = class {
3239
3255
  );
3240
3256
  }
3241
3257
  metadata.forEach((page, index) => {
3242
- if (!page.id || !page.name || !page.path || !page.bundleUrl) {
3258
+ if (!page.id || !page.name || !page.path || !page.url) {
3243
3259
  throw new Error(
3244
3260
  `Invalid page metadata at index ${index}: missing required fields`
3245
3261
  );
@@ -0,0 +1,3 @@
1
+ export { useSettings } from './useSettings';
2
+ export { useApi } from './useApi';
3
+ export { default as useAvailableSubservices } from './useAvailableSubservices';
@@ -0,0 +1 @@
1
+ export declare function useApi<T>(type: "json" | "text" | "void", key: readonly unknown[], path: string, params?: Record<string, any>, enabled?: boolean, refetchInterval?: number): import("@tanstack/react-query").UseQueryResult<import("@tanstack/react-query").NoInfer<T>, Error>;
@@ -0,0 +1,13 @@
1
+ export interface Option {
2
+ label: string;
3
+ value: string;
4
+ }
5
+ /**
6
+ * Returns an array of select options for a given service key.
7
+ * - `serviceKey` should match the service identifier used by the backend (e.g. 'xcoder-audioencoder').
8
+ * - `fallbackCount` specifies how many default channels to generate when discovery is unavailable.
9
+ */
10
+ export default function useAvailableSubservices(serviceKey: string, fallbackCount?: number): {
11
+ options: Option[];
12
+ loading: boolean;
13
+ };
@@ -0,0 +1,45 @@
1
+ export interface UseSettingsOptions<T> {
2
+ /** Unique key for react-query caching */
3
+ queryKey: readonly unknown[];
4
+ /** API path for fetching settings (GET) */
5
+ fetchPath: string;
6
+ /** API path for saving settings (PATCH/PUT) - defaults to fetchPath */
7
+ savePath?: string;
8
+ /** Query params for fetch request */
9
+ fetchParams?: Record<string, any>;
10
+ /** Transform raw API response to settings model */
11
+ transform?: (data: any) => T;
12
+ /** Transform settings to API payload before save */
13
+ toPayload?: (settings: T) => any;
14
+ /** HTTP method for save: 'patch' | 'put' | 'post' */
15
+ saveMethod?: 'patch' | 'put' | 'post';
16
+ /** Enable/disable fetching */
17
+ enabled?: boolean;
18
+ /** Refetch interval in ms */
19
+ refetchInterval?: number;
20
+ }
21
+ export interface UseSettingsResult<T> {
22
+ /** Current working settings (editable) */
23
+ settings: T;
24
+ /** Last saved settings from server */
25
+ savedSettings: T;
26
+ /** Update a single field */
27
+ updateField: <K extends keyof T>(key: K, value: T[K]) => void;
28
+ /** Update multiple fields at once */
29
+ updateSettings: (partial: Partial<T>) => void;
30
+ /** Reset settings to last saved state */
31
+ discard: () => void;
32
+ /** Save current settings to server */
33
+ save: () => Promise<void>;
34
+ /** Whether settings have unsaved changes */
35
+ isDirty: boolean;
36
+ /** Whether initial fetch is loading */
37
+ isLoading: boolean;
38
+ /** Whether save is in progress */
39
+ isSaving: boolean;
40
+ /** Error from fetch or save */
41
+ error: Error | null;
42
+ /** Refetch settings from server */
43
+ refetch: () => void;
44
+ }
45
+ export declare function useSettings<T extends Record<string, any>>(defaultSettings: T, options: UseSettingsOptions<T>): UseSettingsResult<T>;
package/dist/hooks.js CHANGED
@@ -3945,19 +3945,36 @@ var {
3945
3945
  } = axios_default;
3946
3946
 
3947
3947
  // src/services/api.ts
3948
- var getApiBaseUrl = () => {
3949
- if (typeof import.meta !== "undefined" && import.meta.env?.VITE_API_BASE_URL) {
3950
- return import.meta.env.VITE_API_BASE_URL;
3948
+ var normalizeOrigin = (raw) => {
3949
+ if (!raw)
3950
+ return "";
3951
+ if (/^https?:\/\//i.test(raw) || /^wss?:\/\//i.test(raw))
3952
+ return raw.replace(/\/$/, "");
3953
+ return `http://${raw.replace(/\/$/, "")}`;
3954
+ };
3955
+ var getApiOrigin = () => {
3956
+ try {
3957
+ if (typeof import.meta !== "undefined" && import.meta.env?.VITE_API_BASE_URL) {
3958
+ return normalizeOrigin(import.meta.env.VITE_API_BASE_URL);
3959
+ }
3960
+ } catch (e) {
3961
+ }
3962
+ if (typeof window !== "undefined") {
3963
+ const win = window;
3964
+ if (win.__VIASOFT_API_BASE_URL)
3965
+ return normalizeOrigin(win.__VIASOFT_API_BASE_URL);
3966
+ if (window.location && window.location.origin)
3967
+ return window.location.origin.replace(/\/$/, "");
3951
3968
  }
3952
- return "192.168.100.9:3000";
3969
+ return "http://localhost:3000";
3953
3970
  };
3954
- var serverUrl = getApiBaseUrl();
3971
+ var apiOrigin = getApiOrigin();
3955
3972
  var api = axios_default.create({
3956
- baseURL: `http://${serverUrl}`,
3973
+ baseURL: apiOrigin,
3957
3974
  timeout: 1e4
3958
3975
  });
3959
3976
  var authApi = axios_default.create({
3960
- baseURL: `http://${serverUrl}`,
3977
+ baseURL: apiOrigin,
3961
3978
  timeout: 1e4
3962
3979
  });
3963
3980
  function getAccessToken() {
@@ -4121,7 +4138,6 @@ var fetchApi = {
4121
4138
  }
4122
4139
  }
4123
4140
  };
4124
- var serverOrigin = `http://${serverUrl}`;
4125
4141
 
4126
4142
  // src/services/loadRemoteModule.ts
4127
4143
  import * as React7 from "react";
@@ -4154,7 +4170,7 @@ var MetadataLoader = class {
4154
4170
  );
4155
4171
  }
4156
4172
  metadata.forEach((page, index) => {
4157
- if (!page.id || !page.name || !page.path || !page.bundleUrl) {
4173
+ if (!page.id || !page.name || !page.path || !page.url) {
4158
4174
  throw new Error(
4159
4175
  `Invalid page metadata at index ${index}: missing required fields`
4160
4176
  );
package/dist/i18n.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import i18n from 'i18next';
2
+ export default i18n;
@@ -0,0 +1,6 @@
1
+ export * from './services';
2
+ export * from './components';
3
+ export * from './context';
4
+ export * from './types';
5
+ export * from './i18n';
6
+ export * from './hooks';