cabbage-react 1.0.1 → 1.0.2
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/README.md +21 -12
- package/dist/cabbage/cabbage.d.ts +15 -1
- package/dist/cabbage/cabbage.d.ts.map +1 -1
- package/dist/hooks/useCabbageProperties.d.ts +1 -1
- package/dist/hooks/useCabbageProperties.d.ts.map +1 -1
- package/dist/hooks/useCabbageState.d.ts +1 -1
- package/dist/hooks/useCabbageState.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +76 -60
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,8 +20,10 @@ npm install cabbage-react
|
|
|
20
20
|
|
|
21
21
|
Synchronize a parameter with Cabbage. This hook:
|
|
22
22
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
23
|
+
- Identifies and sets the default value defined in Cabbage to the state.
|
|
24
|
+
- Handles initialization when opening an existing session, or reopening the plugin window.
|
|
25
|
+
- Listens for value updates from the host (DAW), or from Csound.
|
|
26
|
+
- Sends changes back to Cabbage when using the provided value-setter.
|
|
25
27
|
|
|
26
28
|
### useCabbageProperties
|
|
27
29
|
|
|
@@ -33,21 +35,28 @@ This hook:
|
|
|
33
35
|
|
|
34
36
|
## Usage
|
|
35
37
|
|
|
36
|
-
```
|
|
38
|
+
```tsx
|
|
37
39
|
import { InputHTMLAttributes } from "react";
|
|
38
40
|
import { useCabbageProperties, useCabbageState } from "cabbage-react";
|
|
39
41
|
|
|
40
42
|
const HorizontalSlider = ({
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
channelId,
|
|
44
|
+
parameterIndex,
|
|
43
45
|
inputProps,
|
|
44
46
|
}: {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
channelId: string;
|
|
48
|
+
parameterIndex: number;
|
|
47
49
|
inputProps?: InputHTMLAttributes<HTMLInputElement>;
|
|
48
50
|
}) => {
|
|
49
|
-
const { properties } = useCabbageProperties(
|
|
50
|
-
const
|
|
51
|
+
const { properties } = useCabbageProperties(channelId);
|
|
52
|
+
const channelProperties = properties?.channels.find(
|
|
53
|
+
(c: any) => c.id === channelId
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const { value, setValue } = useCabbageState<number>(
|
|
57
|
+
channelId,
|
|
58
|
+
parameterIndex
|
|
59
|
+
);
|
|
51
60
|
|
|
52
61
|
return (
|
|
53
62
|
<div>
|
|
@@ -56,9 +65,9 @@ const HorizontalSlider = ({
|
|
|
56
65
|
|
|
57
66
|
<input
|
|
58
67
|
type="range"
|
|
59
|
-
min={
|
|
60
|
-
max={
|
|
61
|
-
step={
|
|
68
|
+
min={channelProperties?.range?.min ?? 0}
|
|
69
|
+
max={channelProperties?.range?.max ?? 1}
|
|
70
|
+
step={channelProperties?.range?.increment ?? 0.01}
|
|
62
71
|
value={value}
|
|
63
72
|
onChange={(e) => setValue(e.target.valueAsNumber)}
|
|
64
73
|
{...inputProps}
|
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
export class Cabbage {
|
|
2
|
+
/**
|
|
3
|
+
* Main entry point for sending any data from UI widgets to the Cabbage backend.
|
|
4
|
+
* This function automatically routes messages to the appropriate backend function
|
|
5
|
+
* based on the automatable flag:
|
|
6
|
+
*
|
|
7
|
+
* - automatable=1: Routes to sendParameterUpdate for real-time parameter control /
|
|
8
|
+
* this also sends the value as channel data to Csound
|
|
9
|
+
*
|
|
10
|
+
* - automatable=0: Routes to sendChannelData for string/numeric data transmission
|
|
11
|
+
*
|
|
12
|
+
* All widget interactions should use this function instead of calling the lower-level
|
|
13
|
+
* sendParameterUpdate or sendChannelData functions directly.
|
|
14
|
+
*/
|
|
15
|
+
static sendChannelUpdate(message: any, vscode?: null, automatable?: number): void;
|
|
2
16
|
static sendParameterUpdate(message: any, vscode?: null): void;
|
|
3
17
|
static sendCustomCommand(command: any, vscode?: null): void;
|
|
4
18
|
static sendWidgetUpdate(widget: any, vscode?: null): void;
|
|
5
19
|
static sendMidiMessageFromUI(statusByte: any, dataByte1: any, dataByte2: any, vscode?: null): void;
|
|
6
20
|
static sendChannelData(channel: any, data: any, vscode?: null): void;
|
|
7
21
|
static MidiMessageFromHost(statusByte: any, dataByte1: any, dataByte2: any): void;
|
|
8
|
-
static triggerFileOpenDialog(vscode: any, channel: any): void;
|
|
22
|
+
static triggerFileOpenDialog(vscode: any, channel: any, options?: {}): void;
|
|
9
23
|
static openUrl(vscode: any, url: any, file: any): void;
|
|
10
24
|
}
|
|
11
25
|
//# sourceMappingURL=cabbage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cabbage.d.ts","sourceRoot":"","sources":["../../src/cabbage/cabbage.js"],"names":[],"mappings":"AAMA;IAEE,8DAcC;IAED,4DAYC;IAED,0DAYC;IAED,mGAmBC;IAED,qEA2BC;IAED,kFAEC;IAED,
|
|
1
|
+
{"version":3,"file":"cabbage.d.ts","sourceRoot":"","sources":["../../src/cabbage/cabbage.js"],"names":[],"mappings":"AAMA;IAEE;;;;;;;;;;;;OAYG;IACH,kFASC;IAED,8DAcC;IAED,4DAYC;IAED,0DAYC;IAED,mGAmBC;IAED,qEA2BC;IAED,kFAEC;IAED,4EAkBC;IAED,uDAgBC;CAGF"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* This hook listens for updates to parameter properties via Cabbage and updates the local state
|
|
4
4
|
* whenever new data is received.
|
|
5
5
|
*/
|
|
6
|
-
export declare const useCabbageProperties: (
|
|
6
|
+
export declare const useCabbageProperties: (channelId: string) => {
|
|
7
7
|
properties: Record<string, any> | undefined;
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=useCabbageProperties.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCabbageProperties.d.ts","sourceRoot":"","sources":["../../src/hooks/useCabbageProperties.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"useCabbageProperties.d.ts","sourceRoot":"","sources":["../../src/hooks/useCabbageProperties.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,cAAe,MAAM;;CAgCrD,CAAC"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* This hook listens for updates to a parameter value from Cabbage and
|
|
4
4
|
* sends updates to Cabbage when the parameter value changes locally (e.g., through a UI slider).
|
|
5
5
|
*/
|
|
6
|
-
export declare const useCabbageState: <T>(
|
|
6
|
+
export declare const useCabbageState: <T>(channelId: string, parameterIndex: number) => {
|
|
7
7
|
value: T | undefined;
|
|
8
8
|
setValue: (newValue: T) => void;
|
|
9
9
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCabbageState.d.ts","sourceRoot":"","sources":["../../src/hooks/useCabbageState.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"useCabbageState.d.ts","sourceRoot":"","sources":["../../src/hooks/useCabbageState.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,aACrB,MAAM,kBACD,MAAM;;yBAMe,CAAC;CA6EtC,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("react");console.log("Cabbage: loading cabbage.js");class c{static sendChannelUpdate(n,e=null,a=0){if(a===1)c.sendParameterUpdate(n,e);else{const s=n.value!==void 0?n.value:n.stringData||n.floatData;c.sendChannelData(n.channel,s,e)}}static sendParameterUpdate(n,e=null){const a={command:"parameterChange",...n};console.log("Cabbage.sendParameterUpdate:",n,"vscode:",e,"msg:",a),e!==null?(console.log("Sending via vscode.postMessage"),e.postMessage(a)):(console.log("Sending via window.sendMessageFromUI"),window.sendMessageFromUI(a))}static sendCustomCommand(n,e=null){const a={command:n,text:JSON.stringify({})};console.log("Cabbage: sending custom command from UI",a),e!==null?e.postMessage(a):window.sendMessageFromUI(a)}static sendWidgetUpdate(n,e=null){console.log("Cabbage: sending widget update from UI",n.props);const a={command:"widgetStateUpdate",obj:JSON.stringify(CabbageUtils.sanitizeForEditor(n))};e!==null?e.postMessage(a):window.sendMessageFromUI(a)}static sendMidiMessageFromUI(n,e,a,s=null){var t={statusByte:n,dataByte1:e,dataByte2:a};const o={command:"midiMessage",obj:JSON.stringify(t)};console.log("Cabbage: sending midi message from UI",t),s!==null?s.postMessage(o):window.sendMessageFromUI(o)}static sendChannelData(n,e,a=null){var s={channel:n};if(typeof e=="string")s.stringData=e;else if(typeof e=="number")s.floatData=e;else{console.warn("Cabbage: sendChannelData received unsupported data type:",typeof e);return}const t={command:"channelData",obj:JSON.stringify(s)};console.log("Cabbage: sending channel data from UI",s),a!==null?a.postMessage(t):window.sendMessageFromUI(t)}static MidiMessageFromHost(n,e,a){console.log("Cabbage: Got MIDI Message"+n+":"+e+":"+a)}static triggerFileOpenDialog(n,e,a={}){var s={channel:e,directory:a.directory||"",filters:a.filters||"*",openAtLastKnownLocation:a.openAtLastKnownLocation!==void 0?a.openAtLastKnownLocation:!0};const t={command:"fileOpen",obj:JSON.stringify(s)};n!==null?n.postMessage(t):window.sendMessageFromUI(t)}static openUrl(n,e,a){var s={url:e,file:a};const t={command:"openUrl",obj:JSON.stringify(s)};n!==null?n.postMessage(t):window.sendMessageFromUI(t)}}const u=r=>{const[n,e]=g.useState();return g.useEffect(()=>{const a=s=>{const{id:t,widgetJson:o,command:l}=s.data;if(t===r&&o&&l==="widgetUpdate"){const i=JSON.parse(o);console.log(`[Cabbage-React] Received properties for channelId ${t}`,i),e(i)}};return window.addEventListener("message",a),()=>{window.removeEventListener("message",a)}},[]),{properties:n}},f=(r,n)=>{const{properties:e}=u(r),[a,s]=g.useState(),t=o=>{s(o);const l={paramIdx:n,channel:r,value:o};c.sendParameterUpdate(l,null)};return g.useEffect(()=>{var d;const o=e==null?void 0:e.value;if(o!=null){console.log(`[Cabbage-React] Received initial value for channelId "${r}"`,o),s(o);return}const l=e==null?void 0:e.channels.find(m=>m.id===r);if(!l)return;const i=(d=l.range)==null?void 0:d.defaultValue;a===void 0&&i!==void 0&&(console.log(`[Cabbage-React] Received default value for channelId "${l.id}"`,i),s(i))},[e]),g.useEffect(()=>{const o=l=>{const{command:i}=l.data;if(i==="parameterChange"){const{value:d,paramIdx:m}=l.data;if(m!==n||d===null)return;console.log(`[Cabbage-React] Received value change for parameterIndex ${m}`,d),s(d)}};return window.addEventListener("message",o),()=>{window.removeEventListener("message",o)}},[]),{value:a,setValue:t}};exports.Cabbage=c;exports.useCabbageProperties=u;exports.useCabbageState=f;
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,31 @@
|
|
|
1
|
-
import { useState as
|
|
1
|
+
import { useState as u, useEffect as m } from "react";
|
|
2
2
|
console.log("Cabbage: loading cabbage.js");
|
|
3
|
-
class
|
|
3
|
+
class c {
|
|
4
|
+
/**
|
|
5
|
+
* Main entry point for sending any data from UI widgets to the Cabbage backend.
|
|
6
|
+
* This function automatically routes messages to the appropriate backend function
|
|
7
|
+
* based on the automatable flag:
|
|
8
|
+
*
|
|
9
|
+
* - automatable=1: Routes to sendParameterUpdate for real-time parameter control /
|
|
10
|
+
* this also sends the value as channel data to Csound
|
|
11
|
+
*
|
|
12
|
+
* - automatable=0: Routes to sendChannelData for string/numeric data transmission
|
|
13
|
+
*
|
|
14
|
+
* All widget interactions should use this function instead of calling the lower-level
|
|
15
|
+
* sendParameterUpdate or sendChannelData functions directly.
|
|
16
|
+
*/
|
|
17
|
+
static sendChannelUpdate(a, e = null, n = 0) {
|
|
18
|
+
if (n === 1)
|
|
19
|
+
c.sendParameterUpdate(a, e);
|
|
20
|
+
else {
|
|
21
|
+
const s = a.value !== void 0 ? a.value : a.stringData || a.floatData;
|
|
22
|
+
c.sendChannelData(a.channel, s, e);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
4
25
|
static sendParameterUpdate(a, e = null) {
|
|
5
26
|
const n = {
|
|
6
27
|
command: "parameterChange",
|
|
7
|
-
|
|
28
|
+
...a
|
|
8
29
|
};
|
|
9
30
|
console.log("Cabbage.sendParameterUpdate:", a, "vscode:", e, "msg:", n), e !== null ? (console.log("Sending via vscode.postMessage"), e.postMessage(n)) : (console.log("Sending via window.sendMessageFromUI"), window.sendMessageFromUI(n));
|
|
10
31
|
}
|
|
@@ -29,11 +50,11 @@ class C {
|
|
|
29
50
|
dataByte1: e,
|
|
30
51
|
dataByte2: n
|
|
31
52
|
};
|
|
32
|
-
const
|
|
53
|
+
const o = {
|
|
33
54
|
command: "midiMessage",
|
|
34
55
|
obj: JSON.stringify(t)
|
|
35
56
|
};
|
|
36
|
-
console.log("Cabbage: sending midi message from UI", t), s !== null ? s.postMessage(
|
|
57
|
+
console.log("Cabbage: sending midi message from UI", t), s !== null ? s.postMessage(o) : window.sendMessageFromUI(o);
|
|
37
58
|
}
|
|
38
59
|
static sendChannelData(a, e, n = null) {
|
|
39
60
|
var s = {
|
|
@@ -48,7 +69,7 @@ class C {
|
|
|
48
69
|
return;
|
|
49
70
|
}
|
|
50
71
|
const t = {
|
|
51
|
-
command: "
|
|
72
|
+
command: "channelData",
|
|
52
73
|
obj: JSON.stringify(s)
|
|
53
74
|
};
|
|
54
75
|
console.log("Cabbage: sending channel data from UI", s), n !== null ? n.postMessage(t) : window.sendMessageFromUI(t);
|
|
@@ -56,15 +77,18 @@ class C {
|
|
|
56
77
|
static MidiMessageFromHost(a, e, n) {
|
|
57
78
|
console.log("Cabbage: Got MIDI Message" + a + ":" + e + ":" + n);
|
|
58
79
|
}
|
|
59
|
-
static triggerFileOpenDialog(a, e) {
|
|
60
|
-
var
|
|
61
|
-
channel: e
|
|
80
|
+
static triggerFileOpenDialog(a, e, n = {}) {
|
|
81
|
+
var s = {
|
|
82
|
+
channel: e,
|
|
83
|
+
directory: n.directory || "",
|
|
84
|
+
filters: n.filters || "*",
|
|
85
|
+
openAtLastKnownLocation: n.openAtLastKnownLocation !== void 0 ? n.openAtLastKnownLocation : !0
|
|
62
86
|
};
|
|
63
|
-
const
|
|
87
|
+
const t = {
|
|
64
88
|
command: "fileOpen",
|
|
65
|
-
obj: JSON.stringify(
|
|
89
|
+
obj: JSON.stringify(s)
|
|
66
90
|
};
|
|
67
|
-
a !== null ? a.postMessage(
|
|
91
|
+
a !== null ? a.postMessage(t) : window.sendMessageFromUI(t);
|
|
68
92
|
}
|
|
69
93
|
static openUrl(a, e, n) {
|
|
70
94
|
var s = {
|
|
@@ -78,17 +102,17 @@ class C {
|
|
|
78
102
|
a !== null ? a.postMessage(t) : window.sendMessageFromUI(t);
|
|
79
103
|
}
|
|
80
104
|
}
|
|
81
|
-
const
|
|
82
|
-
const [a, e] =
|
|
83
|
-
return
|
|
105
|
+
const f = (r) => {
|
|
106
|
+
const [a, e] = u();
|
|
107
|
+
return m(() => {
|
|
84
108
|
const n = (s) => {
|
|
85
|
-
const {
|
|
86
|
-
if (t === r &&
|
|
87
|
-
const
|
|
109
|
+
const { id: t, widgetJson: o, command: l } = s.data;
|
|
110
|
+
if (t === r && o && l === "widgetUpdate") {
|
|
111
|
+
const i = JSON.parse(o);
|
|
88
112
|
console.log(
|
|
89
|
-
`[Cabbage-React]
|
|
90
|
-
|
|
91
|
-
), e(
|
|
113
|
+
`[Cabbage-React] Received properties for channelId ${t}`,
|
|
114
|
+
i
|
|
115
|
+
), e(i);
|
|
92
116
|
}
|
|
93
117
|
};
|
|
94
118
|
return window.addEventListener("message", n), () => {
|
|
@@ -97,53 +121,45 @@ const w = (r) => {
|
|
|
97
121
|
}, []), {
|
|
98
122
|
properties: a
|
|
99
123
|
};
|
|
100
|
-
},
|
|
101
|
-
const { properties: e } =
|
|
124
|
+
}, b = (r, a) => {
|
|
125
|
+
const { properties: e } = f(r), [n, s] = u(), t = (o) => {
|
|
102
126
|
s(o);
|
|
103
127
|
const l = {
|
|
104
128
|
paramIdx: a,
|
|
105
|
-
channelType: t,
|
|
106
129
|
channel: r,
|
|
107
130
|
value: o
|
|
108
131
|
};
|
|
109
|
-
|
|
110
|
-
}, c = (o) => {
|
|
111
|
-
if (typeof o == "number") return "number";
|
|
112
|
-
if (typeof o == "string") return "string";
|
|
132
|
+
c.sendParameterUpdate(l, null);
|
|
113
133
|
};
|
|
114
|
-
return
|
|
115
|
-
var
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (n === void 0 && o !== void 0) {
|
|
134
|
+
return m(() => {
|
|
135
|
+
var d;
|
|
136
|
+
const o = e == null ? void 0 : e.value;
|
|
137
|
+
if (o != null) {
|
|
119
138
|
console.log(
|
|
120
|
-
`[Cabbage-React]
|
|
139
|
+
`[Cabbage-React] Received initial value for channelId "${r}"`,
|
|
121
140
|
o
|
|
122
141
|
), s(o);
|
|
123
|
-
|
|
124
|
-
d && i(d);
|
|
142
|
+
return;
|
|
125
143
|
}
|
|
126
|
-
|
|
144
|
+
const l = e == null ? void 0 : e.channels.find(
|
|
145
|
+
(g) => g.id === r
|
|
146
|
+
);
|
|
147
|
+
if (!l) return;
|
|
148
|
+
const i = (d = l.range) == null ? void 0 : d.defaultValue;
|
|
149
|
+
n === void 0 && i !== void 0 && (console.log(
|
|
150
|
+
`[Cabbage-React] Received default value for channelId "${l.id}"`,
|
|
151
|
+
i
|
|
152
|
+
), s(i));
|
|
153
|
+
}, [e]), m(() => {
|
|
127
154
|
const o = (l) => {
|
|
128
|
-
const { command:
|
|
129
|
-
if (
|
|
130
|
-
const {
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
`[Cabbage-React]
|
|
134
|
-
|
|
135
|
-
),
|
|
136
|
-
s(g);
|
|
137
|
-
const p = c(g);
|
|
138
|
-
p && i(p);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
if (d === "parameterChange") {
|
|
142
|
-
const { paramIdx: m, value: g } = l.data.data || {};
|
|
143
|
-
m === a && g !== void 0 && (console.log(
|
|
144
|
-
`[Cabbage-React] ${d}: Received value change for paramIdx: ${m}`,
|
|
145
|
-
g
|
|
146
|
-
), s(g));
|
|
155
|
+
const { command: i } = l.data;
|
|
156
|
+
if (i === "parameterChange") {
|
|
157
|
+
const { value: d, paramIdx: g } = l.data;
|
|
158
|
+
if (g !== a || d === null) return;
|
|
159
|
+
console.log(
|
|
160
|
+
`[Cabbage-React] Received value change for parameterIndex ${g}`,
|
|
161
|
+
d
|
|
162
|
+
), s(d);
|
|
147
163
|
}
|
|
148
164
|
};
|
|
149
165
|
return window.addEventListener("message", o), () => {
|
|
@@ -151,11 +167,11 @@ const w = (r) => {
|
|
|
151
167
|
};
|
|
152
168
|
}, []), {
|
|
153
169
|
value: n,
|
|
154
|
-
setValue:
|
|
170
|
+
setValue: t
|
|
155
171
|
};
|
|
156
172
|
};
|
|
157
173
|
export {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
174
|
+
c as Cabbage,
|
|
175
|
+
f as useCabbageProperties,
|
|
176
|
+
b as useCabbageState
|
|
161
177
|
};
|