@arcanewizards/timecode-toolbox 0.1.3 → 0.1.5

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.
@@ -13963,7 +13963,7 @@ function cnd(condition, truthyClassName, falseyClassName) {
13963
13963
  return condition ? truthyClassName : falseyClassName;
13964
13964
  }
13965
13965
 
13966
- // ../../packages/sigil/dist/chunk-E3VUC3Q4.js
13966
+ // ../../packages/sigil/dist/chunk-LDUYBGRY.js
13967
13967
  var import_react11 = require("react");
13968
13968
 
13969
13969
  // ../../node_modules/.pnpm/@arcanejs+toolkit-frontend@0.11.0/node_modules/@arcanejs/toolkit-frontend/dist/chunk-DK4BAXVE.mjs
@@ -14002,7 +14002,7 @@ var TRANSPARENCY_SVG = `
14002
14002
  `;
14003
14003
  var TRANSPARENCY_SVG_URI = `data:image/svg+xml,${encodeURIComponent(TRANSPARENCY_SVG)}`;
14004
14004
 
14005
- // ../../packages/sigil/dist/chunk-E3VUC3Q4.js
14005
+ // ../../packages/sigil/dist/chunk-LDUYBGRY.js
14006
14006
  var import_react12 = require("react");
14007
14007
  var import_jsx_runtime18 = require("react/jsx-runtime");
14008
14008
  var import_react13 = require("react");
@@ -14069,7 +14069,8 @@ var clsControlButton = ({
14069
14069
  touching,
14070
14070
  position,
14071
14071
  className,
14072
- primary
14072
+ primary,
14073
+ destructive
14073
14074
  }) => cn(
14074
14075
  `sigil-control-button`,
14075
14076
  cnd(variant === "border", `sigil-control-button-variant-border`),
@@ -14082,6 +14083,7 @@ var clsControlButton = ({
14082
14083
  cnd(active, `sigil-control-button-active`),
14083
14084
  cnd(touching && active, `sigil-control-button-active-touching`),
14084
14085
  cnd(primary, `sigil-control-button-primary`),
14086
+ cnd(destructive, `sigil-control-button-destructive`),
14085
14087
  clsControlPosition(position),
14086
14088
  className
14087
14089
  );
@@ -14099,6 +14101,7 @@ var ControlButtonFrame = (0, import_react12.forwardRef)(
14099
14101
  tooltipSide,
14100
14102
  position,
14101
14103
  primary,
14104
+ destructive,
14102
14105
  ...props
14103
14106
  }, ref) => {
14104
14107
  const btn = /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
@@ -14114,6 +14117,7 @@ var ControlButtonFrame = (0, import_react12.forwardRef)(
14114
14117
  touching,
14115
14118
  position,
14116
14119
  primary,
14120
+ destructive,
14117
14121
  className
14118
14122
  }),
14119
14123
  children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
@@ -14223,7 +14227,7 @@ ControlParagraph.displayName = "ControlParagraph";
14223
14227
  var ControlLabel = (0, import_react13.forwardRef)(
14224
14228
  ({ className, disabled, nonMicro, position = "label", subgrid, ...props }, ref) => {
14225
14229
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
14226
- "div",
14230
+ "label",
14227
14231
  {
14228
14232
  ...props,
14229
14233
  ref,
@@ -14272,10 +14276,17 @@ var InputSpanningTitle = (0, import_react13.forwardRef)(({ className, position =
14272
14276
  ));
14273
14277
  InputSpanningTitle.displayName = "InputSpanningTitle";
14274
14278
  var ControlDialogButtons = (0, import_react14.forwardRef)(({ children, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
14275
- ControlButtonGroup,
14279
+ "div",
14276
14280
  {
14277
14281
  ref,
14278
- className: cn("control-grid-pos-row", className),
14282
+ className: cn(
14283
+ `
14284
+ flex items-stretch gap-1
14285
+ [&>button]:grow
14286
+ `,
14287
+ clsControlPosition("row"),
14288
+ className
14289
+ ),
14279
14290
  ...props,
14280
14291
  children
14281
14292
  }
@@ -14458,19 +14469,9 @@ var ControlSelect = ({
14458
14469
  }
14459
14470
  );
14460
14471
  };
14461
- var COLOR_OPTIONS = {
14462
- red: { label: "Red", value: "red" },
14463
- blue: { label: "Blue", value: "blue" },
14464
- teal: { label: "Teal", value: "teal" },
14465
- green: { label: "Green", value: "green" },
14466
- yellow: { label: "Yellow", value: "yellow" },
14467
- purple: { label: "Purple", value: "purple" },
14468
- orange: { label: "Orange", value: "orange" },
14469
- brown: { label: "Brown", value: "brown" },
14470
- gray: { label: "Gray", value: "gray" }
14471
- };
14472
- var ControlColorSelect = ({
14473
- color,
14472
+ var ControlColoredSelect = ({
14473
+ options,
14474
+ value,
14474
14475
  onChange,
14475
14476
  variant,
14476
14477
  position,
@@ -14478,13 +14479,13 @@ var ControlColorSelect = ({
14478
14479
  placeholder,
14479
14480
  ...props
14480
14481
  }) => {
14481
- const options = Object.values(COLOR_OPTIONS);
14482
- const selectedColor = sigilColorUsage(color || "gray");
14482
+ const selectedOption = options.find((option) => option.value === value);
14483
+ const selectedColor = sigilColorUsage(selectedOption?.color ?? "gray");
14483
14484
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
14484
14485
  ControlSelect,
14485
14486
  {
14486
14487
  options,
14487
- value: color,
14488
+ value,
14488
14489
  onChange,
14489
14490
  triggerButton: (option) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
14490
14491
  dist_exports2.Trigger,
@@ -14538,7 +14539,7 @@ var ControlColorSelect = ({
14538
14539
  {
14539
14540
  className: "",
14540
14541
  style: {
14541
- color: `var(--sigil-usage-${option.value}-foreground)`
14542
+ color: `var(--sigil-usage-${option.color}-foreground)`
14542
14543
  },
14543
14544
  children: option.label
14544
14545
  }
@@ -14550,6 +14551,31 @@ var ControlColorSelect = ({
14550
14551
  }
14551
14552
  );
14552
14553
  };
14554
+ var COLOR_OPTIONS = {
14555
+ red: { label: "Red", value: "red", color: "red" },
14556
+ blue: { label: "Blue", value: "blue", color: "blue" },
14557
+ teal: { label: "Teal", value: "teal", color: "teal" },
14558
+ green: { label: "Green", value: "green", color: "green" },
14559
+ yellow: { label: "Yellow", value: "yellow", color: "yellow" },
14560
+ purple: { label: "Purple", value: "purple", color: "purple" },
14561
+ orange: { label: "Orange", value: "orange", color: "orange" },
14562
+ brown: { label: "Brown", value: "brown", color: "brown" },
14563
+ gray: { label: "Gray", value: "gray", color: "gray" }
14564
+ };
14565
+ var COLOR_OPTIONS_ARRAY = Object.values(COLOR_OPTIONS);
14566
+ var ControlColorSelect = ({
14567
+ color,
14568
+ ...props
14569
+ }) => {
14570
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
14571
+ ControlColoredSelect,
14572
+ {
14573
+ options: COLOR_OPTIONS_ARRAY,
14574
+ value: color,
14575
+ ...props
14576
+ }
14577
+ );
14578
+ };
14553
14579
  var isDarkDialog = (variant) => variant === "dark" || variant === "dark-compact";
14554
14580
  var DialogContext = (0, import_react11.createContext)({
14555
14581
  createDialog: () => {
@@ -15582,6 +15608,7 @@ var createBrowserMediaSession = () => {
15582
15608
  };
15583
15609
  var createDefaultBrowserContext = (browser) => {
15584
15610
  const defaults = {
15611
+ appListenerChangesHandledExternally: false,
15585
15612
  openExternalLink: (url) => {
15586
15613
  window.open(url, "_blank", "noopener,noreferrer");
15587
15614
  },
@@ -15803,6 +15830,30 @@ var startSigilFrontend = ({
15803
15830
  return resolvedBrowser;
15804
15831
  };
15805
15832
 
15833
+ // ../../packages/sigil/dist/shared/config.js
15834
+ var APP_LISTENER_CONFIG = zod_default.object({
15835
+ port: zod_default.union([
15836
+ zod_default.number().int().min(1).max(65535),
15837
+ zod_default.object({
15838
+ from: zod_default.number().int().min(1).max(65535),
15839
+ to: zod_default.number().int().min(1).max(65535)
15840
+ }).refine((data) => data.to >= data.from, {
15841
+ message: '"to" must be greater than or equal to "from"'
15842
+ })
15843
+ ]),
15844
+ interface: zod_default.string().optional()
15845
+ });
15846
+ var ALL_APP_LISTENER_CONFIG = zod_default.record(
15847
+ zod_default.string(),
15848
+ APP_LISTENER_CONFIG
15849
+ );
15850
+ var portString = (port) => {
15851
+ if (typeof port === "number") {
15852
+ return port.toString();
15853
+ }
15854
+ return `${port.from}-${port.to}`;
15855
+ };
15856
+
15806
15857
  // src/components/proto.ts
15807
15858
  var NET_UTILS_GENERAL_TARGET_DEFINITION = zod_default.union([
15808
15859
  zod_default.object({
@@ -15880,6 +15931,7 @@ var OUTPUT_CONFIG = zod_default.object({
15880
15931
  link: INPUT_OR_GENERATOR_INSTANCE_ID.nullable()
15881
15932
  });
15882
15933
  var TOOLBOX_CONFIG = zod_default.object({
15934
+ appListener: APP_LISTENER_CONFIG.partial().optional(),
15883
15935
  inputs: zod_default.record(zod_default.string(), INPUT_CONFIG),
15884
15936
  generators: zod_default.record(zod_default.string(), GENERATOR_CONFIG),
15885
15937
  outputs: zod_default.record(zod_default.string(), OUTPUT_CONFIG),
@@ -15895,7 +15947,7 @@ var NAMESPACE = "timecode-toolbox";
15895
15947
  var isTimecodeToolboxComponent = (component) => component.namespace === NAMESPACE;
15896
15948
 
15897
15949
  // src/components/frontend/toolbox/root.tsx
15898
- var import_react42 = require("react");
15950
+ var import_react50 = require("react");
15899
15951
 
15900
15952
  // ../../packages/artnet/dist/chunk-J2HDMITA.js
15901
15953
  var ARTNET_PORT = 6454;
@@ -15937,10 +15989,16 @@ var STRINGS = {
15937
15989
  },
15938
15990
  inputs: {
15939
15991
  title: "INPUTS",
15992
+ unnamed: "Unnamed Input",
15993
+ enable: "Enable Input",
15994
+ disable: "Disable Input",
15995
+ edit: "Edit Input",
15940
15996
  noChildren: "No inputs yet. Please add one using the buttons below.",
15941
15997
  addButton: (protocol) => `Add ${protocol}`,
15942
15998
  addDialog: (protocol) => `Add ${protocol} Input`,
15943
- editDialog: (protocol, name) => `Edit ${protocol} Input ${name}`
15999
+ editDialog: (protocol, name) => `Edit ${protocol} Input ${name}`,
16000
+ deleteDialog: `Delete input?`,
16001
+ deleteDialogDetails: `Are you sure you want to delete this input? This action cannot be undone.`
15944
16002
  },
15945
16003
  smtpeModes: {
15946
16004
  SMPTE: `SMPTE ${TIMECODE_FPS.SMPTE}FPS`,
@@ -15958,22 +16016,49 @@ var STRINGS = {
15958
16016
  delay: (delayMs) => `Delay: ${MS_FORMAT.format(delayMs)}`,
15959
16017
  generators: {
15960
16018
  title: "GENERATORS",
16019
+ unnamed: "Unnamed Generator",
16020
+ edit: "Edit Generator",
15961
16021
  noChildren: "No generators yet. Please add one using the buttons below.",
15962
16022
  type: {
15963
16023
  clock: "Clock"
15964
16024
  },
15965
16025
  addDialog: (protocol) => `Add ${protocol} Generator`,
15966
- editDialog: (protocol, name) => `Edit ${protocol} Generator ${name}`
16026
+ editDialog: (protocol, name) => `Edit ${protocol} Generator ${name}`,
16027
+ deleteDialog: `Delete generator?`,
16028
+ deleteDialogDetails: `Are you sure you want to delete this generator? This action cannot be undone.`
15967
16029
  },
15968
16030
  outputs: {
15969
16031
  title: "OUTPUTS",
16032
+ unnamed: "Unnamed Output",
16033
+ enable: "Enable Output",
16034
+ disable: "Disable Output",
16035
+ link: "Link Output",
16036
+ edit: "Edit Output",
15970
16037
  noChildren: "No outputs yet. Please add one using the buttons below.",
15971
16038
  addButton: (protocol) => `Add ${protocol}`,
15972
16039
  addDialog: (protocol) => `Add ${protocol} Output`,
15973
- editDialog: (protocol, name) => `Edit ${protocol} Output ${name}`
16040
+ editDialog: (protocol, name) => `Edit ${protocol} Output ${name}`,
16041
+ deleteDialog: `Delete output?`,
16042
+ deleteDialogDetails: `Are you sure you want to delete this output? This action cannot be undone.`
15974
16043
  },
15975
16044
  settings: {
15976
- title: "Settings"
16045
+ title: "Settings",
16046
+ network: {
16047
+ appPortLabel: "Application Port",
16048
+ appInterfaceLabel: "Application Interface",
16049
+ anyInterface: "Any Interface",
16050
+ 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.`,
16051
+ appPortEnvOverride: (envPort) => `Note: The application port is currently set to ${envPort} via the PORT environment variable, and cannot be configured here.`,
16052
+ defaultPort: (port) => `Default: (${port})`,
16053
+ saveChanges: "Save Changes",
16054
+ saveWarning: {
16055
+ external: "When you hit Save, the UI will reload",
16056
+ 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."
16057
+ },
16058
+ invalidPortSingle: "Port numbers must be an integer between 1 and 65535",
16059
+ invalidPort: 'Please enter a valid port number or range (e.g. "1234" or "8000-8100")',
16060
+ invalidPortRange: 'The first port in a range must be less than or equal to the second port (e.g. "8000-8100")'
16061
+ }
15977
16062
  },
15978
16063
  controls: {
15979
16064
  play: "Play",
@@ -16281,7 +16366,9 @@ var TimecodeDisplay = ({
16281
16366
  id,
16282
16367
  timecode: { state, metadata },
16283
16368
  config,
16284
- headerComponents
16369
+ headerComponents,
16370
+ disabled,
16371
+ rootState
16285
16372
  }) => {
16286
16373
  const { handlers, callHandler } = useApplicationHandlers();
16287
16374
  const hooks = id && getTreeValue(handlers, id);
@@ -16332,29 +16419,41 @@ var TimecodeDisplay = ({
16332
16419
  )
16333
16420
  ),
16334
16421
  children: [
16335
- headerComponents && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex flex-wrap gap-0.25", children: headerComponents }),
16422
+ headerComponents && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex gap-0.25", children: headerComponents }),
16336
16423
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16337
16424
  SizeAwareDiv,
16338
16425
  {
16339
- className: cn(
16340
- "relative min-h-timecode-min-height grow",
16341
- cnd(state?.state === "stopped", "opacity-50"),
16342
- cnd(
16343
- hooks?.play && hooks?.pause,
16344
- `
16345
- cursor-pointer
16346
- hover:opacity-100
16347
- `
16348
- )
16349
- ),
16426
+ className: "relative min-h-timecode-min-height grow",
16350
16427
  onClick: toggle,
16351
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: cn("font-mono text-timecode-adaptive"), children: state.state === "none" ? "--:--:--:---" : state.state === "stopped" ? displayMillis(state.positionMillis) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16352
- ActiveTimecodeText,
16428
+ children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16429
+ SizeAwareDiv,
16430
+ {
16431
+ className: "\n pointer-events-none absolute inset-0 flex items-center\n justify-center\n ",
16432
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Icon2, { icon: "pause", className: "text-timecode-adaptive" })
16433
+ }
16434
+ ) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16435
+ "div",
16353
16436
  {
16354
- effectiveStartTimeMillis: state.effectiveStartTimeMillis,
16355
- speed: state.speed
16437
+ className: cn(
16438
+ "absolute inset-0 flex items-center justify-center",
16439
+ cnd(state?.state === "stopped", "opacity-50"),
16440
+ cnd(
16441
+ hooks?.play && hooks?.pause,
16442
+ `
16443
+ cursor-pointer
16444
+ hover:opacity-100
16445
+ `
16446
+ )
16447
+ ),
16448
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: cn("font-mono text-timecode-adaptive"), children: state.state === "none" ? "--:--:--:---" : state.state === "stopped" ? displayMillis(state.positionMillis) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16449
+ ActiveTimecodeText,
16450
+ {
16451
+ effectiveStartTimeMillis: state.effectiveStartTimeMillis,
16452
+ speed: state.speed
16453
+ }
16454
+ ) })
16356
16455
  }
16357
- ) }) })
16456
+ )
16358
16457
  }
16359
16458
  ),
16360
16459
  hooks?.pause || hooks?.play ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex justify-center gap-px", children: [
@@ -16442,9 +16541,53 @@ var TimecodeDisplay = ({
16442
16541
  metadata.artist && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "grow truncate bg-sigil-bg-light p-0.5", children: metadata.artist })
16443
16542
  ] })
16444
16543
  }
16445
- ) : null
16544
+ ) : null,
16545
+ rootState.errors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex gap-px", children: rootState.errors.map((error, index2) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16546
+ "div",
16547
+ {
16548
+ className: "\n grow truncate bg-sigil-usage-red-background p-0.5\n text-sigil-usage-red-text\n ",
16549
+ children: error
16550
+ },
16551
+ index2
16552
+ )) }),
16553
+ rootState.warnings.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex gap-px", children: rootState.warnings.map((warning, index2) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16554
+ "div",
16555
+ {
16556
+ className: "\n grow truncate bg-sigil-usage-orange-background p-0.5\n text-sigil-usage-orange-text\n ",
16557
+ children: warning
16558
+ },
16559
+ index2
16560
+ )) })
16446
16561
  ] });
16447
16562
  };
16563
+ var getLinkedSourceInfo = (link, config) => {
16564
+ if (!link) {
16565
+ return void 0;
16566
+ }
16567
+ let info = void 0;
16568
+ if (link[0] === "input") {
16569
+ const input = config.inputs?.[link[1]];
16570
+ if (input) {
16571
+ info = {
16572
+ color: input.color,
16573
+ type: STRINGS.protocols[input.definition.type].short,
16574
+ name: input.name ? [input.name] : [],
16575
+ namePlaceholder: STRINGS.inputs.unnamed
16576
+ };
16577
+ }
16578
+ } else if (link[0] === "generator") {
16579
+ const generator = config.generators?.[link[1]];
16580
+ if (generator) {
16581
+ info = {
16582
+ color: generator.color,
16583
+ type: STRINGS.generators.type[generator.definition.type],
16584
+ name: generator.name ? [generator.name] : [],
16585
+ namePlaceholder: STRINGS.generators.unnamed
16586
+ };
16587
+ }
16588
+ }
16589
+ return info;
16590
+ };
16448
16591
  var EMPTY_TIMECODE = {
16449
16592
  name: null,
16450
16593
  state: {
@@ -16463,8 +16606,10 @@ var TimecodeTreeDisplay = ({
16463
16606
  id,
16464
16607
  type,
16465
16608
  name,
16609
+ link,
16466
16610
  color,
16467
16611
  timecode,
16612
+ rootState,
16468
16613
  namePlaceholder,
16469
16614
  buttons,
16470
16615
  assignToOutput
@@ -16478,8 +16623,8 @@ var TimecodeTreeDisplay = ({
16478
16623
  });
16479
16624
  }
16480
16625
  }, [id, openNewWidow]);
16481
- name = timecode?.name ? [...name, timecode.name] : name;
16482
- if (isTimecodeGroup(timecode) && Object.values(timecode.timecodes).length) {
16626
+ name = timecode !== "disabled" && timecode?.name ? [...name, timecode.name] : name;
16627
+ if (timecode !== "disabled" && isTimecodeGroup(timecode) && Object.values(timecode.timecodes).length) {
16483
16628
  return Object.entries(timecode.timecodes).map(([key, child]) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16484
16629
  TimecodeTreeDisplay,
16485
16630
  {
@@ -16489,6 +16634,7 @@ var TimecodeTreeDisplay = ({
16489
16634
  name,
16490
16635
  color: timecode.color ?? color,
16491
16636
  timecode: child,
16637
+ rootState,
16492
16638
  namePlaceholder,
16493
16639
  buttons,
16494
16640
  assignToOutput
@@ -16506,28 +16652,67 @@ var TimecodeTreeDisplay = ({
16506
16652
  TimecodeDisplay,
16507
16653
  {
16508
16654
  id,
16509
- timecode: isTimecodeInstance(timecode) ? timecode : EMPTY_TIMECODE,
16655
+ timecode: timecode !== "disabled" && isTimecodeInstance(timecode) ? timecode : EMPTY_TIMECODE,
16656
+ rootState,
16657
+ disabled: timecode === "disabled",
16510
16658
  config,
16511
16659
  headerComponents: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
16512
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex grow items-start gap-0.25", children: [
16513
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16514
- "div",
16515
- {
16516
- className: "\n m-0.25 rounded-md border border-sigil-bg-light\n bg-timecode-usage-foreground px-1 py-0.25 text-sigil-control\n text-timecode-usage-text\n ",
16517
- children: type
16518
- }
16519
- ),
16520
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16660
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex grow basis-0 items-start gap-0.25", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "grow", children: [
16661
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-0.25", children: [
16662
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16663
+ "div",
16664
+ {
16665
+ className: "\n m-0.25 rounded-md border border-sigil-bg-light\n bg-timecode-usage-foreground px-1 py-0.25\n text-sigil-control text-timecode-usage-text\n ",
16666
+ children: type
16667
+ }
16668
+ ),
16669
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16670
+ "div",
16671
+ {
16672
+ className: cn(
16673
+ "w-0 grow truncate p-0.5",
16674
+ cnd(name.length, "font-bold", "italic opacity-50")
16675
+ ),
16676
+ children: name.length ? name.join(" / ") : namePlaceholder
16677
+ }
16678
+ )
16679
+ ] }),
16680
+ link && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
16521
16681
  "div",
16522
16682
  {
16523
- className: cn(
16524
- "grow basis-0 truncate p-0.5",
16525
- cnd(name.length, "font-bold", "italic opacity-50")
16683
+ className: "\n flex items-center gap-0.25 text-timecode-usage-foreground\n ",
16684
+ style: cssSigilColorUsageVariables(
16685
+ "timecode-usage",
16686
+ // Override timecode color with the user hint preferences
16687
+ // when no color is specified
16688
+ // as that will be what's used by the linked input/generator
16689
+ sigilColorUsage(link.color ?? "hint")
16526
16690
  ),
16527
- children: name.length ? name.join(" / ") : namePlaceholder
16691
+ children: [
16692
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
16693
+ "div",
16694
+ {
16695
+ className: "\n m-0.25 flex items-center gap-0.25 rounded-md border\n border-sigil-bg-light bg-timecode-usage-foreground px-1\n py-0.25 text-sigil-control text-timecode-usage-text\n ",
16696
+ children: [
16697
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Icon2, { icon: "link", className: "text-[120%]" }),
16698
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: link.type })
16699
+ ]
16700
+ }
16701
+ ),
16702
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16703
+ "div",
16704
+ {
16705
+ className: cn(
16706
+ "w-0 grow truncate p-0.5",
16707
+ cnd(link.name.length, "font-bold", "italic opacity-50")
16708
+ ),
16709
+ children: link.name.length ? link.name.join(" / ") : link.namePlaceholder
16710
+ }
16711
+ )
16712
+ ]
16528
16713
  }
16529
16714
  )
16530
- ] }),
16715
+ ] }) }),
16531
16716
  /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(ControlButtonGroup, { className: "rounded-md bg-sigil-bg-light", children: [
16532
16717
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
16533
16718
  ControlButton,
@@ -16565,7 +16750,7 @@ var FullscreenTimecodeDisplay = ({
16565
16750
  return getTimecodeInstance(applicationState, id);
16566
16751
  } else {
16567
16752
  const c = config.outputs[id[1]];
16568
- if (!c) {
16753
+ if (!c || !c.enabled) {
16569
16754
  return null;
16570
16755
  }
16571
16756
  return augmentUpstreamTimecodeWithOutputMetadata(
@@ -16574,6 +16759,15 @@ var FullscreenTimecodeDisplay = ({
16574
16759
  );
16575
16760
  }
16576
16761
  }, [applicationState, id, config.outputs]);
16762
+ const linkedSourceInfo = (0, import_react31.useMemo)(() => {
16763
+ if (isOutputInstanceId(id)) {
16764
+ const c = config.outputs[id[1]];
16765
+ if (c?.link) {
16766
+ return getLinkedSourceInfo(c.link, config);
16767
+ }
16768
+ }
16769
+ return void 0;
16770
+ }, [id, config]);
16577
16771
  const instanceConfig = (0, import_react31.useMemo)(() => {
16578
16772
  if (isInputInstanceId(id)) {
16579
16773
  const c = config.inputs[id[1]];
@@ -16585,7 +16779,8 @@ var FullscreenTimecodeDisplay = ({
16585
16779
  type: STRINGS.protocols[c.definition.type].short,
16586
16780
  name: c.name ? [c.name] : [],
16587
16781
  color: c.color,
16588
- namePlaceholder: `Unnamed Input`
16782
+ namePlaceholder: STRINGS.inputs.unnamed,
16783
+ disabled: !c.enabled
16589
16784
  };
16590
16785
  } else if (isGeneratorInstanceId(id)) {
16591
16786
  const c = config.generators[id[1]];
@@ -16597,7 +16792,8 @@ var FullscreenTimecodeDisplay = ({
16597
16792
  type: STRINGS.generators.type[c.definition.type],
16598
16793
  name: c.name ? [c.name] : [],
16599
16794
  color: c.color,
16600
- namePlaceholder: `Unnamed Generator`
16795
+ namePlaceholder: STRINGS.generators.unnamed,
16796
+ disabled: false
16601
16797
  };
16602
16798
  } else {
16603
16799
  const c = config.outputs[id[1]];
@@ -16609,10 +16805,29 @@ var FullscreenTimecodeDisplay = ({
16609
16805
  type: STRINGS.protocols[c.definition.type].short,
16610
16806
  name: c.name ? [c.name] : [],
16611
16807
  color: c.color,
16612
- namePlaceholder: `Unnamed Output`
16808
+ namePlaceholder: STRINGS.outputs.unnamed,
16809
+ disabled: !c.enabled
16613
16810
  };
16614
16811
  }
16615
16812
  }, [id, config]);
16813
+ const rootState = (0, import_react31.useMemo)(() => {
16814
+ if (isInputInstanceId(id)) {
16815
+ return {
16816
+ errors: applicationState.inputs?.[id[1]]?.errors ?? [],
16817
+ warnings: applicationState.inputs?.[id[1]]?.warnings ?? []
16818
+ };
16819
+ } else if (isGeneratorInstanceId(id)) {
16820
+ return {
16821
+ errors: [],
16822
+ warnings: []
16823
+ };
16824
+ } else {
16825
+ return {
16826
+ errors: applicationState.outputs?.[id[1]]?.errors ?? [],
16827
+ warnings: applicationState.outputs?.[id[1]]?.warnings ?? []
16828
+ };
16829
+ }
16830
+ }, [id, applicationState]);
16616
16831
  if (!instanceConfig) {
16617
16832
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
16618
16833
  SizeAwareDiv,
@@ -16633,9 +16848,11 @@ var FullscreenTimecodeDisplay = ({
16633
16848
  TimecodeTreeDisplay,
16634
16849
  {
16635
16850
  id,
16636
- timecode,
16851
+ timecode: instanceConfig.disabled ? "disabled" : timecode,
16852
+ rootState,
16637
16853
  assignToOutput: null,
16638
16854
  buttons: null,
16855
+ link: linkedSourceInfo,
16639
16856
  ...instanceConfig
16640
16857
  }
16641
16858
  )
@@ -16895,7 +17112,7 @@ var DmxConnectionSettings = ({
16895
17112
  var OutputSettingsDialog = ({
16896
17113
  target,
16897
17114
  output,
16898
- close
17115
+ setDialogMode
16899
17116
  }) => {
16900
17117
  const { config, updateConfig } = (0, import_react32.useContext)(ConfigContext);
16901
17118
  const [newData, setNewData] = (0, import_react32.useState)({
@@ -16911,6 +17128,7 @@ var OutputSettingsDialog = ({
16911
17128
  },
16912
17129
  link: null
16913
17130
  });
17131
+ const close = (0, import_react32.useCallback)(() => setDialogMode(null), [setDialogMode]);
16914
17132
  const updateSettings = (0, import_react32.useCallback)(
16915
17133
  (change) => {
16916
17134
  if (target.type === "add") {
@@ -17041,10 +17259,25 @@ var OutputSettingsDialog = ({
17041
17259
  }
17042
17260
  }
17043
17261
  ),
17044
- resolvedTarget === "add" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(ControlDialogButtons, { children: [
17262
+ target.type === "add" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(ControlDialogButtons, { children: [
17045
17263
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ControlButton, { onClick: close, variant: "large", children: "Cancel" }),
17046
17264
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ControlButton, { onClick: addOutput, variant: "large", children: "Add Output" })
17047
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ControlDialogButtons, { children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ControlButton, { onClick: close, variant: "large", children: "Close" }) })
17265
+ ] }) : target.type === "edit" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(ControlDialogButtons, { children: [
17266
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
17267
+ ControlButton,
17268
+ {
17269
+ onClick: () => setDialogMode({
17270
+ section: { type: "outputs", output },
17271
+ target: { type: "delete", uuid: target.uuid }
17272
+ }),
17273
+ variant: "large",
17274
+ destructive: true,
17275
+ icon: "delete",
17276
+ children: "Delete"
17277
+ }
17278
+ ),
17279
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ControlButton, { onClick: close, variant: "large", children: "Close" })
17280
+ ] }) : null
17048
17281
  ]
17049
17282
  }
17050
17283
  ) });
@@ -17057,7 +17290,7 @@ var OutputDisplay = ({
17057
17290
  setAssignToOutput
17058
17291
  }) => {
17059
17292
  const applicationState = useApplicationState();
17060
- const { updateConfig } = (0, import_react32.useContext)(ConfigContext);
17293
+ const { config: allConfig, updateConfig } = (0, import_react32.useContext)(ConfigContext);
17061
17294
  const clearLink = (0, import_react32.useCallback)(() => {
17062
17295
  updateConfig((current) => {
17063
17296
  const currentOutput = current.outputs?.[uuid];
@@ -17085,6 +17318,10 @@ var OutputDisplay = ({
17085
17318
  const tc = config.link && getTimecodeInstance(applicationState, config.link);
17086
17319
  return augmentUpstreamTimecodeWithOutputMetadata(tc, config);
17087
17320
  }, [applicationState, config]);
17321
+ const link = (0, import_react32.useMemo)(
17322
+ () => getLinkedSourceInfo(config.link, allConfig),
17323
+ [config.link, allConfig]
17324
+ );
17088
17325
  const toggleEnabled = (0, import_react32.useCallback)(() => {
17089
17326
  updateConfig((current) => {
17090
17327
  const existing = current.outputs?.[uuid];
@@ -17103,6 +17340,13 @@ var OutputDisplay = ({
17103
17340
  };
17104
17341
  });
17105
17342
  }, [uuid, updateConfig]);
17343
+ const rootState = (0, import_react32.useMemo)(
17344
+ () => ({
17345
+ errors: applicationState.outputs[uuid]?.errors ?? [],
17346
+ warnings: applicationState.outputs[uuid]?.warnings ?? []
17347
+ }),
17348
+ [applicationState.outputs, uuid]
17349
+ );
17106
17350
  return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
17107
17351
  "div",
17108
17352
  {
@@ -17121,23 +17365,25 @@ var OutputDisplay = ({
17121
17365
  type: STRINGS.protocols[config.definition.type].short,
17122
17366
  name: config.name ? [config.name] : [],
17123
17367
  color: config.color,
17124
- timecode: config.enabled ? timecode : null,
17125
- namePlaceholder: `Unnamed Output`,
17368
+ timecode: config.enabled ? timecode : "disabled",
17369
+ rootState,
17370
+ namePlaceholder: STRINGS.outputs.unnamed,
17371
+ link,
17126
17372
  buttons: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
17127
17373
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
17128
17374
  ControlButton,
17129
17375
  {
17130
17376
  variant: "large",
17131
- title: config.enabled ? "Stop Input" : "Start Input",
17377
+ title: config.enabled ? STRINGS.outputs.disable : STRINGS.outputs.enable,
17132
17378
  onClick: toggleEnabled,
17133
- icon: config.enabled ? "stop" : "play_arrow"
17379
+ icon: config.enabled ? "pause" : "play_arrow"
17134
17380
  }
17135
17381
  ),
17136
17382
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
17137
17383
  ControlButton,
17138
17384
  {
17139
17385
  variant: "large",
17140
- title: "Link Output",
17386
+ title: STRINGS.outputs.link,
17141
17387
  active: assignToOutput === uuid,
17142
17388
  onClick: linkCallback,
17143
17389
  icon: config.link ? "link" : "link_off"
@@ -17147,7 +17393,7 @@ var OutputDisplay = ({
17147
17393
  ControlButton,
17148
17394
  {
17149
17395
  variant: "large",
17150
- title: "Edit Output",
17396
+ title: STRINGS.outputs.edit,
17151
17397
  onClick: () => setDialogMode({
17152
17398
  section: { type: "outputs", output: config.definition.type },
17153
17399
  target: { type: "edit", uuid }
@@ -17256,7 +17502,7 @@ var ClockSpecificSettings = ({
17256
17502
  var GeneratorSettingsDialog = ({
17257
17503
  target,
17258
17504
  generator,
17259
- close
17505
+ setDialogMode
17260
17506
  }) => {
17261
17507
  const { config, updateConfig } = (0, import_react33.useContext)(ConfigContext);
17262
17508
  const [newData, setNewData] = (0, import_react33.useState)({
@@ -17266,6 +17512,7 @@ var GeneratorSettingsDialog = ({
17266
17512
  speed: 1
17267
17513
  }
17268
17514
  });
17515
+ const close = (0, import_react33.useCallback)(() => setDialogMode(null), [setDialogMode]);
17269
17516
  const updateSettings = (0, import_react33.useCallback)(
17270
17517
  (change) => {
17271
17518
  if (target.type === "add") {
@@ -17373,10 +17620,25 @@ var GeneratorSettingsDialog = ({
17373
17620
  updateSettings: updateDefinition
17374
17621
  }
17375
17622
  ) : null,
17376
- resolvedTarget === "add" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(ControlDialogButtons, { children: [
17623
+ target.type === "add" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(ControlDialogButtons, { children: [
17377
17624
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ControlButton, { onClick: close, variant: "large", children: "Cancel" }),
17378
17625
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ControlButton, { onClick: addGenerator, variant: "large", children: "Add Generator" })
17379
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ControlDialogButtons, { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ControlButton, { onClick: close, variant: "large", children: "Close" }) })
17626
+ ] }) : target.type === "edit" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(ControlDialogButtons, { children: [
17627
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
17628
+ ControlButton,
17629
+ {
17630
+ onClick: () => setDialogMode({
17631
+ section: { type: "generators", generator },
17632
+ target: { type: "delete", uuid: target.uuid }
17633
+ }),
17634
+ variant: "large",
17635
+ destructive: true,
17636
+ icon: "delete",
17637
+ children: "Delete"
17638
+ }
17639
+ ),
17640
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ControlButton, { onClick: close, variant: "large", children: "Close" })
17641
+ ] }) : null
17380
17642
  ]
17381
17643
  }
17382
17644
  ) });
@@ -17389,6 +17651,7 @@ var GeneratorDisplay = ({
17389
17651
  }) => {
17390
17652
  const { generators } = useApplicationState();
17391
17653
  const state = generators[uuid];
17654
+ const rootState = (0, import_react33.useMemo)(() => ({ errors: [], warnings: [] }), []);
17392
17655
  return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
17393
17656
  TimecodeTreeDisplay,
17394
17657
  {
@@ -17398,12 +17661,13 @@ var GeneratorDisplay = ({
17398
17661
  name: config.name ? [config.name] : [],
17399
17662
  color: config.color,
17400
17663
  timecode: state?.timecode ?? null,
17401
- namePlaceholder: `Unnamed Generator`,
17664
+ rootState,
17665
+ namePlaceholder: STRINGS.generators.unnamed,
17402
17666
  buttons: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_jsx_runtime44.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
17403
17667
  ControlButton,
17404
17668
  {
17405
17669
  variant: "large",
17406
- title: "Edit Generator",
17670
+ title: STRINGS.generators.edit,
17407
17671
  onClick: () => setDialogMode({
17408
17672
  section: {
17409
17673
  type: "generators",
@@ -17590,7 +17854,7 @@ var TCNetConnectionSettings = ({
17590
17854
  var InputSettingsDialog = ({
17591
17855
  target,
17592
17856
  input,
17593
- close
17857
+ setDialogMode
17594
17858
  }) => {
17595
17859
  const { config, updateConfig } = (0, import_react34.useContext)(ConfigContext);
17596
17860
  const [newData, setNewData] = (0, import_react34.useState)({
@@ -17605,6 +17869,7 @@ var InputSettingsDialog = ({
17605
17869
  iface: ""
17606
17870
  }
17607
17871
  });
17872
+ const close = (0, import_react34.useCallback)(() => setDialogMode(null), [setDialogMode]);
17608
17873
  const updateSettings = (0, import_react34.useCallback)(
17609
17874
  (change) => {
17610
17875
  if (target.type === "add") {
@@ -17741,10 +18006,25 @@ var InputSettingsDialog = ({
17741
18006
  }
17742
18007
  }
17743
18008
  ),
17744
- resolvedTarget === "add" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(ControlDialogButtons, { children: [
18009
+ target.type === "add" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(ControlDialogButtons, { children: [
17745
18010
  /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ControlButton, { onClick: close, variant: "large", children: "Cancel" }),
17746
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ControlButton, { onClick: addInput, variant: "large", children: "Add Input" })
17747
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ControlDialogButtons, { children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ControlButton, { onClick: close, variant: "large", children: "Close" }) })
18011
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ControlButton, { onClick: addInput, variant: "large", primary: true, children: "Add Input" })
18012
+ ] }) : target?.type === "edit" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(ControlDialogButtons, { children: [
18013
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
18014
+ ControlButton,
18015
+ {
18016
+ onClick: () => setDialogMode({
18017
+ section: { type: "inputs", input },
18018
+ target: { type: "delete", uuid: target.uuid }
18019
+ }),
18020
+ variant: "large",
18021
+ destructive: true,
18022
+ icon: "delete",
18023
+ children: "Delete"
18024
+ }
18025
+ ),
18026
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ControlButton, { onClick: close, variant: "large", children: "Close" })
18027
+ ] }) : null
17748
18028
  ]
17749
18029
  }
17750
18030
  ) });
@@ -17776,6 +18056,10 @@ var InputDisplay = ({
17776
18056
  };
17777
18057
  });
17778
18058
  }, [uuid, updateConfig]);
18059
+ const rootState = (0, import_react34.useMemo)(
18060
+ () => ({ errors: state?.errors ?? [], warnings: state?.warnings ?? [] }),
18061
+ [state?.errors, state?.warnings]
18062
+ );
17779
18063
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
17780
18064
  TimecodeTreeDisplay,
17781
18065
  {
@@ -17784,23 +18068,24 @@ var InputDisplay = ({
17784
18068
  type: STRINGS.protocols[config.definition.type].short,
17785
18069
  name: config.name ? [config.name] : [],
17786
18070
  color: config.color,
17787
- timecode: state?.timecode ?? null,
17788
- namePlaceholder: `Unnamed Input`,
18071
+ timecode: config.enabled ? state?.timecode ?? null : "disabled",
18072
+ rootState,
18073
+ namePlaceholder: STRINGS.inputs.unnamed,
17789
18074
  buttons: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
17790
18075
  /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
17791
18076
  ControlButton,
17792
18077
  {
17793
18078
  variant: "large",
17794
- title: config.enabled ? "Stop Input" : "Start Input",
18079
+ title: config.enabled ? STRINGS.inputs.disable : STRINGS.inputs.enable,
17795
18080
  onClick: toggleEnabled,
17796
- icon: config.enabled ? "stop" : "play_arrow"
18081
+ icon: config.enabled ? "pause" : "play_arrow"
17797
18082
  }
17798
18083
  ),
17799
18084
  /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
17800
18085
  ControlButton,
17801
18086
  {
17802
18087
  variant: "large",
17803
- title: "Edit Input",
18088
+ title: STRINGS.inputs.edit,
17804
18089
  onClick: () => setDialogMode({
17805
18090
  section: { type: "inputs", input: config.definition.type },
17806
18091
  target: { type: "edit", uuid }
@@ -17933,6 +18218,11 @@ var diffJson = (a, b) => {
17933
18218
  return { type: "value", after: b };
17934
18219
  };
17935
18220
 
18221
+ // src/components/frontend/toolbox/types.ts
18222
+ var isDeleteDialogMode = (mode) => {
18223
+ return mode?.target.type === "delete";
18224
+ };
18225
+
17936
18226
  // src/components/frontend/toolbox/settings.tsx
17937
18227
  var import_react37 = require("react");
17938
18228
 
@@ -18087,6 +18377,180 @@ var ENABLED_DISABLED_OPTIONS = [
18087
18377
  var DATE_FORMATTER = new Intl.DateTimeFormat(void 0, {
18088
18378
  timeStyle: "medium"
18089
18379
  });
18380
+ var AppPortConfig = () => {
18381
+ const { getNetworkInterfaces } = (0, import_react37.useContext)(NetworkContext);
18382
+ const [interfaces, setInterfaces] = (0, import_react37.useState)(null);
18383
+ const refreshInterfaces = (0, import_react37.useCallback)(() => {
18384
+ setInterfaces(null);
18385
+ getNetworkInterfaces().then((ifs) => setInterfaces(ifs));
18386
+ }, [getNetworkInterfaces]);
18387
+ (0, import_react37.useEffect)(() => {
18388
+ refreshInterfaces();
18389
+ }, [refreshInterfaces]);
18390
+ const { appListenerChangesHandledExternally } = useBrowserContext();
18391
+ const { network, config, updateConfig } = (0, import_react37.useContext)(ConfigContext);
18392
+ const [nextPort, setNextPort] = (0, import_react37.useState)(null);
18393
+ const [nextInterface, setNextInterface] = (0, import_react37.useState)(
18394
+ null
18395
+ );
18396
+ const iface = nextInterface ?? (config.appListener?.interface ? `specific:${config.appListener?.interface}` : "any");
18397
+ const port = nextPort ?? config.appListener?.port;
18398
+ const currentPortString = !port ? "" : typeof port === "string" ? port : portString(port);
18399
+ const hasNetworkChanges = nextPort !== null || nextInterface !== null;
18400
+ const nextUrlRef = (0, import_react37.useRef)(null);
18401
+ const validatedPort = (0, import_react37.useMemo)(() => {
18402
+ if (nextPort === null) {
18403
+ return { type: "unchanged" };
18404
+ }
18405
+ if (nextPort.trim() === "") {
18406
+ return { type: "empty" };
18407
+ }
18408
+ const portParts = nextPort.split("-").map((part) => parseInt(part.trim(), 10));
18409
+ if (portParts.length === 1) {
18410
+ const [singlePort] = portParts;
18411
+ if (!singlePort || isNaN(singlePort) || singlePort < 1 || singlePort > 65535) {
18412
+ return {
18413
+ type: "invalid",
18414
+ error: STRINGS.settings.network.invalidPortSingle
18415
+ };
18416
+ }
18417
+ return { type: "valid", port: singlePort };
18418
+ }
18419
+ if (portParts.length === 2) {
18420
+ const [from, to] = portParts;
18421
+ if (!from || isNaN(from) || from < 1 || from > 65535 || !to || isNaN(to) || to < 1 || to > 65535) {
18422
+ return {
18423
+ type: "invalid",
18424
+ error: STRINGS.settings.network.invalidPortSingle
18425
+ };
18426
+ } else if (from > to) {
18427
+ return {
18428
+ type: "invalid",
18429
+ error: STRINGS.settings.network.invalidPortRange
18430
+ };
18431
+ }
18432
+ return { type: "valid", port: { from, to } };
18433
+ }
18434
+ return { type: "invalid", error: STRINGS.settings.network.invalidPort };
18435
+ }, [nextPort]);
18436
+ const canSave = hasNetworkChanges && validatedPort?.type !== "invalid";
18437
+ const saveNetworkConfig = (0, import_react37.useCallback)(() => {
18438
+ if (validatedPort?.type === "invalid") {
18439
+ return;
18440
+ }
18441
+ const newPort = validatedPort;
18442
+ updateConfig((current) => {
18443
+ const config2 = {
18444
+ ...current,
18445
+ appListener: {
18446
+ port: newPort.type === "empty" ? void 0 : newPort.type === "valid" ? newPort.port : current.appListener?.port,
18447
+ interface: nextInterface === "any" ? void 0 : nextInterface ? nextInterface.replace("specific:", "") : current.appListener?.interface
18448
+ }
18449
+ };
18450
+ const nextUrl = new URL(window.location.href);
18451
+ if (config2.appListener?.interface) {
18452
+ nextUrl.hostname = interfaces?.[config2.appListener.interface]?.address ?? nextUrl.hostname;
18453
+ }
18454
+ const port2 = config2.appListener?.port ?? network.defaultPort;
18455
+ nextUrl.port = (typeof port2 === "number" ? port2 : port2.from).toString();
18456
+ nextUrlRef.current = nextUrl;
18457
+ return config2;
18458
+ });
18459
+ setNextPort(null);
18460
+ setNextInterface(null);
18461
+ }, [
18462
+ interfaces,
18463
+ nextInterface,
18464
+ validatedPort,
18465
+ updateConfig,
18466
+ network.defaultPort
18467
+ ]);
18468
+ (0, import_react37.useEffect)(() => {
18469
+ return () => {
18470
+ if (!appListenerChangesHandledExternally && nextUrlRef.current) {
18471
+ window.location.href = nextUrlRef.current.href;
18472
+ }
18473
+ };
18474
+ }, [appListenerChangesHandledExternally]);
18475
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
18476
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ControlLabel, { children: STRINGS.settings.network.appInterfaceLabel }),
18477
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
18478
+ ControlSelect,
18479
+ {
18480
+ value: iface,
18481
+ options: [
18482
+ { label: STRINGS.settings.network.anyInterface, value: "any" },
18483
+ ...!interfaces ? [] : Object.values(interfaces).map((iface2) => ({
18484
+ label: `${iface2.name} (${iface2.address})`,
18485
+ value: `specific:${iface2.name}`
18486
+ }))
18487
+ ],
18488
+ onChange: setNextInterface,
18489
+ position: "first",
18490
+ variant: "large",
18491
+ triggerClassName: cn("text-sigil-control")
18492
+ }
18493
+ ),
18494
+ iface && interfaces?.[iface]?.internal && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
18495
+ ControlDetails,
18496
+ {
18497
+ position: "second",
18498
+ className: "text-sigil-warning-foreground",
18499
+ children: STRINGS.settings.network.internalInterfaceUsed(iface)
18500
+ }
18501
+ ),
18502
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
18503
+ ControlButton,
18504
+ {
18505
+ onClick: refreshInterfaces,
18506
+ title: "Refresh Interfaces",
18507
+ position: "extra",
18508
+ variant: "large",
18509
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Icon2, { icon: "refresh", className: "text-arcane-normal" })
18510
+ }
18511
+ ),
18512
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ControlLabel, { children: STRINGS.settings.network.appPortLabel }),
18513
+ network.envPort ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ControlDetails, { position: "both", children: STRINGS.settings.network.appPortEnvOverride(network.envPort) }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
18514
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
18515
+ ControlInput,
18516
+ {
18517
+ value: currentPortString,
18518
+ onChange: setNextPort,
18519
+ placeholder: STRINGS.settings.network.defaultPort(
18520
+ portString(network.defaultPort)
18521
+ )
18522
+ }
18523
+ ),
18524
+ validatedPort.type === "invalid" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
18525
+ ControlDetails,
18526
+ {
18527
+ position: "second",
18528
+ className: "text-sigil-error-foreground",
18529
+ children: validatedPort.error
18530
+ }
18531
+ )
18532
+ ] }),
18533
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
18534
+ ControlButton,
18535
+ {
18536
+ onClick: saveNetworkConfig,
18537
+ variant: "large",
18538
+ position: "first",
18539
+ disabled: !canSave,
18540
+ children: STRINGS.settings.network.saveChanges
18541
+ }
18542
+ ),
18543
+ hasNetworkChanges && appListenerChangesHandledExternally && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ControlDetails, { position: "second", children: STRINGS.settings.network.saveWarning.external }),
18544
+ hasNetworkChanges && !appListenerChangesHandledExternally && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
18545
+ ControlDetails,
18546
+ {
18547
+ position: "second",
18548
+ className: "text-sigil-warning-foreground",
18549
+ children: STRINGS.settings.network.saveWarning.internal
18550
+ }
18551
+ )
18552
+ ] });
18553
+ };
18090
18554
  var Settings = ({ setWindowMode }) => {
18091
18555
  const { preferences, updateBrowserPrefs } = useBrowserPreferences();
18092
18556
  const { config, updateConfig } = (0, import_react37.useContext)(ConfigContext);
@@ -18134,7 +18598,8 @@ var Settings = ({ setWindowMode }) => {
18134
18598
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ControlDetails, { children: STRINGS.updates.settingsDetails }),
18135
18599
  updates && "lastCheckedMillis" in updates && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ControlDetails, { children: STRINGS.updates.lastChecked(
18136
18600
  DATE_FORMATTER.format(updates.lastCheckedMillis)
18137
- ) })
18601
+ ) }),
18602
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(AppPortConfig, {})
18138
18603
  ] })
18139
18604
  }
18140
18605
  )
@@ -18531,7 +18996,7 @@ var Layout = ({
18531
18996
  const { connection, reconnect } = (0, import_react39.useContext)(StageContext);
18532
18997
  const { preferences } = useBrowserPreferences();
18533
18998
  useRootHintVariables(preferences.color);
18534
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex h-screen flex-col", children: [
18999
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex h-dvh flex-col", children: [
18535
19000
  /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ToolbarWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(ToolbarRow, { children: [
18536
19001
  /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
18537
19002
  "div",
@@ -18710,65 +19175,660 @@ var UpdateBanner = () => {
18710
19175
  return null;
18711
19176
  };
18712
19177
 
18713
- // src/components/frontend/toolbox/root.tsx
19178
+ // ../../packages/sigil/src/frontend/controls/dialogs.tsx
19179
+ var import_react49 = require("react");
19180
+
19181
+ // ../../packages/sigil/src/frontend/dialogs.tsx
19182
+ var import_react48 = require("react");
19183
+
19184
+ // ../../packages/sigil/src/frontend/controls/buttons.tsx
19185
+ var import_react44 = require("react");
19186
+
19187
+ // ../../packages/sigil/src/frontend/styling.ts
19188
+ var SIGIL_COLOR2 = external_exports.enum([
19189
+ "purple",
19190
+ "blue",
19191
+ "teal",
19192
+ "red",
19193
+ "green",
19194
+ "yellow",
19195
+ "brown",
19196
+ "orange",
19197
+ "gray"
19198
+ ]);
19199
+ function cnd2(condition, truthyClassName, falseyClassName) {
19200
+ return condition ? truthyClassName : falseyClassName;
19201
+ }
19202
+
19203
+ // ../../packages/sigil/src/frontend/tooltip.tsx
19204
+ var import_react42 = require("react");
18714
19205
  var import_jsx_runtime53 = require("react/jsx-runtime");
18715
- var ToolboxRoot = ({ info }) => {
18716
- const { config } = info;
18717
- const { sendMessage, call } = (0, import_react42.useContext)(StageContext);
18718
- const [dialogMode, setDialogMode] = (0, import_react42.useState)(null);
18719
- const [assignToOutput, setAssignToOutput] = (0, import_react42.useState)(null);
18720
- (0, import_react42.useEffect)(() => {
18721
- if (assignToOutput) {
18722
- const onEscape = (e) => {
18723
- if (e.key === "Escape") {
18724
- setAssignToOutput(null);
18725
- }
18726
- };
18727
- window.addEventListener("keydown", onEscape);
18728
- return () => {
18729
- window.removeEventListener("keydown", onEscape);
18730
- };
18731
- }
18732
- }, [assignToOutput]);
18733
- const updateConfig = (0, import_react42.useCallback)(
18734
- (change) => {
18735
- const diff = diffJson(config, change(config));
18736
- sendMessage?.({
18737
- type: "component-message",
18738
- namespace: "timecode-toolbox",
18739
- component: "toolbox-root",
18740
- componentKey: info.key,
18741
- action: "update-config",
18742
- diff
18743
- });
18744
- },
18745
- [sendMessage, info.key, config]
18746
- );
18747
- const configContext = (0, import_react42.useMemo)(
18748
- () => ({
18749
- config,
18750
- updateConfig
18751
- }),
18752
- [config, updateConfig]
18753
- );
18754
- const closeDialog = (0, import_react42.useCallback)(() => setDialogMode(null), []);
18755
- const getNetworkInterfaces = (0, import_react42.useCallback)(async () => {
18756
- if (!call) {
18757
- throw new Error("No call function available");
18758
- }
18759
- return call({
18760
- namespace: "timecode-toolbox",
18761
- type: "component-call",
18762
- componentKey: info.key,
18763
- action: "toolbox-root-get-network-interfaces"
18764
- });
18765
- }, [call, info.key]);
18766
- const networkContextValue = (0, import_react42.useMemo)(() => {
18767
- return {
19206
+ var Content4 = (0, import_react42.forwardRef)(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
19207
+ dist_exports4.Content,
19208
+ {
19209
+ ...props,
19210
+ ref,
19211
+ className: cn(
19212
+ `
19213
+ relative z-sigil-tooltip rounded-sigil-control
19214
+ bg-sigil-usage-hint-background px-1 py-0.5 leading-[1.5]
19215
+ text-sigil-usage-hint-text shadow-sigil-box
19216
+ `,
19217
+ className
19218
+ )
19219
+ }
19220
+ ));
19221
+ Content4.displayName = "Content";
19222
+ var Arrow4 = (0, import_react42.forwardRef)(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
19223
+ dist_exports4.Arrow,
19224
+ {
19225
+ ...props,
19226
+ ref,
19227
+ className: cn(
19228
+ "fill-sigil-usage-hint-background drop-shadow-sigil-tooltip-arrow",
19229
+ className
19230
+ )
19231
+ }
19232
+ ));
19233
+ Arrow4.displayName = "Arrow";
19234
+ var TooltipBoundaryContext2 = (0, import_react42.createContext)(null);
19235
+ var TooltipWrapper2 = ({
19236
+ tooltip,
19237
+ children,
19238
+ side = "top"
19239
+ }) => {
19240
+ const boundary = (0, import_react42.useContext)(TooltipBoundaryContext2);
19241
+ if (!tooltip) {
19242
+ return children;
19243
+ }
19244
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(dist_exports4.Root, { children: [
19245
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(dist_exports4.Trigger, { asChild: true, children }),
19246
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
19247
+ Content4,
19248
+ {
19249
+ side,
19250
+ align: "center",
19251
+ sideOffset: 5,
19252
+ alignOffset: 0,
19253
+ collisionBoundary: boundary ? [boundary] : [],
19254
+ collisionPadding: 10,
19255
+ children: [
19256
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Arrow4, {}),
19257
+ tooltip
19258
+ ]
19259
+ }
19260
+ )
19261
+ ] });
19262
+ };
19263
+
19264
+ // ../../packages/sigil/src/frontend/input.ts
19265
+ var import_react43 = require("react");
19266
+ var usePressable3 = (click) => {
19267
+ const [touching, setTouching] = (0, import_react43.useState)(false);
19268
+ return {
19269
+ touching,
19270
+ handlers: {
19271
+ onClick: click,
19272
+ onTouchStart: () => {
19273
+ setTouching(true);
19274
+ },
19275
+ onTouchMove: () => {
19276
+ setTouching(false);
19277
+ },
19278
+ onTouchEnd: (event) => {
19279
+ if (touching) {
19280
+ event.preventDefault();
19281
+ setTouching(false);
19282
+ click(event);
19283
+ }
19284
+ }
19285
+ }
19286
+ };
19287
+ };
19288
+ var useLongPressable3 = ({
19289
+ onPress,
19290
+ onRelease
19291
+ }) => {
19292
+ const [touching, setTouching] = (0, import_react43.useState)(false);
19293
+ return (0, import_react43.useMemo)(
19294
+ () => ({
19295
+ touching,
19296
+ handlers: {
19297
+ onTouchStart: () => {
19298
+ setTouching(true);
19299
+ onPress();
19300
+ },
19301
+ onMouseDown: () => {
19302
+ setTouching(true);
19303
+ onPress();
19304
+ },
19305
+ onMouseUp: () => {
19306
+ setTouching(false);
19307
+ onRelease();
19308
+ },
19309
+ onTouchMove: () => {
19310
+ setTouching(false);
19311
+ onRelease();
19312
+ },
19313
+ onTouchEnd: (event) => {
19314
+ if (touching) {
19315
+ event.preventDefault();
19316
+ setTouching(false);
19317
+ onRelease();
19318
+ }
19319
+ }
19320
+ }
19321
+ }),
19322
+ [touching, onRelease, onPress]
19323
+ );
19324
+ };
19325
+
19326
+ // ../../packages/sigil/src/frontend/controls/utils.ts
19327
+ var clsControlPosition2 = (position) => {
19328
+ if (!position) return void 0;
19329
+ switch (position) {
19330
+ case "row":
19331
+ return "control-grid-pos-row";
19332
+ case "label":
19333
+ return "control-grid-pos-label";
19334
+ case "first":
19335
+ return "control-grid-pos-first";
19336
+ case "second":
19337
+ return "control-grid-pos-second";
19338
+ case "both":
19339
+ return "control-grid-pos-both";
19340
+ case "all":
19341
+ return "control-grid-pos-all";
19342
+ case "extra":
19343
+ return "control-grid-pos-extra";
19344
+ }
19345
+ };
19346
+ var clsControlSubgridPosition2 = (position, subgrid) => {
19347
+ if (!subgrid) return void 0;
19348
+ switch (position) {
19349
+ case "label":
19350
+ return "col-[1/span_1]";
19351
+ case "first":
19352
+ return "col-[2/span_1]";
19353
+ case "second":
19354
+ return "col-[3/span_1]";
19355
+ }
19356
+ };
19357
+
19358
+ // ../../packages/sigil/src/frontend/controls/buttons.tsx
19359
+ var import_jsx_runtime54 = require("react/jsx-runtime");
19360
+ var clsControlButton2 = ({
19361
+ variant,
19362
+ active,
19363
+ touching,
19364
+ position,
19365
+ className,
19366
+ primary,
19367
+ destructive
19368
+ }) => cn(
19369
+ `sigil-control-button`,
19370
+ cnd2(variant === "border", `sigil-control-button-variant-border`),
19371
+ cnd2(variant === "large", `sigil-control-button-variant-large`),
19372
+ cnd2(variant === "properties", `sigil-control-button-variant-properties`),
19373
+ cnd2(variant === "table-row", `sigil-control-button-variant-table-row`),
19374
+ cnd2(variant === "toolbar", `sigil-control-button-variant-toolbar`),
19375
+ cnd2(variant === "titlebar", `sigil-control-button-variant-titlebar`),
19376
+ cnd2(touching, `sigil-control-button-touching`),
19377
+ cnd2(active, `sigil-control-button-active`),
19378
+ cnd2(touching && active, `sigil-control-button-active-touching`),
19379
+ cnd2(primary, `sigil-control-button-primary`),
19380
+ cnd2(destructive, `sigil-control-button-destructive`),
19381
+ clsControlPosition2(position),
19382
+ className
19383
+ );
19384
+ var ControlButtonFrame2 = (0, import_react44.forwardRef)(
19385
+ ({
19386
+ children,
19387
+ className,
19388
+ type,
19389
+ variant = "toolbar",
19390
+ icon,
19391
+ active,
19392
+ touching,
19393
+ disabled,
19394
+ title,
19395
+ tooltipSide,
19396
+ position,
19397
+ primary,
19398
+ destructive,
19399
+ ...props
19400
+ }, ref) => {
19401
+ const btn = /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
19402
+ "button",
19403
+ {
19404
+ ...props,
19405
+ ref,
19406
+ type: type ?? "button",
19407
+ disabled,
19408
+ className: clsControlButton2({
19409
+ variant,
19410
+ active,
19411
+ touching,
19412
+ position,
19413
+ primary,
19414
+ destructive,
19415
+ className
19416
+ }),
19417
+ children: /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { children: [
19418
+ icon && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
19419
+ Icon2,
19420
+ {
19421
+ icon,
19422
+ className: cn(cnd2(children, "text-[120%]", "text-[150%]"))
19423
+ }
19424
+ ),
19425
+ children
19426
+ ] })
19427
+ }
19428
+ );
19429
+ if (!title) return btn;
19430
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(TooltipWrapper2, { tooltip: title, side: tooltipSide, children: btn });
19431
+ }
19432
+ );
19433
+ ControlButtonFrame2.displayName = "ControlButtonFrame";
19434
+ var ControlButton2 = (0, import_react44.forwardRef)(
19435
+ ({ onClick, disabled, ...props }, ref) => {
19436
+ const { handlers, touching } = usePressable3(onClick);
19437
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
19438
+ ControlButtonFrame2,
19439
+ {
19440
+ ...props,
19441
+ ref,
19442
+ disabled,
19443
+ touching,
19444
+ ...!disabled ? handlers : {}
19445
+ }
19446
+ );
19447
+ }
19448
+ );
19449
+ ControlButton2.displayName = "ControlButton";
19450
+ var CheckboxControlButton2 = (0, import_react44.forwardRef)(({ active, label, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(ControlButton2, { ...props, ref, active, children: [
19451
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Icon2, { icon: active ? "check_box" : "check_box_outline_blank" }),
19452
+ label
19453
+ ] }));
19454
+ CheckboxControlButton2.displayName = "CheckboxControlButton";
19455
+ var LongPressableControlButton2 = (0, import_react44.forwardRef)(({ active, disabled, onPress, onRelease, ...props }, ref) => {
19456
+ const { handlers, touching } = useLongPressable3({ onPress, onRelease });
19457
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
19458
+ ControlButtonFrame2,
19459
+ {
19460
+ ...props,
19461
+ ref,
19462
+ active: active || touching,
19463
+ disabled,
19464
+ ...!disabled ? handlers : {}
19465
+ }
19466
+ );
19467
+ });
19468
+ LongPressableControlButton2.displayName = "LongPressableControlButton";
19469
+ var ControlButtonGroup2 = (0, import_react44.forwardRef)(({ children, className, position, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
19470
+ "div",
19471
+ {
19472
+ ...props,
19473
+ ref,
19474
+ className: cn(
19475
+ `
19476
+ flex items-stretch gap-sigil-control-gap
19477
+ [&>button]:grow
19478
+ `,
19479
+ clsControlPosition2(position),
19480
+ className
19481
+ ),
19482
+ children
19483
+ }
19484
+ ));
19485
+ ControlButtonGroup2.displayName = "ControlButtonGroup";
19486
+
19487
+ // ../../packages/sigil/src/frontend/controls/content.tsx
19488
+ var import_react45 = require("react");
19489
+ var import_jsx_runtime55 = require("react/jsx-runtime");
19490
+ var ControlParagraph2 = (0, import_react45.forwardRef)(({ className, mode, position = "all", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
19491
+ "p",
19492
+ {
19493
+ ...props,
19494
+ ref,
19495
+ className: cn(
19496
+ "border border-transparent",
19497
+ clsControlPosition2(position),
19498
+ cnd2(
19499
+ mode === "success",
19500
+ `
19501
+ border-sigil-usage-green-dimmed-border
19502
+ bg-sigil-usage-green-dimmed-background p-1 text-sigil-usage-green-text
19503
+ `
19504
+ ),
19505
+ cnd2(
19506
+ mode === "warning",
19507
+ `
19508
+ border-sigil-usage-yellow-dimmed-border
19509
+ bg-sigil-usage-yellow-dimmed-background p-1
19510
+ text-sigil-usage-yellow-text
19511
+ `
19512
+ ),
19513
+ cnd2(
19514
+ mode === "error",
19515
+ `
19516
+ border-sigil-usage-red-dimmed-border
19517
+ bg-sigil-usage-red-dimmed-background p-1 text-sigil-usage-red-text
19518
+ `
19519
+ ),
19520
+ className
19521
+ )
19522
+ }
19523
+ ));
19524
+ ControlParagraph2.displayName = "ControlParagraph";
19525
+ var ControlLabel2 = (0, import_react45.forwardRef)(
19526
+ ({ className, disabled, nonMicro, position = "label", subgrid, ...props }, ref) => {
19527
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
19528
+ "label",
19529
+ {
19530
+ ...props,
19531
+ ref,
19532
+ className: cn(
19533
+ "flex items-center justify-end gap-0.6 p-0.6",
19534
+ clsControlPosition2(position),
19535
+ cnd2(nonMicro, "max-[550px]:hidden"),
19536
+ cnd2(disabled, "opacity-50"),
19537
+ clsControlSubgridPosition2(position, subgrid),
19538
+ className
19539
+ )
19540
+ }
19541
+ );
19542
+ }
19543
+ );
19544
+ ControlLabel2.displayName = "ControlLabel";
19545
+ var ControlDetails2 = (0, import_react45.forwardRef)(
19546
+ ({ align, className, position = "all", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
19547
+ "div",
19548
+ {
19549
+ ...props,
19550
+ ref,
19551
+ className: cn(
19552
+ "flex items-center px-0.3 text-sigil-foreground-muted",
19553
+ clsControlPosition2(position),
19554
+ cnd2(align === "start", "justify-start"),
19555
+ cnd2(align === "center", "justify-center"),
19556
+ cnd2(align === "end", "justify-end"),
19557
+ className
19558
+ )
19559
+ }
19560
+ )
19561
+ );
19562
+ ControlDetails2.displayName = "ControlDetails";
19563
+ var InputSpanningTitle2 = (0, import_react45.forwardRef)(({ className, position = "row", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
19564
+ "div",
19565
+ {
19566
+ ...props,
19567
+ ref,
19568
+ className: cn(
19569
+ "truncate p-0.6 text-center text-[0.8rem] font-bold",
19570
+ clsControlPosition2(position),
19571
+ className
19572
+ )
19573
+ }
19574
+ ));
19575
+ InputSpanningTitle2.displayName = "InputSpanningTitle";
19576
+
19577
+ // ../../packages/sigil/src/frontend/controls/input.tsx
19578
+ var import_react46 = require("react");
19579
+ var import_jsx_runtime56 = require("react/jsx-runtime");
19580
+
19581
+ // ../../packages/sigil/src/frontend/controls/select.tsx
19582
+ var import_react47 = require("react");
19583
+ var import_jsx_runtime57 = require("react/jsx-runtime");
19584
+ var COLOR_OPTIONS2 = {
19585
+ red: { label: "Red", value: "red", color: "red" },
19586
+ blue: { label: "Blue", value: "blue", color: "blue" },
19587
+ teal: { label: "Teal", value: "teal", color: "teal" },
19588
+ green: { label: "Green", value: "green", color: "green" },
19589
+ yellow: { label: "Yellow", value: "yellow", color: "yellow" },
19590
+ purple: { label: "Purple", value: "purple", color: "purple" },
19591
+ orange: { label: "Orange", value: "orange", color: "orange" },
19592
+ brown: { label: "Brown", value: "brown", color: "brown" },
19593
+ gray: { label: "Gray", value: "gray", color: "gray" }
19594
+ };
19595
+ var COLOR_OPTIONS_ARRAY2 = Object.values(COLOR_OPTIONS2);
19596
+
19597
+ // ../../packages/sigil/src/frontend/dialogs.tsx
19598
+ var import_jsx_runtime58 = require("react/jsx-runtime");
19599
+ var isDarkDialog2 = (variant) => variant === "dark" || variant === "dark-compact";
19600
+ var DialogContext2 = (0, import_react48.createContext)({
19601
+ createDialog: () => {
19602
+ throw new Error("DialogContext not provided");
19603
+ },
19604
+ displayMessage: () => {
19605
+ throw new Error("DialogContext not provided");
19606
+ },
19607
+ displayError: () => {
19608
+ throw new Error("DialogContext not provided");
19609
+ }
19610
+ });
19611
+ var DialogTitle2 = (0, import_react48.forwardRef)(
19612
+ ({ className, variant = "light", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19613
+ "div",
19614
+ {
19615
+ ...props,
19616
+ ref,
19617
+ className: cn(
19618
+ `
19619
+ flex items-center justify-center gap-0.6 border-b border-sigil-border
19620
+ p-arcane font-bold
19621
+ `,
19622
+ cnd2(isDarkDialog2(variant), "bg-sigil-bg-light", "bg-sigil-bg-dark"),
19623
+ className
19624
+ )
19625
+ }
19626
+ )
19627
+ );
19628
+ DialogTitle2.displayName = "DialogTitle";
19629
+ var DialogButtons2 = (0, import_react48.forwardRef)(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19630
+ "div",
19631
+ {
19632
+ ...props,
19633
+ ref,
19634
+ className: cn("mt-arcane flex justify-end gap-0.6", className)
19635
+ }
19636
+ ));
19637
+ DialogButtons2.displayName = "DialogButtons";
19638
+ var Dialog2 = ({
19639
+ children,
19640
+ dialogClosed,
19641
+ closable = true,
19642
+ title,
19643
+ variant = "light"
19644
+ }) => {
19645
+ const [dialogRef, setDialogRef] = (0, import_react48.useState)(null);
19646
+ (0, import_react48.useEffect)(() => {
19647
+ if (!dialogRef) return;
19648
+ dialogRef.showModal();
19649
+ }, [dialogRef]);
19650
+ const close = () => dialogRef?.close();
19651
+ const onClose = (event) => {
19652
+ if (closable) {
19653
+ dialogClosed();
19654
+ return;
19655
+ }
19656
+ event.preventDefault();
19657
+ event.currentTarget.showModal();
19658
+ };
19659
+ const onMouseDown = (event) => {
19660
+ if (event.target === event.currentTarget) {
19661
+ close();
19662
+ }
19663
+ };
19664
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19665
+ "dialog",
19666
+ {
19667
+ ref: setDialogRef,
19668
+ onMouseDown,
19669
+ onClose,
19670
+ className: cn(
19671
+ `
19672
+ max-w-[80vw] min-w-[10vw] border-none p-0 text-sigil-dialog-foreground
19673
+ outline-none backdrop-sigil-dialog
19674
+ `,
19675
+ cnd2(isDarkDialog2(variant), "bg-sigil-bg-dark", "bg-sigil-bg-light")
19676
+ ),
19677
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "border border-sigil-border", children: [
19678
+ title && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(DialogTitle2, { variant, children: title }),
19679
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19680
+ "div",
19681
+ {
19682
+ className: cn(
19683
+ "text-sigil-foreground",
19684
+ cnd2(
19685
+ variant === "light-compact" || variant === "dark-compact",
19686
+ "p-0"
19687
+ ),
19688
+ cnd2(
19689
+ variant !== "light-compact" && variant !== "dark-compact",
19690
+ "p-arcane"
19691
+ )
19692
+ ),
19693
+ children
19694
+ }
19695
+ )
19696
+ ] })
19697
+ }
19698
+ );
19699
+ };
19700
+
19701
+ // ../../packages/sigil/src/frontend/controls/dialogs.tsx
19702
+ var import_jsx_runtime59 = require("react/jsx-runtime");
19703
+ var ControlDialogButtons2 = (0, import_react49.forwardRef)(({ children, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
19704
+ "div",
19705
+ {
19706
+ ref,
19707
+ className: cn(
19708
+ `
19709
+ flex items-stretch gap-1
19710
+ [&>button]:grow
19711
+ `,
19712
+ clsControlPosition2("row"),
19713
+ className
19714
+ ),
19715
+ ...props,
19716
+ children
19717
+ }
19718
+ ));
19719
+ var ControlDialog2 = ({
19720
+ children,
19721
+ large,
19722
+ ...props
19723
+ }) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Dialog2, { ...props, variant: "dark", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
19724
+ "div",
19725
+ {
19726
+ className: cn(
19727
+ "gap-1 bg-sigil-bg-dark select-none",
19728
+ cnd2(large, "control-grid-large", "control-grid")
19729
+ ),
19730
+ children
19731
+ }
19732
+ ) });
19733
+
19734
+ // src/components/frontend/toolbox/root.tsx
19735
+ var import_jsx_runtime60 = require("react/jsx-runtime");
19736
+ var DeleteConfirmationDialog = ({ dialogMode, setDialogMode }) => {
19737
+ const { updateConfig } = (0, import_react50.useContext)(ConfigContext);
19738
+ const deleteTarget = (0, import_react50.useCallback)(() => {
19739
+ updateConfig((current) => {
19740
+ return {
19741
+ ...current,
19742
+ [dialogMode.section.type]: Object.fromEntries(
19743
+ Object.entries(current[dialogMode.section.type]).filter(
19744
+ ([uuid]) => uuid !== dialogMode.target.uuid
19745
+ )
19746
+ )
19747
+ };
19748
+ });
19749
+ setDialogMode(null);
19750
+ }, [updateConfig, dialogMode, setDialogMode]);
19751
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
19752
+ ControlDialog2,
19753
+ {
19754
+ dialogClosed: () => setDialogMode(null),
19755
+ title: STRINGS[dialogMode.section.type].deleteDialog,
19756
+ children: [
19757
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ControlDetails, { position: "row", children: STRINGS[dialogMode.section.type].deleteDialogDetails }),
19758
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(ControlDialogButtons2, { children: [
19759
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ControlButton, { onClick: () => setDialogMode(null), variant: "large", children: "Cancel" }),
19760
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
19761
+ ControlButton,
19762
+ {
19763
+ onClick: deleteTarget,
19764
+ variant: "large",
19765
+ destructive: true,
19766
+ icon: "delete",
19767
+ children: "Delete"
19768
+ }
19769
+ )
19770
+ ] })
19771
+ ]
19772
+ }
19773
+ );
19774
+ };
19775
+ var ToolboxRoot = ({ info }) => {
19776
+ const { config } = info;
19777
+ const { sendMessage, call } = (0, import_react50.useContext)(StageContext);
19778
+ const [dialogMode, setDialogMode] = (0, import_react50.useState)(null);
19779
+ const [assignToOutput, setAssignToOutput] = (0, import_react50.useState)(null);
19780
+ (0, import_react50.useEffect)(() => {
19781
+ if (assignToOutput) {
19782
+ const onEscape = (e) => {
19783
+ if (e.key === "Escape") {
19784
+ setAssignToOutput(null);
19785
+ }
19786
+ };
19787
+ window.addEventListener("keydown", onEscape);
19788
+ return () => {
19789
+ window.removeEventListener("keydown", onEscape);
19790
+ };
19791
+ }
19792
+ }, [assignToOutput]);
19793
+ const updateConfig = (0, import_react50.useCallback)(
19794
+ (change) => {
19795
+ const diff = diffJson(config, change(config));
19796
+ sendMessage?.({
19797
+ type: "component-message",
19798
+ namespace: "timecode-toolbox",
19799
+ component: "toolbox-root",
19800
+ componentKey: info.key,
19801
+ action: "update-config",
19802
+ diff
19803
+ });
19804
+ },
19805
+ [sendMessage, info.key, config]
19806
+ );
19807
+ const configContext = (0, import_react50.useMemo)(
19808
+ () => ({
19809
+ config,
19810
+ network: info.network,
19811
+ updateConfig
19812
+ }),
19813
+ [config, info.network, updateConfig]
19814
+ );
19815
+ const getNetworkInterfaces = (0, import_react50.useCallback)(async () => {
19816
+ if (!call) {
19817
+ throw new Error("No call function available");
19818
+ }
19819
+ return call({
19820
+ namespace: "timecode-toolbox",
19821
+ type: "component-call",
19822
+ componentKey: info.key,
19823
+ action: "toolbox-root-get-network-interfaces"
19824
+ });
19825
+ }, [call, info.key]);
19826
+ const networkContextValue = (0, import_react50.useMemo)(() => {
19827
+ return {
18768
19828
  getNetworkInterfaces
18769
19829
  };
18770
19830
  }, [getNetworkInterfaces]);
18771
- const assignToOutputCallback = (0, import_react42.useMemo)(() => {
19831
+ const assignToOutputCallback = (0, import_react50.useMemo)(() => {
18772
19832
  if (!assignToOutput) {
18773
19833
  return null;
18774
19834
  }
@@ -18793,7 +19853,7 @@ var ToolboxRoot = ({ info }) => {
18793
19853
  setAssignToOutput(null);
18794
19854
  };
18795
19855
  }, [assignToOutput, updateConfig]);
18796
- const callHandler = (0, import_react42.useCallback)(
19856
+ const callHandler = (0, import_react50.useCallback)(
18797
19857
  async ({ path, handler, args }) => {
18798
19858
  if (!call) {
18799
19859
  throw new Error("No call function available");
@@ -18810,26 +19870,26 @@ var ToolboxRoot = ({ info }) => {
18810
19870
  },
18811
19871
  [call, info.key]
18812
19872
  );
18813
- const handlers = (0, import_react42.useMemo)(
19873
+ const handlers = (0, import_react50.useMemo)(
18814
19874
  () => ({
18815
19875
  handlers: info.handlers,
18816
19876
  callHandler
18817
19877
  }),
18818
19878
  [info.handlers, callHandler]
18819
19879
  );
18820
- const windowedTimecodeId = (0, import_react42.useMemo)(
19880
+ const windowedTimecodeId = (0, import_react50.useMemo)(
18821
19881
  () => getFragmentValue("tc", TIMECODE_INSTANCE_ID),
18822
19882
  []
18823
19883
  );
18824
- const root = (0, import_react42.useMemo)(
18825
- () => windowedTimecodeId ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Layout, { modes: null, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(FullscreenTimecodeDisplay, { id: windowedTimecodeId }) }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
18826
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
19884
+ const root = (0, import_react50.useMemo)(
19885
+ () => windowedTimecodeId ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Layout, { modes: null, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(FullscreenTimecodeDisplay, { id: windowedTimecodeId }) }) : /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
19886
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
18827
19887
  Layout,
18828
19888
  {
18829
19889
  footer: true,
18830
19890
  modes: {
18831
19891
  license: {
18832
- child: (setWindowMode) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
19892
+ child: (setWindowMode) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
18833
19893
  License,
18834
19894
  {
18835
19895
  license: info.license,
@@ -18840,39 +19900,39 @@ var ToolboxRoot = ({ info }) => {
18840
19900
  title: STRINGS.license
18841
19901
  },
18842
19902
  settings: {
18843
- child: (setWindowMode) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Settings, { setWindowMode }),
19903
+ child: (setWindowMode) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Settings, { setWindowMode }),
18844
19904
  icon: "settings",
18845
19905
  title: STRINGS.settings.title
18846
19906
  },
18847
19907
  debug: {
18848
- child: () => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Debugger, { title: STRINGS.debugger, className: "size-full" }),
19908
+ child: () => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Debugger, { title: STRINGS.debugger, className: "size-full" }),
18849
19909
  icon: "bug_report",
18850
19910
  title: STRINGS.debugger
18851
19911
  }
18852
19912
  },
18853
19913
  licenseMode: "license",
18854
- children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
18855
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(UpdateBanner, {}),
18856
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
19914
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
19915
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(UpdateBanner, {}),
19916
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
18857
19917
  "div",
18858
19918
  {
18859
19919
  className: "\n flex h-0 grow flex-col gap-px overflow-y-auto bg-sigil-border\n scrollbar-sigil\n ",
18860
19920
  children: [
18861
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
19921
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
18862
19922
  InputsSection,
18863
19923
  {
18864
19924
  setDialogMode,
18865
19925
  assignToOutput: assignToOutputCallback
18866
19926
  }
18867
19927
  ),
18868
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
19928
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
18869
19929
  GeneratorsSection,
18870
19930
  {
18871
19931
  setDialogMode,
18872
19932
  assignToOutput: assignToOutputCallback
18873
19933
  }
18874
19934
  ),
18875
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
19935
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
18876
19936
  OutputsSection,
18877
19937
  {
18878
19938
  setDialogMode,
@@ -18886,45 +19946,52 @@ var ToolboxRoot = ({ info }) => {
18886
19946
  ] })
18887
19947
  }
18888
19948
  ),
18889
- dialogMode?.section.type === "inputs" && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
18890
- InputSettingsDialog,
19949
+ isDeleteDialogMode(dialogMode) ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
19950
+ DeleteConfirmationDialog,
18891
19951
  {
18892
- close: closeDialog,
18893
- input: dialogMode.section.input,
18894
- target: dialogMode.target
19952
+ dialogMode,
19953
+ setDialogMode
18895
19954
  }
18896
- ),
18897
- dialogMode?.section.type === "generators" && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
18898
- GeneratorSettingsDialog,
18899
- {
18900
- close: closeDialog,
18901
- generator: dialogMode.section.generator,
18902
- target: dialogMode.target
18903
- }
18904
- ),
18905
- dialogMode?.section.type === "outputs" && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
18906
- OutputSettingsDialog,
18907
- {
18908
- close: closeDialog,
18909
- output: dialogMode.section.output,
18910
- target: dialogMode.target
18911
- }
18912
- )
19955
+ ) : /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
19956
+ dialogMode?.section.type === "inputs" && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
19957
+ InputSettingsDialog,
19958
+ {
19959
+ setDialogMode,
19960
+ input: dialogMode.section.input,
19961
+ target: dialogMode.target
19962
+ }
19963
+ ),
19964
+ dialogMode?.section.type === "generators" && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
19965
+ GeneratorSettingsDialog,
19966
+ {
19967
+ setDialogMode,
19968
+ generator: dialogMode.section.generator,
19969
+ target: dialogMode.target
19970
+ }
19971
+ ),
19972
+ dialogMode?.section.type === "outputs" && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
19973
+ OutputSettingsDialog,
19974
+ {
19975
+ setDialogMode,
19976
+ output: dialogMode.section.output,
19977
+ target: dialogMode.target
19978
+ }
19979
+ )
19980
+ ] })
18913
19981
  ] }),
18914
19982
  [
18915
19983
  assignToOutput,
18916
19984
  assignToOutputCallback,
18917
- closeDialog,
18918
19985
  dialogMode,
18919
19986
  windowedTimecodeId,
18920
19987
  info.license
18921
19988
  ]
18922
19989
  );
18923
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ConfigContext.Provider, { value: configContext, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(NetworkContext.Provider, { value: networkContextValue, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ApplicationStateContext.Provider, { value: info.state, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ApplicationHandlersContext.Provider, { value: handlers, children: root }) }) }) });
19990
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ConfigContext.Provider, { value: configContext, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(NetworkContext.Provider, { value: networkContextValue, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ApplicationStateContext.Provider, { value: info.state, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ApplicationHandlersContext.Provider, { value: handlers, children: root }) }) }) });
18924
19991
  };
18925
19992
 
18926
19993
  // src/components/frontend/index.tsx
18927
- var import_jsx_runtime54 = require("react/jsx-runtime");
19994
+ var import_jsx_runtime61 = require("react/jsx-runtime");
18928
19995
  var timecodeToolboxFrontendComponents = () => ({
18929
19996
  namespace: NAMESPACE,
18930
19997
  render: (info) => {
@@ -18933,9 +20000,9 @@ var timecodeToolboxFrontendComponents = () => ({
18933
20000
  }
18934
20001
  switch (info.component) {
18935
20002
  case "toolbox-root":
18936
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(ToolboxRoot, { info });
20003
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(ToolboxRoot, { info });
18937
20004
  case "license-gate":
18938
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(LicenseGate, { info });
20005
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(LicenseGate, { info });
18939
20006
  }
18940
20007
  }
18941
20008
  });
@@ -18943,10 +20010,11 @@ var startTimecodeToolboxServerFrontend = (browser) => {
18943
20010
  startSigilFrontend({
18944
20011
  browser,
18945
20012
  appRenderers: [timecodeToolboxFrontendComponents()],
18946
- loadingState: () => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { style: { width: "100%", textAlign: "center", padding: "2rem" }, children: "Loading Toolbox..." })
20013
+ loadingState: () => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { style: { width: "100%", textAlign: "center", padding: "2rem" }, children: "Loading Toolbox..." })
18947
20014
  });
18948
20015
  };
18949
20016
  window.startTimecodeToolboxServerFrontend = startTimecodeToolboxServerFrontend;
20017
+ window.createBrowserMediaSession = createBrowserMediaSession;
18950
20018
  // Annotate the CommonJS export names for ESM import in node:
18951
20019
  0 && (module.exports = {
18952
20020
  startTimecodeToolboxServerFrontend,