JSX templating for Adobe ExtendScript
npm install extendscript-uiextendscript-uiHave you ever wanted to compose ScriptUI with JSX, like so:
``tsx`
Well, now you can! Plus, TypeScript will guide you through each prop with auto completions!
You can even create functional components:
`tsx
const MyHeader = ({ text }: { text: string }) => (
);
const MyUI = (
);
`
And what would JSX be without "hooks":
`tsx
import { onWindow, uniqueId, type ScriptUIElements } from "extendscript-ui";
const MyButton = ({ text, onClick }: ScriptUIElements["button"]) => {
const name = uniqueId("my_button");
onWindow((window) => {
const el = window.findElement(name);
el.addEventListener("mouseover", () => (el.text = "Hello mouse!"));
el.addEventListener("mouseout", () => (el.text = text));
});
return ;
};
`
That's not enough, you say? What if you could render SVGs? (You can!)
`tsx`
const MySVG = ({ fill, stroke }: { fill: string, stroke: string }) => (
));
> [!TIP]
> For a super basic example, check out /examples/basic!
You'll need TypeScript and a bundler for your code. Here are some ExtendScript starters with TypeScript support to check out:
- @motiondeveloper/adobe-script-starter
- @fartinmartin/adobe-lib-starter
- @Klustre/extender (see note on TypeScript)
`bash`
npm i extendscript-ui
Update your tsconfig.json:
`jsonc
{
"compilerOptions": {
// ...your other config options
// tell TypeScript how to find extendscript-ui's jsx.d.ts declarations:
"typeRoots": ["./node_modules/extendscript-ui/dist"],
"types": ["types/jsx.d.ts"],
// tell TypeScript how to transform your JSX code and the name of the jsxFactory fn to use when doing so:
"jsx": "react",
"jsxFactory": "jsx" // this is the fn that extendscript-ui exports!
}
// ...any other options
}
`
Be sure to use .tsx files for JSX syntax highlighting. Import jsx to satisfy TypeScript and for code completion:
`tsx
// index.tsx
import { jsx } from "extendscript-ui";
export const ExampleUI = (
);
`
Then, use createWindow to render your template. This will create a Window, wire up your event callbacks, and return the Window.
`tsx
import { createWindow } from "extendscript-ui";
const window = createWindow(ExampleUI); // ExampleUI from previous code block
window.show();
`
To define behavior that requires the elements to be rendered (e.g. element.addEventListener) use the onWindow "hook". The callback function passed to onWindow will run after the Window object has been created and receives a reference to it.
`tsx`
onWindow((window) => {
window.addEventListener("mouseover", () => alert("Hello!"));
});
> [!TIP]
> ScriptUI has a helpful findElement method to use inside this hook! extendscript-ui also exports a uniqueId helper to ensure element properties.name values are valid.
`tsx
import { onWindow, uniqueId } from "extendscript-ui";
const MyText = ({ text, properties }) => {
const name = properties?.name ?? uniqueId("my_text");
onWindow((window) => {
const el = window.findElement(name);
el.addEventListener("mouseover", () => (el.text = "Hello mouse!"));
el.addEventListener("mouseout", () => (el.text = text));
});
return
};
`
extendscript-ui uses a custom jsxFactory to transform JSX into a ScriptUI Resource Specifications-compliant string. This string is passed to new Window(specString) to build the UI. Once the UI is built, createWindow adds any event handlers to the created UI elements and runs all of the side effect functions you passed to onWindow.
- [ ] Set element's size based on