How to Install and Import Spectrum Web Components (SWC)

Hello everyone! Can I please, sorry for my stupid question.
How do I install and import Spectrum Web Components (SWC)? I swear I never get it right, and today, once and for all, I would like to understand how this works.
I’m using the VSCode terminal.
• Node, npm and yarn are all already installed
Photoshop: 26
UXP: 8.1.0
Template: Vanilha

I’m trying “sp-number-field”
Termnal:

yarn add @spectrum-web-components/number-field

trying to import by:
js

import '@spectrum-web-components/number-field/sp-number-field.js'; 

manifest.json

 "featureFlags": { 
 "enableSWCSupport": true, 
 "CSSNextSupport": true 
}, 

html

<sp-number-field label="Size" value="1024"size="m" style="--spectrum-stepper-width: 110px"></sp-number-field>

Nothing happens.

I don’t think you are stupid. Adobe team prioritized making it easy for themselves instead of making it easy for 3rd party devs. I had to have a call with them where they explained me how it works. And it worked.

For some reason I expected complete documentation in documentation but instead, I found key missing parts in the starter project here: uxp-photoshop-plugin-samples/swc-uxp-react-starter/README.md at main · AdobeDocs/uxp-photoshop-plugin-samples · GitHub

But I am not sure if wrappers are not targeting different spectrum version today.

Because template says “0.16.9” but docs says “0.37.0” https://developer.adobe.com/photoshop/uxp/2022/uxp-api/reference-spectrum/swc/

From 3rd party developer experience I would expect no need to install wrappers + spectrum. And no need to choose yarn over npm. No need to deal with resolutions/aliases. Just import one package, use it and that would be all.

2 Likes

Thanks for replying @Jarda . Honestly, I think I’m going to abandon this feature, it’s too complex, for now, I’m giving up.

I also used this as a starting point.

Not even the template provided in the documentation works, always an empty panel and nothing happens. Honestly, I think it’s much simpler to improvise the component I need just using html and css.

I ended up with the same conclusion. I am waiting for it to become more mature.

2 Likes

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;
2 Likes