@arcanewizards/timecode-toolbox 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13970,7 +13970,7 @@ function cnd(condition, truthyClassName, falseyClassName) {
13970
13970
  return condition ? truthyClassName : falseyClassName;
13971
13971
  }
13972
13972
 
13973
- // ../../packages/sigil/dist/chunk-E3VUC3Q4.js
13973
+ // ../../packages/sigil/dist/chunk-LDUYBGRY.js
13974
13974
  import {
13975
13975
  createContext as createContext6,
13976
13976
  forwardRef as forwardRef42,
@@ -14014,7 +14014,7 @@ var TRANSPARENCY_SVG = `
14014
14014
  `;
14015
14015
  var TRANSPARENCY_SVG_URI = `data:image/svg+xml,${encodeURIComponent(TRANSPARENCY_SVG)}`;
14016
14016
 
14017
- // ../../packages/sigil/dist/chunk-E3VUC3Q4.js
14017
+ // ../../packages/sigil/dist/chunk-LDUYBGRY.js
14018
14018
  import {
14019
14019
  forwardRef as forwardRef15
14020
14020
  } from "react";
@@ -14087,7 +14087,8 @@ var clsControlButton = ({
14087
14087
  touching,
14088
14088
  position,
14089
14089
  className,
14090
- primary
14090
+ primary,
14091
+ destructive
14091
14092
  }) => cn(
14092
14093
  `sigil-control-button`,
14093
14094
  cnd(variant === "border", `sigil-control-button-variant-border`),
@@ -14100,6 +14101,7 @@ var clsControlButton = ({
14100
14101
  cnd(active, `sigil-control-button-active`),
14101
14102
  cnd(touching && active, `sigil-control-button-active-touching`),
14102
14103
  cnd(primary, `sigil-control-button-primary`),
14104
+ cnd(destructive, `sigil-control-button-destructive`),
14103
14105
  clsControlPosition(position),
14104
14106
  className
14105
14107
  );
@@ -14117,6 +14119,7 @@ var ControlButtonFrame = forwardRef15(
14117
14119
  tooltipSide,
14118
14120
  position,
14119
14121
  primary,
14122
+ destructive,
14120
14123
  ...props
14121
14124
  }, ref) => {
14122
14125
  const btn = /* @__PURE__ */ jsx17(
@@ -14132,6 +14135,7 @@ var ControlButtonFrame = forwardRef15(
14132
14135
  touching,
14133
14136
  position,
14134
14137
  primary,
14138
+ destructive,
14135
14139
  className
14136
14140
  }),
14137
14141
  children: /* @__PURE__ */ jsxs4("span", { children: [
@@ -14241,7 +14245,7 @@ ControlParagraph.displayName = "ControlParagraph";
14241
14245
  var ControlLabel = forwardRef22(
14242
14246
  ({ className, disabled, nonMicro, position = "label", subgrid, ...props }, ref) => {
14243
14247
  return /* @__PURE__ */ jsx23(
14244
- "div",
14248
+ "label",
14245
14249
  {
14246
14250
  ...props,
14247
14251
  ref,
@@ -14290,10 +14294,17 @@ var InputSpanningTitle = forwardRef22(({ className, position = "row", ...props }
14290
14294
  ));
14291
14295
  InputSpanningTitle.displayName = "InputSpanningTitle";
14292
14296
  var ControlDialogButtons = forwardRef32(({ children, className, ...props }, ref) => /* @__PURE__ */ jsx32(
14293
- ControlButtonGroup,
14297
+ "div",
14294
14298
  {
14295
14299
  ref,
14296
- className: cn("control-grid-pos-row", className),
14300
+ className: cn(
14301
+ `
14302
+ flex items-stretch gap-1
14303
+ [&>button]:grow
14304
+ `,
14305
+ clsControlPosition("row"),
14306
+ className
14307
+ ),
14297
14308
  ...props,
14298
14309
  children
14299
14310
  }
@@ -14476,19 +14487,9 @@ var ControlSelect = ({
14476
14487
  }
14477
14488
  );
14478
14489
  };
14479
- var COLOR_OPTIONS = {
14480
- red: { label: "Red", value: "red" },
14481
- blue: { label: "Blue", value: "blue" },
14482
- teal: { label: "Teal", value: "teal" },
14483
- green: { label: "Green", value: "green" },
14484
- yellow: { label: "Yellow", value: "yellow" },
14485
- purple: { label: "Purple", value: "purple" },
14486
- orange: { label: "Orange", value: "orange" },
14487
- brown: { label: "Brown", value: "brown" },
14488
- gray: { label: "Gray", value: "gray" }
14489
- };
14490
- var ControlColorSelect = ({
14491
- color,
14490
+ var ControlColoredSelect = ({
14491
+ options,
14492
+ value,
14492
14493
  onChange,
14493
14494
  variant,
14494
14495
  position,
@@ -14496,13 +14497,13 @@ var ControlColorSelect = ({
14496
14497
  placeholder,
14497
14498
  ...props
14498
14499
  }) => {
14499
- const options = Object.values(COLOR_OPTIONS);
14500
- const selectedColor = sigilColorUsage(color || "gray");
14500
+ const selectedOption = options.find((option) => option.value === value);
14501
+ const selectedColor = sigilColorUsage(selectedOption?.color ?? "gray");
14501
14502
  return /* @__PURE__ */ jsx52(
14502
14503
  ControlSelect,
14503
14504
  {
14504
14505
  options,
14505
- value: color,
14506
+ value,
14506
14507
  onChange,
14507
14508
  triggerButton: (option) => /* @__PURE__ */ jsx52(
14508
14509
  dist_exports2.Trigger,
@@ -14556,7 +14557,7 @@ var ControlColorSelect = ({
14556
14557
  {
14557
14558
  className: "",
14558
14559
  style: {
14559
- color: `var(--sigil-usage-${option.value}-foreground)`
14560
+ color: `var(--sigil-usage-${option.color}-foreground)`
14560
14561
  },
14561
14562
  children: option.label
14562
14563
  }
@@ -14568,6 +14569,31 @@ var ControlColorSelect = ({
14568
14569
  }
14569
14570
  );
14570
14571
  };
14572
+ var COLOR_OPTIONS = {
14573
+ red: { label: "Red", value: "red", color: "red" },
14574
+ blue: { label: "Blue", value: "blue", color: "blue" },
14575
+ teal: { label: "Teal", value: "teal", color: "teal" },
14576
+ green: { label: "Green", value: "green", color: "green" },
14577
+ yellow: { label: "Yellow", value: "yellow", color: "yellow" },
14578
+ purple: { label: "Purple", value: "purple", color: "purple" },
14579
+ orange: { label: "Orange", value: "orange", color: "orange" },
14580
+ brown: { label: "Brown", value: "brown", color: "brown" },
14581
+ gray: { label: "Gray", value: "gray", color: "gray" }
14582
+ };
14583
+ var COLOR_OPTIONS_ARRAY = Object.values(COLOR_OPTIONS);
14584
+ var ControlColorSelect = ({
14585
+ color,
14586
+ ...props
14587
+ }) => {
14588
+ return /* @__PURE__ */ jsx52(
14589
+ ControlColoredSelect,
14590
+ {
14591
+ options: COLOR_OPTIONS_ARRAY,
14592
+ value: color,
14593
+ ...props
14594
+ }
14595
+ );
14596
+ };
14571
14597
  var isDarkDialog = (variant) => variant === "dark" || variant === "dark-compact";
14572
14598
  var DialogContext = createContext6({
14573
14599
  createDialog: () => {
@@ -15603,6 +15629,7 @@ var createBrowserMediaSession = () => {
15603
15629
  };
15604
15630
  var createDefaultBrowserContext = (browser) => {
15605
15631
  const defaults = {
15632
+ appListenerChangesHandledExternally: false,
15606
15633
  openExternalLink: (url) => {
15607
15634
  window.open(url, "_blank", "noopener,noreferrer");
15608
15635
  },
@@ -15824,6 +15851,30 @@ var startSigilFrontend = ({
15824
15851
  return resolvedBrowser;
15825
15852
  };
15826
15853
 
15854
+ // ../../packages/sigil/dist/shared/config.js
15855
+ var APP_LISTENER_CONFIG = zod_default.object({
15856
+ port: zod_default.union([
15857
+ zod_default.number().int().min(1).max(65535),
15858
+ zod_default.object({
15859
+ from: zod_default.number().int().min(1).max(65535),
15860
+ to: zod_default.number().int().min(1).max(65535)
15861
+ }).refine((data) => data.to >= data.from, {
15862
+ message: '"to" must be greater than or equal to "from"'
15863
+ })
15864
+ ]),
15865
+ interface: zod_default.string().optional()
15866
+ });
15867
+ var ALL_APP_LISTENER_CONFIG = zod_default.record(
15868
+ zod_default.string(),
15869
+ APP_LISTENER_CONFIG
15870
+ );
15871
+ var portString = (port) => {
15872
+ if (typeof port === "number") {
15873
+ return port.toString();
15874
+ }
15875
+ return `${port.from}-${port.to}`;
15876
+ };
15877
+
15827
15878
  // src/components/proto.ts
15828
15879
  var NET_UTILS_GENERAL_TARGET_DEFINITION = zod_default.union([
15829
15880
  zod_default.object({
@@ -15901,6 +15952,7 @@ var OUTPUT_CONFIG = zod_default.object({
15901
15952
  link: INPUT_OR_GENERATOR_INSTANCE_ID.nullable()
15902
15953
  });
15903
15954
  var TOOLBOX_CONFIG = zod_default.object({
15955
+ appListener: APP_LISTENER_CONFIG.partial().optional(),
15904
15956
  inputs: zod_default.record(zod_default.string(), INPUT_CONFIG),
15905
15957
  generators: zod_default.record(zod_default.string(), GENERATOR_CONFIG),
15906
15958
  outputs: zod_default.record(zod_default.string(), OUTPUT_CONFIG),
@@ -15917,11 +15969,11 @@ var isTimecodeToolboxComponent = (component) => component.namespace === NAMESPAC
15917
15969
 
15918
15970
  // src/components/frontend/toolbox/root.tsx
15919
15971
  import {
15920
- useCallback as useCallback20,
15921
- useContext as useContext16,
15922
- useEffect as useEffect31,
15923
- useMemo as useMemo15,
15924
- useState as useState31
15972
+ useCallback as useCallback24,
15973
+ useContext as useContext17,
15974
+ useEffect as useEffect34,
15975
+ useMemo as useMemo17,
15976
+ useState as useState36
15925
15977
  } from "react";
15926
15978
 
15927
15979
  // ../../packages/artnet/dist/chunk-J2HDMITA.js
@@ -15967,7 +16019,9 @@ var STRINGS = {
15967
16019
  noChildren: "No inputs yet. Please add one using the buttons below.",
15968
16020
  addButton: (protocol) => `Add ${protocol}`,
15969
16021
  addDialog: (protocol) => `Add ${protocol} Input`,
15970
- editDialog: (protocol, name) => `Edit ${protocol} Input ${name}`
16022
+ editDialog: (protocol, name) => `Edit ${protocol} Input ${name}`,
16023
+ deleteDialog: `Delete input?`,
16024
+ deleteDialogDetails: `Are you sure you want to delete this input? This action cannot be undone.`
15971
16025
  },
15972
16026
  smtpeModes: {
15973
16027
  SMPTE: `SMPTE ${TIMECODE_FPS.SMPTE}FPS`,
@@ -15990,17 +16044,37 @@ var STRINGS = {
15990
16044
  clock: "Clock"
15991
16045
  },
15992
16046
  addDialog: (protocol) => `Add ${protocol} Generator`,
15993
- editDialog: (protocol, name) => `Edit ${protocol} Generator ${name}`
16047
+ editDialog: (protocol, name) => `Edit ${protocol} Generator ${name}`,
16048
+ deleteDialog: `Delete generator?`,
16049
+ deleteDialogDetails: `Are you sure you want to delete this generator? This action cannot be undone.`
15994
16050
  },
15995
16051
  outputs: {
15996
16052
  title: "OUTPUTS",
15997
16053
  noChildren: "No outputs yet. Please add one using the buttons below.",
15998
16054
  addButton: (protocol) => `Add ${protocol}`,
15999
16055
  addDialog: (protocol) => `Add ${protocol} Output`,
16000
- editDialog: (protocol, name) => `Edit ${protocol} Output ${name}`
16056
+ editDialog: (protocol, name) => `Edit ${protocol} Output ${name}`,
16057
+ deleteDialog: `Delete output?`,
16058
+ deleteDialogDetails: `Are you sure you want to delete this output? This action cannot be undone.`
16001
16059
  },
16002
16060
  settings: {
16003
- title: "Settings"
16061
+ title: "Settings",
16062
+ network: {
16063
+ appPortLabel: "Application Port",
16064
+ appInterfaceLabel: "Application Interface",
16065
+ anyInterface: "Any Interface",
16066
+ internalInterfaceUsed: (iface) => `Note: The interface ${iface} is only accessible from this device, which means that other devices will not be able to connect to Timecode Toolbox.`,
16067
+ appPortEnvOverride: (envPort) => `Note: The application port is currently set to ${envPort} via the PORT environment variable, and cannot be configured here.`,
16068
+ defaultPort: (port) => `Default: (${port})`,
16069
+ saveChanges: "Save Changes",
16070
+ saveWarning: {
16071
+ external: "When you hit Save, the UI will reload",
16072
+ internal: "When you hit Save, the app will attempt to reconnect using the new network settings, but may require you to adjust the URL manually."
16073
+ },
16074
+ invalidPortSingle: "Port numbers must be an integer between 1 and 65535",
16075
+ invalidPort: 'Please enter a valid port number or range (e.g. "1234" or "8000-8100")',
16076
+ invalidPortRange: 'The first port in a range must be less than or equal to the second port (e.g. "8000-8100")'
16077
+ }
16004
16078
  },
16005
16079
  controls: {
16006
16080
  play: "Play",
@@ -16934,7 +17008,7 @@ var DmxConnectionSettings = ({
16934
17008
  var OutputSettingsDialog = ({
16935
17009
  target,
16936
17010
  output,
16937
- close
17011
+ setDialogMode
16938
17012
  }) => {
16939
17013
  const { config, updateConfig } = useContext10(ConfigContext);
16940
17014
  const [newData, setNewData] = useState25({
@@ -16950,6 +17024,7 @@ var OutputSettingsDialog = ({
16950
17024
  },
16951
17025
  link: null
16952
17026
  });
17027
+ const close = useCallback14(() => setDialogMode(null), [setDialogMode]);
16953
17028
  const updateSettings = useCallback14(
16954
17029
  (change) => {
16955
17030
  if (target.type === "add") {
@@ -17080,10 +17155,25 @@ var OutputSettingsDialog = ({
17080
17155
  }
17081
17156
  }
17082
17157
  ),
17083
- resolvedTarget === "add" ? /* @__PURE__ */ jsxs11(ControlDialogButtons, { children: [
17158
+ target.type === "add" ? /* @__PURE__ */ jsxs11(ControlDialogButtons, { children: [
17084
17159
  /* @__PURE__ */ jsx28(ControlButton, { onClick: close, variant: "large", children: "Cancel" }),
17085
17160
  /* @__PURE__ */ jsx28(ControlButton, { onClick: addOutput, variant: "large", children: "Add Output" })
17086
- ] }) : /* @__PURE__ */ jsx28(ControlDialogButtons, { children: /* @__PURE__ */ jsx28(ControlButton, { onClick: close, variant: "large", children: "Close" }) })
17161
+ ] }) : target.type === "edit" ? /* @__PURE__ */ jsxs11(ControlDialogButtons, { children: [
17162
+ /* @__PURE__ */ jsx28(
17163
+ ControlButton,
17164
+ {
17165
+ onClick: () => setDialogMode({
17166
+ section: { type: "outputs", output },
17167
+ target: { type: "delete", uuid: target.uuid }
17168
+ }),
17169
+ variant: "large",
17170
+ destructive: true,
17171
+ icon: "delete",
17172
+ children: "Delete"
17173
+ }
17174
+ ),
17175
+ /* @__PURE__ */ jsx28(ControlButton, { onClick: close, variant: "large", children: "Close" })
17176
+ ] }) : null
17087
17177
  ]
17088
17178
  }
17089
17179
  ) });
@@ -17295,7 +17385,7 @@ var ClockSpecificSettings = ({
17295
17385
  var GeneratorSettingsDialog = ({
17296
17386
  target,
17297
17387
  generator,
17298
- close
17388
+ setDialogMode
17299
17389
  }) => {
17300
17390
  const { config, updateConfig } = useContext11(ConfigContext);
17301
17391
  const [newData, setNewData] = useState26({
@@ -17305,6 +17395,7 @@ var GeneratorSettingsDialog = ({
17305
17395
  speed: 1
17306
17396
  }
17307
17397
  });
17398
+ const close = useCallback15(() => setDialogMode(null), [setDialogMode]);
17308
17399
  const updateSettings = useCallback15(
17309
17400
  (change) => {
17310
17401
  if (target.type === "add") {
@@ -17412,10 +17503,25 @@ var GeneratorSettingsDialog = ({
17412
17503
  updateSettings: updateDefinition
17413
17504
  }
17414
17505
  ) : null,
17415
- resolvedTarget === "add" ? /* @__PURE__ */ jsxs12(ControlDialogButtons, { children: [
17506
+ target.type === "add" ? /* @__PURE__ */ jsxs12(ControlDialogButtons, { children: [
17416
17507
  /* @__PURE__ */ jsx29(ControlButton, { onClick: close, variant: "large", children: "Cancel" }),
17417
17508
  /* @__PURE__ */ jsx29(ControlButton, { onClick: addGenerator, variant: "large", children: "Add Generator" })
17418
- ] }) : /* @__PURE__ */ jsx29(ControlDialogButtons, { children: /* @__PURE__ */ jsx29(ControlButton, { onClick: close, variant: "large", children: "Close" }) })
17509
+ ] }) : target.type === "edit" ? /* @__PURE__ */ jsxs12(ControlDialogButtons, { children: [
17510
+ /* @__PURE__ */ jsx29(
17511
+ ControlButton,
17512
+ {
17513
+ onClick: () => setDialogMode({
17514
+ section: { type: "generators", generator },
17515
+ target: { type: "delete", uuid: target.uuid }
17516
+ }),
17517
+ variant: "large",
17518
+ destructive: true,
17519
+ icon: "delete",
17520
+ children: "Delete"
17521
+ }
17522
+ ),
17523
+ /* @__PURE__ */ jsx29(ControlButton, { onClick: close, variant: "large", children: "Close" })
17524
+ ] }) : null
17419
17525
  ]
17420
17526
  }
17421
17527
  ) });
@@ -17629,7 +17735,7 @@ var TCNetConnectionSettings = ({
17629
17735
  var InputSettingsDialog = ({
17630
17736
  target,
17631
17737
  input,
17632
- close
17738
+ setDialogMode
17633
17739
  }) => {
17634
17740
  const { config, updateConfig } = useContext12(ConfigContext);
17635
17741
  const [newData, setNewData] = useState27({
@@ -17644,6 +17750,7 @@ var InputSettingsDialog = ({
17644
17750
  iface: ""
17645
17751
  }
17646
17752
  });
17753
+ const close = useCallback16(() => setDialogMode(null), [setDialogMode]);
17647
17754
  const updateSettings = useCallback16(
17648
17755
  (change) => {
17649
17756
  if (target.type === "add") {
@@ -17780,10 +17887,25 @@ var InputSettingsDialog = ({
17780
17887
  }
17781
17888
  }
17782
17889
  ),
17783
- resolvedTarget === "add" ? /* @__PURE__ */ jsxs13(ControlDialogButtons, { children: [
17890
+ target.type === "add" ? /* @__PURE__ */ jsxs13(ControlDialogButtons, { children: [
17784
17891
  /* @__PURE__ */ jsx30(ControlButton, { onClick: close, variant: "large", children: "Cancel" }),
17785
- /* @__PURE__ */ jsx30(ControlButton, { onClick: addInput, variant: "large", children: "Add Input" })
17786
- ] }) : /* @__PURE__ */ jsx30(ControlDialogButtons, { children: /* @__PURE__ */ jsx30(ControlButton, { onClick: close, variant: "large", children: "Close" }) })
17892
+ /* @__PURE__ */ jsx30(ControlButton, { onClick: addInput, variant: "large", primary: true, children: "Add Input" })
17893
+ ] }) : target?.type === "edit" ? /* @__PURE__ */ jsxs13(ControlDialogButtons, { children: [
17894
+ /* @__PURE__ */ jsx30(
17895
+ ControlButton,
17896
+ {
17897
+ onClick: () => setDialogMode({
17898
+ section: { type: "inputs", input },
17899
+ target: { type: "delete", uuid: target.uuid }
17900
+ }),
17901
+ variant: "large",
17902
+ destructive: true,
17903
+ icon: "delete",
17904
+ children: "Delete"
17905
+ }
17906
+ ),
17907
+ /* @__PURE__ */ jsx30(ControlButton, { onClick: close, variant: "large", children: "Close" })
17908
+ ] }) : null
17787
17909
  ]
17788
17910
  }
17789
17911
  ) });
@@ -17972,8 +18094,20 @@ var diffJson = (a, b) => {
17972
18094
  return { type: "value", after: b };
17973
18095
  };
17974
18096
 
18097
+ // src/components/frontend/toolbox/types.ts
18098
+ var isDeleteDialogMode = (mode) => {
18099
+ return mode?.target.type === "delete";
18100
+ };
18101
+
17975
18102
  // src/components/frontend/toolbox/settings.tsx
17976
- import { useContext as useContext13 } from "react";
18103
+ import {
18104
+ useCallback as useCallback18,
18105
+ useContext as useContext13,
18106
+ useEffect as useEffect29,
18107
+ useMemo as useMemo15,
18108
+ useRef as useRef17,
18109
+ useState as useState29
18110
+ } from "react";
17977
18111
 
17978
18112
  // ../../packages/sigil/dist/frontend/appearance.js
17979
18113
  import { useCallback as useCallback17 } from "react";
@@ -18118,7 +18252,7 @@ var TOOLBOX_PREFERENCES = {
18118
18252
  var useBrowserPreferences = createBrowserPreferencesHook(TOOLBOX_PREFERENCES);
18119
18253
 
18120
18254
  // src/components/frontend/toolbox/settings.tsx
18121
- import { jsx as jsx35, jsxs as jsxs15 } from "react/jsx-runtime";
18255
+ import { Fragment as Fragment12, jsx as jsx35, jsxs as jsxs15 } from "react/jsx-runtime";
18122
18256
  var ENABLED_DISABLED_OPTIONS = [
18123
18257
  { value: "enabled", label: STRINGS.general.enabled },
18124
18258
  { value: "disabled", label: STRINGS.general.disabled }
@@ -18126,6 +18260,180 @@ var ENABLED_DISABLED_OPTIONS = [
18126
18260
  var DATE_FORMATTER = new Intl.DateTimeFormat(void 0, {
18127
18261
  timeStyle: "medium"
18128
18262
  });
18263
+ var AppPortConfig = () => {
18264
+ const { getNetworkInterfaces } = useContext13(NetworkContext);
18265
+ const [interfaces, setInterfaces] = useState29(null);
18266
+ const refreshInterfaces = useCallback18(() => {
18267
+ setInterfaces(null);
18268
+ getNetworkInterfaces().then((ifs) => setInterfaces(ifs));
18269
+ }, [getNetworkInterfaces]);
18270
+ useEffect29(() => {
18271
+ refreshInterfaces();
18272
+ }, [refreshInterfaces]);
18273
+ const { appListenerChangesHandledExternally } = useBrowserContext();
18274
+ const { network, config, updateConfig } = useContext13(ConfigContext);
18275
+ const [nextPort, setNextPort] = useState29(null);
18276
+ const [nextInterface, setNextInterface] = useState29(
18277
+ null
18278
+ );
18279
+ const iface = nextInterface ?? (config.appListener?.interface ? `specific:${config.appListener?.interface}` : "any");
18280
+ const port = nextPort ?? config.appListener?.port;
18281
+ const currentPortString = !port ? "" : typeof port === "string" ? port : portString(port);
18282
+ const hasNetworkChanges = nextPort !== null || nextInterface !== null;
18283
+ const nextUrlRef = useRef17(null);
18284
+ const validatedPort = useMemo15(() => {
18285
+ if (nextPort === null) {
18286
+ return { type: "unchanged" };
18287
+ }
18288
+ if (nextPort.trim() === "") {
18289
+ return { type: "empty" };
18290
+ }
18291
+ const portParts = nextPort.split("-").map((part) => parseInt(part.trim(), 10));
18292
+ if (portParts.length === 1) {
18293
+ const [singlePort] = portParts;
18294
+ if (!singlePort || isNaN(singlePort) || singlePort < 1 || singlePort > 65535) {
18295
+ return {
18296
+ type: "invalid",
18297
+ error: STRINGS.settings.network.invalidPortSingle
18298
+ };
18299
+ }
18300
+ return { type: "valid", port: singlePort };
18301
+ }
18302
+ if (portParts.length === 2) {
18303
+ const [from, to] = portParts;
18304
+ if (!from || isNaN(from) || from < 1 || from > 65535 || !to || isNaN(to) || to < 1 || to > 65535) {
18305
+ return {
18306
+ type: "invalid",
18307
+ error: STRINGS.settings.network.invalidPortSingle
18308
+ };
18309
+ } else if (from > to) {
18310
+ return {
18311
+ type: "invalid",
18312
+ error: STRINGS.settings.network.invalidPortRange
18313
+ };
18314
+ }
18315
+ return { type: "valid", port: { from, to } };
18316
+ }
18317
+ return { type: "invalid", error: STRINGS.settings.network.invalidPort };
18318
+ }, [nextPort]);
18319
+ const canSave = hasNetworkChanges && validatedPort?.type !== "invalid";
18320
+ const saveNetworkConfig = useCallback18(() => {
18321
+ if (validatedPort?.type === "invalid") {
18322
+ return;
18323
+ }
18324
+ const newPort = validatedPort;
18325
+ updateConfig((current) => {
18326
+ const config2 = {
18327
+ ...current,
18328
+ appListener: {
18329
+ port: newPort.type === "empty" ? void 0 : newPort.type === "valid" ? newPort.port : current.appListener?.port,
18330
+ interface: nextInterface === "any" ? void 0 : nextInterface ? nextInterface.replace("specific:", "") : current.appListener?.interface
18331
+ }
18332
+ };
18333
+ const nextUrl = new URL(window.location.href);
18334
+ if (config2.appListener?.interface) {
18335
+ nextUrl.hostname = interfaces?.[config2.appListener.interface]?.address ?? nextUrl.hostname;
18336
+ }
18337
+ const port2 = config2.appListener?.port ?? network.defaultPort;
18338
+ nextUrl.port = (typeof port2 === "number" ? port2 : port2.from).toString();
18339
+ nextUrlRef.current = nextUrl;
18340
+ return config2;
18341
+ });
18342
+ setNextPort(null);
18343
+ setNextInterface(null);
18344
+ }, [
18345
+ interfaces,
18346
+ nextInterface,
18347
+ validatedPort,
18348
+ updateConfig,
18349
+ network.defaultPort
18350
+ ]);
18351
+ useEffect29(() => {
18352
+ return () => {
18353
+ if (!appListenerChangesHandledExternally && nextUrlRef.current) {
18354
+ window.location.href = nextUrlRef.current.href;
18355
+ }
18356
+ };
18357
+ }, [appListenerChangesHandledExternally]);
18358
+ return /* @__PURE__ */ jsxs15(Fragment12, { children: [
18359
+ /* @__PURE__ */ jsx35(ControlLabel, { children: STRINGS.settings.network.appInterfaceLabel }),
18360
+ /* @__PURE__ */ jsx35(
18361
+ ControlSelect,
18362
+ {
18363
+ value: iface,
18364
+ options: [
18365
+ { label: STRINGS.settings.network.anyInterface, value: "any" },
18366
+ ...!interfaces ? [] : Object.values(interfaces).map((iface2) => ({
18367
+ label: `${iface2.name} (${iface2.address})`,
18368
+ value: `specific:${iface2.name}`
18369
+ }))
18370
+ ],
18371
+ onChange: setNextInterface,
18372
+ position: "first",
18373
+ variant: "large",
18374
+ triggerClassName: cn("text-sigil-control")
18375
+ }
18376
+ ),
18377
+ iface && interfaces?.[iface]?.internal && /* @__PURE__ */ jsx35(
18378
+ ControlDetails,
18379
+ {
18380
+ position: "second",
18381
+ className: "text-sigil-warning-foreground",
18382
+ children: STRINGS.settings.network.internalInterfaceUsed(iface)
18383
+ }
18384
+ ),
18385
+ /* @__PURE__ */ jsx35(
18386
+ ControlButton,
18387
+ {
18388
+ onClick: refreshInterfaces,
18389
+ title: "Refresh Interfaces",
18390
+ position: "extra",
18391
+ variant: "large",
18392
+ children: /* @__PURE__ */ jsx35(Icon2, { icon: "refresh", className: "text-arcane-normal" })
18393
+ }
18394
+ ),
18395
+ /* @__PURE__ */ jsx35(ControlLabel, { children: STRINGS.settings.network.appPortLabel }),
18396
+ network.envPort ? /* @__PURE__ */ jsx35(ControlDetails, { position: "both", children: STRINGS.settings.network.appPortEnvOverride(network.envPort) }) : /* @__PURE__ */ jsxs15(Fragment12, { children: [
18397
+ /* @__PURE__ */ jsx35(
18398
+ ControlInput,
18399
+ {
18400
+ value: currentPortString,
18401
+ onChange: setNextPort,
18402
+ placeholder: STRINGS.settings.network.defaultPort(
18403
+ portString(network.defaultPort)
18404
+ )
18405
+ }
18406
+ ),
18407
+ validatedPort.type === "invalid" && /* @__PURE__ */ jsx35(
18408
+ ControlDetails,
18409
+ {
18410
+ position: "second",
18411
+ className: "text-sigil-error-foreground",
18412
+ children: validatedPort.error
18413
+ }
18414
+ )
18415
+ ] }),
18416
+ /* @__PURE__ */ jsx35(
18417
+ ControlButton,
18418
+ {
18419
+ onClick: saveNetworkConfig,
18420
+ variant: "large",
18421
+ position: "first",
18422
+ disabled: !canSave,
18423
+ children: STRINGS.settings.network.saveChanges
18424
+ }
18425
+ ),
18426
+ hasNetworkChanges && appListenerChangesHandledExternally && /* @__PURE__ */ jsx35(ControlDetails, { position: "second", children: STRINGS.settings.network.saveWarning.external }),
18427
+ hasNetworkChanges && !appListenerChangesHandledExternally && /* @__PURE__ */ jsx35(
18428
+ ControlDetails,
18429
+ {
18430
+ position: "second",
18431
+ className: "text-sigil-warning-foreground",
18432
+ children: STRINGS.settings.network.saveWarning.internal
18433
+ }
18434
+ )
18435
+ ] });
18436
+ };
18129
18437
  var Settings = ({ setWindowMode }) => {
18130
18438
  const { preferences, updateBrowserPrefs } = useBrowserPreferences();
18131
18439
  const { config, updateConfig } = useContext13(ConfigContext);
@@ -18173,7 +18481,8 @@ var Settings = ({ setWindowMode }) => {
18173
18481
  /* @__PURE__ */ jsx35(ControlDetails, { children: STRINGS.updates.settingsDetails }),
18174
18482
  updates && "lastCheckedMillis" in updates && /* @__PURE__ */ jsx35(ControlDetails, { children: STRINGS.updates.lastChecked(
18175
18483
  DATE_FORMATTER.format(updates.lastCheckedMillis)
18176
- ) })
18484
+ ) }),
18485
+ /* @__PURE__ */ jsx35(AppPortConfig, {})
18177
18486
  ] })
18178
18487
  }
18179
18488
  )
@@ -18181,7 +18490,7 @@ var Settings = ({ setWindowMode }) => {
18181
18490
  };
18182
18491
 
18183
18492
  // src/components/frontend/toolbox/license.tsx
18184
- import { useCallback as useCallback18, useContext as useContext15 } from "react";
18493
+ import { useCallback as useCallback19, useContext as useContext15 } from "react";
18185
18494
 
18186
18495
  // src/components/frontend/toolbox/logo.tsx
18187
18496
  import { jsx as jsx36, jsxs as jsxs16 } from "react/jsx-runtime";
@@ -18520,10 +18829,10 @@ var TimecodeToolboxLogo = (props) => /* @__PURE__ */ jsxs16(
18520
18829
  );
18521
18830
 
18522
18831
  // src/components/frontend/toolbox/core/layout.tsx
18523
- import { useContext as useContext14, useState as useState29 } from "react";
18832
+ import { useContext as useContext14, useState as useState30 } from "react";
18524
18833
 
18525
18834
  // src/components/frontend/toolbox/core/footer.tsx
18526
- import { Fragment as Fragment12, jsx as jsx37, jsxs as jsxs17 } from "react/jsx-runtime";
18835
+ import { Fragment as Fragment13, jsx as jsx37, jsxs as jsxs17 } from "react/jsx-runtime";
18527
18836
  var Footer = ({ openLicenseDetails }) => {
18528
18837
  return /* @__PURE__ */ jsxs17(
18529
18838
  "div",
@@ -18537,7 +18846,7 @@ var Footer = ({ openLicenseDetails }) => {
18537
18846
  ] }),
18538
18847
  /* @__PURE__ */ jsx37(ToolbarDivider, {}),
18539
18848
  /* @__PURE__ */ jsx37(ExternalLink, { href: SOURCE_CODE_URL, children: STRINGS.sourceCode }),
18540
- openLicenseDetails && /* @__PURE__ */ jsxs17(Fragment12, { children: [
18849
+ openLicenseDetails && /* @__PURE__ */ jsxs17(Fragment13, { children: [
18541
18850
  /* @__PURE__ */ jsx37(ToolbarDivider, {}),
18542
18851
  /* @__PURE__ */ jsx37(TextButton, { onClick: openLicenseDetails, children: STRINGS.license })
18543
18852
  ] })
@@ -18547,9 +18856,9 @@ var Footer = ({ openLicenseDetails }) => {
18547
18856
  };
18548
18857
 
18549
18858
  // ../../packages/sigil/dist/frontend/styling.hooks.js
18550
- import { useEffect as useEffect29 } from "react";
18859
+ import { useEffect as useEffect30 } from "react";
18551
18860
  var useRootHintVariables = (color) => {
18552
- useEffect29(() => {
18861
+ useEffect30(() => {
18553
18862
  const root = document.querySelector(".arcane-theme-root");
18554
18863
  if (!root) return;
18555
18864
  Object.entries(cssHintColorVariables(color)).forEach(([key, value]) => {
@@ -18559,18 +18868,18 @@ var useRootHintVariables = (color) => {
18559
18868
  };
18560
18869
 
18561
18870
  // src/components/frontend/toolbox/core/layout.tsx
18562
- import { Fragment as Fragment13, jsx as jsx38, jsxs as jsxs18 } from "react/jsx-runtime";
18871
+ import { Fragment as Fragment14, jsx as jsx38, jsxs as jsxs18 } from "react/jsx-runtime";
18563
18872
  var Layout = ({
18564
18873
  modes,
18565
18874
  children,
18566
18875
  licenseMode,
18567
18876
  footer
18568
18877
  }) => {
18569
- const [windowMode, setWindowMode] = useState29(null);
18878
+ const [windowMode, setWindowMode] = useState30(null);
18570
18879
  const { connection, reconnect } = useContext14(StageContext);
18571
18880
  const { preferences } = useBrowserPreferences();
18572
18881
  useRootHintVariables(preferences.color);
18573
- return /* @__PURE__ */ jsxs18("div", { className: "flex h-screen flex-col", children: [
18882
+ return /* @__PURE__ */ jsxs18("div", { className: "flex h-dvh flex-col", children: [
18574
18883
  /* @__PURE__ */ jsx38(ToolbarWrapper, { children: /* @__PURE__ */ jsxs18(ToolbarRow, { children: [
18575
18884
  /* @__PURE__ */ jsx38(
18576
18885
  "div",
@@ -18579,7 +18888,7 @@ var Layout = ({
18579
18888
  children: /* @__PURE__ */ jsx38("span", { className: "font-bold text-hint-gradient", children: STRINGS.title })
18580
18889
  }
18581
18890
  ),
18582
- modes && /* @__PURE__ */ jsxs18(Fragment13, { children: [
18891
+ modes && /* @__PURE__ */ jsxs18(Fragment14, { children: [
18583
18892
  /* @__PURE__ */ jsx38(ToolbarDivider, {}),
18584
18893
  Object.entries(modes).map(([key, { icon, title }]) => /* @__PURE__ */ jsx38(
18585
18894
  ControlButton,
@@ -18644,7 +18953,7 @@ var License = ({ license, setWindowMode }) => {
18644
18953
  };
18645
18954
  var LicenseGate = ({ info }) => {
18646
18955
  const { sendMessage } = useContext15(StageContext);
18647
- const acceptLicense = useCallback18(() => {
18956
+ const acceptLicense = useCallback19(() => {
18648
18957
  sendMessage?.({
18649
18958
  type: "component-message",
18650
18959
  namespace: "timecode-toolbox",
@@ -18691,19 +19000,19 @@ var LicenseGate = ({ info }) => {
18691
19000
  };
18692
19001
 
18693
19002
  // src/components/frontend/toolbox/core/updates.tsx
18694
- import { useCallback as useCallback19, useEffect as useEffect30, useState as useState30 } from "react";
19003
+ import { useCallback as useCallback20, useEffect as useEffect31, useState as useState31 } from "react";
18695
19004
  import { jsx as jsx40, jsxs as jsxs20 } from "react/jsx-runtime";
18696
19005
  var UpdateBanner = () => {
18697
19006
  const { updates } = useApplicationState();
18698
19007
  const { version } = useSystemInformation();
18699
19008
  const { openExternalLink } = useBrowserContext();
18700
- const [displayState, setDisplayState] = useState30();
18701
- useEffect30(() => {
19009
+ const [displayState, setDisplayState] = useState31();
19010
+ useEffect31(() => {
18702
19011
  if (updates?.type !== "loading") {
18703
19012
  setDisplayState(updates);
18704
19013
  }
18705
19014
  }, [updates]);
18706
- const openDownloadLink = useCallback19(() => {
19015
+ const openDownloadLink = useCallback20(() => {
18707
19016
  if (displayState?.type === "updates-available" && displayState.response.downloadUrl) {
18708
19017
  openExternalLink(displayState.response.downloadUrl);
18709
19018
  }
@@ -18749,52 +19058,663 @@ var UpdateBanner = () => {
18749
19058
  return null;
18750
19059
  };
18751
19060
 
18752
- // src/components/frontend/toolbox/root.tsx
18753
- import { Fragment as Fragment14, jsx as jsx41, jsxs as jsxs21 } from "react/jsx-runtime";
18754
- var ToolboxRoot = ({ info }) => {
18755
- const { config } = info;
18756
- const { sendMessage, call } = useContext16(StageContext);
18757
- const [dialogMode, setDialogMode] = useState31(null);
18758
- const [assignToOutput, setAssignToOutput] = useState31(null);
18759
- useEffect31(() => {
18760
- if (assignToOutput) {
18761
- const onEscape = (e) => {
18762
- if (e.key === "Escape") {
18763
- setAssignToOutput(null);
19061
+ // ../../packages/sigil/src/frontend/controls/dialogs.tsx
19062
+ import { forwardRef as forwardRef20 } from "react";
19063
+
19064
+ // ../../packages/sigil/src/frontend/dialogs.tsx
19065
+ import {
19066
+ createContext as createContext11,
19067
+ forwardRef as forwardRef19,
19068
+ useEffect as useEffect33,
19069
+ useState as useState35
19070
+ } from "react";
19071
+
19072
+ // ../../packages/sigil/src/frontend/controls/buttons.tsx
19073
+ import {
19074
+ forwardRef as forwardRef17
19075
+ } from "react";
19076
+
19077
+ // ../../packages/sigil/src/frontend/styling.ts
19078
+ var SIGIL_COLOR2 = external_exports.enum([
19079
+ "purple",
19080
+ "blue",
19081
+ "teal",
19082
+ "red",
19083
+ "green",
19084
+ "yellow",
19085
+ "brown",
19086
+ "orange",
19087
+ "gray"
19088
+ ]);
19089
+ function cnd2(condition, truthyClassName, falseyClassName) {
19090
+ return condition ? truthyClassName : falseyClassName;
19091
+ }
19092
+
19093
+ // ../../packages/sigil/src/frontend/tooltip.tsx
19094
+ import {
19095
+ createContext as createContext10,
19096
+ forwardRef as forwardRef16,
19097
+ useContext as useContext16,
19098
+ useState as useState33
19099
+ } from "react";
19100
+ import { Fragment as Fragment15, jsx as jsx41, jsxs as jsxs21 } from "react/jsx-runtime";
19101
+ var Content4 = forwardRef16(({ className, ...props }, ref) => /* @__PURE__ */ jsx41(
19102
+ dist_exports4.Content,
19103
+ {
19104
+ ...props,
19105
+ ref,
19106
+ className: cn(
19107
+ `
19108
+ relative z-sigil-tooltip rounded-sigil-control
19109
+ bg-sigil-usage-hint-background px-1 py-0.5 leading-[1.5]
19110
+ text-sigil-usage-hint-text shadow-sigil-box
19111
+ `,
19112
+ className
19113
+ )
19114
+ }
19115
+ ));
19116
+ Content4.displayName = "Content";
19117
+ var Arrow4 = forwardRef16(({ className, ...props }, ref) => /* @__PURE__ */ jsx41(
19118
+ dist_exports4.Arrow,
19119
+ {
19120
+ ...props,
19121
+ ref,
19122
+ className: cn(
19123
+ "fill-sigil-usage-hint-background drop-shadow-sigil-tooltip-arrow",
19124
+ className
19125
+ )
19126
+ }
19127
+ ));
19128
+ Arrow4.displayName = "Arrow";
19129
+ var TooltipBoundaryContext2 = createContext10(null);
19130
+ var TooltipWrapper2 = ({
19131
+ tooltip,
19132
+ children,
19133
+ side = "top"
19134
+ }) => {
19135
+ const boundary = useContext16(TooltipBoundaryContext2);
19136
+ if (!tooltip) {
19137
+ return children;
19138
+ }
19139
+ return /* @__PURE__ */ jsxs21(dist_exports4.Root, { children: [
19140
+ /* @__PURE__ */ jsx41(dist_exports4.Trigger, { asChild: true, children }),
19141
+ /* @__PURE__ */ jsxs21(
19142
+ Content4,
19143
+ {
19144
+ side,
19145
+ align: "center",
19146
+ sideOffset: 5,
19147
+ alignOffset: 0,
19148
+ collisionBoundary: boundary ? [boundary] : [],
19149
+ collisionPadding: 10,
19150
+ children: [
19151
+ /* @__PURE__ */ jsx41(Arrow4, {}),
19152
+ tooltip
19153
+ ]
19154
+ }
19155
+ )
19156
+ ] });
19157
+ };
19158
+
19159
+ // ../../packages/sigil/src/frontend/input.ts
19160
+ import { useMemo as useMemo16, useState as useState34 } from "react";
19161
+ var usePressable3 = (click) => {
19162
+ const [touching, setTouching] = useState34(false);
19163
+ return {
19164
+ touching,
19165
+ handlers: {
19166
+ onClick: click,
19167
+ onTouchStart: () => {
19168
+ setTouching(true);
19169
+ },
19170
+ onTouchMove: () => {
19171
+ setTouching(false);
19172
+ },
19173
+ onTouchEnd: (event) => {
19174
+ if (touching) {
19175
+ event.preventDefault();
19176
+ setTouching(false);
19177
+ click(event);
18764
19178
  }
18765
- };
18766
- window.addEventListener("keydown", onEscape);
18767
- return () => {
18768
- window.removeEventListener("keydown", onEscape);
18769
- };
19179
+ }
18770
19180
  }
18771
- }, [assignToOutput]);
18772
- const updateConfig = useCallback20(
18773
- (change) => {
18774
- const diff = diffJson(config, change(config));
18775
- sendMessage?.({
18776
- type: "component-message",
18777
- namespace: "timecode-toolbox",
18778
- component: "toolbox-root",
18779
- componentKey: info.key,
18780
- action: "update-config",
18781
- diff
18782
- });
18783
- },
18784
- [sendMessage, info.key, config]
18785
- );
18786
- const configContext = useMemo15(
19181
+ };
19182
+ };
19183
+ var useLongPressable3 = ({
19184
+ onPress,
19185
+ onRelease
19186
+ }) => {
19187
+ const [touching, setTouching] = useState34(false);
19188
+ return useMemo16(
18787
19189
  () => ({
18788
- config,
18789
- updateConfig
18790
- }),
18791
- [config, updateConfig]
18792
- );
18793
- const closeDialog = useCallback20(() => setDialogMode(null), []);
18794
- const getNetworkInterfaces = useCallback20(async () => {
18795
- if (!call) {
18796
- throw new Error("No call function available");
18797
- }
19190
+ touching,
19191
+ handlers: {
19192
+ onTouchStart: () => {
19193
+ setTouching(true);
19194
+ onPress();
19195
+ },
19196
+ onMouseDown: () => {
19197
+ setTouching(true);
19198
+ onPress();
19199
+ },
19200
+ onMouseUp: () => {
19201
+ setTouching(false);
19202
+ onRelease();
19203
+ },
19204
+ onTouchMove: () => {
19205
+ setTouching(false);
19206
+ onRelease();
19207
+ },
19208
+ onTouchEnd: (event) => {
19209
+ if (touching) {
19210
+ event.preventDefault();
19211
+ setTouching(false);
19212
+ onRelease();
19213
+ }
19214
+ }
19215
+ }
19216
+ }),
19217
+ [touching, onRelease, onPress]
19218
+ );
19219
+ };
19220
+
19221
+ // ../../packages/sigil/src/frontend/controls/utils.ts
19222
+ var clsControlPosition2 = (position) => {
19223
+ if (!position) return void 0;
19224
+ switch (position) {
19225
+ case "row":
19226
+ return "control-grid-pos-row";
19227
+ case "label":
19228
+ return "control-grid-pos-label";
19229
+ case "first":
19230
+ return "control-grid-pos-first";
19231
+ case "second":
19232
+ return "control-grid-pos-second";
19233
+ case "both":
19234
+ return "control-grid-pos-both";
19235
+ case "all":
19236
+ return "control-grid-pos-all";
19237
+ case "extra":
19238
+ return "control-grid-pos-extra";
19239
+ }
19240
+ };
19241
+ var clsControlSubgridPosition2 = (position, subgrid) => {
19242
+ if (!subgrid) return void 0;
19243
+ switch (position) {
19244
+ case "label":
19245
+ return "col-[1/span_1]";
19246
+ case "first":
19247
+ return "col-[2/span_1]";
19248
+ case "second":
19249
+ return "col-[3/span_1]";
19250
+ }
19251
+ };
19252
+
19253
+ // ../../packages/sigil/src/frontend/controls/buttons.tsx
19254
+ import { jsx as jsx45, jsxs as jsxs24 } from "react/jsx-runtime";
19255
+ var clsControlButton2 = ({
19256
+ variant,
19257
+ active,
19258
+ touching,
19259
+ position,
19260
+ className,
19261
+ primary,
19262
+ destructive
19263
+ }) => cn(
19264
+ `sigil-control-button`,
19265
+ cnd2(variant === "border", `sigil-control-button-variant-border`),
19266
+ cnd2(variant === "large", `sigil-control-button-variant-large`),
19267
+ cnd2(variant === "properties", `sigil-control-button-variant-properties`),
19268
+ cnd2(variant === "table-row", `sigil-control-button-variant-table-row`),
19269
+ cnd2(variant === "toolbar", `sigil-control-button-variant-toolbar`),
19270
+ cnd2(variant === "titlebar", `sigil-control-button-variant-titlebar`),
19271
+ cnd2(touching, `sigil-control-button-touching`),
19272
+ cnd2(active, `sigil-control-button-active`),
19273
+ cnd2(touching && active, `sigil-control-button-active-touching`),
19274
+ cnd2(primary, `sigil-control-button-primary`),
19275
+ cnd2(destructive, `sigil-control-button-destructive`),
19276
+ clsControlPosition2(position),
19277
+ className
19278
+ );
19279
+ var ControlButtonFrame2 = forwardRef17(
19280
+ ({
19281
+ children,
19282
+ className,
19283
+ type,
19284
+ variant = "toolbar",
19285
+ icon,
19286
+ active,
19287
+ touching,
19288
+ disabled,
19289
+ title,
19290
+ tooltipSide,
19291
+ position,
19292
+ primary,
19293
+ destructive,
19294
+ ...props
19295
+ }, ref) => {
19296
+ const btn = /* @__PURE__ */ jsx45(
19297
+ "button",
19298
+ {
19299
+ ...props,
19300
+ ref,
19301
+ type: type ?? "button",
19302
+ disabled,
19303
+ className: clsControlButton2({
19304
+ variant,
19305
+ active,
19306
+ touching,
19307
+ position,
19308
+ primary,
19309
+ destructive,
19310
+ className
19311
+ }),
19312
+ children: /* @__PURE__ */ jsxs24("span", { children: [
19313
+ icon && /* @__PURE__ */ jsx45(
19314
+ Icon2,
19315
+ {
19316
+ icon,
19317
+ className: cn(cnd2(children, "text-[120%]", "text-[150%]"))
19318
+ }
19319
+ ),
19320
+ children
19321
+ ] })
19322
+ }
19323
+ );
19324
+ if (!title) return btn;
19325
+ return /* @__PURE__ */ jsx45(TooltipWrapper2, { tooltip: title, side: tooltipSide, children: btn });
19326
+ }
19327
+ );
19328
+ ControlButtonFrame2.displayName = "ControlButtonFrame";
19329
+ var ControlButton2 = forwardRef17(
19330
+ ({ onClick, disabled, ...props }, ref) => {
19331
+ const { handlers, touching } = usePressable3(onClick);
19332
+ return /* @__PURE__ */ jsx45(
19333
+ ControlButtonFrame2,
19334
+ {
19335
+ ...props,
19336
+ ref,
19337
+ disabled,
19338
+ touching,
19339
+ ...!disabled ? handlers : {}
19340
+ }
19341
+ );
19342
+ }
19343
+ );
19344
+ ControlButton2.displayName = "ControlButton";
19345
+ var CheckboxControlButton2 = forwardRef17(({ active, label, ...props }, ref) => /* @__PURE__ */ jsxs24(ControlButton2, { ...props, ref, active, children: [
19346
+ /* @__PURE__ */ jsx45(Icon2, { icon: active ? "check_box" : "check_box_outline_blank" }),
19347
+ label
19348
+ ] }));
19349
+ CheckboxControlButton2.displayName = "CheckboxControlButton";
19350
+ var LongPressableControlButton2 = forwardRef17(({ active, disabled, onPress, onRelease, ...props }, ref) => {
19351
+ const { handlers, touching } = useLongPressable3({ onPress, onRelease });
19352
+ return /* @__PURE__ */ jsx45(
19353
+ ControlButtonFrame2,
19354
+ {
19355
+ ...props,
19356
+ ref,
19357
+ active: active || touching,
19358
+ disabled,
19359
+ ...!disabled ? handlers : {}
19360
+ }
19361
+ );
19362
+ });
19363
+ LongPressableControlButton2.displayName = "LongPressableControlButton";
19364
+ var ControlButtonGroup2 = forwardRef17(({ children, className, position, ...props }, ref) => /* @__PURE__ */ jsx45(
19365
+ "div",
19366
+ {
19367
+ ...props,
19368
+ ref,
19369
+ className: cn(
19370
+ `
19371
+ flex items-stretch gap-sigil-control-gap
19372
+ [&>button]:grow
19373
+ `,
19374
+ clsControlPosition2(position),
19375
+ className
19376
+ ),
19377
+ children
19378
+ }
19379
+ ));
19380
+ ControlButtonGroup2.displayName = "ControlButtonGroup";
19381
+
19382
+ // ../../packages/sigil/src/frontend/controls/content.tsx
19383
+ import { forwardRef as forwardRef18 } from "react";
19384
+ import { jsx as jsx46 } from "react/jsx-runtime";
19385
+ var ControlParagraph2 = forwardRef18(({ className, mode, position = "all", ...props }, ref) => /* @__PURE__ */ jsx46(
19386
+ "p",
19387
+ {
19388
+ ...props,
19389
+ ref,
19390
+ className: cn(
19391
+ "border border-transparent",
19392
+ clsControlPosition2(position),
19393
+ cnd2(
19394
+ mode === "success",
19395
+ `
19396
+ border-sigil-usage-green-dimmed-border
19397
+ bg-sigil-usage-green-dimmed-background p-1 text-sigil-usage-green-text
19398
+ `
19399
+ ),
19400
+ cnd2(
19401
+ mode === "warning",
19402
+ `
19403
+ border-sigil-usage-yellow-dimmed-border
19404
+ bg-sigil-usage-yellow-dimmed-background p-1
19405
+ text-sigil-usage-yellow-text
19406
+ `
19407
+ ),
19408
+ cnd2(
19409
+ mode === "error",
19410
+ `
19411
+ border-sigil-usage-red-dimmed-border
19412
+ bg-sigil-usage-red-dimmed-background p-1 text-sigil-usage-red-text
19413
+ `
19414
+ ),
19415
+ className
19416
+ )
19417
+ }
19418
+ ));
19419
+ ControlParagraph2.displayName = "ControlParagraph";
19420
+ var ControlLabel2 = forwardRef18(
19421
+ ({ className, disabled, nonMicro, position = "label", subgrid, ...props }, ref) => {
19422
+ return /* @__PURE__ */ jsx46(
19423
+ "label",
19424
+ {
19425
+ ...props,
19426
+ ref,
19427
+ className: cn(
19428
+ "flex items-center justify-end gap-0.6 p-0.6",
19429
+ clsControlPosition2(position),
19430
+ cnd2(nonMicro, "max-[550px]:hidden"),
19431
+ cnd2(disabled, "opacity-50"),
19432
+ clsControlSubgridPosition2(position, subgrid),
19433
+ className
19434
+ )
19435
+ }
19436
+ );
19437
+ }
19438
+ );
19439
+ ControlLabel2.displayName = "ControlLabel";
19440
+ var ControlDetails2 = forwardRef18(
19441
+ ({ align, className, position = "all", ...props }, ref) => /* @__PURE__ */ jsx46(
19442
+ "div",
19443
+ {
19444
+ ...props,
19445
+ ref,
19446
+ className: cn(
19447
+ "flex items-center px-0.3 text-sigil-foreground-muted",
19448
+ clsControlPosition2(position),
19449
+ cnd2(align === "start", "justify-start"),
19450
+ cnd2(align === "center", "justify-center"),
19451
+ cnd2(align === "end", "justify-end"),
19452
+ className
19453
+ )
19454
+ }
19455
+ )
19456
+ );
19457
+ ControlDetails2.displayName = "ControlDetails";
19458
+ var InputSpanningTitle2 = forwardRef18(({ className, position = "row", ...props }, ref) => /* @__PURE__ */ jsx46(
19459
+ "div",
19460
+ {
19461
+ ...props,
19462
+ ref,
19463
+ className: cn(
19464
+ "truncate p-0.6 text-center text-[0.8rem] font-bold",
19465
+ clsControlPosition2(position),
19466
+ className
19467
+ )
19468
+ }
19469
+ ));
19470
+ InputSpanningTitle2.displayName = "InputSpanningTitle";
19471
+
19472
+ // ../../packages/sigil/src/frontend/controls/input.tsx
19473
+ import {
19474
+ useCallback as useCallback21,
19475
+ useEffect as useEffect32,
19476
+ useRef as useRef18
19477
+ } from "react";
19478
+ import { jsx as jsx47 } from "react/jsx-runtime";
19479
+
19480
+ // ../../packages/sigil/src/frontend/controls/select.tsx
19481
+ import { useCallback as useCallback23 } from "react";
19482
+ import { Fragment as Fragment16, jsx as jsx48, jsxs as jsxs25 } from "react/jsx-runtime";
19483
+ var COLOR_OPTIONS2 = {
19484
+ red: { label: "Red", value: "red", color: "red" },
19485
+ blue: { label: "Blue", value: "blue", color: "blue" },
19486
+ teal: { label: "Teal", value: "teal", color: "teal" },
19487
+ green: { label: "Green", value: "green", color: "green" },
19488
+ yellow: { label: "Yellow", value: "yellow", color: "yellow" },
19489
+ purple: { label: "Purple", value: "purple", color: "purple" },
19490
+ orange: { label: "Orange", value: "orange", color: "orange" },
19491
+ brown: { label: "Brown", value: "brown", color: "brown" },
19492
+ gray: { label: "Gray", value: "gray", color: "gray" }
19493
+ };
19494
+ var COLOR_OPTIONS_ARRAY2 = Object.values(COLOR_OPTIONS2);
19495
+
19496
+ // ../../packages/sigil/src/frontend/dialogs.tsx
19497
+ import { Fragment as Fragment17, jsx as jsx49, jsxs as jsxs26 } from "react/jsx-runtime";
19498
+ var isDarkDialog2 = (variant) => variant === "dark" || variant === "dark-compact";
19499
+ var DialogContext2 = createContext11({
19500
+ createDialog: () => {
19501
+ throw new Error("DialogContext not provided");
19502
+ },
19503
+ displayMessage: () => {
19504
+ throw new Error("DialogContext not provided");
19505
+ },
19506
+ displayError: () => {
19507
+ throw new Error("DialogContext not provided");
19508
+ }
19509
+ });
19510
+ var DialogTitle2 = forwardRef19(
19511
+ ({ className, variant = "light", ...props }, ref) => /* @__PURE__ */ jsx49(
19512
+ "div",
19513
+ {
19514
+ ...props,
19515
+ ref,
19516
+ className: cn(
19517
+ `
19518
+ flex items-center justify-center gap-0.6 border-b border-sigil-border
19519
+ p-arcane font-bold
19520
+ `,
19521
+ cnd2(isDarkDialog2(variant), "bg-sigil-bg-light", "bg-sigil-bg-dark"),
19522
+ className
19523
+ )
19524
+ }
19525
+ )
19526
+ );
19527
+ DialogTitle2.displayName = "DialogTitle";
19528
+ var DialogButtons2 = forwardRef19(({ className, ...props }, ref) => /* @__PURE__ */ jsx49(
19529
+ "div",
19530
+ {
19531
+ ...props,
19532
+ ref,
19533
+ className: cn("mt-arcane flex justify-end gap-0.6", className)
19534
+ }
19535
+ ));
19536
+ DialogButtons2.displayName = "DialogButtons";
19537
+ var Dialog2 = ({
19538
+ children,
19539
+ dialogClosed,
19540
+ closable = true,
19541
+ title,
19542
+ variant = "light"
19543
+ }) => {
19544
+ const [dialogRef, setDialogRef] = useState35(null);
19545
+ useEffect33(() => {
19546
+ if (!dialogRef) return;
19547
+ dialogRef.showModal();
19548
+ }, [dialogRef]);
19549
+ const close = () => dialogRef?.close();
19550
+ const onClose = (event) => {
19551
+ if (closable) {
19552
+ dialogClosed();
19553
+ return;
19554
+ }
19555
+ event.preventDefault();
19556
+ event.currentTarget.showModal();
19557
+ };
19558
+ const onMouseDown = (event) => {
19559
+ if (event.target === event.currentTarget) {
19560
+ close();
19561
+ }
19562
+ };
19563
+ return /* @__PURE__ */ jsx49(
19564
+ "dialog",
19565
+ {
19566
+ ref: setDialogRef,
19567
+ onMouseDown,
19568
+ onClose,
19569
+ className: cn(
19570
+ `
19571
+ max-w-[80vw] min-w-[10vw] border-none p-0 text-sigil-dialog-foreground
19572
+ outline-none backdrop-sigil-dialog
19573
+ `,
19574
+ cnd2(isDarkDialog2(variant), "bg-sigil-bg-dark", "bg-sigil-bg-light")
19575
+ ),
19576
+ children: /* @__PURE__ */ jsxs26("div", { className: "border border-sigil-border", children: [
19577
+ title && /* @__PURE__ */ jsx49(DialogTitle2, { variant, children: title }),
19578
+ /* @__PURE__ */ jsx49(
19579
+ "div",
19580
+ {
19581
+ className: cn(
19582
+ "text-sigil-foreground",
19583
+ cnd2(
19584
+ variant === "light-compact" || variant === "dark-compact",
19585
+ "p-0"
19586
+ ),
19587
+ cnd2(
19588
+ variant !== "light-compact" && variant !== "dark-compact",
19589
+ "p-arcane"
19590
+ )
19591
+ ),
19592
+ children
19593
+ }
19594
+ )
19595
+ ] })
19596
+ }
19597
+ );
19598
+ };
19599
+
19600
+ // ../../packages/sigil/src/frontend/controls/dialogs.tsx
19601
+ import { jsx as jsx50 } from "react/jsx-runtime";
19602
+ var ControlDialogButtons2 = forwardRef20(({ children, className, ...props }, ref) => /* @__PURE__ */ jsx50(
19603
+ "div",
19604
+ {
19605
+ ref,
19606
+ className: cn(
19607
+ `
19608
+ flex items-stretch gap-1
19609
+ [&>button]:grow
19610
+ `,
19611
+ clsControlPosition2("row"),
19612
+ className
19613
+ ),
19614
+ ...props,
19615
+ children
19616
+ }
19617
+ ));
19618
+ var ControlDialog2 = ({
19619
+ children,
19620
+ large,
19621
+ ...props
19622
+ }) => /* @__PURE__ */ jsx50(Dialog2, { ...props, variant: "dark", children: /* @__PURE__ */ jsx50(
19623
+ "div",
19624
+ {
19625
+ className: cn(
19626
+ "gap-1 bg-sigil-bg-dark select-none",
19627
+ cnd2(large, "control-grid-large", "control-grid")
19628
+ ),
19629
+ children
19630
+ }
19631
+ ) });
19632
+
19633
+ // src/components/frontend/toolbox/root.tsx
19634
+ import { Fragment as Fragment18, jsx as jsx51, jsxs as jsxs27 } from "react/jsx-runtime";
19635
+ var DeleteConfirmationDialog = ({ dialogMode, setDialogMode }) => {
19636
+ const { updateConfig } = useContext17(ConfigContext);
19637
+ const deleteTarget = useCallback24(() => {
19638
+ updateConfig((current) => {
19639
+ return {
19640
+ ...current,
19641
+ [dialogMode.section.type]: Object.fromEntries(
19642
+ Object.entries(current[dialogMode.section.type]).filter(
19643
+ ([uuid]) => uuid !== dialogMode.target.uuid
19644
+ )
19645
+ )
19646
+ };
19647
+ });
19648
+ setDialogMode(null);
19649
+ }, [updateConfig, dialogMode, setDialogMode]);
19650
+ return /* @__PURE__ */ jsxs27(
19651
+ ControlDialog2,
19652
+ {
19653
+ dialogClosed: () => setDialogMode(null),
19654
+ title: STRINGS[dialogMode.section.type].deleteDialog,
19655
+ children: [
19656
+ /* @__PURE__ */ jsx51(ControlDetails, { position: "row", children: STRINGS[dialogMode.section.type].deleteDialogDetails }),
19657
+ /* @__PURE__ */ jsxs27(ControlDialogButtons2, { children: [
19658
+ /* @__PURE__ */ jsx51(ControlButton, { onClick: () => setDialogMode(null), variant: "large", children: "Cancel" }),
19659
+ /* @__PURE__ */ jsx51(
19660
+ ControlButton,
19661
+ {
19662
+ onClick: deleteTarget,
19663
+ variant: "large",
19664
+ destructive: true,
19665
+ icon: "delete",
19666
+ children: "Delete"
19667
+ }
19668
+ )
19669
+ ] })
19670
+ ]
19671
+ }
19672
+ );
19673
+ };
19674
+ var ToolboxRoot = ({ info }) => {
19675
+ const { config } = info;
19676
+ const { sendMessage, call } = useContext17(StageContext);
19677
+ const [dialogMode, setDialogMode] = useState36(null);
19678
+ const [assignToOutput, setAssignToOutput] = useState36(null);
19679
+ useEffect34(() => {
19680
+ if (assignToOutput) {
19681
+ const onEscape = (e) => {
19682
+ if (e.key === "Escape") {
19683
+ setAssignToOutput(null);
19684
+ }
19685
+ };
19686
+ window.addEventListener("keydown", onEscape);
19687
+ return () => {
19688
+ window.removeEventListener("keydown", onEscape);
19689
+ };
19690
+ }
19691
+ }, [assignToOutput]);
19692
+ const updateConfig = useCallback24(
19693
+ (change) => {
19694
+ const diff = diffJson(config, change(config));
19695
+ sendMessage?.({
19696
+ type: "component-message",
19697
+ namespace: "timecode-toolbox",
19698
+ component: "toolbox-root",
19699
+ componentKey: info.key,
19700
+ action: "update-config",
19701
+ diff
19702
+ });
19703
+ },
19704
+ [sendMessage, info.key, config]
19705
+ );
19706
+ const configContext = useMemo17(
19707
+ () => ({
19708
+ config,
19709
+ network: info.network,
19710
+ updateConfig
19711
+ }),
19712
+ [config, info.network, updateConfig]
19713
+ );
19714
+ const getNetworkInterfaces = useCallback24(async () => {
19715
+ if (!call) {
19716
+ throw new Error("No call function available");
19717
+ }
18798
19718
  return call({
18799
19719
  namespace: "timecode-toolbox",
18800
19720
  type: "component-call",
@@ -18802,12 +19722,12 @@ var ToolboxRoot = ({ info }) => {
18802
19722
  action: "toolbox-root-get-network-interfaces"
18803
19723
  });
18804
19724
  }, [call, info.key]);
18805
- const networkContextValue = useMemo15(() => {
19725
+ const networkContextValue = useMemo17(() => {
18806
19726
  return {
18807
19727
  getNetworkInterfaces
18808
19728
  };
18809
19729
  }, [getNetworkInterfaces]);
18810
- const assignToOutputCallback = useMemo15(() => {
19730
+ const assignToOutputCallback = useMemo17(() => {
18811
19731
  if (!assignToOutput) {
18812
19732
  return null;
18813
19733
  }
@@ -18832,7 +19752,7 @@ var ToolboxRoot = ({ info }) => {
18832
19752
  setAssignToOutput(null);
18833
19753
  };
18834
19754
  }, [assignToOutput, updateConfig]);
18835
- const callHandler = useCallback20(
19755
+ const callHandler = useCallback24(
18836
19756
  async ({ path, handler, args }) => {
18837
19757
  if (!call) {
18838
19758
  throw new Error("No call function available");
@@ -18849,26 +19769,26 @@ var ToolboxRoot = ({ info }) => {
18849
19769
  },
18850
19770
  [call, info.key]
18851
19771
  );
18852
- const handlers = useMemo15(
19772
+ const handlers = useMemo17(
18853
19773
  () => ({
18854
19774
  handlers: info.handlers,
18855
19775
  callHandler
18856
19776
  }),
18857
19777
  [info.handlers, callHandler]
18858
19778
  );
18859
- const windowedTimecodeId = useMemo15(
19779
+ const windowedTimecodeId = useMemo17(
18860
19780
  () => getFragmentValue("tc", TIMECODE_INSTANCE_ID),
18861
19781
  []
18862
19782
  );
18863
- const root = useMemo15(
18864
- () => windowedTimecodeId ? /* @__PURE__ */ jsx41(Layout, { modes: null, children: /* @__PURE__ */ jsx41(FullscreenTimecodeDisplay, { id: windowedTimecodeId }) }) : /* @__PURE__ */ jsxs21(Fragment14, { children: [
18865
- /* @__PURE__ */ jsx41(
19783
+ const root = useMemo17(
19784
+ () => windowedTimecodeId ? /* @__PURE__ */ jsx51(Layout, { modes: null, children: /* @__PURE__ */ jsx51(FullscreenTimecodeDisplay, { id: windowedTimecodeId }) }) : /* @__PURE__ */ jsxs27(Fragment18, { children: [
19785
+ /* @__PURE__ */ jsx51(
18866
19786
  Layout,
18867
19787
  {
18868
19788
  footer: true,
18869
19789
  modes: {
18870
19790
  license: {
18871
- child: (setWindowMode) => /* @__PURE__ */ jsx41(
19791
+ child: (setWindowMode) => /* @__PURE__ */ jsx51(
18872
19792
  License,
18873
19793
  {
18874
19794
  license: info.license,
@@ -18879,39 +19799,39 @@ var ToolboxRoot = ({ info }) => {
18879
19799
  title: STRINGS.license
18880
19800
  },
18881
19801
  settings: {
18882
- child: (setWindowMode) => /* @__PURE__ */ jsx41(Settings, { setWindowMode }),
19802
+ child: (setWindowMode) => /* @__PURE__ */ jsx51(Settings, { setWindowMode }),
18883
19803
  icon: "settings",
18884
19804
  title: STRINGS.settings.title
18885
19805
  },
18886
19806
  debug: {
18887
- child: () => /* @__PURE__ */ jsx41(Debugger, { title: STRINGS.debugger, className: "size-full" }),
19807
+ child: () => /* @__PURE__ */ jsx51(Debugger, { title: STRINGS.debugger, className: "size-full" }),
18888
19808
  icon: "bug_report",
18889
19809
  title: STRINGS.debugger
18890
19810
  }
18891
19811
  },
18892
19812
  licenseMode: "license",
18893
- children: /* @__PURE__ */ jsxs21(Fragment14, { children: [
18894
- /* @__PURE__ */ jsx41(UpdateBanner, {}),
18895
- /* @__PURE__ */ jsxs21(
19813
+ children: /* @__PURE__ */ jsxs27(Fragment18, { children: [
19814
+ /* @__PURE__ */ jsx51(UpdateBanner, {}),
19815
+ /* @__PURE__ */ jsxs27(
18896
19816
  "div",
18897
19817
  {
18898
19818
  className: "\n flex h-0 grow flex-col gap-px overflow-y-auto bg-sigil-border\n scrollbar-sigil\n ",
18899
19819
  children: [
18900
- /* @__PURE__ */ jsx41(
19820
+ /* @__PURE__ */ jsx51(
18901
19821
  InputsSection,
18902
19822
  {
18903
19823
  setDialogMode,
18904
19824
  assignToOutput: assignToOutputCallback
18905
19825
  }
18906
19826
  ),
18907
- /* @__PURE__ */ jsx41(
19827
+ /* @__PURE__ */ jsx51(
18908
19828
  GeneratorsSection,
18909
19829
  {
18910
19830
  setDialogMode,
18911
19831
  assignToOutput: assignToOutputCallback
18912
19832
  }
18913
19833
  ),
18914
- /* @__PURE__ */ jsx41(
19834
+ /* @__PURE__ */ jsx51(
18915
19835
  OutputsSection,
18916
19836
  {
18917
19837
  setDialogMode,
@@ -18925,45 +19845,52 @@ var ToolboxRoot = ({ info }) => {
18925
19845
  ] })
18926
19846
  }
18927
19847
  ),
18928
- dialogMode?.section.type === "inputs" && /* @__PURE__ */ jsx41(
18929
- InputSettingsDialog,
18930
- {
18931
- close: closeDialog,
18932
- input: dialogMode.section.input,
18933
- target: dialogMode.target
18934
- }
18935
- ),
18936
- dialogMode?.section.type === "generators" && /* @__PURE__ */ jsx41(
18937
- GeneratorSettingsDialog,
18938
- {
18939
- close: closeDialog,
18940
- generator: dialogMode.section.generator,
18941
- target: dialogMode.target
18942
- }
18943
- ),
18944
- dialogMode?.section.type === "outputs" && /* @__PURE__ */ jsx41(
18945
- OutputSettingsDialog,
19848
+ isDeleteDialogMode(dialogMode) ? /* @__PURE__ */ jsx51(
19849
+ DeleteConfirmationDialog,
18946
19850
  {
18947
- close: closeDialog,
18948
- output: dialogMode.section.output,
18949
- target: dialogMode.target
19851
+ dialogMode,
19852
+ setDialogMode
18950
19853
  }
18951
- )
19854
+ ) : /* @__PURE__ */ jsxs27(Fragment18, { children: [
19855
+ dialogMode?.section.type === "inputs" && /* @__PURE__ */ jsx51(
19856
+ InputSettingsDialog,
19857
+ {
19858
+ setDialogMode,
19859
+ input: dialogMode.section.input,
19860
+ target: dialogMode.target
19861
+ }
19862
+ ),
19863
+ dialogMode?.section.type === "generators" && /* @__PURE__ */ jsx51(
19864
+ GeneratorSettingsDialog,
19865
+ {
19866
+ setDialogMode,
19867
+ generator: dialogMode.section.generator,
19868
+ target: dialogMode.target
19869
+ }
19870
+ ),
19871
+ dialogMode?.section.type === "outputs" && /* @__PURE__ */ jsx51(
19872
+ OutputSettingsDialog,
19873
+ {
19874
+ setDialogMode,
19875
+ output: dialogMode.section.output,
19876
+ target: dialogMode.target
19877
+ }
19878
+ )
19879
+ ] })
18952
19880
  ] }),
18953
19881
  [
18954
19882
  assignToOutput,
18955
19883
  assignToOutputCallback,
18956
- closeDialog,
18957
19884
  dialogMode,
18958
19885
  windowedTimecodeId,
18959
19886
  info.license
18960
19887
  ]
18961
19888
  );
18962
- return /* @__PURE__ */ jsx41(ConfigContext.Provider, { value: configContext, children: /* @__PURE__ */ jsx41(NetworkContext.Provider, { value: networkContextValue, children: /* @__PURE__ */ jsx41(ApplicationStateContext.Provider, { value: info.state, children: /* @__PURE__ */ jsx41(ApplicationHandlersContext.Provider, { value: handlers, children: root }) }) }) });
19889
+ return /* @__PURE__ */ jsx51(ConfigContext.Provider, { value: configContext, children: /* @__PURE__ */ jsx51(NetworkContext.Provider, { value: networkContextValue, children: /* @__PURE__ */ jsx51(ApplicationStateContext.Provider, { value: info.state, children: /* @__PURE__ */ jsx51(ApplicationHandlersContext.Provider, { value: handlers, children: root }) }) }) });
18963
19890
  };
18964
19891
 
18965
19892
  // src/components/frontend/index.tsx
18966
- import { jsx as jsx45 } from "react/jsx-runtime";
19893
+ import { jsx as jsx54 } from "react/jsx-runtime";
18967
19894
  var timecodeToolboxFrontendComponents = () => ({
18968
19895
  namespace: NAMESPACE,
18969
19896
  render: (info) => {
@@ -18972,9 +19899,9 @@ var timecodeToolboxFrontendComponents = () => ({
18972
19899
  }
18973
19900
  switch (info.component) {
18974
19901
  case "toolbox-root":
18975
- return /* @__PURE__ */ jsx45(ToolboxRoot, { info });
19902
+ return /* @__PURE__ */ jsx54(ToolboxRoot, { info });
18976
19903
  case "license-gate":
18977
- return /* @__PURE__ */ jsx45(LicenseGate, { info });
19904
+ return /* @__PURE__ */ jsx54(LicenseGate, { info });
18978
19905
  }
18979
19906
  }
18980
19907
  });
@@ -18982,10 +19909,11 @@ var startTimecodeToolboxServerFrontend = (browser) => {
18982
19909
  startSigilFrontend({
18983
19910
  browser,
18984
19911
  appRenderers: [timecodeToolboxFrontendComponents()],
18985
- loadingState: () => /* @__PURE__ */ jsx45("div", { style: { width: "100%", textAlign: "center", padding: "2rem" }, children: "Loading Toolbox..." })
19912
+ loadingState: () => /* @__PURE__ */ jsx54("div", { style: { width: "100%", textAlign: "center", padding: "2rem" }, children: "Loading Toolbox..." })
18986
19913
  });
18987
19914
  };
18988
19915
  window.startTimecodeToolboxServerFrontend = startTimecodeToolboxServerFrontend;
19916
+ window.createBrowserMediaSession = createBrowserMediaSession;
18989
19917
  export {
18990
19918
  startTimecodeToolboxServerFrontend,
18991
19919
  timecodeToolboxFrontendComponents