@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.js CHANGED
@@ -2702,7 +2702,7 @@ function DspIoPage({
2702
2702
  const row = /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2703
2703
  "div",
2704
2704
  {
2705
- className: "flex h-full items-stretch gap-[0.3em] px-[0.5em] py-[0.5em]",
2705
+ className: `flex h-full items-stretch gap-[0.3em] px-[0.5em] py-[0.5em]${bare ? "" : " w-max mx-auto"}`,
2706
2706
  style: { minWidth: "min-content" },
2707
2707
  children: sections.map((sec, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col h-full", children: [
2708
2708
  hasHeaders && // Header band: spans this group's strips. The 1px separator lives only
@@ -2762,6 +2762,7 @@ var DSP_CLASS_DEFAULTS = {
2762
2762
  faderThumb: "bg-[#4f5152] rounded",
2763
2763
  mute: "w-full h-full rounded-lg flex items-center justify-center transition-colors bg-[#4f5152] text-white",
2764
2764
  muteActive: "bg-[#dc2626] text-white",
2765
+ mixerBackplate: "bg-[#282C34]",
2765
2766
  mixerCorner: "sticky z-30 flex items-center justify-center bg-[#282C34] text-[#4f5152] text-[1.1em] font-bold border border-black/30",
2766
2767
  mixerChrome: "sticky flex items-center justify-center text-center bg-[#282C34] text-white leading-tight border border-black/30",
2767
2768
  cell: "z-10 flex items-center justify-center border border-black/30",
@@ -2856,15 +2857,42 @@ var import_cris_webui_ch5_core13 = require("@imperosoft/cris-webui-ch5-core");
2856
2857
  // src/components/dsp/DspMixer.tsx
2857
2858
  var import_react7 = require("react");
2858
2859
  var import_jsx_runtime16 = require("react/jsx-runtime");
2859
- var GROUP_W = "2.6em";
2860
- var COMMON_W = "9em";
2861
- var CHAN_W = "3em";
2862
- var GROUP_H = "2.2em";
2863
- var COMMON_H = "2.4em";
2864
- var CHAN_H = "2.1em";
2865
- var CELL_W = "7.5em";
2866
- var ROW_H = "4.5em";
2860
+ var DEFAULT_GROUP_W = "2.6em";
2861
+ var DEFAULT_COMMON_W = "9em";
2862
+ var DEFAULT_CHAN_W = "3em";
2863
+ var DEFAULT_GROUP_H = "2.2em";
2864
+ var DEFAULT_COMMON_H = "2.4em";
2865
+ var DEFAULT_CHAN_H = "2.1em";
2866
+ var DEFAULT_CELL_W = "7.5em";
2867
+ var DEFAULT_ROW_H = "4.5em";
2867
2868
  var DRAG_FACTOR = 0.6;
2869
+ function resolveGeometry(o, inputCount, outputCount) {
2870
+ const groupW = o?.groupW ?? DEFAULT_GROUP_W;
2871
+ const commonW = o?.commonW ?? DEFAULT_COMMON_W;
2872
+ const chanW = o?.chanW ?? DEFAULT_CHAN_W;
2873
+ const groupH = o?.groupH ?? DEFAULT_GROUP_H;
2874
+ const commonH = o?.commonH ?? DEFAULT_COMMON_H;
2875
+ const chanH = o?.chanH ?? DEFAULT_CHAN_H;
2876
+ const cellW = o?.cellW ?? DEFAULT_CELL_W;
2877
+ const rowH = o?.rowH ?? DEFAULT_ROW_H;
2878
+ return {
2879
+ groupW,
2880
+ commonW,
2881
+ chanW,
2882
+ groupH,
2883
+ commonH,
2884
+ chanH,
2885
+ cellW,
2886
+ rowH,
2887
+ topLink: groupH,
2888
+ topChan: `calc(${groupH} + ${commonH})`,
2889
+ leftLink: groupW,
2890
+ leftChan: `calc(${groupW} + ${commonW})`,
2891
+ z: { corner: 40, group: 30, link: 25, chan: 20 },
2892
+ inputCount,
2893
+ outputCount
2894
+ };
2895
+ }
2868
2896
  function CrosspointOnIcon({ icon }) {
2869
2897
  if (typeof icon !== "string") return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: icon });
2870
2898
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
@@ -2878,7 +2906,17 @@ function CrosspointOnIcon({ icon }) {
2878
2906
  }
2879
2907
  );
2880
2908
  }
2881
- function DspMixer({ status, oid, send, cls, icons }) {
2909
+ function DspMixer({
2910
+ status,
2911
+ oid,
2912
+ send,
2913
+ cls,
2914
+ icons,
2915
+ geometry,
2916
+ renderInputHeader,
2917
+ renderOutputHeader,
2918
+ renderCorner
2919
+ }) {
2882
2920
  const scrollRef = (0, import_react7.useRef)(null);
2883
2921
  const startRef = (0, import_react7.useRef)(null);
2884
2922
  const movedRef = (0, import_react7.useRef)(false);
@@ -2928,13 +2966,167 @@ function DspMixer({ status, oid, send, cls, icons }) {
2928
2966
  if (inputs.length === 0 || outputs.length === 0) {
2929
2967
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: cls.message, children: "Sin crosspoints" });
2930
2968
  }
2969
+ const geom = resolveGeometry(geometry, inputs.length, outputs.length);
2931
2970
  const inAxis = buildMixerAxisGrouped(inputs, linksFor(status?.ln, "in"), groupsFor(status?.dg, "in"));
2932
2971
  const outAxis = buildMixerAxisGrouped(outputs, linksFor(status?.ln, "out"), groupsFor(status?.dg, "out"));
2933
- const topLink = GROUP_H;
2934
- const topChan = `calc(${GROUP_H} + ${COMMON_H})`;
2935
- const leftLink = GROUP_W;
2936
- const leftChan = `calc(${GROUP_W} + ${COMMON_W})`;
2937
- const Z = { corner: 40, group: 30, link: 25, chan: 20 };
2972
+ const { topLink, topChan, leftLink, leftChan, z: Z } = geom;
2973
+ const defaultInputHeader = () => inAxis.flatMap((it, ii) => {
2974
+ const col = 4 + ii;
2975
+ const nodes = [];
2976
+ if (it.groupStart) {
2977
+ nodes.push(
2978
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2979
+ "div",
2980
+ {
2981
+ className: cls.mixerGroup,
2982
+ style: { top: 0, zIndex: Z.group, gridRow: 1, gridColumn: `${col} / span ${it.groupSpan}` },
2983
+ title: it.groupName,
2984
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2 px-[0.2em]", children: it.groupName })
2985
+ },
2986
+ `igrp:${it.id}`
2987
+ )
2988
+ );
2989
+ } else if (it.groupName === void 0) {
2990
+ nodes.push(
2991
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2992
+ "div",
2993
+ {
2994
+ className: cls.mixerChrome,
2995
+ style: { top: 0, zIndex: Z.group, gridRow: 1, gridColumn: col }
2996
+ },
2997
+ `ifill:${it.id}`
2998
+ )
2999
+ );
3000
+ }
3001
+ if (it.linkCommon !== void 0) {
3002
+ if (it.linkStart) {
3003
+ nodes.push(
3004
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3005
+ "div",
3006
+ {
3007
+ className: `${cls.mixerChrome} px-[0.2em] font-semibold`,
3008
+ style: { top: topLink, zIndex: Z.link, gridRow: 2, gridColumn: `${col} / span ${it.linkSpan}` },
3009
+ title: it.linkCommon,
3010
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2", children: it.linkCommon })
3011
+ },
3012
+ `ilnk:${it.id}`
3013
+ )
3014
+ );
3015
+ }
3016
+ nodes.push(
3017
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3018
+ "div",
3019
+ {
3020
+ className: `${cls.mixerChrome} px-[0.2em]`,
3021
+ style: { top: topChan, zIndex: Z.chan, gridRow: 3, gridColumn: col },
3022
+ title: it.channelLabel,
3023
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-1", children: it.channelLabel })
3024
+ },
3025
+ `ichn:${it.id}`
3026
+ )
3027
+ );
3028
+ } else {
3029
+ nodes.push(
3030
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3031
+ "div",
3032
+ {
3033
+ className: cls.mixerChrome,
3034
+ style: { top: topLink, zIndex: Z.link, gridRow: 2, gridColumn: col }
3035
+ },
3036
+ `ilf:${it.id}`
3037
+ ),
3038
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3039
+ "div",
3040
+ {
3041
+ className: `${cls.mixerChrome} px-[0.2em]`,
3042
+ style: { top: topChan, zIndex: Z.chan, gridRow: 3, gridColumn: col },
3043
+ title: it.channelLabel,
3044
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2", children: it.channelLabel })
3045
+ },
3046
+ `ichn:${it.id}`
3047
+ )
3048
+ );
3049
+ }
3050
+ return nodes;
3051
+ });
3052
+ const defaultOutputHeader = () => outAxis.flatMap((it, oo) => {
3053
+ const row = 4 + oo;
3054
+ const nodes = [];
3055
+ if (it.groupStart) {
3056
+ nodes.push(
3057
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3058
+ "div",
3059
+ {
3060
+ className: cls.mixerGroupV,
3061
+ style: {
3062
+ left: 0,
3063
+ zIndex: Z.group,
3064
+ gridColumn: 1,
3065
+ gridRow: `${row} / span ${it.groupSpan}`,
3066
+ writingMode: "vertical-rl",
3067
+ transform: "rotate(180deg)"
3068
+ },
3069
+ title: it.groupName,
3070
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2", children: it.groupName })
3071
+ },
3072
+ `ogrp:${it.id}`
3073
+ )
3074
+ );
3075
+ } else if (it.groupName === void 0) {
3076
+ nodes.push(
3077
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3078
+ "div",
3079
+ {
3080
+ className: cls.mixerChrome,
3081
+ style: { left: 0, zIndex: Z.group, gridColumn: 1, gridRow: row }
3082
+ },
3083
+ `ofill:${it.id}`
3084
+ )
3085
+ );
3086
+ }
3087
+ if (it.linkCommon !== void 0) {
3088
+ if (it.linkStart) {
3089
+ nodes.push(
3090
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3091
+ "div",
3092
+ {
3093
+ className: `${cls.mixerChrome} justify-start px-[0.4em] font-semibold`,
3094
+ style: { left: leftLink, zIndex: Z.link, gridColumn: 2, gridRow: `${row} / span ${it.linkSpan}` },
3095
+ title: it.linkCommon,
3096
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2 text-left", children: it.linkCommon })
3097
+ },
3098
+ `olnk:${it.id}`
3099
+ )
3100
+ );
3101
+ }
3102
+ nodes.push(
3103
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3104
+ "div",
3105
+ {
3106
+ className: cls.mixerChrome,
3107
+ style: { left: leftChan, zIndex: Z.chan, gridColumn: 3, gridRow: row },
3108
+ title: it.channelLabel,
3109
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-1", children: it.channelLabel })
3110
+ },
3111
+ `ochn:${it.id}`
3112
+ )
3113
+ );
3114
+ } else {
3115
+ nodes.push(
3116
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3117
+ "div",
3118
+ {
3119
+ className: `${cls.mixerChrome} justify-start px-[0.4em]`,
3120
+ style: { left: leftLink, zIndex: Z.chan, gridColumn: "2 / span 2", gridRow: row },
3121
+ title: it.channelLabel,
3122
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2 text-left", children: it.channelLabel })
3123
+ },
3124
+ `ochn:${it.id}`
3125
+ )
3126
+ );
3127
+ }
3128
+ return nodes;
3129
+ });
2938
3130
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2939
3131
  "div",
2940
3132
  {
@@ -2943,15 +3135,15 @@ function DspMixer({ status, oid, send, cls, icons }) {
2943
3135
  onPointerMove,
2944
3136
  onPointerUp,
2945
3137
  onPointerCancel: onPointerUp,
2946
- className: "w-full h-full overflow-auto no-scrollbar relative touch-none select-none cursor-grab",
3138
+ className: "w-full h-full overflow-auto no-scrollbar relative touch-none select-none cursor-grab flex",
2947
3139
  children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
2948
3140
  "div",
2949
3141
  {
2950
- className: "grid",
3142
+ className: "grid m-auto",
2951
3143
  style: {
2952
3144
  // cols: [out group][out link][out channel][inputs…] rows: [in group][in link][in channel][outputs…]
2953
- gridTemplateColumns: `${GROUP_W} ${COMMON_W} ${CHAN_W} repeat(${inputs.length}, ${CELL_W})`,
2954
- gridTemplateRows: `${GROUP_H} ${COMMON_H} ${CHAN_H} repeat(${outputs.length}, ${ROW_H})`,
3145
+ gridTemplateColumns: `${geom.groupW} ${geom.commonW} ${geom.chanW} repeat(${inputs.length}, ${geom.cellW})`,
3146
+ gridTemplateRows: `${geom.groupH} ${geom.commonH} ${geom.chanH} repeat(${outputs.length}, ${geom.rowH})`,
2955
3147
  minWidth: "min-content"
2956
3148
  },
2957
3149
  children: [
@@ -2959,7 +3151,7 @@ function DspMixer({ status, oid, send, cls, icons }) {
2959
3151
  "div",
2960
3152
  {
2961
3153
  "aria-hidden": true,
2962
- className: "sticky bg-[#282C34]",
3154
+ className: `sticky ${cls.mixerBackplate}`,
2963
3155
  style: { top: 0, zIndex: 15, gridColumn: "1 / -1", gridRow: "1 / span 3" }
2964
3156
  }
2965
3157
  ),
@@ -2967,7 +3159,7 @@ function DspMixer({ status, oid, send, cls, icons }) {
2967
3159
  "div",
2968
3160
  {
2969
3161
  "aria-hidden": true,
2970
- className: "sticky bg-[#282C34]",
3162
+ className: `sticky ${cls.mixerBackplate}`,
2971
3163
  style: { left: 0, zIndex: 15, gridColumn: "1 / span 3", gridRow: "1 / -1" }
2972
3164
  }
2973
3165
  ),
@@ -2976,166 +3168,11 @@ function DspMixer({ status, oid, send, cls, icons }) {
2976
3168
  {
2977
3169
  className: cls.mixerCorner,
2978
3170
  style: { top: 0, left: 0, zIndex: Z.corner, gridColumn: "1 / span 3", gridRow: "1 / span 3" },
2979
- children: "OUT \\ IN"
3171
+ children: renderCorner ? renderCorner(geom) : "OUT \\ IN"
2980
3172
  }
2981
3173
  ),
2982
- inAxis.flatMap((it, ii) => {
2983
- const col = 4 + ii;
2984
- const nodes = [];
2985
- if (it.groupStart) {
2986
- nodes.push(
2987
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2988
- "div",
2989
- {
2990
- className: cls.mixerGroup,
2991
- style: { top: 0, zIndex: Z.group, gridRow: 1, gridColumn: `${col} / span ${it.groupSpan}` },
2992
- title: it.groupName,
2993
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2 px-[0.2em]", children: it.groupName })
2994
- },
2995
- `igrp:${it.id}`
2996
- )
2997
- );
2998
- } else if (it.groupName === void 0) {
2999
- nodes.push(
3000
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3001
- "div",
3002
- {
3003
- className: cls.mixerChrome,
3004
- style: { top: 0, zIndex: Z.group, gridRow: 1, gridColumn: col }
3005
- },
3006
- `ifill:${it.id}`
3007
- )
3008
- );
3009
- }
3010
- if (it.linkCommon !== void 0) {
3011
- if (it.linkStart) {
3012
- nodes.push(
3013
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3014
- "div",
3015
- {
3016
- className: `${cls.mixerChrome} px-[0.2em] font-semibold`,
3017
- style: { top: topLink, zIndex: Z.link, gridRow: 2, gridColumn: `${col} / span ${it.linkSpan}` },
3018
- title: it.linkCommon,
3019
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2", children: it.linkCommon })
3020
- },
3021
- `ilnk:${it.id}`
3022
- )
3023
- );
3024
- }
3025
- nodes.push(
3026
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3027
- "div",
3028
- {
3029
- className: `${cls.mixerChrome} px-[0.2em]`,
3030
- style: { top: topChan, zIndex: Z.chan, gridRow: 3, gridColumn: col },
3031
- title: it.channelLabel,
3032
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-1", children: it.channelLabel })
3033
- },
3034
- `ichn:${it.id}`
3035
- )
3036
- );
3037
- } else {
3038
- nodes.push(
3039
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3040
- "div",
3041
- {
3042
- className: cls.mixerChrome,
3043
- style: { top: topLink, zIndex: Z.link, gridRow: 2, gridColumn: col }
3044
- },
3045
- `ilf:${it.id}`
3046
- ),
3047
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3048
- "div",
3049
- {
3050
- className: `${cls.mixerChrome} px-[0.2em]`,
3051
- style: { top: topChan, zIndex: Z.chan, gridRow: 3, gridColumn: col },
3052
- title: it.channelLabel,
3053
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2", children: it.channelLabel })
3054
- },
3055
- `ichn:${it.id}`
3056
- )
3057
- );
3058
- }
3059
- return nodes;
3060
- }),
3061
- outAxis.flatMap((it, oo) => {
3062
- const row = 4 + oo;
3063
- const nodes = [];
3064
- if (it.groupStart) {
3065
- nodes.push(
3066
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3067
- "div",
3068
- {
3069
- className: cls.mixerGroupV,
3070
- style: {
3071
- left: 0,
3072
- zIndex: Z.group,
3073
- gridColumn: 1,
3074
- gridRow: `${row} / span ${it.groupSpan}`,
3075
- writingMode: "vertical-rl",
3076
- transform: "rotate(180deg)"
3077
- },
3078
- title: it.groupName,
3079
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2", children: it.groupName })
3080
- },
3081
- `ogrp:${it.id}`
3082
- )
3083
- );
3084
- } else if (it.groupName === void 0) {
3085
- nodes.push(
3086
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3087
- "div",
3088
- {
3089
- className: cls.mixerChrome,
3090
- style: { left: 0, zIndex: Z.group, gridColumn: 1, gridRow: row }
3091
- },
3092
- `ofill:${it.id}`
3093
- )
3094
- );
3095
- }
3096
- if (it.linkCommon !== void 0) {
3097
- if (it.linkStart) {
3098
- nodes.push(
3099
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3100
- "div",
3101
- {
3102
- className: `${cls.mixerChrome} justify-start px-[0.4em] font-semibold`,
3103
- style: { left: leftLink, zIndex: Z.link, gridColumn: 2, gridRow: `${row} / span ${it.linkSpan}` },
3104
- title: it.linkCommon,
3105
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2 text-left", children: it.linkCommon })
3106
- },
3107
- `olnk:${it.id}`
3108
- )
3109
- );
3110
- }
3111
- nodes.push(
3112
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3113
- "div",
3114
- {
3115
- className: cls.mixerChrome,
3116
- style: { left: leftChan, zIndex: Z.chan, gridColumn: 3, gridRow: row },
3117
- title: it.channelLabel,
3118
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-1", children: it.channelLabel })
3119
- },
3120
- `ochn:${it.id}`
3121
- )
3122
- );
3123
- } else {
3124
- nodes.push(
3125
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3126
- "div",
3127
- {
3128
- className: `${cls.mixerChrome} justify-start px-[0.4em]`,
3129
- style: { left: leftLink, zIndex: Z.chan, gridColumn: "2 / span 2", gridRow: row },
3130
- title: it.channelLabel,
3131
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[1.1em] line-clamp-2 text-left", children: it.channelLabel })
3132
- },
3133
- `ochn:${it.id}`
3134
- )
3135
- );
3136
- }
3137
- return nodes;
3138
- }),
3174
+ renderInputHeader ? renderInputHeader(inAxis, geom) : defaultInputHeader(),
3175
+ renderOutputHeader ? renderOutputHeader(outAxis, geom) : defaultOutputHeader(),
3139
3176
  outAxis.map(
3140
3177
  (orow, oo) => inAxis.map((icol, ii) => {
3141
3178
  const on = isOn(orow.id, icol.id);
@@ -3162,12 +3199,34 @@ function DspMixer({ status, oid, send, cls, icons }) {
3162
3199
 
3163
3200
  // src/components/dsp/CrisViewDspMixer.tsx
3164
3201
  var import_jsx_runtime17 = require("react/jsx-runtime");
3165
- function CrisViewDspMixer({ oid, classes, icons, className }) {
3202
+ function CrisViewDspMixer({
3203
+ oid,
3204
+ classes,
3205
+ icons,
3206
+ className,
3207
+ geometry,
3208
+ renderInputHeader,
3209
+ renderOutputHeader,
3210
+ renderCorner
3211
+ }) {
3166
3212
  const status = (0, import_cris_webui_ch5_core13.useCustomObject)(oid, { subscribe: true });
3167
3213
  const send = (0, import_cris_webui_ch5_core13.useCustomObjectSend)();
3168
3214
  const cls = resolveDspClasses(classes);
3169
3215
  const ic = resolveDspIcons(icons);
3170
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: `w-full h-full ${className ?? ""}`, children: status === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: cls.message, children: "Conectando\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DspMixer, { status, oid, send, cls, icons: ic }) });
3216
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: `w-full h-full ${className ?? ""}`, children: status === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: cls.message, children: "Conectando\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3217
+ DspMixer,
3218
+ {
3219
+ status,
3220
+ oid,
3221
+ send,
3222
+ cls,
3223
+ icons: ic,
3224
+ geometry,
3225
+ renderInputHeader,
3226
+ renderOutputHeader,
3227
+ renderCorner
3228
+ }
3229
+ ) });
3171
3230
  }
3172
3231
 
3173
3232
  // src/components/dsp/DspPresets.tsx
@@ -3237,6 +3296,7 @@ function DspPresets({
3237
3296
 
3238
3297
  // src/components/dsp/CrisViewDspFull.tsx
3239
3298
  var import_jsx_runtime19 = require("react/jsx-runtime");
3299
+ var lastTabByOid = /* @__PURE__ */ new Map();
3240
3300
  function CrisViewDspFull({
3241
3301
  oid,
3242
3302
  presets,
@@ -3249,8 +3309,13 @@ function CrisViewDspFull({
3249
3309
  className,
3250
3310
  initialTab = "in"
3251
3311
  }) {
3252
- const safeInitial = initialTab === "mix" && skipCrosspoints ? "in" : initialTab;
3253
- const [tab, setTab] = (0, import_react9.useState)(safeInitial);
3312
+ const remembered = lastTabByOid.get(oid) ?? initialTab;
3313
+ const safeInitial = remembered === "mix" && skipCrosspoints ? "in" : remembered;
3314
+ const [tab, setTabState] = (0, import_react9.useState)(safeInitial);
3315
+ const setTab = (t) => {
3316
+ lastTabByOid.set(oid, t);
3317
+ setTabState(t);
3318
+ };
3254
3319
  const status = (0, import_cris_webui_ch5_core14.useCustomObject)(oid, { subscribe: true });
3255
3320
  const send = (0, import_cris_webui_ch5_core14.useCustomObjectSend)();
3256
3321
  const cls = resolveDspClasses(classes);