@rozenite/controls-plugin 1.4.0 → 1.5.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/CHANGELOG.md +13 -0
- package/dist/rozenite.json +1 -1
- package/dist/src/react-native/useControlsAgentTools.d.ts +2 -0
- package/dist/useRozeniteControlsPlugin.cjs +1 -1
- package/dist/useRozeniteControlsPlugin.js +333 -139
- package/package.json +6 -4
- package/src/react-native/useControlsAgentTools.ts +277 -0
- package/src/react-native/useRozeniteControlsPlugin.ts +3 -0
- package/.turbo/turbo-build.log +0 -16
- package/.turbo/turbo-lint.log +0 -4
- package/.turbo/turbo-typecheck.log +0 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @rozenite/controls-plugin
|
|
2
|
+
|
|
3
|
+
## 1.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#190](https://github.com/callstackincubator/rozenite/pull/190) [`5ae53a4`](https://github.com/callstackincubator/rozenite/commit/5ae53a4b509adbd8536ea24812f7ca523a95b625) Thanks [@V3RON](https://github.com/V3RON)! - Added Rozenite for Agents support to the Controls, MMKV, React Navigation, and Storage plugins.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`5ae53a4`](https://github.com/callstackincubator/rozenite/commit/5ae53a4b509adbd8536ea24812f7ca523a95b625)]:
|
|
12
|
+
- @rozenite/agent-bridge@1.5.0
|
|
13
|
+
- @rozenite/plugin-bridge@1.5.0
|
package/dist/rozenite.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@rozenite/controls-plugin","version":"
|
|
1
|
+
{"name":"@rozenite/controls-plugin","version":"1.5.0","description":"A Rozenite plugin for exposing app-defined controls directly in React Native DevTools.","panels":[{"name":"Controls","source":"/panel.html"}]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("@rozenite/plugin-bridge"),c=require("react"),f=require("@rozenite/agent-bridge"),w=(o,t)=>o?o(t):{valid:!0},U=o=>o.type==="text"?o:o.type==="toggle"?{id:o.id,type:o.type,title:o.title,value:o.value,description:o.description,disabled:o.disabled}:o.type==="button"?{id:o.id,type:o.type,title:o.title,actionLabel:o.actionLabel,description:o.description,disabled:o.disabled}:o.type==="select"?{id:o.id,type:o.type,title:o.title,value:o.value,options:o.options,description:o.description,disabled:o.disabled}:{id:o.id,type:o.type,title:o.title,value:o.value,placeholder:o.placeholder,applyLabel:o.applyLabel,description:o.description,disabled:o.disabled},P=o=>o.map(t=>({id:t.id,title:t.title,description:t.description,items:t.items.map(U)})),z=o=>{const t=new Map;return o.forEach(n=>{n.items.forEach(e=>{const i=`${n.id}:${e.id}`;e.type==="toggle"&&t.set(i,{type:"toggle",validate:e.validate,onUpdate:e.onUpdate}),e.type==="button"&&t.set(i,{type:"button",onPress:e.onPress}),e.type==="select"&&t.set(i,{type:"select",validate:e.validate,onUpdate:e.onUpdate}),e.type==="input"&&t.set(i,{type:"input",validate:e.validate,onUpdate:e.onUpdate})})}),t},$=(o,t)=>`${o}:${t}`,b="@rozenite/controls-plugin",S={name:"list-sections",description:"List all controls sections with their item IDs, types, and titles. Does not include values — call get-item for that.",inputSchema:{type:"object",properties:{}}},A={name:"get-item",description:"Get full details of a single controls item including its current value. For select items this includes available options.",inputSchema:{type:"object",properties:{sectionId:{type:"string",description:"Section ID."},itemId:{type:"string",description:"Item ID."}},required:["sectionId","itemId"]}},T={name:"set-value",description:"Update the value of a toggle, select, or input item. Runs the validate callback when present. Fails for text (read-only) and button items.",inputSchema:{type:"object",properties:{sectionId:{type:"string",description:"Section ID."},itemId:{type:"string",description:"Item ID."},value:{description:"New value. Boolean for toggle items, string for select/input items."}},required:["sectionId","itemId","value"]}},C={name:"press-button",description:"Trigger a button item's action. Fails if the item is not a button or is disabled.",inputSchema:{type:"object",properties:{sectionId:{type:"string",description:"Section ID."},itemId:{type:"string",description:"Item ID."}},required:["sectionId","itemId"]}},v=(o,t,n)=>{const e=o.find(s=>s.id===t);if(!e){const s=o.map(u=>u.id).join(", ");throw new Error(`Section "${t}" not found. Available: ${s||"(none)"}`)}const i=e.items.find(s=>s.id===n);if(!i){const s=e.items.map(u=>u.id).join(", ");throw new Error(`Item "${n}" not found in section "${t}". Available: ${s||"(none)"}`)}return{section:e,item:i}},D=o=>{f.useRozenitePluginAgentTool({pluginId:b,tool:S,handler:()=>({sections:o.map(t=>({id:t.id,title:t.title,description:t.description,items:t.items.map(n=>({id:n.id,type:n.type,title:n.title,disabled:"disabled"in n?n.disabled:void 0}))}))})}),f.useRozenitePluginAgentTool({pluginId:b,tool:A,handler:({sectionId:t,itemId:n})=>{const{item:e}=v(o,t,n);return e.type==="text"?{sectionId:t,item:{id:e.id,type:e.type,title:e.title,value:e.value,description:e.description}}:e.type==="toggle"?{sectionId:t,item:{id:e.id,type:e.type,title:e.title,value:e.value,description:e.description,disabled:e.disabled}}:e.type==="button"?{sectionId:t,item:{id:e.id,type:e.type,title:e.title,actionLabel:e.actionLabel,description:e.description,disabled:e.disabled}}:e.type==="select"?{sectionId:t,item:{id:e.id,type:e.type,title:e.title,value:e.value,options:e.options,description:e.description,disabled:e.disabled}}:{sectionId:t,item:{id:e.id,type:e.type,title:e.title,value:e.value,placeholder:e.placeholder,applyLabel:e.applyLabel,description:e.description,disabled:e.disabled}}}}),f.useRozenitePluginAgentTool({pluginId:b,tool:T,handler:async({sectionId:t,itemId:n,value:e})=>{const{item:i}=v(o,t,n);if(i.type==="text")throw new Error(`Item "${n}" is a read-only text item and cannot be updated.`);if(i.type==="button")throw new Error(`Item "${n}" is a button. Use press-button to trigger its action.`);if(i.disabled)throw new Error(`Item "${n}" is disabled.`);if(i.type==="toggle"){if(typeof e!="boolean")throw new Error(`Expected boolean value for toggle item "${n}".`);if(i.validate){const s=i.validate(e);if(!s.valid)throw new Error(s.message)}return await i.onUpdate(e),{applied:!0,sectionId:t,itemId:n}}if(typeof e!="string")throw new Error(`Expected string value for ${i.type} item "${n}".`);if(i.type==="select"){const s=i.options.map(u=>u.value);if(!s.includes(e))throw new Error(`Invalid option "${e}" for item "${n}". Valid options: ${s.join(", ")}`)}if(i.validate){const s=i.validate(e);if(!s.valid)throw new Error(s.message)}return await i.onUpdate(e),{applied:!0,sectionId:t,itemId:n}}}),f.useRozenitePluginAgentTool({pluginId:b,tool:C,handler:async({sectionId:t,itemId:n})=>{const{item:e}=v(o,t,n);if(e.type!=="button")throw new Error(`Item "${n}" is not a button (type: ${e.type}). Use set-value to update its value.`);if(e.disabled)throw new Error(`Button "${n}" is disabled.`);return await e.onPress(),{pressed:!0,sectionId:t,itemId:n}}})},L=({sections:o})=>{const t=R.useRozeniteDevToolsClient({pluginId:"@rozenite/controls-plugin"});D(o);const n=c.useMemo(()=>P(o),[o]),e=c.useMemo(()=>z(o),[o]),i=c.useRef(e);return c.useEffect(()=>{i.current=e},[e]),c.useEffect(()=>{t&&t.send("snapshot",{type:"snapshot",sections:n})},[t,n]),c.useEffect(()=>{if(!t)return;const s=async({requestId:r,sectionId:a,itemId:l,value:d})=>{const y=$(a,l),p=i.current.get(y);if(!p||p.type==="button"){t.send("update-result",{type:"update-result",requestId:r,sectionId:a,itemId:l,status:"error",message:"Update target not found."});return}try{if(p.type==="toggle"){if(typeof d!="boolean"){t.send("update-result",{type:"update-result",requestId:r,sectionId:a,itemId:l,status:"error",message:"Invalid toggle value."});return}const h=w(p.validate,d);if(!h.valid){t.send("update-result",{type:"update-result",requestId:r,sectionId:a,itemId:l,status:"error",message:h.message});return}await p.onUpdate(d),t.send("update-result",{type:"update-result",requestId:r,sectionId:a,itemId:l,status:"ok"});return}if(typeof d!="string"){t.send("update-result",{type:"update-result",requestId:r,sectionId:a,itemId:l,status:"error",message:`Invalid ${p.type} value.`});return}const g=w(p.validate,d);if(!g.valid){t.send("update-result",{type:"update-result",requestId:r,sectionId:a,itemId:l,status:"error",message:g.message});return}await p.onUpdate(d),t.send("update-result",{type:"update-result",requestId:r,sectionId:a,itemId:l,status:"ok"})}catch(g){console.warn(`[Rozenite] Controls Plugin: Update failed for ${a}/${l}.`,g),t.send("update-result",{type:"update-result",requestId:r,sectionId:a,itemId:l,status:"error",message:"Update failed on the device."})}},u=async({sectionId:r,itemId:a,action:l})=>{if(l!=="press"){console.warn(`[Rozenite] Controls Plugin: Unsupported action "${l}" for ${r}/${a}.`);return}const d=$(r,a),y=i.current.get(d);if(!y){console.warn(`[Rozenite] Controls Plugin: Action target not found for ${r}/${a}.`);return}try{if(y.type!=="button"){console.warn(`[Rozenite] Controls Plugin: Invalid press action payload for ${r}/${a}.`);return}await y.onPress()}catch(p){console.warn(`[Rozenite] Controls Plugin: Action failed for ${r}/${a}.`,p)}},E=[t.onMessage("get-snapshot",()=>{t.send("snapshot",{type:"snapshot",sections:n})}),t.onMessage("update-request",r=>{s(r)}),t.onMessage("invoke-action",r=>{u(r)})];return()=>{E.forEach(r=>r.remove())}},[t,n]),t};exports.useRozeniteControlsPlugin=L;
|
|
@@ -1,226 +1,420 @@
|
|
|
1
1
|
import { useRozeniteDevToolsClient as R } from "@rozenite/plugin-bridge";
|
|
2
|
-
import { useMemo as
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
2
|
+
import { useMemo as w, useRef as z, useEffect as b } from "react";
|
|
3
|
+
import { useRozenitePluginAgentTool as f } from "@rozenite/agent-bridge";
|
|
4
|
+
const $ = (o, e) => o ? o(e) : { valid: !0 }, P = (o) => o.type === "text" ? o : o.type === "toggle" ? {
|
|
5
|
+
id: o.id,
|
|
6
|
+
type: o.type,
|
|
7
|
+
title: o.title,
|
|
8
|
+
value: o.value,
|
|
9
|
+
description: o.description,
|
|
10
|
+
disabled: o.disabled
|
|
11
|
+
} : o.type === "button" ? {
|
|
12
|
+
id: o.id,
|
|
13
|
+
type: o.type,
|
|
14
|
+
title: o.title,
|
|
15
|
+
actionLabel: o.actionLabel,
|
|
16
|
+
description: o.description,
|
|
17
|
+
disabled: o.disabled
|
|
18
|
+
} : o.type === "select" ? {
|
|
19
|
+
id: o.id,
|
|
20
|
+
type: o.type,
|
|
21
|
+
title: o.title,
|
|
22
|
+
value: o.value,
|
|
23
|
+
options: o.options,
|
|
24
|
+
description: o.description,
|
|
25
|
+
disabled: o.disabled
|
|
25
26
|
} : {
|
|
27
|
+
id: o.id,
|
|
28
|
+
type: o.type,
|
|
29
|
+
title: o.title,
|
|
30
|
+
value: o.value,
|
|
31
|
+
placeholder: o.placeholder,
|
|
32
|
+
applyLabel: o.applyLabel,
|
|
33
|
+
description: o.description,
|
|
34
|
+
disabled: o.disabled
|
|
35
|
+
}, S = (o) => o.map((e) => ({
|
|
26
36
|
id: e.id,
|
|
27
|
-
type: e.type,
|
|
28
37
|
title: e.title,
|
|
29
|
-
value: e.value,
|
|
30
|
-
placeholder: e.placeholder,
|
|
31
|
-
applyLabel: e.applyLabel,
|
|
32
38
|
description: e.description,
|
|
33
|
-
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const t = /* @__PURE__ */ new Map();
|
|
41
|
-
return e.forEach((u) => {
|
|
42
|
-
u.items.forEach((n) => {
|
|
43
|
-
const p = `${u.id}:${n.id}`;
|
|
44
|
-
n.type === "toggle" && t.set(p, {
|
|
39
|
+
items: e.items.map(P)
|
|
40
|
+
})), m = (o) => {
|
|
41
|
+
const e = /* @__PURE__ */ new Map();
|
|
42
|
+
return o.forEach((n) => {
|
|
43
|
+
n.items.forEach((t) => {
|
|
44
|
+
const r = `${n.id}:${t.id}`;
|
|
45
|
+
t.type === "toggle" && e.set(r, {
|
|
45
46
|
type: "toggle",
|
|
46
|
-
validate:
|
|
47
|
-
onUpdate:
|
|
48
|
-
}),
|
|
47
|
+
validate: t.validate,
|
|
48
|
+
onUpdate: t.onUpdate
|
|
49
|
+
}), t.type === "button" && e.set(r, {
|
|
49
50
|
type: "button",
|
|
50
|
-
onPress:
|
|
51
|
-
}),
|
|
51
|
+
onPress: t.onPress
|
|
52
|
+
}), t.type === "select" && e.set(r, {
|
|
52
53
|
type: "select",
|
|
53
|
-
validate:
|
|
54
|
-
onUpdate:
|
|
55
|
-
}),
|
|
54
|
+
validate: t.validate,
|
|
55
|
+
onUpdate: t.onUpdate
|
|
56
|
+
}), t.type === "input" && e.set(r, {
|
|
56
57
|
type: "input",
|
|
57
|
-
validate:
|
|
58
|
-
onUpdate:
|
|
58
|
+
validate: t.validate,
|
|
59
|
+
onUpdate: t.onUpdate
|
|
59
60
|
});
|
|
60
61
|
});
|
|
61
|
-
}),
|
|
62
|
-
},
|
|
63
|
-
|
|
62
|
+
}), e;
|
|
63
|
+
}, E = (o, e) => `${o}:${e}`, g = "@rozenite/controls-plugin", A = {
|
|
64
|
+
name: "list-sections",
|
|
65
|
+
description: "List all controls sections with their item IDs, types, and titles. Does not include values — call get-item for that.",
|
|
66
|
+
inputSchema: { type: "object", properties: {} }
|
|
67
|
+
}, D = {
|
|
68
|
+
name: "get-item",
|
|
69
|
+
description: "Get full details of a single controls item including its current value. For select items this includes available options.",
|
|
70
|
+
inputSchema: {
|
|
71
|
+
type: "object",
|
|
72
|
+
properties: {
|
|
73
|
+
sectionId: { type: "string", description: "Section ID." },
|
|
74
|
+
itemId: { type: "string", description: "Item ID." }
|
|
75
|
+
},
|
|
76
|
+
required: ["sectionId", "itemId"]
|
|
77
|
+
}
|
|
78
|
+
}, L = {
|
|
79
|
+
name: "set-value",
|
|
80
|
+
description: "Update the value of a toggle, select, or input item. Runs the validate callback when present. Fails for text (read-only) and button items.",
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: "object",
|
|
83
|
+
properties: {
|
|
84
|
+
sectionId: { type: "string", description: "Section ID." },
|
|
85
|
+
itemId: { type: "string", description: "Item ID." },
|
|
86
|
+
value: {
|
|
87
|
+
description: "New value. Boolean for toggle items, string for select/input items."
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
required: ["sectionId", "itemId", "value"]
|
|
91
|
+
}
|
|
92
|
+
}, k = {
|
|
93
|
+
name: "press-button",
|
|
94
|
+
description: "Trigger a button item's action. Fails if the item is not a button or is disabled.",
|
|
95
|
+
inputSchema: {
|
|
96
|
+
type: "object",
|
|
97
|
+
properties: {
|
|
98
|
+
sectionId: { type: "string", description: "Section ID." },
|
|
99
|
+
itemId: { type: "string", description: "Item ID." }
|
|
100
|
+
},
|
|
101
|
+
required: ["sectionId", "itemId"]
|
|
102
|
+
}
|
|
103
|
+
}, v = (o, e, n) => {
|
|
104
|
+
const t = o.find((s) => s.id === e);
|
|
105
|
+
if (!t) {
|
|
106
|
+
const s = o.map((u) => u.id).join(", ");
|
|
107
|
+
throw new Error(
|
|
108
|
+
`Section "${e}" not found. Available: ${s || "(none)"}`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
const r = t.items.find((s) => s.id === n);
|
|
112
|
+
if (!r) {
|
|
113
|
+
const s = t.items.map((u) => u.id).join(", ");
|
|
114
|
+
throw new Error(
|
|
115
|
+
`Item "${n}" not found in section "${e}". Available: ${s || "(none)"}`
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return { section: t, item: r };
|
|
119
|
+
}, x = (o) => {
|
|
120
|
+
f({
|
|
121
|
+
pluginId: g,
|
|
122
|
+
tool: A,
|
|
123
|
+
handler: () => ({
|
|
124
|
+
sections: o.map((e) => ({
|
|
125
|
+
id: e.id,
|
|
126
|
+
title: e.title,
|
|
127
|
+
description: e.description,
|
|
128
|
+
items: e.items.map((n) => ({
|
|
129
|
+
id: n.id,
|
|
130
|
+
type: n.type,
|
|
131
|
+
title: n.title,
|
|
132
|
+
disabled: "disabled" in n ? n.disabled : void 0
|
|
133
|
+
}))
|
|
134
|
+
}))
|
|
135
|
+
})
|
|
136
|
+
}), f({
|
|
137
|
+
pluginId: g,
|
|
138
|
+
tool: D,
|
|
139
|
+
handler: ({ sectionId: e, itemId: n }) => {
|
|
140
|
+
const { item: t } = v(o, e, n);
|
|
141
|
+
return t.type === "text" ? {
|
|
142
|
+
sectionId: e,
|
|
143
|
+
item: {
|
|
144
|
+
id: t.id,
|
|
145
|
+
type: t.type,
|
|
146
|
+
title: t.title,
|
|
147
|
+
value: t.value,
|
|
148
|
+
description: t.description
|
|
149
|
+
}
|
|
150
|
+
} : t.type === "toggle" ? {
|
|
151
|
+
sectionId: e,
|
|
152
|
+
item: {
|
|
153
|
+
id: t.id,
|
|
154
|
+
type: t.type,
|
|
155
|
+
title: t.title,
|
|
156
|
+
value: t.value,
|
|
157
|
+
description: t.description,
|
|
158
|
+
disabled: t.disabled
|
|
159
|
+
}
|
|
160
|
+
} : t.type === "button" ? {
|
|
161
|
+
sectionId: e,
|
|
162
|
+
item: {
|
|
163
|
+
id: t.id,
|
|
164
|
+
type: t.type,
|
|
165
|
+
title: t.title,
|
|
166
|
+
actionLabel: t.actionLabel,
|
|
167
|
+
description: t.description,
|
|
168
|
+
disabled: t.disabled
|
|
169
|
+
}
|
|
170
|
+
} : t.type === "select" ? {
|
|
171
|
+
sectionId: e,
|
|
172
|
+
item: {
|
|
173
|
+
id: t.id,
|
|
174
|
+
type: t.type,
|
|
175
|
+
title: t.title,
|
|
176
|
+
value: t.value,
|
|
177
|
+
options: t.options,
|
|
178
|
+
description: t.description,
|
|
179
|
+
disabled: t.disabled
|
|
180
|
+
}
|
|
181
|
+
} : {
|
|
182
|
+
sectionId: e,
|
|
183
|
+
item: {
|
|
184
|
+
id: t.id,
|
|
185
|
+
type: t.type,
|
|
186
|
+
title: t.title,
|
|
187
|
+
value: t.value,
|
|
188
|
+
placeholder: t.placeholder,
|
|
189
|
+
applyLabel: t.applyLabel,
|
|
190
|
+
description: t.description,
|
|
191
|
+
disabled: t.disabled
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}), f({
|
|
196
|
+
pluginId: g,
|
|
197
|
+
tool: L,
|
|
198
|
+
handler: async ({ sectionId: e, itemId: n, value: t }) => {
|
|
199
|
+
const { item: r } = v(o, e, n);
|
|
200
|
+
if (r.type === "text")
|
|
201
|
+
throw new Error(
|
|
202
|
+
`Item "${n}" is a read-only text item and cannot be updated.`
|
|
203
|
+
);
|
|
204
|
+
if (r.type === "button")
|
|
205
|
+
throw new Error(
|
|
206
|
+
`Item "${n}" is a button. Use press-button to trigger its action.`
|
|
207
|
+
);
|
|
208
|
+
if (r.disabled)
|
|
209
|
+
throw new Error(`Item "${n}" is disabled.`);
|
|
210
|
+
if (r.type === "toggle") {
|
|
211
|
+
if (typeof t != "boolean")
|
|
212
|
+
throw new Error(
|
|
213
|
+
`Expected boolean value for toggle item "${n}".`
|
|
214
|
+
);
|
|
215
|
+
if (r.validate) {
|
|
216
|
+
const s = r.validate(t);
|
|
217
|
+
if (!s.valid)
|
|
218
|
+
throw new Error(s.message);
|
|
219
|
+
}
|
|
220
|
+
return await r.onUpdate(t), { applied: !0, sectionId: e, itemId: n };
|
|
221
|
+
}
|
|
222
|
+
if (typeof t != "string")
|
|
223
|
+
throw new Error(
|
|
224
|
+
`Expected string value for ${r.type} item "${n}".`
|
|
225
|
+
);
|
|
226
|
+
if (r.type === "select") {
|
|
227
|
+
const s = r.options.map((u) => u.value);
|
|
228
|
+
if (!s.includes(t))
|
|
229
|
+
throw new Error(
|
|
230
|
+
`Invalid option "${t}" for item "${n}". Valid options: ${s.join(", ")}`
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
if (r.validate) {
|
|
234
|
+
const s = r.validate(t);
|
|
235
|
+
if (!s.valid)
|
|
236
|
+
throw new Error(s.message);
|
|
237
|
+
}
|
|
238
|
+
return await r.onUpdate(t), { applied: !0, sectionId: e, itemId: n };
|
|
239
|
+
}
|
|
240
|
+
}), f({
|
|
241
|
+
pluginId: g,
|
|
242
|
+
tool: k,
|
|
243
|
+
handler: async ({ sectionId: e, itemId: n }) => {
|
|
244
|
+
const { item: t } = v(o, e, n);
|
|
245
|
+
if (t.type !== "button")
|
|
246
|
+
throw new Error(
|
|
247
|
+
`Item "${n}" is not a button (type: ${t.type}). Use set-value to update its value.`
|
|
248
|
+
);
|
|
249
|
+
if (t.disabled)
|
|
250
|
+
throw new Error(`Button "${n}" is disabled.`);
|
|
251
|
+
return await t.onPress(), { pressed: !0, sectionId: e, itemId: n };
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}, M = ({
|
|
255
|
+
sections: o
|
|
64
256
|
}) => {
|
|
65
|
-
const
|
|
257
|
+
const e = R({
|
|
66
258
|
pluginId: "@rozenite/controls-plugin"
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
259
|
+
});
|
|
260
|
+
x(o);
|
|
261
|
+
const n = w(() => S(o), [o]), t = w(() => m(o), [o]), r = z(t);
|
|
262
|
+
return b(() => {
|
|
263
|
+
r.current = t;
|
|
264
|
+
}, [t]), b(() => {
|
|
265
|
+
e && e.send("snapshot", {
|
|
72
266
|
type: "snapshot",
|
|
73
|
-
sections:
|
|
267
|
+
sections: n
|
|
74
268
|
});
|
|
75
|
-
}, [
|
|
76
|
-
if (!
|
|
269
|
+
}, [e, n]), b(() => {
|
|
270
|
+
if (!e)
|
|
77
271
|
return;
|
|
78
|
-
const
|
|
79
|
-
requestId:
|
|
80
|
-
sectionId:
|
|
81
|
-
itemId:
|
|
82
|
-
value:
|
|
272
|
+
const s = async ({
|
|
273
|
+
requestId: i,
|
|
274
|
+
sectionId: a,
|
|
275
|
+
itemId: l,
|
|
276
|
+
value: d
|
|
83
277
|
}) => {
|
|
84
|
-
const
|
|
85
|
-
if (!
|
|
86
|
-
|
|
278
|
+
const c = E(a, l), p = r.current.get(c);
|
|
279
|
+
if (!p || p.type === "button") {
|
|
280
|
+
e.send("update-result", {
|
|
87
281
|
type: "update-result",
|
|
88
|
-
requestId:
|
|
89
|
-
sectionId:
|
|
90
|
-
itemId:
|
|
282
|
+
requestId: i,
|
|
283
|
+
sectionId: a,
|
|
284
|
+
itemId: l,
|
|
91
285
|
status: "error",
|
|
92
286
|
message: "Update target not found."
|
|
93
287
|
});
|
|
94
288
|
return;
|
|
95
289
|
}
|
|
96
290
|
try {
|
|
97
|
-
if (
|
|
98
|
-
if (typeof
|
|
99
|
-
|
|
291
|
+
if (p.type === "toggle") {
|
|
292
|
+
if (typeof d != "boolean") {
|
|
293
|
+
e.send("update-result", {
|
|
100
294
|
type: "update-result",
|
|
101
|
-
requestId:
|
|
102
|
-
sectionId:
|
|
103
|
-
itemId:
|
|
295
|
+
requestId: i,
|
|
296
|
+
sectionId: a,
|
|
297
|
+
itemId: l,
|
|
104
298
|
status: "error",
|
|
105
299
|
message: "Invalid toggle value."
|
|
106
300
|
});
|
|
107
301
|
return;
|
|
108
302
|
}
|
|
109
|
-
const
|
|
110
|
-
if (!
|
|
111
|
-
|
|
303
|
+
const h = $(p.validate, d);
|
|
304
|
+
if (!h.valid) {
|
|
305
|
+
e.send("update-result", {
|
|
112
306
|
type: "update-result",
|
|
113
|
-
requestId:
|
|
114
|
-
sectionId:
|
|
115
|
-
itemId:
|
|
307
|
+
requestId: i,
|
|
308
|
+
sectionId: a,
|
|
309
|
+
itemId: l,
|
|
116
310
|
status: "error",
|
|
117
|
-
message:
|
|
311
|
+
message: h.message
|
|
118
312
|
});
|
|
119
313
|
return;
|
|
120
314
|
}
|
|
121
|
-
await
|
|
315
|
+
await p.onUpdate(d), e.send("update-result", {
|
|
122
316
|
type: "update-result",
|
|
123
|
-
requestId:
|
|
124
|
-
sectionId:
|
|
125
|
-
itemId:
|
|
317
|
+
requestId: i,
|
|
318
|
+
sectionId: a,
|
|
319
|
+
itemId: l,
|
|
126
320
|
status: "ok"
|
|
127
321
|
});
|
|
128
322
|
return;
|
|
129
323
|
}
|
|
130
|
-
if (typeof
|
|
131
|
-
|
|
324
|
+
if (typeof d != "string") {
|
|
325
|
+
e.send("update-result", {
|
|
132
326
|
type: "update-result",
|
|
133
|
-
requestId:
|
|
134
|
-
sectionId:
|
|
135
|
-
itemId:
|
|
327
|
+
requestId: i,
|
|
328
|
+
sectionId: a,
|
|
329
|
+
itemId: l,
|
|
136
330
|
status: "error",
|
|
137
|
-
message: `Invalid ${
|
|
331
|
+
message: `Invalid ${p.type} value.`
|
|
138
332
|
});
|
|
139
333
|
return;
|
|
140
334
|
}
|
|
141
|
-
const
|
|
142
|
-
if (!
|
|
143
|
-
|
|
335
|
+
const y = $(p.validate, d);
|
|
336
|
+
if (!y.valid) {
|
|
337
|
+
e.send("update-result", {
|
|
144
338
|
type: "update-result",
|
|
145
|
-
requestId:
|
|
146
|
-
sectionId:
|
|
147
|
-
itemId:
|
|
339
|
+
requestId: i,
|
|
340
|
+
sectionId: a,
|
|
341
|
+
itemId: l,
|
|
148
342
|
status: "error",
|
|
149
|
-
message:
|
|
343
|
+
message: y.message
|
|
150
344
|
});
|
|
151
345
|
return;
|
|
152
346
|
}
|
|
153
|
-
await
|
|
347
|
+
await p.onUpdate(d), e.send("update-result", {
|
|
154
348
|
type: "update-result",
|
|
155
|
-
requestId:
|
|
156
|
-
sectionId:
|
|
157
|
-
itemId:
|
|
349
|
+
requestId: i,
|
|
350
|
+
sectionId: a,
|
|
351
|
+
itemId: l,
|
|
158
352
|
status: "ok"
|
|
159
353
|
});
|
|
160
|
-
} catch (
|
|
354
|
+
} catch (y) {
|
|
161
355
|
console.warn(
|
|
162
|
-
`[Rozenite] Controls Plugin: Update failed for ${
|
|
163
|
-
|
|
164
|
-
),
|
|
356
|
+
`[Rozenite] Controls Plugin: Update failed for ${a}/${l}.`,
|
|
357
|
+
y
|
|
358
|
+
), e.send("update-result", {
|
|
165
359
|
type: "update-result",
|
|
166
|
-
requestId:
|
|
167
|
-
sectionId:
|
|
168
|
-
itemId:
|
|
360
|
+
requestId: i,
|
|
361
|
+
sectionId: a,
|
|
362
|
+
itemId: l,
|
|
169
363
|
status: "error",
|
|
170
364
|
message: "Update failed on the device."
|
|
171
365
|
});
|
|
172
366
|
}
|
|
173
|
-
},
|
|
174
|
-
sectionId:
|
|
175
|
-
itemId:
|
|
176
|
-
action:
|
|
367
|
+
}, u = async ({
|
|
368
|
+
sectionId: i,
|
|
369
|
+
itemId: a,
|
|
370
|
+
action: l
|
|
177
371
|
}) => {
|
|
178
|
-
if (
|
|
372
|
+
if (l !== "press") {
|
|
179
373
|
console.warn(
|
|
180
|
-
`[Rozenite] Controls Plugin: Unsupported action "${
|
|
374
|
+
`[Rozenite] Controls Plugin: Unsupported action "${l}" for ${i}/${a}.`
|
|
181
375
|
);
|
|
182
376
|
return;
|
|
183
377
|
}
|
|
184
|
-
const
|
|
185
|
-
if (!
|
|
378
|
+
const d = E(i, a), c = r.current.get(d);
|
|
379
|
+
if (!c) {
|
|
186
380
|
console.warn(
|
|
187
|
-
`[Rozenite] Controls Plugin: Action target not found for ${
|
|
381
|
+
`[Rozenite] Controls Plugin: Action target not found for ${i}/${a}.`
|
|
188
382
|
);
|
|
189
383
|
return;
|
|
190
384
|
}
|
|
191
385
|
try {
|
|
192
|
-
if (
|
|
386
|
+
if (c.type !== "button") {
|
|
193
387
|
console.warn(
|
|
194
|
-
`[Rozenite] Controls Plugin: Invalid press action payload for ${
|
|
388
|
+
`[Rozenite] Controls Plugin: Invalid press action payload for ${i}/${a}.`
|
|
195
389
|
);
|
|
196
390
|
return;
|
|
197
391
|
}
|
|
198
|
-
await
|
|
199
|
-
} catch (
|
|
392
|
+
await c.onPress();
|
|
393
|
+
} catch (p) {
|
|
200
394
|
console.warn(
|
|
201
|
-
`[Rozenite] Controls Plugin: Action failed for ${
|
|
202
|
-
|
|
395
|
+
`[Rozenite] Controls Plugin: Action failed for ${i}/${a}.`,
|
|
396
|
+
p
|
|
203
397
|
);
|
|
204
398
|
}
|
|
205
|
-
},
|
|
206
|
-
|
|
207
|
-
|
|
399
|
+
}, U = [
|
|
400
|
+
e.onMessage("get-snapshot", () => {
|
|
401
|
+
e.send("snapshot", {
|
|
208
402
|
type: "snapshot",
|
|
209
|
-
sections:
|
|
403
|
+
sections: n
|
|
210
404
|
});
|
|
211
405
|
}),
|
|
212
|
-
|
|
213
|
-
|
|
406
|
+
e.onMessage("update-request", (i) => {
|
|
407
|
+
s(i);
|
|
214
408
|
}),
|
|
215
|
-
|
|
216
|
-
|
|
409
|
+
e.onMessage("invoke-action", (i) => {
|
|
410
|
+
u(i);
|
|
217
411
|
})
|
|
218
412
|
];
|
|
219
413
|
return () => {
|
|
220
|
-
|
|
414
|
+
U.forEach((i) => i.remove());
|
|
221
415
|
};
|
|
222
|
-
}, [
|
|
416
|
+
}, [e, n]), e;
|
|
223
417
|
};
|
|
224
418
|
export {
|
|
225
|
-
|
|
419
|
+
M as useRozeniteControlsPlugin
|
|
226
420
|
};
|
package/package.json
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rozenite/controls-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A Rozenite plugin for exposing app-defined controls directly in React Native DevTools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/react-native.cjs",
|
|
7
7
|
"module": "./dist/react-native.js",
|
|
8
8
|
"types": "./dist/react-native.d.ts",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@rozenite/
|
|
10
|
+
"@rozenite/agent-bridge": "1.5.0",
|
|
11
|
+
"@rozenite/plugin-bridge": "1.5.0"
|
|
11
12
|
},
|
|
12
13
|
"devDependencies": {
|
|
13
14
|
"@types/react": "~19.2.2",
|
|
15
|
+
"@types/react-dom": "~19.1.7",
|
|
14
16
|
"autoprefixer": "^10.4.21",
|
|
15
17
|
"postcss": "^8.5.6",
|
|
16
18
|
"react": "19.2.0",
|
|
@@ -21,8 +23,8 @@
|
|
|
21
23
|
"tailwindcss-animate": "^1.0.7",
|
|
22
24
|
"typescript": "~5.9.3",
|
|
23
25
|
"vite": "^7.3.1",
|
|
24
|
-
"
|
|
25
|
-
"rozenite": "1.
|
|
26
|
+
"rozenite": "1.5.0",
|
|
27
|
+
"@rozenite/vite-plugin": "1.5.0"
|
|
26
28
|
},
|
|
27
29
|
"peerDependencies": {
|
|
28
30
|
"react": "*",
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { useRozenitePluginAgentTool, type AgentTool } from '@rozenite/agent-bridge';
|
|
2
|
+
import type { ControlsSection } from '../shared/types';
|
|
3
|
+
|
|
4
|
+
type SectionItemInput = {
|
|
5
|
+
sectionId: string;
|
|
6
|
+
itemId: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type SetValueInput = SectionItemInput & {
|
|
10
|
+
value: boolean | string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const pluginId = '@rozenite/controls-plugin';
|
|
14
|
+
|
|
15
|
+
const listSectionsTool: AgentTool = {
|
|
16
|
+
name: 'list-sections',
|
|
17
|
+
description:
|
|
18
|
+
'List all controls sections with their item IDs, types, and titles. Does not include values — call get-item for that.',
|
|
19
|
+
inputSchema: { type: 'object', properties: {} },
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const getItemTool: AgentTool = {
|
|
23
|
+
name: 'get-item',
|
|
24
|
+
description:
|
|
25
|
+
'Get full details of a single controls item including its current value. For select items this includes available options.',
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: 'object',
|
|
28
|
+
properties: {
|
|
29
|
+
sectionId: { type: 'string', description: 'Section ID.' },
|
|
30
|
+
itemId: { type: 'string', description: 'Item ID.' },
|
|
31
|
+
},
|
|
32
|
+
required: ['sectionId', 'itemId'],
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const setValueTool: AgentTool = {
|
|
37
|
+
name: 'set-value',
|
|
38
|
+
description:
|
|
39
|
+
'Update the value of a toggle, select, or input item. Runs the validate callback when present. Fails for text (read-only) and button items.',
|
|
40
|
+
inputSchema: {
|
|
41
|
+
type: 'object',
|
|
42
|
+
properties: {
|
|
43
|
+
sectionId: { type: 'string', description: 'Section ID.' },
|
|
44
|
+
itemId: { type: 'string', description: 'Item ID.' },
|
|
45
|
+
value: {
|
|
46
|
+
description:
|
|
47
|
+
'New value. Boolean for toggle items, string for select/input items.',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
required: ['sectionId', 'itemId', 'value'],
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const pressButtonTool: AgentTool = {
|
|
55
|
+
name: 'press-button',
|
|
56
|
+
description: "Trigger a button item's action. Fails if the item is not a button or is disabled.",
|
|
57
|
+
inputSchema: {
|
|
58
|
+
type: 'object',
|
|
59
|
+
properties: {
|
|
60
|
+
sectionId: { type: 'string', description: 'Section ID.' },
|
|
61
|
+
itemId: { type: 'string', description: 'Item ID.' },
|
|
62
|
+
},
|
|
63
|
+
required: ['sectionId', 'itemId'],
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const resolveItem = (
|
|
68
|
+
sections: ControlsSection[],
|
|
69
|
+
sectionId: string,
|
|
70
|
+
itemId: string
|
|
71
|
+
) => {
|
|
72
|
+
const section = sections.find((s) => s.id === sectionId);
|
|
73
|
+
|
|
74
|
+
if (!section) {
|
|
75
|
+
const available = sections.map((s) => s.id).join(', ');
|
|
76
|
+
throw new Error(
|
|
77
|
+
`Section "${sectionId}" not found. Available: ${available || '(none)'}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const item = section.items.find((i) => i.id === itemId);
|
|
82
|
+
|
|
83
|
+
if (!item) {
|
|
84
|
+
const available = section.items.map((i) => i.id).join(', ');
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Item "${itemId}" not found in section "${sectionId}". Available: ${available || '(none)'}`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { section, item };
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const useControlsAgentTools = (sections: ControlsSection[]) => {
|
|
94
|
+
useRozenitePluginAgentTool({
|
|
95
|
+
pluginId,
|
|
96
|
+
tool: listSectionsTool,
|
|
97
|
+
handler: () => ({
|
|
98
|
+
sections: sections.map((section) => ({
|
|
99
|
+
id: section.id,
|
|
100
|
+
title: section.title,
|
|
101
|
+
description: section.description,
|
|
102
|
+
items: section.items.map((item) => ({
|
|
103
|
+
id: item.id,
|
|
104
|
+
type: item.type,
|
|
105
|
+
title: item.title,
|
|
106
|
+
disabled: 'disabled' in item ? item.disabled : undefined,
|
|
107
|
+
})),
|
|
108
|
+
})),
|
|
109
|
+
}),
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
useRozenitePluginAgentTool<SectionItemInput>({
|
|
113
|
+
pluginId,
|
|
114
|
+
tool: getItemTool,
|
|
115
|
+
handler: ({ sectionId, itemId }) => {
|
|
116
|
+
const { item } = resolveItem(sections, sectionId, itemId);
|
|
117
|
+
|
|
118
|
+
if (item.type === 'text') {
|
|
119
|
+
return {
|
|
120
|
+
sectionId,
|
|
121
|
+
item: {
|
|
122
|
+
id: item.id,
|
|
123
|
+
type: item.type,
|
|
124
|
+
title: item.title,
|
|
125
|
+
value: item.value,
|
|
126
|
+
description: item.description,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (item.type === 'toggle') {
|
|
132
|
+
return {
|
|
133
|
+
sectionId,
|
|
134
|
+
item: {
|
|
135
|
+
id: item.id,
|
|
136
|
+
type: item.type,
|
|
137
|
+
title: item.title,
|
|
138
|
+
value: item.value,
|
|
139
|
+
description: item.description,
|
|
140
|
+
disabled: item.disabled,
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (item.type === 'button') {
|
|
146
|
+
return {
|
|
147
|
+
sectionId,
|
|
148
|
+
item: {
|
|
149
|
+
id: item.id,
|
|
150
|
+
type: item.type,
|
|
151
|
+
title: item.title,
|
|
152
|
+
actionLabel: item.actionLabel,
|
|
153
|
+
description: item.description,
|
|
154
|
+
disabled: item.disabled,
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (item.type === 'select') {
|
|
160
|
+
return {
|
|
161
|
+
sectionId,
|
|
162
|
+
item: {
|
|
163
|
+
id: item.id,
|
|
164
|
+
type: item.type,
|
|
165
|
+
title: item.title,
|
|
166
|
+
value: item.value,
|
|
167
|
+
options: item.options,
|
|
168
|
+
description: item.description,
|
|
169
|
+
disabled: item.disabled,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
sectionId,
|
|
176
|
+
item: {
|
|
177
|
+
id: item.id,
|
|
178
|
+
type: item.type,
|
|
179
|
+
title: item.title,
|
|
180
|
+
value: item.value,
|
|
181
|
+
placeholder: item.placeholder,
|
|
182
|
+
applyLabel: item.applyLabel,
|
|
183
|
+
description: item.description,
|
|
184
|
+
disabled: item.disabled,
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
useRozenitePluginAgentTool<SetValueInput>({
|
|
191
|
+
pluginId,
|
|
192
|
+
tool: setValueTool,
|
|
193
|
+
handler: async ({ sectionId, itemId, value }) => {
|
|
194
|
+
const { item } = resolveItem(sections, sectionId, itemId);
|
|
195
|
+
|
|
196
|
+
if (item.type === 'text') {
|
|
197
|
+
throw new Error(
|
|
198
|
+
`Item "${itemId}" is a read-only text item and cannot be updated.`
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (item.type === 'button') {
|
|
203
|
+
throw new Error(
|
|
204
|
+
`Item "${itemId}" is a button. Use press-button to trigger its action.`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (item.disabled) {
|
|
209
|
+
throw new Error(`Item "${itemId}" is disabled.`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (item.type === 'toggle') {
|
|
213
|
+
if (typeof value !== 'boolean') {
|
|
214
|
+
throw new Error(
|
|
215
|
+
`Expected boolean value for toggle item "${itemId}".`
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (item.validate) {
|
|
220
|
+
const result = item.validate(value);
|
|
221
|
+
if (!result.valid) {
|
|
222
|
+
throw new Error(result.message);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
await item.onUpdate(value);
|
|
227
|
+
return { applied: true, sectionId, itemId };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (typeof value !== 'string') {
|
|
231
|
+
throw new Error(
|
|
232
|
+
`Expected string value for ${item.type} item "${itemId}".`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (item.type === 'select') {
|
|
237
|
+
const validOptions = item.options.map((o) => o.value);
|
|
238
|
+
if (!validOptions.includes(value)) {
|
|
239
|
+
throw new Error(
|
|
240
|
+
`Invalid option "${value}" for item "${itemId}". Valid options: ${validOptions.join(', ')}`
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (item.validate) {
|
|
246
|
+
const result = item.validate(value);
|
|
247
|
+
if (!result.valid) {
|
|
248
|
+
throw new Error(result.message);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
await item.onUpdate(value);
|
|
253
|
+
return { applied: true, sectionId, itemId };
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
useRozenitePluginAgentTool<SectionItemInput>({
|
|
258
|
+
pluginId,
|
|
259
|
+
tool: pressButtonTool,
|
|
260
|
+
handler: async ({ sectionId, itemId }) => {
|
|
261
|
+
const { item } = resolveItem(sections, sectionId, itemId);
|
|
262
|
+
|
|
263
|
+
if (item.type !== 'button') {
|
|
264
|
+
throw new Error(
|
|
265
|
+
`Item "${itemId}" is not a button (type: ${item.type}). Use set-value to update its value.`
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (item.disabled) {
|
|
270
|
+
throw new Error(`Button "${itemId}" is disabled.`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
await item.onPress();
|
|
274
|
+
return { pressed: true, sectionId, itemId };
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
};
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
serializeSections,
|
|
13
13
|
validateValue,
|
|
14
14
|
} from '../shared/serialization';
|
|
15
|
+
import { useControlsAgentTools } from './useControlsAgentTools';
|
|
15
16
|
|
|
16
17
|
export const useRozeniteControlsPlugin = ({
|
|
17
18
|
sections,
|
|
@@ -20,6 +21,8 @@ export const useRozeniteControlsPlugin = ({
|
|
|
20
21
|
pluginId: '@rozenite/controls-plugin',
|
|
21
22
|
});
|
|
22
23
|
|
|
24
|
+
useControlsAgentTools(sections);
|
|
25
|
+
|
|
23
26
|
const snapshot = useMemo(() => serializeSections(sections), [sections]);
|
|
24
27
|
const actionRegistry = useMemo(() => buildActionRegistry(sections), [sections]);
|
|
25
28
|
const actionRegistryRef = useRef(actionRegistry);
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
> @rozenite/controls-plugin@0.0.0 build /Users/szymon.chmal/Projects/rn-devtools/packages/controls-plugin
|
|
4
|
-
> rozenite build
|
|
5
|
-
|
|
6
|
-
[90m┌[39m Rozenite
|
|
7
|
-
[?25l[90m│[39m
|
|
8
|
-
|
|
9
|
-
[1D[0K[35m◒[39m Cleaning output directory[999D[J[35m◐[39m Cleaning output directory[999D[J[32m◇[39m Output directory cleaned
|
|
10
|
-
[?25h[?25l[90m│[39m
|
|
11
|
-
[35m◒[39m Building panels[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels[999D[J[35m◐[39m Building panels[999D[J[35m◓[39m Building panels[999D[J[35m◑[39m Building panels[999D[J[35m◒[39m Building panels[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels.[999D[J[35m◓[39m Building panels.[999D[J[35m◑[39m Building panels.[999D[J[35m◒[39m Building panels.[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels..[999D[J[35m◓[39m Building panels..[999D[J[35m◑[39m Building panels..[999D[J[35m◒[39m Building panels..[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels...[999D[J[35m◑[39m Building panels...[999D[J[35m◒[39m Building panels...[999D[J[35m◐[39m Building panels...[999D[J[35m◓[39m Building panels[999D[J[32m◇[39m Panels built
|
|
12
|
-
[?25h[?25l[90m│[39m
|
|
13
|
-
[35m◒[39m Building React Native entry point[999D[J[35m◐[39m Building React Native entry point[999D[J[35m◓[39m Building React Native entry point[999D[J[35m◑[39m Building React Native entry point[999D[J[35m◒[39m Building React Native entry point[999D[J[35m◐[39m Building React Native entry point[999D[J[35m◓[39m Building React Native entry point[999D[J[35m◑[39m Building React Native entry point[999D[J[35m◒[39m Building React Native entry point.[999D[J[35m◐[39m Building React Native entry point.[999D[J[35m◓[39m Building React Native entry point.[999D[J[35m◑[39m Building React Native entry point.[999D[J[35m◒[39m Building React Native entry point.[999D[J[35m◐[39m Building React Native entry point.[999D[J[35m◓[39m Building React Native entry point.[999D[J[35m◑[39m Building React Native entry point.[999D[J[35m◒[39m Building React Native entry point..[999D[J[35m◐[39m Building React Native entry point..[999D[J[35m◓[39m Building React Native entry point..[999D[J[35m◑[39m Building React Native entry point..[999D[J[35m◒[39m Building React Native entry point..[999D[J[35m◐[39m Building React Native entry point..[999D[J[35m◓[39m Building React Native entry point..[999D[J[35m◑[39m Building React Native entry point..[999D[J[35m◒[39m Building React Native entry point...[999D[J[35m◐[39m Building React Native entry point...[999D[J[35m◓[39m Building React Native entry point...[999D[J[35m◑[39m Building React Native entry point...[999D[J[35m◒[39m Building React Native entry point...[999D[J[35m◐[39m Building React Native entry point...[999D[J[35m◓[39m Building React Native entry point...[999D[J[35m◑[39m Building React Native entry point...[999D[J[35m◒[39m Building React Native entry point...[999D[J[35m◐[39m Building React Native entry point[999D[J[35m◓[39m Building React Native entry point[999D[J[35m◑[39m Building React Native entry point[999D[J[35m◒[39m Building React Native entry point[999D[J[35m◐[39m Building React Native entry point[999D[J[35m◓[39m Building React Native entry point[999D[J[35m◑[39m Building React Native entry point[999D[J[35m◒[39m Building React Native entry point[999D[J[35m◐[39m Building React Native entry point.[999D[J[35m◓[39m Building React Native entry point.[999D[J[35m◑[39m Building React Native entry point.[999D[J[35m◒[39m Building React Native entry point.[999D[J[35m◐[39m Building React Native entry point.[999D[J[35m◓[39m Building React Native entry point.[999D[J[35m◑[39m Building React Native entry point.[999D[J[35m◒[39m Building React Native entry point.[999D[J[35m◐[39m Building React Native entry point..[999D[J[35m◓[39m Building React Native entry point..[999D[J[35m◑[39m Building React Native entry point..[999D[J[35m◒[39m Building React Native entry point..[999D[J[35m◐[39m Building React Native entry point..[999D[J[35m◓[39m Building React Native entry point..[999D[J[35m◑[39m Building React Native entry point..[999D[J[35m◒[39m Building React Native entry point..[999D[J[35m◐[39m Building React Native entry point...[999D[J[35m◓[39m Building React Native entry point...[999D[J[35m◑[39m Building React Native entry point...[999D[J[35m◒[39m Building React Native entry point...[999D[J[35m◐[39m Building React Native entry point...[999D[J[35m◓[39m Building React Native entry point...[999D[J[35m◑[39m Building React Native entry point...[999D[J[35m◒[39m Building React Native entry point...[999D[J[35m◐[39m Building React Native entry point...[999D[J[35m◓[39m Building React Native entry point[999D[J[35m◑[39m Building React Native entry point[999D[J[35m◒[39m Building React Native entry point[999D[J[35m◐[39m Building React Native entry point[999D[J[35m◓[39m Building React Native entry point[999D[J[35m◑[39m Building React Native entry point[999D[J[35m◒[39m Building React Native entry point[999D[J[35m◐[39m Building React Native entry point[999D[J[35m◓[39m Building React Native entry point.[999D[J[35m◑[39m Building React Native entry point.[999D[J[35m◒[39m Building React Native entry point.[999D[J[35m◐[39m Building React Native entry point.[999D[J[35m◓[39m Building React Native entry point.[999D[J[35m◑[39m Building React Native entry point.[999D[J[35m◒[39m Building React Native entry point.[999D[J[35m◐[39m Building React Native entry point.[999D[J[35m◓[39m Building React Native entry point..[999D[J[35m◑[39m Building React Native entry point..[999D[J[35m◒[39m Building React Native entry point..[999D[J[35m◐[39m Building React Native entry point..[999D[J[35m◓[39m Building React Native entry point..[999D[J[35m◑[39m Building React Native entry point..[999D[J[35m◒[39m Building React Native entry point..[999D[J[35m◐[39m Building React Native entry point..[999D[J[35m◓[39m Building React Native entry point...[999D[J[35m◑[39m Building React Native entry point...[999D[J[35m◒[39m Building React Native entry point...[999D[J[35m◐[39m Building React Native entry point...[999D[J[35m◓[39m Building React Native entry point...[999D[J[35m◑[39m Building React Native entry point...[999D[J[35m◒[39m Building React Native entry point...[999D[J[35m◐[39m Building React Native entry point...[999D[J[35m◓[39m Building React Native entry point...[999D[J[35m◑[39m Building React Native entry point[999D[J[35m◒[39m Building React Native entry point[999D[J[35m◐[39m Building React Native entry point[999D[J[35m◓[39m Building React Native entry point[999D[J[35m◑[39m Building React Native entry point[999D[J[35m◒[39m Building React Native entry point[999D[J[35m◐[39m Building React Native entry point[999D[J[35m◓[39m Building React Native entry point[999D[J[35m◑[39m Building React Native entry point.[999D[J[35m◒[39m Building React Native entry point.[999D[J[35m◐[39m Building React Native entry point.[999D[J[35m◓[39m Building React Native entry point.[999D[J[35m◑[39m Building React Native entry point.[999D[J[35m◒[39m Building React Native entry point.[999D[J[35m◐[39m Building React Native entry point.[999D[J[35m◓[39m Building React Native entry point.[999D[J[35m◑[39m Building React Native entry point..[999D[J[35m◒[39m Building React Native entry point..[999D[J[35m◐[39m Building React Native entry point..[999D[J[35m◓[39m Building React Native entry point..[999D[J[35m◑[39m Building React Native entry point..[999D[J[35m◒[39m Building React Native entry point..[999D[J[35m◐[39m Building React Native entry point..[999D[J[35m◓[39m Building React Native entry point..[999D[J[35m◑[39m Building React Native entry point...[999D[J[35m◒[39m Building React Native entry point...[999D[J[35m◐[39m Building React Native entry point...[999D[J[35m◓[39m Building React Native entry point...[999D[J[35m◑[39m Building React Native entry point...[999D[J[35m◒[39m Building React Native entry point...[999D[J[35m◐[39m Building React Native entry point...[999D[J[35m◓[39m Building React Native entry point...[999D[J[35m◑[39m Building React Native entry point...[999D[J[35m◒[39m Building React Native entry point[999D[J[35m◐[39m Building React Native entry point[999D[J[35m◓[39m Building React Native entry point[999D[J[35m◑[39m Building React Native entry point[999D[J[35m◒[39m Building React Native entry point[999D[J[35m◐[39m Building React Native entry point[999D[J[35m◓[39m Building React Native entry point[999D[J[35m◑[39m Building React Native entry point[999D[J[35m◒[39m Building React Native entry point.[999D[J[35m◐[39m Building React Native entry point.[999D[J[35m◓[39m Building React Native entry point.[999D[J[35m◑[39m Building React Native entry point.[999D[J[35m◒[39m Building React Native entry point.[999D[J[35m◐[39m Building React Native entry point.[999D[J[35m◓[39m Building React Native entry point.[999D[J[35m◑[39m Building React Native entry point.[999D[J[35m◒[39m Building React Native entry point..[999D[J[35m◐[39m Building React Native entry point..[999D[J[35m◓[39m Building React Native entry point..[999D[J[35m◑[39m Building React Native entry point..[999D[J[35m◒[39m Building React Native entry point..[999D[J[35m◐[39m Building React Native entry point..[999D[J[32m◇[39m React Native entry point built
|
|
14
|
-
[?25h[90m│[39m
|
|
15
|
-
[90m└[39m Plugin built successfully
|
|
16
|
-
|
package/.turbo/turbo-lint.log
DELETED