@gorilla-engine-sdk/create-gorilla-engine-plugin 1.0.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.
Files changed (101) hide show
  1. package/LICENSE.md +64 -0
  2. package/README.md +103 -0
  3. package/generator-gorilla-engine-plugin/app/index.js +338 -0
  4. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/SKILL.md +295 -0
  5. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/effects-filters.md +186 -0
  6. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/indexing.md +129 -0
  7. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/instrument-files.md +547 -0
  8. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/key-rules.md +81 -0
  9. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/modulation.md +210 -0
  10. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/module-control.md +217 -0
  11. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/module-reference-bus-effects.md +663 -0
  12. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/module-reference-core.md +145 -0
  13. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/module-reference-misc.md +59 -0
  14. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/module-reference-modulation.md +85 -0
  15. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/module-reference-voice-effects.md +407 -0
  16. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/note-events.md +278 -0
  17. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/properties.md +230 -0
  18. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/script-patterns.md +494 -0
  19. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-dsp/references/time-tempo.md +209 -0
  20. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/SKILL.md +104 -0
  21. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/advanced-controls.md +194 -0
  22. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/base-props.md +167 -0
  23. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/basic-controls.md +230 -0
  24. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/bindings.md +183 -0
  25. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/composite-components.md +258 -0
  26. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/containers.md +149 -0
  27. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/editors.md +191 -0
  28. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/event-handlers.md +150 -0
  29. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/getting-started.md +143 -0
  30. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/gorilla-engine-api.md +147 -0
  31. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/instrument-api.md +250 -0
  32. package/generator-gorilla-engine-plugin/app/templates/.agents/skills/gorilla-engine-ui/references/visualization.md +209 -0
  33. package/generator-gorilla-engine-plugin/app/templates/.prettierignore +13 -0
  34. package/generator-gorilla-engine-plugin/app/templates/.vscode/settings.json +14 -0
  35. package/generator-gorilla-engine-plugin/app/templates/.vscode_input/launch.json +89 -0
  36. package/generator-gorilla-engine-plugin/app/templates/README.md +36 -0
  37. package/generator-gorilla-engine-plugin/app/templates/assets/fonts/OFL.txt +93 -0
  38. package/generator-gorilla-engine-plugin/app/templates/assets/fonts/Roboto-Bold.otf +0 -0
  39. package/generator-gorilla-engine-plugin/app/templates/assets/fonts/Roboto-Medium.otf +0 -0
  40. package/generator-gorilla-engine-plugin/app/templates/assets/fonts/Roboto-Regular.otf +0 -0
  41. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/Presets/Factory/Category 1/Init.preset +1 -0
  42. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/Presets/Factory/Category 1/Three Quarters.preset +1 -0
  43. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/Horizontal Slider.png +0 -0
  44. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/Horizontal Slider@2x.png +0 -0
  45. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/Rotary Bipolar.png +0 -0
  46. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/Rotary-Bipolar@2x.png +0 -0
  47. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/Rotary.png +0 -0
  48. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/Rotary@2x.png +0 -0
  49. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-down-default.png +0 -0
  50. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-down-default@2x.png +0 -0
  51. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-down-hover.png +0 -0
  52. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-down-hover@2x.png +0 -0
  53. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-down-pressed.png +0 -0
  54. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-down-pressed@2x.png +0 -0
  55. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-up-default.png +0 -0
  56. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-up-default@2x.png +0 -0
  57. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-up-hover.png +0 -0
  58. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-up-hover@2x.png +0 -0
  59. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-up-pressed.png +0 -0
  60. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/arrow-up-pressed@2x.png +0 -0
  61. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/toggle-default.png +0 -0
  62. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/toggle-default@2x.png +0 -0
  63. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/toggle-pressed.png +0 -0
  64. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/images/toggle-pressed@2x.png +0 -0
  65. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/instruments/Basic Synth Example_part1.blob +0 -0
  66. package/generator-gorilla-engine-plugin/app/templates/basic-synth/assets/instruments/Basic Synth Example_part2.blob +1 -0
  67. package/generator-gorilla-engine-plugin/app/templates/basic-synth/instrument/Basic Synth Example.inst +157 -0
  68. package/generator-gorilla-engine-plugin/app/templates/basic-synth/instrument/Basic Synth Example.txt +184 -0
  69. package/generator-gorilla-engine-plugin/app/templates/basic-synth/src/app/Root.tsx +35 -0
  70. package/generator-gorilla-engine-plugin/app/templates/basic-synth/src/app/components/ErrorBoundary.tsx +138 -0
  71. package/generator-gorilla-engine-plugin/app/templates/basic-synth/src/app/components/UserInterface.tsx +338 -0
  72. package/generator-gorilla-engine-plugin/app/templates/basic-synth/src/app/pluginConfig.ts +4 -0
  73. package/generator-gorilla-engine-plugin/app/templates/basic-synth/src/dialogsCustomStyle.ts +98 -0
  74. package/generator-gorilla-engine-plugin/app/templates/basic-synth/src/index.tsx +217 -0
  75. package/generator-gorilla-engine-plugin/app/templates/basic-synth/src/presetBrowserCustomStyle.ts +124 -0
  76. package/generator-gorilla-engine-plugin/app/templates/build.ugep +173 -0
  77. package/generator-gorilla-engine-plugin/app/templates/effect/assets/Presets/Factory/Category 1/01 - All The Way Down.preset +1 -0
  78. package/generator-gorilla-engine-plugin/app/templates/effect/assets/Presets/Factory/Category 1/02 - About Half.preset +1 -0
  79. package/generator-gorilla-engine-plugin/app/templates/effect/assets/Presets/Factory/Category 1/03 - Three Quarters.preset +1 -0
  80. package/generator-gorilla-engine-plugin/app/templates/effect/assets/Presets/Factory/Category 1/04 - All The Way Up.preset +1 -0
  81. package/generator-gorilla-engine-plugin/app/templates/effect/assets/images/Rotary.png +0 -0
  82. package/generator-gorilla-engine-plugin/app/templates/effect/assets/images/Rotary@2x.png +0 -0
  83. package/generator-gorilla-engine-plugin/app/templates/effect/assets/instruments/Reverb Example_part1.blob +0 -0
  84. package/generator-gorilla-engine-plugin/app/templates/effect/assets/instruments/Reverb Example_part2.blob +1 -0
  85. package/generator-gorilla-engine-plugin/app/templates/effect/instrument/Reverb Example.inst +73 -0
  86. package/generator-gorilla-engine-plugin/app/templates/effect/instrument/Reverb Example.txt +21 -0
  87. package/generator-gorilla-engine-plugin/app/templates/effect/src/app/Root.tsx +35 -0
  88. package/generator-gorilla-engine-plugin/app/templates/effect/src/app/components/ErrorBoundary.tsx +114 -0
  89. package/generator-gorilla-engine-plugin/app/templates/effect/src/app/components/UserInterface.tsx +85 -0
  90. package/generator-gorilla-engine-plugin/app/templates/effect/src/app/pluginConfig.ts +4 -0
  91. package/generator-gorilla-engine-plugin/app/templates/effect/src/dialogsCustomStyle.ts +101 -0
  92. package/generator-gorilla-engine-plugin/app/templates/effect/src/index.tsx +214 -0
  93. package/generator-gorilla-engine-plugin/app/templates/effect/src/presetBrowserCustomStyle.ts +124 -0
  94. package/generator-gorilla-engine-plugin/app/templates/gitignore +9 -0
  95. package/generator-gorilla-engine-plugin/app/templates/licence.txt +0 -0
  96. package/generator-gorilla-engine-plugin/app/templates/package.json +38 -0
  97. package/generator-gorilla-engine-plugin/app/templates/prettierrc +9 -0
  98. package/generator-gorilla-engine-plugin/app/templates/tsconfig.json +20 -0
  99. package/generator-gorilla-engine-plugin/package.json +17 -0
  100. package/index.js +72 -0
  101. package/package.json +42 -0
@@ -0,0 +1,230 @@
1
+ # Basic Controls
2
+
3
+ ## geLabel
4
+
5
+ Display text, images, or act as a container/panel. The most versatile component.
6
+
7
+ **JSX tag:** `<geLabel />`
8
+ **Interfaces:** Common, Bounds, Background, Font, Clickable, Margin, Keyable
9
+ **Handlers:** ClickableHandlers, KeyableHandlers
10
+
11
+ | Prop | Type | Description |
12
+ |------|------|-------------|
13
+ | `text` | `string \| number` | Display text (updates at runtime) |
14
+ | `value` | `any` | Initial text (doesn't update at runtime) |
15
+ | `format` | `string` | Text format string |
16
+ | `multiLine` | `boolean` | Enable multi-line text |
17
+ | `stretchText` | `boolean` | Stretch text to fit bounds |
18
+
19
+ **As a container/panel:**
20
+ ```tsx
21
+ <geLabel x={0} y={0} width={400} height={300}
22
+ backgroundColor="FF1a1a2e" cornerRadius={8}
23
+ border={{ width: 1, color: "FF444444" }}>
24
+ <geKnob x={10} y={10} width={60} height={60} />
25
+ <geLabel x={80} y={25} width={100} height={20} text="Volume" textColor="FFFFFF" />
26
+ </geLabel>
27
+ ```
28
+
29
+ **As a text label:**
30
+ ```tsx
31
+ <geLabel x={10} y={10} width={100} height={20}
32
+ text="Hello World" textColor="FFFFFF" fontSize={14} textAlign="center"
33
+ />
34
+ ```
35
+
36
+ ---
37
+
38
+ ## geButton
39
+
40
+ Trigger button — fires an action on click, does NOT toggle.
41
+
42
+ **JSX tag:** `<geButton />`
43
+ **Native class:** `GorillaEngine.UI.Trigger`
44
+ **Interfaces:** Common, Bounds, Font, Clickable, Background, KeyboardFocus, Keyable
45
+ **Handlers:** ClickableHandlers, KeyableHandlers
46
+
47
+ | Prop | Type | Description |
48
+ |------|------|-------------|
49
+ | `text` | `string` | Button label text |
50
+ | `isDumb` | `boolean` | If true, button has no built-in behavior |
51
+ | `images` | `object` | `{ normal?, hover?, down? }` — image paths per state |
52
+ | `animation` | `LottieAnimation` | Linked Lottie animation |
53
+
54
+ **Note:** geButton gets a default `keyboardFocus.color` of `"00000000"` (transparent).
55
+
56
+ ```tsx
57
+ <geButton x={10} y={10} width={120} height={35}
58
+ text="Save Preset"
59
+ backgroundColor="FF4444FF" textColor="FFFFFF"
60
+ images={{ normal: 'btn.png', hover: 'btn_hover.png', down: 'btn_down.png' }}
61
+ onClick={() => savePreset()}
62
+ />
63
+ ```
64
+
65
+ ---
66
+
67
+ ## geKnob
68
+
69
+ Rotary dial control for numeric values.
70
+
71
+ **JSX tag:** `<geKnob />`
72
+ **Interfaces:** Common, Bounds, Clickable, Background, Skinnable, MIDILearn, Highlight
73
+ **Handlers:** ClickableHandlers, `onChange`
74
+
75
+ | Prop | Type | Description |
76
+ |------|------|-------------|
77
+ | `text` | `string` | Display text |
78
+ | `min` | `number` | Minimum value |
79
+ | `max` | `number` | Maximum value |
80
+ | `value` | `number` | Current value (between min and max) |
81
+ | `stepSize` | `number` | Value increment per interaction step |
82
+ | `scrollWheelEnabled` | `boolean` | Allow mouse wheel adjustment |
83
+ | `image` | `string` | Single image path (rotated between minRotation/maxRotation) |
84
+ | `minRotation` | `number` | Min rotation angle in degrees (for `image` mode) |
85
+ | `maxRotation` | `number` | Max rotation angle in degrees (for `image` mode) |
86
+ | `inverted` | `boolean` | Invert the control direction |
87
+ | `filmstrip` | `object` | `{ path, count, direction? }` — filmstrip animation |
88
+
89
+ **Filmstrip mode (most common):**
90
+ ```tsx
91
+ <geKnob x={50} y={50} width={60} height={60}
92
+ min={0} max={100} value={50}
93
+ filmstrip={{ path: 'assets/knob.png', count: 128 }}
94
+ onChange={(v) => setVolume(v)}
95
+ />
96
+ ```
97
+
98
+ **Single image rotation mode:**
99
+ ```tsx
100
+ <geKnob x={50} y={50} width={60} height={60}
101
+ min={0} max={127} value={64}
102
+ image="assets/knob_pointer.png"
103
+ minRotation={-135} maxRotation={135}
104
+ />
105
+ ```
106
+
107
+ ---
108
+
109
+ ## geSlider
110
+
111
+ Linear slider control (horizontal or vertical). Internally a Knob with `type: 'slider'`.
112
+
113
+ **JSX tag:** `<geSlider />`
114
+ **Native class:** `GorillaEngine.UI.Knob` with `type: 'slider'`
115
+ **Interfaces:** Same as geKnob + slider-specific props
116
+ **Handlers:** ClickableHandlers, `onChange`
117
+
118
+ | Prop | Type | Description |
119
+ |------|------|-------------|
120
+ | *(all geKnob props)* | | Inherits knob properties |
121
+ | `direction` | `'horizontal' \| 'vertical'` | Slider orientation |
122
+ | `thumbImage` | `string` | Path to thumb/handle image |
123
+ | `sliderBounds` | `object` | `{ x, y, width, height }` — custom track bounds |
124
+
125
+ ```tsx
126
+ <geSlider x={10} y={100} width={200} height={30}
127
+ min={0} max={100} value={75}
128
+ direction="horizontal"
129
+ filmstrip={{ path: 'assets/slider_track.png', count: 128 }}
130
+ thumbImage="assets/slider_thumb.png"
131
+ onChange={(v) => setPan(v)}
132
+ />
133
+ ```
134
+
135
+ ---
136
+
137
+ ## geToggle
138
+
139
+ Two-state toggle control (on/off).
140
+
141
+ **JSX tag:** `<geToggle />`
142
+ **Interfaces:** Common, Bounds, Font, Clickable, Background, Highlight, MIDILearn, Margin
143
+ **Handlers:** ClickableHandlers, `onChange`
144
+
145
+ | Prop | Type | Description |
146
+ |------|------|-------------|
147
+ | `text` | `string` | Label text |
148
+ | `value` | `boolean` | Current state |
149
+ | `onColor` | `string` | Background color when on |
150
+ | `offColor` | `string` | Background color when off |
151
+ | `onColorHover` | `string` | Hover color when on |
152
+ | `offColorHover` | `string` | Hover color when off |
153
+ | `textColorOn` / `textColorOff` | `string` | Text color per state |
154
+ | `textColorOnHover` / `textColorOffHover` | `string` | Text hover color per state |
155
+ | `onImage` / `offImage` | `string` | Image per state |
156
+ | `onImagePressed` / `offImagePressed` | `string` | Pressed image per state |
157
+ | `onImageHovered` / `offImageHovered` | `string` | Hover image per state |
158
+ | `disabledImage` | `string` | Image when disabled |
159
+ | `radioIndex` / `radioValue` | `number` | Radio group behavior |
160
+ | `drawTick` | `boolean` | Draw a tick box |
161
+ | `fitToText` | `boolean` | Auto-size font to fit bounds |
162
+ | `animation` | `LottieAnimation` | Linked Lottie animation |
163
+
164
+ **Color-based toggle:**
165
+ ```tsx
166
+ <geToggle x={10} y={10} width={60} height={30}
167
+ value={isMuted}
168
+ text="Mute"
169
+ onColor="FFFF4444" offColor="FF444444"
170
+ textColorOn="FFFFFF" textColorOff="AAAAAA"
171
+ onChange={(isOn) => setMuted(isOn)}
172
+ />
173
+ ```
174
+
175
+ **Image-based toggle:**
176
+ ```tsx
177
+ <geToggle x={10} y={10} width={40} height={40}
178
+ value={isSolo}
179
+ onImage="solo_on.png" offImage="solo_off.png"
180
+ onChange={(isOn) => setSolo(isOn)}
181
+ />
182
+ ```
183
+
184
+ ---
185
+
186
+ ## geTextBox
187
+
188
+ Editable text input.
189
+
190
+ **JSX tag:** `<geTextBox />`
191
+ **Interfaces:** Font, Clickable, Bounds, Background, Margin, Keyable
192
+ **Handlers:** KeyableHandlers, `onChange`, `onFocusLost`
193
+
194
+ | Prop | Type | Description |
195
+ |------|------|-------------|
196
+ | `text` | `string` | Current text value |
197
+ | `placeholder` | `string` | Placeholder text |
198
+ | `unit` | `string` | Suffix displayed (doesn't alter value) |
199
+ | `placeHolderColor` | `string` | Placeholder text color |
200
+ | `caretColor` | `string` | Cursor color |
201
+ | `maxLength` | `number` | Max character count |
202
+ | `passwordCharacter` | `string` | Mask character for passwords |
203
+ | `multiLine` | `boolean` | Allow multiple lines |
204
+ | `readOnly` | `boolean` | Disable editing |
205
+ | `acceptedDataType` | `string` | `'integer'`, `'int'`, `'float'`, or `'string'` |
206
+ | `minValue` / `maxValue` | `number` | Numeric bounds (when numeric type) |
207
+ | `textChangedAction` | `string` | ViewModel action on enter (not on change) |
208
+ | `focusLostUpdate` | `boolean` | Update on focus lost |
209
+
210
+ ```tsx
211
+ <geTextBox x={10} y={10} width={200} height={30}
212
+ text={presetName}
213
+ placeholder="Enter preset name..."
214
+ backgroundColor="FF222222" textColor="FFFFFF"
215
+ fontSize={13}
216
+ onChange={(text) => setPresetName(text)}
217
+ onFocusLost={(text) => savePresetName(text)}
218
+ />
219
+ ```
220
+
221
+ **Numeric input:**
222
+ ```tsx
223
+ <geTextBox x={10} y={50} width={80} height={30}
224
+ text="440"
225
+ acceptedDataType="float"
226
+ minValue={20} maxValue={20000}
227
+ unit=" Hz"
228
+ onChange={(text) => setFrequency(parseFloat(text))}
229
+ />
230
+ ```
@@ -0,0 +1,183 @@
1
+ # Bindings
2
+
3
+ Declarative data binding connects UI component properties to instrument parameters or view model paths.
4
+
5
+ ## Binding Targets
6
+
7
+ Binding values can be either an **`InstrumentProperty` object** (preferred) or a **string path**.
8
+
9
+ ### Object binding (preferred)
10
+
11
+ Pass the `InstrumentProperty` directly. This is type-safe and avoids string typos:
12
+
13
+ ```tsx
14
+ // instrument[propName] returns an InstrumentProperty object
15
+ bindings={{ value: instrument.volume }}
16
+ bindings={{ value: instrument.filtercutoff, text: instrument.filtercutoff }}
17
+ ```
18
+
19
+ ### String path binding
20
+
21
+ Three string formats are supported:
22
+
23
+ | Format | Example | Description |
24
+ | -------------------- | ---------------------- | --------------------------------------------------------- |
25
+ | Instrument parameter | `'instrument.volume'` | References an instrument parameter by key name |
26
+ | Engine path | `'Scripts/0/Volume'` | Direct path into the instrument parameter tree |
27
+ | View model path | `'viewModel.property'` | `namespace.property` — references a registered view model |
28
+
29
+ **View model namespaces:**
30
+
31
+ - `'instrument'` — the active instrument (set via `GorillaEngine.setActiveInstrument()`); each property is an `InstrumentProperty` by its key name
32
+ - Any custom name registered with `initViewModel(name, initialState)` (e.g. `'viewModel.myProp'`)
33
+
34
+ > **`initViewModel` is deprecated.** Prefer using `useInstrumentProperty` hooks or object bindings.
35
+
36
+ ## React Props Syntax
37
+
38
+ Use the `bindings` prop on any component. Values can be `InstrumentProperty` objects or string paths:
39
+
40
+ ```tsx
41
+ // Object binding (preferred) — pass the InstrumentProperty directly
42
+ <geKnob
43
+ x={0} y={0} width={60} height={60}
44
+ bindings={{ value: instrument.volume }}
45
+ filmstrip={{ path: 'knob.png', count: 128 }}
46
+ />
47
+
48
+ // String binding — equivalent, but less safe
49
+ <geKnob
50
+ x={0} y={0} width={60} height={60}
51
+ bindings={{ value: 'instrument.volume' }}
52
+ filmstrip={{ path: 'knob.png', count: 128 }}
53
+ />
54
+ ```
55
+
56
+ The `bindings` object maps **native property names** to **binding targets** (object or string).
57
+
58
+ ### How It Works
59
+
60
+ The reconciler appends `&` to each binding key and passes the target through to the native layer:
61
+
62
+ ```
63
+ React: { bindings: { value: instrument.volume } } → Native: { 'value&': instrument.volume }
64
+ React: { bindings: { value: 'instrument.volume' } } → Native: { 'value&': 'instrument.volume' }
65
+ ```
66
+
67
+ ### Nested Bindings
68
+
69
+ Bindings can also be applied to nested object properties:
70
+
71
+ ```tsx
72
+ <geKnob
73
+ x={0}
74
+ y={0}
75
+ width={60}
76
+ height={60}
77
+ filmstrip={{ path: 'knob.png', count: 128, bindings: { path: 'vm.knobAsset' } }}
78
+ />
79
+ ```
80
+
81
+ This translates to:
82
+
83
+ ```
84
+ Native: { filmstrip: { count: 128, 'path&': 'vm.knobAsset' } }
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Runtime Binding API
90
+
91
+ All controls that support dynamic bindings expose these methods. Check support with `control.supportsSetBindings()` — returns `true` for most controls.
92
+
93
+ ### `control.setBindings(bindingsObj)`
94
+
95
+ Binds multiple properties at once. Pass `{}` to clear all bindings on the control.
96
+
97
+ The binding target can be a **string path** or an **`InstrumentProperty` object** directly (preferred).
98
+
99
+ ```js
100
+ // Bind by InstrumentProperty object (preferred)
101
+ control.setBindings({ value: instrument.volume });
102
+
103
+ // Bind by string path
104
+ control.setBindings({ value: 'instrument.volume', width: 'viewModel.size' });
105
+
106
+ // Clear all bindings
107
+ control.setBindings({});
108
+ ```
109
+
110
+ ### `control.bind(propertyPath, target)`
111
+
112
+ Rebinds a single property at runtime. Supports dot-separated paths for nested properties. Replaces any existing binding for that property.
113
+
114
+ ```js
115
+ // Bind by object (preferred)
116
+ control.bind('value', instrument.volume);
117
+
118
+ // Bind by string path
119
+ control.bind('value', 'instrument.volume');
120
+
121
+ // Bind nested property
122
+ control.bind('midiLearn.enabled', instrument.int1);
123
+ control.bind('filmstrip.path', 'viewModel.assetPath');
124
+ ```
125
+
126
+ ### `control.unbind(propertyPath)`
127
+
128
+ Removes the binding for a single property.
129
+
130
+ ```js
131
+ control.unbind('value');
132
+ ```
133
+
134
+ ### `control.supportsSetBindings()`
135
+
136
+ Returns `true` if the control supports runtime `setBindings`/`bind`. Most controls support this.
137
+
138
+ ---
139
+
140
+ ## Common Binding Targets
141
+
142
+ | Component | Object binding (preferred) | String equivalent |
143
+ | ---------- | --------------------------------- | ----------------------------------------- |
144
+ | geKnob | `{ value: instrument.volume }` | `{ value: 'instrument.volume' }` |
145
+ | geSlider | `{ value: instrument.Pan }` | `{ value: 'instrument.Pan' }` |
146
+ | geToggle | `{ value: instrument.Mute }` | `{ value: 'instrument.Mute' }` |
147
+ | geComboBox | `{ value: instrument.WaveShape }` | `{ value: 'instrument.WaveShape' }` |
148
+ | geLabel | `{ text: instrument.volume }` | `{ text: 'vm.displayText' }` (view model) |
149
+ | geWaveform | — | `{ value: 'vm.waveformData' }` |
150
+
151
+ ## Bindings vs. Hooks
152
+
153
+ | Approach | When to use |
154
+ | ----------------------- | ------------------------------------------------------------------------------------- |
155
+ | `bindings` | Direct engine parameter binding; no React state needed; simpler |
156
+ | `useInstrumentProperty` | Need React-side state, formatting, conditional logic, or cross-component coordination |
157
+
158
+ You can mix both approaches. Bindings are processed natively (more efficient for simple cases), while hooks give you full React control.
159
+
160
+ ## Example: Combined Approach
161
+
162
+ ```tsx
163
+ function FilterSection({ instrument }) {
164
+ // Use hook when you need the value in React
165
+ const [cutoff, setCutoff] = useInstrumentProperty(instrument, 'FilterCutoff');
166
+
167
+ return (
168
+ <geLabel x={0} y={0} width={200} height={100} backgroundColor="FF333333">
169
+ {/* Binding: knob value syncs directly with engine (object preferred) */}
170
+ <geKnob
171
+ x={10}
172
+ y={10}
173
+ width={60}
174
+ height={60}
175
+ bindings={{ value: instrument.filtercutoff }}
176
+ filmstrip={{ path: 'knob.png', count: 128 }}
177
+ />
178
+ {/* Hook: use React state for display text */}
179
+ <geLabel x={80} y={30} width={100} height={20} text={`${cutoff.text}`} textColor="FFFFFF" />
180
+ </geLabel>
181
+ );
182
+ }
183
+ ```
@@ -0,0 +1,258 @@
1
+ # Composite & Utility Components
2
+
3
+ ## geTagBrowser
4
+
5
+ Tag-based browser UI for filtering content.
6
+
7
+ **JSX tag:** `<geTagBrowser />`
8
+ **Interfaces:** Common, Bounds, Background, Font
9
+
10
+ | Prop | Type | Description |
11
+ | ------- | ------- | ------------------------ |
12
+ | `value` | `any` | Current selection value |
13
+ | `tags` | `Tag[]` | Array of tag definitions |
14
+
15
+ **Tag configuration:**
16
+
17
+ ```typescript
18
+ interface Tag {
19
+ height: number;
20
+ borderSize: number;
21
+ cornerRadius: number;
22
+ textColor: { normal: string; active: string; header: string };
23
+ backgroundColor: { normal: string; active: string; header: string };
24
+ cancel: { x: number; width: number };
25
+ }
26
+ ```
27
+
28
+ ```tsx
29
+ <geTagBrowser
30
+ x={10}
31
+ y={10}
32
+ width={300}
33
+ height={400}
34
+ backgroundColor="FF222222"
35
+ tags={tagDefinitions}
36
+ bindings={{ value: 'vm.selectedTags' }}
37
+ />
38
+ ```
39
+
40
+ ---
41
+
42
+ ## geTagEditor
43
+
44
+ Editable tag interface.
45
+
46
+ **JSX tag:** `<geTagEditor />`
47
+ **Interfaces:** Common, Bounds, Background, Font
48
+
49
+ | Prop | Type | Description |
50
+ | -------------- | --------- | -------------------------------------- |
51
+ | `value` | `any` | Current tags value |
52
+ | `tags` | `Tag[]` | Tag definitions (same as geTagBrowser) |
53
+ | `editable` | `boolean` | Allow editing tags |
54
+ | `action` | `string` | ViewModel action on change |
55
+ | `removeAction` | `string` | ViewModel action on tag removal |
56
+
57
+ ```tsx
58
+ <geTagEditor
59
+ x={10}
60
+ y={10}
61
+ width={300}
62
+ height={100}
63
+ backgroundColor="FF222222"
64
+ editable={true}
65
+ tags={tagDefinitions}
66
+ bindings={{ value: 'vm.editableTags' }}
67
+ />
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Labeled Controls
73
+
74
+ Use `@gorilla-engine-sdk/ge-labeled-components` when a control needs a name label, a formatted value label, or interaction-driven label visibility. These components bind directly to Gorilla Engine instrument properties.
75
+
76
+ ```tsx
77
+ import {
78
+ LabeledComboBox,
79
+ LabeledKnob,
80
+ LabeledMeterSlider,
81
+ LabeledRTToggle,
82
+ LabeledSlider,
83
+ LabeledToggle,
84
+ } from '@gorilla-engine-sdk/ge-labeled-components';
85
+ ```
86
+
87
+ The package exports:
88
+
89
+ | Component | Use case | Control configuration prop |
90
+ | -------------------- | --------------------------------------------- | -------------------------- |
91
+ | `LabeledKnob` | Rotary parameter control | `knob` |
92
+ | `LabeledSlider` | Horizontal or vertical parameter control | `slider` |
93
+ | `LabeledToggle` | Persistent on/off parameter control | `toggle` |
94
+ | `LabeledComboBox` | Selection from a parameter's available values | `comboBox` |
95
+ | `LabeledMeterSlider` | Parameter slider over a live level meter | `slider`, `meter` |
96
+ | `LabeledRTToggle` | Momentary control active while pressed | `button` |
97
+
98
+ ### Shared Props
99
+
100
+ | Prop | Type | Description |
101
+ | ------------------------- | ---------------------------------- | ----------------------------------------------- |
102
+ | `x`, `y` | `number` | Position of the labeled component container |
103
+ | `width`, `height` | `number` | Size of the labeled component container |
104
+ | `instrument` | `GorillaEngine.Instrument` | Instrument instance supplied to the UI |
105
+ | `instrumentProp` | `GorillaEngine.InstrumentProperty` | Instrument property controlled by the component |
106
+ | `textLabel` | Partial label props | Name-label position, appearance, and `text` |
107
+ | `valueLabel` | Partial label props | Value-label position and appearance |
108
+ | `hideValueLabel` | `boolean` | Hide the value until the configured interaction |
109
+ | `hideTextValue` | `boolean` | Hide the name while the value is visible |
110
+ | `toggleVisibilityOnHover` | `boolean` | Show the value on hover instead of mouse down |
111
+ | `ranges` | `{ from?, to?, text }[]` | Format values for matching numeric ranges |
112
+
113
+ Pass geometry and assets for the native control inside its component-specific configuration prop. Bind through `instrumentProp`; do not mirror parameter values into React state.
114
+
115
+ ### Knob Example
116
+
117
+ ```tsx
118
+ <LabeledKnob
119
+ x={40}
120
+ y={40}
121
+ width={90}
122
+ height={110}
123
+ instrument={instrument}
124
+ instrumentProp={instrument.volume}
125
+ hideValueLabel={true}
126
+ hideTextValue={true}
127
+ toggleVisibilityOnHover={true}
128
+ textLabel={{
129
+ y: 88,
130
+ height: 18,
131
+ text: 'VOLUME',
132
+ font: 'fonts/Roboto-Medium.otf',
133
+ fontSize: 12,
134
+ textAlign: 'center',
135
+ }}
136
+ valueLabel={{
137
+ y: 88,
138
+ height: 18,
139
+ font: 'fonts/Roboto-Medium.otf',
140
+ fontSize: 12,
141
+ textAlign: 'center',
142
+ }}
143
+ ranges={[{ text: '$value(1) dB' }]}
144
+ knob={{
145
+ width: 80,
146
+ height: 80,
147
+ filmstrip: {
148
+ path: 'images/volume-knob.png',
149
+ count: 128,
150
+ direction: 'vertical',
151
+ },
152
+ }}
153
+ />
154
+ ```
155
+
156
+ ### Slider And Toggle Example
157
+
158
+ ```tsx
159
+ <LabeledSlider
160
+ x={160}
161
+ y={40}
162
+ width={60}
163
+ height={220}
164
+ instrument={instrument}
165
+ instrumentProp={instrument.output}
166
+ textLabel={{ y: 194, height: 18, text: 'OUTPUT', textAlign: 'center' }}
167
+ valueLabel={{ y: 194, height: 18, textAlign: 'center' }}
168
+ ranges={[{ text: '$value(1) dB' }]}
169
+ slider={{
170
+ y: 0,
171
+ width: 40,
172
+ height: 180,
173
+ filmstrip: {
174
+ path: 'images/output-slider.png',
175
+ count: 128,
176
+ direction: 'vertical',
177
+ },
178
+ }}
179
+ />
180
+
181
+ <LabeledToggle
182
+ x={250}
183
+ y={40}
184
+ width={80}
185
+ height={90}
186
+ instrument={instrument}
187
+ instrumentProp={instrument.bypass}
188
+ textLabel={{ y: 66, height: 18, text: 'BYPASS', textAlign: 'center' }}
189
+ toggle={{
190
+ width: 60,
191
+ height: 60,
192
+ filmstrip: {
193
+ path: 'images/bypass-toggle.png',
194
+ count: 2,
195
+ direction: 'vertical',
196
+ },
197
+ }}
198
+ />
199
+ ```
200
+
201
+ ### Selection, Meter, And Momentary Examples
202
+
203
+ ```tsx
204
+ <LabeledComboBox
205
+ x={360}
206
+ y={40}
207
+ width={140}
208
+ height={70}
209
+ instrument={instrument}
210
+ instrumentProp={instrument.mode}
211
+ textLabel={{ y: 48, height: 18, text: 'MODE', textAlign: 'center' }}
212
+ comboBox={{ y: 0, width: 120, height: 36 }}
213
+ />
214
+
215
+ <LabeledMeterSlider
216
+ x={520}
217
+ y={40}
218
+ width={60}
219
+ height={240}
220
+ instrument={instrument}
221
+ instrumentProp={instrument.master_volume}
222
+ meterProp={instrument.master_level}
223
+ textLabel={{ y: 214, height: 18, text: 'MASTER', textAlign: 'center' }}
224
+ valueLabel={{ y: 214, height: 18, textAlign: 'center' }}
225
+ meter={{ y: 0, width: 30, height: 200 }}
226
+ slider={{ y: 0, width: 40, height: 200 }}
227
+ />
228
+
229
+ <LabeledRTToggle
230
+ x={610}
231
+ y={40}
232
+ width={80}
233
+ height={90}
234
+ instrument={instrument}
235
+ instrumentProp={instrument.trigger}
236
+ textLabel={{ y: 66, height: 18, text: 'TRIGGER', textAlign: 'center' }}
237
+ button={{ width: 60, height: 60 }}
238
+ />
239
+ ```
240
+
241
+ `LabeledRTToggle` writes `1` while pressed and returns the property to `0` when released.
242
+
243
+ ### Value Formatting
244
+
245
+ Use `ranges` to format the displayed value. `$value` inserts the raw value, `$value(n)` fixes it to `n` decimal places, and `$text_value` uses the parameter's formatted text.
246
+
247
+ ```tsx
248
+ <LabeledKnob
249
+ instrument={instrument}
250
+ instrumentProp={instrument.frequency}
251
+ ranges={[
252
+ { to: 999, text: '$value(0) Hz' },
253
+ { from: 1000, text: '$value(2) kHz' },
254
+ ]}
255
+ textLabel={{ text: 'FREQUENCY' }}
256
+ knob={{ width: 80, height: 80 }}
257
+ />
258
+ ```