@imperosoft/cris-webui-components 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2646,7 +2646,7 @@ function DspIoPage({
2646
2646
  const row = /* @__PURE__ */ jsx13(
2647
2647
  "div",
2648
2648
  {
2649
- className: "flex h-full items-stretch gap-[0.3em] px-[0.5em] py-[0.5em]",
2649
+ className: `flex h-full items-stretch gap-[0.3em] px-[0.5em] py-[0.5em]${bare ? "" : " w-max mx-auto"}`,
2650
2650
  style: { minWidth: "min-content" },
2651
2651
  children: sections.map((sec, i) => /* @__PURE__ */ jsxs11("div", { className: "flex flex-col h-full", children: [
2652
2652
  hasHeaders && // Header band: spans this group's strips. The 1px separator lives only
@@ -2706,6 +2706,7 @@ var DSP_CLASS_DEFAULTS = {
2706
2706
  faderThumb: "bg-[#4f5152] rounded",
2707
2707
  mute: "w-full h-full rounded-lg flex items-center justify-center transition-colors bg-[#4f5152] text-white",
2708
2708
  muteActive: "bg-[#dc2626] text-white",
2709
+ mixerBackplate: "bg-[#282C34]",
2709
2710
  mixerCorner: "sticky z-30 flex items-center justify-center bg-[#282C34] text-[#4f5152] text-[1.1em] font-bold border border-black/30",
2710
2711
  mixerChrome: "sticky flex items-center justify-center text-center bg-[#282C34] text-white leading-tight border border-black/30",
2711
2712
  cell: "z-10 flex items-center justify-center border border-black/30",
@@ -2800,15 +2801,42 @@ import { useCustomObject as useCustomObject6, useCustomObjectSend as useCustomOb
2800
2801
  // src/components/dsp/DspMixer.tsx
2801
2802
  import { useRef as useRef5 } from "react";
2802
2803
  import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
2803
- var GROUP_W = "2.6em";
2804
- var COMMON_W = "9em";
2805
- var CHAN_W = "3em";
2806
- var GROUP_H = "2.2em";
2807
- var COMMON_H = "2.4em";
2808
- var CHAN_H = "2.1em";
2809
- var CELL_W = "7.5em";
2810
- var ROW_H = "4.5em";
2804
+ var DEFAULT_GROUP_W = "2.6em";
2805
+ var DEFAULT_COMMON_W = "9em";
2806
+ var DEFAULT_CHAN_W = "3em";
2807
+ var DEFAULT_GROUP_H = "2.2em";
2808
+ var DEFAULT_COMMON_H = "2.4em";
2809
+ var DEFAULT_CHAN_H = "2.1em";
2810
+ var DEFAULT_CELL_W = "7.5em";
2811
+ var DEFAULT_ROW_H = "4.5em";
2811
2812
  var DRAG_FACTOR = 0.6;
2813
+ function resolveGeometry(o, inputCount, outputCount) {
2814
+ const groupW = o?.groupW ?? DEFAULT_GROUP_W;
2815
+ const commonW = o?.commonW ?? DEFAULT_COMMON_W;
2816
+ const chanW = o?.chanW ?? DEFAULT_CHAN_W;
2817
+ const groupH = o?.groupH ?? DEFAULT_GROUP_H;
2818
+ const commonH = o?.commonH ?? DEFAULT_COMMON_H;
2819
+ const chanH = o?.chanH ?? DEFAULT_CHAN_H;
2820
+ const cellW = o?.cellW ?? DEFAULT_CELL_W;
2821
+ const rowH = o?.rowH ?? DEFAULT_ROW_H;
2822
+ return {
2823
+ groupW,
2824
+ commonW,
2825
+ chanW,
2826
+ groupH,
2827
+ commonH,
2828
+ chanH,
2829
+ cellW,
2830
+ rowH,
2831
+ topLink: groupH,
2832
+ topChan: `calc(${groupH} + ${commonH})`,
2833
+ leftLink: groupW,
2834
+ leftChan: `calc(${groupW} + ${commonW})`,
2835
+ z: { corner: 40, group: 30, link: 25, chan: 20 },
2836
+ inputCount,
2837
+ outputCount
2838
+ };
2839
+ }
2812
2840
  function CrosspointOnIcon({ icon }) {
2813
2841
  if (typeof icon !== "string") return /* @__PURE__ */ jsx16(Fragment3, { children: icon });
2814
2842
  return /* @__PURE__ */ jsx16(
@@ -2822,7 +2850,17 @@ function CrosspointOnIcon({ icon }) {
2822
2850
  }
2823
2851
  );
2824
2852
  }
2825
- function DspMixer({ status, oid, send, cls, icons }) {
2853
+ function DspMixer({
2854
+ status,
2855
+ oid,
2856
+ send,
2857
+ cls,
2858
+ icons,
2859
+ geometry,
2860
+ renderInputHeader,
2861
+ renderOutputHeader,
2862
+ renderCorner
2863
+ }) {
2826
2864
  const scrollRef = useRef5(null);
2827
2865
  const startRef = useRef5(null);
2828
2866
  const movedRef = useRef5(false);
@@ -2872,13 +2910,167 @@ function DspMixer({ status, oid, send, cls, icons }) {
2872
2910
  if (inputs.length === 0 || outputs.length === 0) {
2873
2911
  return /* @__PURE__ */ jsx16("div", { className: cls.message, children: "Sin crosspoints" });
2874
2912
  }
2913
+ const geom = resolveGeometry(geometry, inputs.length, outputs.length);
2875
2914
  const inAxis = buildMixerAxisGrouped(inputs, linksFor(status?.ln, "in"), groupsFor(status?.dg, "in"));
2876
2915
  const outAxis = buildMixerAxisGrouped(outputs, linksFor(status?.ln, "out"), groupsFor(status?.dg, "out"));
2877
- const topLink = GROUP_H;
2878
- const topChan = `calc(${GROUP_H} + ${COMMON_H})`;
2879
- const leftLink = GROUP_W;
2880
- const leftChan = `calc(${GROUP_W} + ${COMMON_W})`;
2881
- const Z = { corner: 40, group: 30, link: 25, chan: 20 };
2916
+ const { topLink, topChan, leftLink, leftChan, z: Z } = geom;
2917
+ const defaultInputHeader = () => inAxis.flatMap((it, ii) => {
2918
+ const col = 4 + ii;
2919
+ const nodes = [];
2920
+ if (it.groupStart) {
2921
+ nodes.push(
2922
+ /* @__PURE__ */ jsx16(
2923
+ "div",
2924
+ {
2925
+ className: cls.mixerGroup,
2926
+ style: { top: 0, zIndex: Z.group, gridRow: 1, gridColumn: `${col} / span ${it.groupSpan}` },
2927
+ title: it.groupName,
2928
+ children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2 px-[0.2em]", children: it.groupName })
2929
+ },
2930
+ `igrp:${it.id}`
2931
+ )
2932
+ );
2933
+ } else if (it.groupName === void 0) {
2934
+ nodes.push(
2935
+ /* @__PURE__ */ jsx16(
2936
+ "div",
2937
+ {
2938
+ className: cls.mixerChrome,
2939
+ style: { top: 0, zIndex: Z.group, gridRow: 1, gridColumn: col }
2940
+ },
2941
+ `ifill:${it.id}`
2942
+ )
2943
+ );
2944
+ }
2945
+ if (it.linkCommon !== void 0) {
2946
+ if (it.linkStart) {
2947
+ nodes.push(
2948
+ /* @__PURE__ */ jsx16(
2949
+ "div",
2950
+ {
2951
+ className: `${cls.mixerChrome} px-[0.2em] font-semibold`,
2952
+ style: { top: topLink, zIndex: Z.link, gridRow: 2, gridColumn: `${col} / span ${it.linkSpan}` },
2953
+ title: it.linkCommon,
2954
+ children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2", children: it.linkCommon })
2955
+ },
2956
+ `ilnk:${it.id}`
2957
+ )
2958
+ );
2959
+ }
2960
+ nodes.push(
2961
+ /* @__PURE__ */ jsx16(
2962
+ "div",
2963
+ {
2964
+ className: `${cls.mixerChrome} px-[0.2em]`,
2965
+ style: { top: topChan, zIndex: Z.chan, gridRow: 3, gridColumn: col },
2966
+ title: it.channelLabel,
2967
+ children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-1", children: it.channelLabel })
2968
+ },
2969
+ `ichn:${it.id}`
2970
+ )
2971
+ );
2972
+ } else {
2973
+ nodes.push(
2974
+ /* @__PURE__ */ jsx16(
2975
+ "div",
2976
+ {
2977
+ className: cls.mixerChrome,
2978
+ style: { top: topLink, zIndex: Z.link, gridRow: 2, gridColumn: col }
2979
+ },
2980
+ `ilf:${it.id}`
2981
+ ),
2982
+ /* @__PURE__ */ jsx16(
2983
+ "div",
2984
+ {
2985
+ className: `${cls.mixerChrome} px-[0.2em]`,
2986
+ style: { top: topChan, zIndex: Z.chan, gridRow: 3, gridColumn: col },
2987
+ title: it.channelLabel,
2988
+ children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2", children: it.channelLabel })
2989
+ },
2990
+ `ichn:${it.id}`
2991
+ )
2992
+ );
2993
+ }
2994
+ return nodes;
2995
+ });
2996
+ const defaultOutputHeader = () => outAxis.flatMap((it, oo) => {
2997
+ const row = 4 + oo;
2998
+ const nodes = [];
2999
+ if (it.groupStart) {
3000
+ nodes.push(
3001
+ /* @__PURE__ */ jsx16(
3002
+ "div",
3003
+ {
3004
+ className: cls.mixerGroupV,
3005
+ style: {
3006
+ left: 0,
3007
+ zIndex: Z.group,
3008
+ gridColumn: 1,
3009
+ gridRow: `${row} / span ${it.groupSpan}`,
3010
+ writingMode: "vertical-rl",
3011
+ transform: "rotate(180deg)"
3012
+ },
3013
+ title: it.groupName,
3014
+ children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2", children: it.groupName })
3015
+ },
3016
+ `ogrp:${it.id}`
3017
+ )
3018
+ );
3019
+ } else if (it.groupName === void 0) {
3020
+ nodes.push(
3021
+ /* @__PURE__ */ jsx16(
3022
+ "div",
3023
+ {
3024
+ className: cls.mixerChrome,
3025
+ style: { left: 0, zIndex: Z.group, gridColumn: 1, gridRow: row }
3026
+ },
3027
+ `ofill:${it.id}`
3028
+ )
3029
+ );
3030
+ }
3031
+ if (it.linkCommon !== void 0) {
3032
+ if (it.linkStart) {
3033
+ nodes.push(
3034
+ /* @__PURE__ */ jsx16(
3035
+ "div",
3036
+ {
3037
+ className: `${cls.mixerChrome} justify-start px-[0.4em] font-semibold`,
3038
+ style: { left: leftLink, zIndex: Z.link, gridColumn: 2, gridRow: `${row} / span ${it.linkSpan}` },
3039
+ title: it.linkCommon,
3040
+ children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2 text-left", children: it.linkCommon })
3041
+ },
3042
+ `olnk:${it.id}`
3043
+ )
3044
+ );
3045
+ }
3046
+ nodes.push(
3047
+ /* @__PURE__ */ jsx16(
3048
+ "div",
3049
+ {
3050
+ className: cls.mixerChrome,
3051
+ style: { left: leftChan, zIndex: Z.chan, gridColumn: 3, gridRow: row },
3052
+ title: it.channelLabel,
3053
+ children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-1", children: it.channelLabel })
3054
+ },
3055
+ `ochn:${it.id}`
3056
+ )
3057
+ );
3058
+ } else {
3059
+ nodes.push(
3060
+ /* @__PURE__ */ jsx16(
3061
+ "div",
3062
+ {
3063
+ className: `${cls.mixerChrome} justify-start px-[0.4em]`,
3064
+ style: { left: leftLink, zIndex: Z.chan, gridColumn: "2 / span 2", gridRow: row },
3065
+ title: it.channelLabel,
3066
+ children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2 text-left", children: it.channelLabel })
3067
+ },
3068
+ `ochn:${it.id}`
3069
+ )
3070
+ );
3071
+ }
3072
+ return nodes;
3073
+ });
2882
3074
  return /* @__PURE__ */ jsx16(
2883
3075
  "div",
2884
3076
  {
@@ -2887,15 +3079,15 @@ function DspMixer({ status, oid, send, cls, icons }) {
2887
3079
  onPointerMove,
2888
3080
  onPointerUp,
2889
3081
  onPointerCancel: onPointerUp,
2890
- className: "w-full h-full overflow-auto no-scrollbar relative touch-none select-none cursor-grab",
3082
+ className: "w-full h-full overflow-auto no-scrollbar relative touch-none select-none cursor-grab flex",
2891
3083
  children: /* @__PURE__ */ jsxs12(
2892
3084
  "div",
2893
3085
  {
2894
- className: "grid",
3086
+ className: "grid m-auto",
2895
3087
  style: {
2896
3088
  // cols: [out group][out link][out channel][inputs…] rows: [in group][in link][in channel][outputs…]
2897
- gridTemplateColumns: `${GROUP_W} ${COMMON_W} ${CHAN_W} repeat(${inputs.length}, ${CELL_W})`,
2898
- gridTemplateRows: `${GROUP_H} ${COMMON_H} ${CHAN_H} repeat(${outputs.length}, ${ROW_H})`,
3089
+ gridTemplateColumns: `${geom.groupW} ${geom.commonW} ${geom.chanW} repeat(${inputs.length}, ${geom.cellW})`,
3090
+ gridTemplateRows: `${geom.groupH} ${geom.commonH} ${geom.chanH} repeat(${outputs.length}, ${geom.rowH})`,
2899
3091
  minWidth: "min-content"
2900
3092
  },
2901
3093
  children: [
@@ -2903,7 +3095,7 @@ function DspMixer({ status, oid, send, cls, icons }) {
2903
3095
  "div",
2904
3096
  {
2905
3097
  "aria-hidden": true,
2906
- className: "sticky bg-[#282C34]",
3098
+ className: `sticky ${cls.mixerBackplate}`,
2907
3099
  style: { top: 0, zIndex: 15, gridColumn: "1 / -1", gridRow: "1 / span 3" }
2908
3100
  }
2909
3101
  ),
@@ -2911,7 +3103,7 @@ function DspMixer({ status, oid, send, cls, icons }) {
2911
3103
  "div",
2912
3104
  {
2913
3105
  "aria-hidden": true,
2914
- className: "sticky bg-[#282C34]",
3106
+ className: `sticky ${cls.mixerBackplate}`,
2915
3107
  style: { left: 0, zIndex: 15, gridColumn: "1 / span 3", gridRow: "1 / -1" }
2916
3108
  }
2917
3109
  ),
@@ -2920,166 +3112,11 @@ function DspMixer({ status, oid, send, cls, icons }) {
2920
3112
  {
2921
3113
  className: cls.mixerCorner,
2922
3114
  style: { top: 0, left: 0, zIndex: Z.corner, gridColumn: "1 / span 3", gridRow: "1 / span 3" },
2923
- children: "OUT \\ IN"
3115
+ children: renderCorner ? renderCorner(geom) : "OUT \\ IN"
2924
3116
  }
2925
3117
  ),
2926
- inAxis.flatMap((it, ii) => {
2927
- const col = 4 + ii;
2928
- const nodes = [];
2929
- if (it.groupStart) {
2930
- nodes.push(
2931
- /* @__PURE__ */ jsx16(
2932
- "div",
2933
- {
2934
- className: cls.mixerGroup,
2935
- style: { top: 0, zIndex: Z.group, gridRow: 1, gridColumn: `${col} / span ${it.groupSpan}` },
2936
- title: it.groupName,
2937
- children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2 px-[0.2em]", children: it.groupName })
2938
- },
2939
- `igrp:${it.id}`
2940
- )
2941
- );
2942
- } else if (it.groupName === void 0) {
2943
- nodes.push(
2944
- /* @__PURE__ */ jsx16(
2945
- "div",
2946
- {
2947
- className: cls.mixerChrome,
2948
- style: { top: 0, zIndex: Z.group, gridRow: 1, gridColumn: col }
2949
- },
2950
- `ifill:${it.id}`
2951
- )
2952
- );
2953
- }
2954
- if (it.linkCommon !== void 0) {
2955
- if (it.linkStart) {
2956
- nodes.push(
2957
- /* @__PURE__ */ jsx16(
2958
- "div",
2959
- {
2960
- className: `${cls.mixerChrome} px-[0.2em] font-semibold`,
2961
- style: { top: topLink, zIndex: Z.link, gridRow: 2, gridColumn: `${col} / span ${it.linkSpan}` },
2962
- title: it.linkCommon,
2963
- children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2", children: it.linkCommon })
2964
- },
2965
- `ilnk:${it.id}`
2966
- )
2967
- );
2968
- }
2969
- nodes.push(
2970
- /* @__PURE__ */ jsx16(
2971
- "div",
2972
- {
2973
- className: `${cls.mixerChrome} px-[0.2em]`,
2974
- style: { top: topChan, zIndex: Z.chan, gridRow: 3, gridColumn: col },
2975
- title: it.channelLabel,
2976
- children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-1", children: it.channelLabel })
2977
- },
2978
- `ichn:${it.id}`
2979
- )
2980
- );
2981
- } else {
2982
- nodes.push(
2983
- /* @__PURE__ */ jsx16(
2984
- "div",
2985
- {
2986
- className: cls.mixerChrome,
2987
- style: { top: topLink, zIndex: Z.link, gridRow: 2, gridColumn: col }
2988
- },
2989
- `ilf:${it.id}`
2990
- ),
2991
- /* @__PURE__ */ jsx16(
2992
- "div",
2993
- {
2994
- className: `${cls.mixerChrome} px-[0.2em]`,
2995
- style: { top: topChan, zIndex: Z.chan, gridRow: 3, gridColumn: col },
2996
- title: it.channelLabel,
2997
- children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2", children: it.channelLabel })
2998
- },
2999
- `ichn:${it.id}`
3000
- )
3001
- );
3002
- }
3003
- return nodes;
3004
- }),
3005
- outAxis.flatMap((it, oo) => {
3006
- const row = 4 + oo;
3007
- const nodes = [];
3008
- if (it.groupStart) {
3009
- nodes.push(
3010
- /* @__PURE__ */ jsx16(
3011
- "div",
3012
- {
3013
- className: cls.mixerGroupV,
3014
- style: {
3015
- left: 0,
3016
- zIndex: Z.group,
3017
- gridColumn: 1,
3018
- gridRow: `${row} / span ${it.groupSpan}`,
3019
- writingMode: "vertical-rl",
3020
- transform: "rotate(180deg)"
3021
- },
3022
- title: it.groupName,
3023
- children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2", children: it.groupName })
3024
- },
3025
- `ogrp:${it.id}`
3026
- )
3027
- );
3028
- } else if (it.groupName === void 0) {
3029
- nodes.push(
3030
- /* @__PURE__ */ jsx16(
3031
- "div",
3032
- {
3033
- className: cls.mixerChrome,
3034
- style: { left: 0, zIndex: Z.group, gridColumn: 1, gridRow: row }
3035
- },
3036
- `ofill:${it.id}`
3037
- )
3038
- );
3039
- }
3040
- if (it.linkCommon !== void 0) {
3041
- if (it.linkStart) {
3042
- nodes.push(
3043
- /* @__PURE__ */ jsx16(
3044
- "div",
3045
- {
3046
- className: `${cls.mixerChrome} justify-start px-[0.4em] font-semibold`,
3047
- style: { left: leftLink, zIndex: Z.link, gridColumn: 2, gridRow: `${row} / span ${it.linkSpan}` },
3048
- title: it.linkCommon,
3049
- children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2 text-left", children: it.linkCommon })
3050
- },
3051
- `olnk:${it.id}`
3052
- )
3053
- );
3054
- }
3055
- nodes.push(
3056
- /* @__PURE__ */ jsx16(
3057
- "div",
3058
- {
3059
- className: cls.mixerChrome,
3060
- style: { left: leftChan, zIndex: Z.chan, gridColumn: 3, gridRow: row },
3061
- title: it.channelLabel,
3062
- children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-1", children: it.channelLabel })
3063
- },
3064
- `ochn:${it.id}`
3065
- )
3066
- );
3067
- } else {
3068
- nodes.push(
3069
- /* @__PURE__ */ jsx16(
3070
- "div",
3071
- {
3072
- className: `${cls.mixerChrome} justify-start px-[0.4em]`,
3073
- style: { left: leftLink, zIndex: Z.chan, gridColumn: "2 / span 2", gridRow: row },
3074
- title: it.channelLabel,
3075
- children: /* @__PURE__ */ jsx16("span", { className: "text-[1.1em] line-clamp-2 text-left", children: it.channelLabel })
3076
- },
3077
- `ochn:${it.id}`
3078
- )
3079
- );
3080
- }
3081
- return nodes;
3082
- }),
3118
+ renderInputHeader ? renderInputHeader(inAxis, geom) : defaultInputHeader(),
3119
+ renderOutputHeader ? renderOutputHeader(outAxis, geom) : defaultOutputHeader(),
3083
3120
  outAxis.map(
3084
3121
  (orow, oo) => inAxis.map((icol, ii) => {
3085
3122
  const on = isOn(orow.id, icol.id);
@@ -3106,12 +3143,34 @@ function DspMixer({ status, oid, send, cls, icons }) {
3106
3143
 
3107
3144
  // src/components/dsp/CrisViewDspMixer.tsx
3108
3145
  import { jsx as jsx17 } from "react/jsx-runtime";
3109
- function CrisViewDspMixer({ oid, classes, icons, className }) {
3146
+ function CrisViewDspMixer({
3147
+ oid,
3148
+ classes,
3149
+ icons,
3150
+ className,
3151
+ geometry,
3152
+ renderInputHeader,
3153
+ renderOutputHeader,
3154
+ renderCorner
3155
+ }) {
3110
3156
  const status = useCustomObject6(oid, { subscribe: true });
3111
3157
  const send = useCustomObjectSend6();
3112
3158
  const cls = resolveDspClasses(classes);
3113
3159
  const ic = resolveDspIcons(icons);
3114
- return /* @__PURE__ */ jsx17("div", { className: `w-full h-full ${className ?? ""}`, children: status === void 0 ? /* @__PURE__ */ jsx17("div", { className: cls.message, children: "Conectando\u2026" }) : /* @__PURE__ */ jsx17(DspMixer, { status, oid, send, cls, icons: ic }) });
3160
+ return /* @__PURE__ */ jsx17("div", { className: `w-full h-full ${className ?? ""}`, children: status === void 0 ? /* @__PURE__ */ jsx17("div", { className: cls.message, children: "Conectando\u2026" }) : /* @__PURE__ */ jsx17(
3161
+ DspMixer,
3162
+ {
3163
+ status,
3164
+ oid,
3165
+ send,
3166
+ cls,
3167
+ icons: ic,
3168
+ geometry,
3169
+ renderInputHeader,
3170
+ renderOutputHeader,
3171
+ renderCorner
3172
+ }
3173
+ ) });
3115
3174
  }
3116
3175
 
3117
3176
  // src/components/dsp/DspPresets.tsx
@@ -3181,6 +3240,7 @@ function DspPresets({
3181
3240
 
3182
3241
  // src/components/dsp/CrisViewDspFull.tsx
3183
3242
  import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
3243
+ var lastTabByOid = /* @__PURE__ */ new Map();
3184
3244
  function CrisViewDspFull({
3185
3245
  oid,
3186
3246
  presets,
@@ -3193,8 +3253,13 @@ function CrisViewDspFull({
3193
3253
  className,
3194
3254
  initialTab = "in"
3195
3255
  }) {
3196
- const safeInitial = initialTab === "mix" && skipCrosspoints ? "in" : initialTab;
3197
- const [tab, setTab] = useState6(safeInitial);
3256
+ const remembered = lastTabByOid.get(oid) ?? initialTab;
3257
+ const safeInitial = remembered === "mix" && skipCrosspoints ? "in" : remembered;
3258
+ const [tab, setTabState] = useState6(safeInitial);
3259
+ const setTab = (t) => {
3260
+ lastTabByOid.set(oid, t);
3261
+ setTabState(t);
3262
+ };
3198
3263
  const status = useCustomObject7(oid, { subscribe: true });
3199
3264
  const send = useCustomObjectSend7();
3200
3265
  const cls = resolveDspClasses(classes);