Skip to content

Commit 4597653

Browse files
author
Nitin Khanna
committed
first push
1 parent b82a3a4 commit 4597653

File tree

8 files changed

+869
-0
lines changed

8 files changed

+869
-0
lines changed

Contents/Executables/Main.js

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
/*
2+
React Studio plugin for a styled image tag.
3+
4+
- 2020 / Nitin Khanna / @nitinthewiz / automedia.ai
5+
6+
. v1.0
7+
. Icon from https://icon-library.com/icon/width-icon-3.html
8+
9+
*/
10+
11+
12+
// -- plugin info requested by host app --
13+
14+
this.describePlugin = function(id, lang) {
15+
switch (id) {
16+
case 'displayName':
17+
return "Styled Image";
18+
19+
case 'shortDisplayText':
20+
return "component for CSS styled images";
21+
22+
case 'defaultNameForNewInstance':
23+
return "styled-img";
24+
}
25+
}
26+
27+
// This is all data for the plugin
28+
// -- private variables --
29+
30+
this._data = {
31+
src: '',
32+
style: '{"display": "block"}'
33+
};
34+
35+
36+
37+
// OFFICIAL dont touch
38+
// -- persistence, i.e. saving and loading --
39+
40+
this.persist = function() {
41+
return this._data;
42+
}
43+
44+
this.unpersist = function(data) {
45+
this._data = data;
46+
}
47+
48+
49+
// WHAT you see in settings in React Studio
50+
// -- inspector UI --
51+
52+
this.reactWebDataLinkKeys = [
53+
"source",
54+
"style"
55+
];
56+
57+
this.inspectorUIDefinition = [
58+
{
59+
"type": "label",
60+
"text": "You can either select a data slot that contains the \nsource URL of the image and manually enter the style \nof the image below, or set these values in the data \nlinkage tab. The data linkage in the data tab \noverrides the plugin parameters below. \n",
61+
"height": 80,
62+
},
63+
{
64+
"type": "label",
65+
"text": "Please ensure style follows the React in-line style \nJSON format, e.g.:\n{\n 'display': 'block',\n 'maxHeight': '100%',\n}",
66+
"height": 80,
67+
},
68+
{
69+
"type": "label",
70+
"text": "Style:",
71+
"height": 20,
72+
},
73+
{
74+
"type": "textinput",
75+
"id": "style", // MAKE SURE THIS is same as the variable name in this._data{}
76+
"label": "Style of the image",
77+
"actionBinding": "this.onUIChange",
78+
"multiline": true,
79+
"height": 100, // HEIGHT of component in RS
80+
},
81+
{
82+
"type": "label",
83+
"text": "Source URL:",
84+
"height": 10,
85+
"paddingTop": 20,
86+
},
87+
{
88+
"type": "dataslot-picker",
89+
"id": "src",
90+
"label": "source URL or dataSlot of image",
91+
"actionBinding": "this.onUIChange"
92+
}
93+
];
94+
95+
// ACTUAL Settings declared
96+
this._uiTextFields = [ 'style'];
97+
this._uiCheckboxes = [];
98+
// this._uiCheckboxes = ['loop', 'play'];
99+
this._uiNumberFields = [];
100+
this._uiColorPickers = [];
101+
this._uiComponentPickers = [];
102+
this._uiDataSlotPickers = [ 'src' ];
103+
104+
this._accessorForDataKey = function(key) {
105+
if (this._uiTextFields.includes(key)) return 'text';
106+
else if (this._uiCheckboxes.includes(key)) return 'checked';
107+
else if (this._uiNumberFields.includes(key)) return 'numberValue';
108+
else if (this._uiColorPickers.includes(key)) return 'rgbaArrayValue';
109+
else if (this._uiComponentPickers.includes(key)) return 'componentName';
110+
else if (this._uiDataSlotPickers.includes(key)) return 'dataSlotName';
111+
return null;
112+
}
113+
114+
this.onCreateUI = function() {
115+
var ui = this.getUI();
116+
for (var controlId in this._data) {
117+
var prop = this._accessorForDataKey(controlId);
118+
if (prop) {
119+
try {
120+
ui.getChildById(controlId)[prop] = this._data[controlId];
121+
} catch (e) {
122+
console.log("** can't set ui value for key "+controlId+", prop "+prop);
123+
}
124+
}
125+
}
126+
}
127+
128+
this.onUIChange = function(controlId) {
129+
var ui = this.getUI();
130+
var prop = this._accessorForDataKey(controlId);
131+
if (prop) {
132+
this._data[controlId] = ui.getChildById(controlId)[prop];
133+
} else {
134+
console.log("** no data property found for controlId "+controlId);
135+
}
136+
}
137+
138+
// -- plugin preview --
139+
140+
this.renderIcon = function(canvas) {
141+
var ctx = canvas.getContext('2d');
142+
var w = canvas.width;
143+
var h = canvas.height;
144+
ctx.save();
145+
if (this.icon == null) {
146+
// got the YouTube logo online
147+
var path = Plugin.getPathForResource("logo.png"); // LOGO image
148+
this.icon = Plugin.loadImage(path);
149+
}
150+
var iconW = this.icon.width;
151+
var iconH = this.icon.height;
152+
var aspectScale = Math.min(w/iconW, h/iconH);
153+
var scale = 0.9 * aspectScale; // add some margin around icon
154+
iconW *= scale;
155+
iconH *= scale;
156+
ctx.drawImage(this.icon, (w-iconW)*0.5, (h-iconH)*0.5, iconW, iconH);
157+
ctx.restore();
158+
};
159+
160+
// WHAT shows in the RS area after dragging component
161+
this.renderEditingCanvasPreview = function(canvas, controller) {
162+
this._renderPreview(canvas, controller);
163+
}
164+
165+
// REAL preview if needed to show while in dev
166+
this._renderPreview = function(canvas, controller) {
167+
var ctx = canvas.getContext('2d');
168+
var w = canvas.width;
169+
var h = canvas.height;
170+
ctx.save();
171+
172+
if (this.icon == null) {
173+
var path = Plugin.getPathForResource("logo.png");
174+
this.icon = Plugin.loadImage(path);
175+
}
176+
var iconW = this.icon.width;
177+
var iconH = this.icon.height;
178+
var aspectScale = Math.min(w/iconW, h/iconH);
179+
var scale = 0.9 * aspectScale; // add some margin around icon
180+
iconW *= scale;
181+
iconH *= scale;
182+
ctx.drawImage(this.icon, (w-iconW)*0.5, (h-iconH)*0.5, iconW, iconH);
183+
ctx.restore();
184+
185+
}
186+
187+
188+
// ACTUALLY TELLING REACT WHERE TO PULL COMPONENT FROM
189+
190+
// -- code generation, React web --
191+
192+
this.getReactWebPackages = function() {
193+
// Return dependencies that need to be included in the exported project's package.json file.
194+
// Each key is an npm package name that must be imported, and the value is the package version.
195+
196+
return;
197+
}
198+
199+
this.getReactWebImports = function(exporter) {
200+
var arr = [];
201+
202+
return arr;
203+
}
204+
205+
this.writesCustomReactWebComponent = false;
206+
207+
this.getReactWebJSXCode = function(exporter) {
208+
const src = this._data.src; // FROM Variable declared at top
209+
const style = this._data.style; // FROM Variable declared at top
210+
var jsx = `<img `;
211+
212+
var sourceLinkage = exporter.getExpressionForLinkKey('source');
213+
var styleLinkage = exporter.getExpressionForLinkKey('style');
214+
215+
if (sourceLinkage) {
216+
jsx += `src={${sourceLinkage}} `;
217+
}
218+
else {
219+
jsx += `src={this.props.appActions.dataSlots['${src}']} `;
220+
}
221+
222+
if (styleLinkage) {
223+
jsx += `style={${styleLinkage}} `;
224+
}
225+
else {
226+
jsx += `style={${style}} `;
227+
}
228+
jsx += ` />`;
229+
return jsx;
230+
}
231+

Contents/Info.plist

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleName</key>
6+
<string>styled image</string>
7+
<key>CFBundleIdentifier</key>
8+
<string>com.neonto.plugin.reactstudio.styledimage</string>
9+
<key>CFBundleVersion</key>
10+
<string>2</string>
11+
<key>CFBundlePackageType</key>
12+
<string>BNDL</string>
13+
<key>CFBundleSignature</key>
14+
<string>????</string>
15+
<key>SPXPluginTypeId</key>
16+
<string>exchange.spx.plugin.element</string>
17+
<key>SPXPluginDependencies</key>
18+
<array>
19+
<string>js/mustache.js</string>
20+
</array>
21+
</dict>
22+
</plist>

0 commit comments

Comments
 (0)