Tried based on @swc-uxp-wrappers/create-swc-uxp-react-app - npm, Successfully got sp-number-field
to appear in the panel. It was generally as described on that npm page, but there are a few traps.
manifest v4 to v5
The manifest.json that was created after executing the command had "manifestVersion": 4
. Now it is basically "manifestVersion": 5
.
Resolve EvalError
With manifest v5, when running webpack with --mode development
, i.e. yarn watch
, etc., we get an EvalError and nothing is displayed in the panel.
Uncaught EvalError: Code generation from strings disallowed for this context
This can be solved by adding "allowCodeGenerationFromStrings": true
to requiredPermissions in manifest.json.
// manifest.json
"requiredPermissions": {
"allowCodeGenerationFromStrings": true
},
Alternatively, editing webpack.config.js to generate a source map with --mode development
without eval
at the beginning, such as cheap-source-map
, is acceptable. This is difficult and will be omitted.
If you have made it this far, you should be able to load the panel.
Make the minVersion realistic
The generated manifest.json allows for versions of Photoshop that do not support UXP8. It would be a good idea to fix this, though it will not cause any build errors.
// manifest.json: before
{
"app": "PS",
"minVersion": "24.4.0"
},
{
"app": "ID",
"minVersion": "18.0.0"
}
// manifest.json: after
{
"app": "PS",
"minVersion": "26.0.0"
},
{
"app": "ID",
"minVersion": "20.0.0"
}
Other notes
Theme is not linked to Photoshop preferences, so you may not be able to read the text depending on the brightness of the UI. You need to write the linking process by yourself.
Here is the code after editing
// package.json
{
"name": "swc-uxp8",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"start": "yarn install && webpack",
"build": "webpack --mode production",
"watch": "yarn install && webpack --watch --mode development"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@swc-react/menu": "0.37.0",
"@swc-react/number-field": "0.37.0",
"@swc-react/popover": "0.37.0",
"@swc-react/theme": "0.37.0",
"@swc-uxp-wrappers/menu": "2.0.0",
"@swc-uxp-wrappers/number-field": "^2.0.0",
"@swc-uxp-wrappers/overlay": "2.0.0",
"@swc-uxp-wrappers/popover": "2.0.0",
"@swc-uxp-wrappers/utils": "2.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1"
},
"devDependencies": {
"@babel/core": "^7.21.4",
"@babel/preset-env": "^7.21.4",
"@babel/preset-react": "^7.18.6",
"babel-loader": "^9.1.2",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^9.1.0",
"css-loader": "^6.7.3",
"cssnano": "^5.0.11",
"html-webpack-plugin": "^5.5.1",
"http-server": "^14.0.0",
"mini-css-extract-plugin": "^2.4.4",
"url-loader": "^4.1.1",
"webpack": "^5.80.0",
"webpack-bundle-analyzer": "^4.5.0",
"webpack-cli": "^5.0.2"
}
}
// manifest.json
{
"name": "swc-uxp8",
"id": "swc-uxp8",
"version": "1.0.0",
"main": "index.html",
"manifestVersion": 5,
"featureFlags": {
"enableSWCSupport": true
},
"requiredPermissions": {
"allowCodeGenerationFromStrings": true
},
"entrypoints": [
{
"type": "panel",
"id": "vanilla",
"label": {
"default": "swc-uxp8"
},
"minimumSize": {
"width": 230,
"height": 200
},
"maximumSize": {
"width": 2000,
"height": 2000
},
"preferredDockedSize": {
"width": 230,
"height": 300
},
"preferredFloatingSize": {
"width": 230,
"height": 300
}
}
],
"host": [
{
"app": "PS",
"minVersion": "26.0.0"
},
{
"app": "ID",
"minVersion": "20.0.0"
}
]
}
// App.js
// copyright etc. here
import React from "react";
import { Menu, MenuGroup, MenuItem, MenuDivider } from "@swc-react/menu";
import "@spectrum-web-components/theme/theme-light.js";
import "@spectrum-web-components/theme/express/theme-light.js";
import "@spectrum-web-components/theme/scale-medium.js";
import "@spectrum-web-components/theme/express/scale-medium.js";
import { Theme } from "@swc-react/theme";
import { NumberField } from "@swc-react/number-field";
function App() {
return (
<div>
<h1>Welcome</h1>
<Theme theme="spectrum" scale="medium" color="light">
<Menu selects="single">
<MenuItem selected>Sample Menu</MenuItem>
<MenuDivider></MenuDivider>
<MenuItem>Select Option 1</MenuItem>
<MenuItem>Select Option 2</MenuItem>
<MenuItem>Select Option 3</MenuItem>
<MenuItem>Select Option 4</MenuItem>
<MenuItem disabled>Disabled Option</MenuItem>
</Menu>
<NumberField value={1}></NumberField>
</Theme>
</div>
);
}
export default App;