From b7360e96042d6f0139514360533c9f529cc7755d Mon Sep 17 00:00:00 2001 From: castastrophe Date: Fri, 3 Jan 2025 13:08:36 -0500 Subject: [PATCH] feat(bundle): bundled css for dev/demos --- .changeset/honest-bulldogs-flow.md | 5 + .changeset/stupid-rice-compare.md | 5 + .storybook/blocks/ComponentDetails.jsx | 6 +- .storybook/blocks/PropertiesTable.jsx | 3 +- .storybook/blocks/utilities.js | 64 ++++---- .storybook/manager.js | 5 + .storybook/package.json | 3 +- .storybook/preview.js | 4 + .storybook/project.json | 2 +- .stylelintignore | 1 + README.md | 22 +-- package.json | 5 +- postcss.config.js | 51 +++++-- stylelint.config.js | 12 ++ tasks/component-builder.js | 56 +++---- tasks/utilities.js | 8 +- tools/bundle/CHANGELOG.md | 1 + tools/bundle/README.md | 5 + tools/bundle/package.json | 120 +++++++++++++++ tools/bundle/postcss.config.js | 34 +++++ tools/bundle/project.json | 50 +++++++ tools/bundle/src/index.css | 99 ++++++++++++ tools/bundle/tasks/bundler.js | 200 +++++++++++++++++++++++++ yarn.lock | 172 ++++++++++++++++----- 24 files changed, 792 insertions(+), 141 deletions(-) create mode 100644 .changeset/honest-bulldogs-flow.md create mode 100644 .changeset/stupid-rice-compare.md create mode 100644 tools/bundle/CHANGELOG.md create mode 100644 tools/bundle/README.md create mode 100644 tools/bundle/package.json create mode 100644 tools/bundle/postcss.config.js create mode 100644 tools/bundle/project.json create mode 100644 tools/bundle/src/index.css create mode 100644 tools/bundle/tasks/bundler.js diff --git a/.changeset/honest-bulldogs-flow.md b/.changeset/honest-bulldogs-flow.md new file mode 100644 index 00000000000..d0fcfb65966 --- /dev/null +++ b/.changeset/honest-bulldogs-flow.md @@ -0,0 +1,5 @@ +--- +"@spectrum-css/preview": minor +--- + +Update Storybook to leverage the new CSS bundled assets. diff --git a/.changeset/stupid-rice-compare.md b/.changeset/stupid-rice-compare.md new file mode 100644 index 00000000000..9d6cac2ec0f --- /dev/null +++ b/.changeset/stupid-rice-compare.md @@ -0,0 +1,5 @@ +--- +"@spectrum-css/bundle": major +--- + +Resurrecting the CSS bundle for development use. Excellent resource for generating quick demo pages by loading all the CSS components in the library in a pre-bundled package with tokens pre-loaded and minified to remove unused tokens. diff --git a/.storybook/blocks/ComponentDetails.jsx b/.storybook/blocks/ComponentDetails.jsx index 1f2299c8b79..dad04d41933 100644 --- a/.storybook/blocks/ComponentDetails.jsx +++ b/.storybook/blocks/ComponentDetails.jsx @@ -2,12 +2,14 @@ import { useOf } from '@storybook/blocks'; import { ResetWrapper } from "@storybook/components"; import { styled } from "@storybook/theming"; import React, { useEffect, useState } from "react"; + +import { Body, Code, Heading } from "./Typography.jsx"; +import { fetchToken } from "./utilities.js"; + import AdobeSVG from "../assets/images/adobe_logo.svg?raw"; import GitHubSVG from "../assets/images/github_logo.svg?raw"; import NpmSVG from "../assets/images/npm_logo.svg?raw"; import WCSVG from "../assets/images/wc_logo.svg?raw"; -import { Body, Code, Heading } from "./Typography.jsx"; -import { fetchToken } from "./utilities.js"; export const DList = styled.dl` display: grid; diff --git a/.storybook/blocks/PropertiesTable.jsx b/.storybook/blocks/PropertiesTable.jsx index b9c44537db7..1cb7e19f872 100644 --- a/.storybook/blocks/PropertiesTable.jsx +++ b/.storybook/blocks/PropertiesTable.jsx @@ -1,9 +1,8 @@ -import "@spectrum-css/table/dist/index.css"; - import { DocsContext, useOf } from "@storybook/blocks"; import { NAVIGATE_URL } from "@storybook/core-events"; import { styled } from "@storybook/theming"; import React, { useContext } from 'react'; + import { ThemeContainer } from "./ThemeContainer.jsx"; import { Body, Code, LinkableHeading } from "./Typography.jsx"; diff --git a/.storybook/blocks/utilities.js b/.storybook/blocks/utilities.js index 1bf41aa4efc..b0f617b1d5b 100644 --- a/.storybook/blocks/utilities.js +++ b/.storybook/blocks/utilities.js @@ -14,30 +14,30 @@ import { useTheme } from "@storybook/theming"; * @returns {string|void} - The value of the token */ function parseData(data, { key, color, platform }) { - // If nothing exists for that key, report that the key is missing - if (!data) { - console.log(`⚠️ Token ${key} can't be found in the spectrum token data`); - return; - } + // If nothing exists for that key, report that the key is missing + if (!data) { + console.log(`⚠️ Token ${key} can't be found in the spectrum token data`); + return; + } - // Check if the key has a value - if (data.value) return data.value; + // Check if the key has a value + if (data.value) return data.value; - if (Object.keys(data.sets).length === 0) { - console.log(`⚠️ Token ${key} has no value or sets`); - return; - } + if (Object.keys(data.sets).length === 0) { + console.log(`⚠️ Token ${key} has no value or sets`); + return; + } - // Check if one of the contexts is a key in the sets - if (color in data.sets) { - return parseData(data.sets[color], { key, color, platform }); - } + // Check if one of the contexts is a key in the sets + if (color in data.sets) { + return parseData(data.sets[color], { key, color, platform }); + } - if (platform in data.sets) { - return parseData(data.sets[platform], { key, color, platform }); - } + if (platform in data.sets) { + return parseData(data.sets[platform], { key, color, platform }); + } - return; + return; } /** @@ -49,23 +49,25 @@ function parseData(data, { key, color, platform }) { * @returns {string|undefined} - The value of the token or a fallback value */ export function fetchToken(key, fallback = undefined, { color, scale } = {}) { - if (typeof key !== "string") return fallback; + if (typeof key !== "string") return fallback; - // Fetch the theme if it exists; this data exists if wrapped in a ThemeProvider + // Fetch the theme if it exists; this data exists if wrapped in a ThemeProvider const theme = useTheme() ?? {}; - // If the color or scale is not provided, use the theme values or a fallback - if (typeof color !== "string" && typeof theme.color == "string") color = theme.color; - else if (!color) color = "light"; + // If the color or scale is not provided, use the theme values or a fallback + if (typeof color !== "string" && typeof theme.color == "string") + color = theme.color; + else if (!color) color = "light"; - if (typeof scale !== "string" && typeof theme.scale == "string") scale = theme.scale; - else if (!scale) scale = "medium"; + if (typeof scale !== "string" && typeof theme.scale == "string") + scale = theme.scale; + else if (!scale) scale = "medium"; - // Create a platform context based on the scale (platform used in the token data) - const platform = scale === "medium" ? "desktop" : "mobile"; + // Create a platform context based on the scale (platform used in the token data) + const platform = scale === "medium" ? "desktop" : "mobile"; - // Check if the spectrum data is available - if (!spectrum || typeof spectrum !== "object") return fallback; + // Check if the spectrum data is available + if (!spectrum || typeof spectrum !== "object") return fallback; - return parseData(spectrum[key], { color, platform }) ?? fallback; + return parseData(spectrum[key], { color, platform }) ?? fallback; } diff --git a/.storybook/manager.js b/.storybook/manager.js index d3bc832002f..5a34a4ef4f8 100644 --- a/.storybook/manager.js +++ b/.storybook/manager.js @@ -1,7 +1,12 @@ import "@spectrum-css/tokens/dist/index.css"; import { addons } from "@storybook/manager-api"; import { create } from "@storybook/theming"; + +// Import the CSS bundle +import "@spectrum-css/bundle/dist/index.min.css"; + import "./assets/index.css"; + import logo from "./assets/logo.svg"; import pkg from "./package.json"; diff --git a/.storybook/package.json b/.storybook/package.json index de34010f6ba..f7cbd180c99 100644 --- a/.storybook/package.json +++ b/.storybook/package.json @@ -29,9 +29,8 @@ }, "dependencies": { "@adobe/spectrum-css-workflow-icons": "^1.5.4", - "@spectrum-css/table": "workspace:^", + "@spectrum-css/bundle": "workspace:^", "@spectrum-css/tokens": "workspace:^", - "@spectrum-css/typography": "workspace:^", "@spectrum-css/ui-icons": "workspace:^" }, "devDependencies": { diff --git a/.storybook/preview.js b/.storybook/preview.js index 3c92dcfe186..9c7d46c3534 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -20,6 +20,10 @@ import { globalTypes } from "./types"; +// Load the Spectrum CSS bundle to style the docs elements +import "@spectrum-css/bundle/dist/index.min.css"; + +// Import the custom base styles import "./assets/base.css"; window.global = window; diff --git a/.storybook/project.json b/.storybook/project.json index 35987674c76..c7896e7adf5 100644 --- a/.storybook/project.json +++ b/.storybook/project.json @@ -11,7 +11,7 @@ "{projectRoot}/modes", "{projectRoot}/templates", "{projectRoot}/types", - "{projectRoot}/*.{js,html,mdx}" + "{projectRoot}/*.{js,html}" ] }, "targets": { diff --git a/.stylelintignore b/.stylelintignore index abcf328da0e..5956478781e 100644 --- a/.stylelintignore +++ b/.stylelintignore @@ -6,6 +6,7 @@ generator dist .storybook/storybook-static *-generated.css +tools/bundle/src/*.css node_modules/**/*.css diff --git a/README.md b/README.md index 006076157fd..f000417280c 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ To switch to Express, **add** the `.spectrum--express` class to the `` ele ```html ``` @@ -212,15 +212,17 @@ Want to join the team? Check out the [contributing guidelines](.github/CONTRIBUT The following tasks are available: -| Command | Description | Examples | -| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -| `clean` | Cleans all output files for the project and all components | `yarn clean` | -| `build` | Performs a build of all components | `yarn build` | -| `start` | Performs a local development build of Storybook | `yarn start` | -| `compare` | This compares the current version of components with the previous versions published to NPM and output a list of all the changes that have been made. This is useful for reviewing changes before a release. The information is provided in the command-line output as well as in a simple web page that is opened in your default browser upon completion. The web page includes links to the visual diffs for each component when the file sizes have changed. | `yarn compare`
`yarn compare accordion`
`yarn compare accordion actionbutton` | -| `lint` | Provides helpful updates and warnings for a component's package.json file. This helps keep all components in alignment. Use `format` to automatically fix any issues that are found. To run on a single component, use `yarn linter accordion` (where `accordion` is the name of the component or components you want to lint). | `yarn lint`
`yarn linter accordion`
`yarn linter accordion actionbutton` | -| `format` | Provides helpful updates and warnings for a component's package.json file. This helps keep all components in alignment. To run on a single component, use `yarn formatter accordion` (where `accordion` is the name of the component or components you want to lint). | `yarn format`
`yarn formatter accordion`
`yarn formatter accordion actionbutton` | -| `refresh:env` | This copies values for the project's `.env` file (an asset never committed to the repo as it contains login secrets) by using the `.env.example` file as a template. This script is useful when you need to update the `.env` file with new values from the `.env.example` file or when you checkout or clean the repo and need to restore the `.env` file. | `yarn refresh:env` | +| Command | Description | Examples | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| `clean` | Cleans all output files for the project and all components | `yarn clean` | +| `build` | Performs a build of all components | `yarn build` | +| `bundle` | Creates a bundled asset for use in demos or development environments | `yarn bundle` | +| `refresh:bundle` | Updates the `tools/bundle/package.json` to accurately reflect the packages in `components/*` and refreshes the `tools/bundle/src/index.css` to include all relevant imports. | `yarn refresh:bundle` | +| `start` | Performs a local development build of Storybook | `yarn start` | +| `compare` | This compares the current version of components with the previous versions published to NPM and output a list of all the changes that have been made. This is useful for reviewing changes before a release. The information is provided in the command-line output as well as in a simple web page that is opened in your default browser upon completion. The web page includes links to the visual diffs for each component when the file sizes have changed. | `yarn compare`
`yarn compare accordion`
`yarn compare accordion actionbutton` | +| `lint` | Provides helpful updates and warnings for a component's package.json file. This helps keep all components in alignment. Use `format` to automatically fix any issues that are found. To run on a single component, use `yarn linter accordion` (where `accordion` is the name of the component or components you want to lint). | `yarn lint`
`yarn linter accordion`
`yarn linter accordion actionbutton` | +| `format` | Provides helpful updates and warnings for a component's package.json file. This helps keep all components in alignment. To run on a single component, use `yarn formatter accordion` (where `accordion` is the name of the component or components you want to lint). | `yarn format`
`yarn formatter accordion`
`yarn formatter accordion actionbutton` | +| `refresh:env` | This copies values for the project's `.env` file (an asset never committed to the repo as it contains login secrets) by using the `.env.example` file as a template. This script is useful when you need to update the `.env` file with new values from the `.env.example` file or when you checkout or clean the repo and need to restore the `.env` file. | `yarn refresh:env` | ## Troubleshooting diff --git a/package.json b/package.json index ee3546a3c2e..0355fab381e 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "build:docs": "nx build storybook --output-dir ../dist/", "build:preview": "nx build storybook", "builder": "nx run-many --target build report --projects", + "bundle": "nx build bundle", "changeset": "changeset", "ci": "cross-env NODE_ENV=production yarn build --skip-nx-cache", "ci:storybook": "cross-env NODE_ENV=development nx run storybook:build:ci --skip-nx-cache", @@ -35,6 +36,7 @@ "precommit": "lint-staged --allow-empty --config lint-staged.config.js", "publish:docs": "cross-env NODE_ENV=production yarn build:docs && gh-pages -d dist/ -f -e . --nojekyll", "refresh": "yarn refresh:env && yarn refresh:config", + "refresh:bundle": "nx refresh bundle", "refresh:config": "bash ./tasks/chromatic-config-creation.sh || exit 0", "refresh:env": "bash ./tasks/copy-env-from-root.sh || exit 0", "release": "yarn ci && changeset publish", @@ -55,7 +57,8 @@ "ui-icons", "generator", ".storybook", - ".github/actions/*" + ".github/actions/*", + "tools/*" ], "devDependencies": { "@changesets/changelog-github": "^0.5.0", diff --git a/postcss.config.js b/postcss.config.js index 96e986f352b..83accd23c40 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -28,6 +28,7 @@ module.exports = ({ lint = true, verbose = true, additionalPlugins = {}, + minify = true, env = process.env.NODE_ENV ?? "development", ...options } = {}) => { @@ -64,7 +65,24 @@ module.exports = ({ /* --------------------------------------------------- */ /* ------------------- IMPORTS ---------------- */ /** @link https://github.com/postcss/postcss-import#postcss-import */ - "postcss-import": resolveImports ? {} : false, + "postcss-import": resolveImports ? { + resolve(id, basedir) { + // Resolve these imports to the local components directory + if (/^@spectrum-css\//.test(id)) { + // Check if the package specifies a file or just the package name + const packageParts = id.split("/"); + const filePath = packageParts.length > 2 ? packageParts.slice(2).join("/") : "index.css"; + + if (packageParts[1] === "tokens") { + return join(__dirname, packageParts[1], "dist", filePath); + } + + return join(__dirname, "components", packageParts[1], filePath); + } + + return join(basedir, id); + } + } : false, /* --------------------------------------------------- */ /* ------------------- SASS-LIKE UTILITIES ----------- */ "postcss-extend": {}, @@ -87,6 +105,20 @@ module.exports = ({ } : false, ...additionalPlugins, /* --------------------------------------------------- */ + /* ------------------- CLEAN-UP --------------------- */ + // Linter needs to run before the minifier removes comments (such as the stylelint-ignore comments) + stylelint: { + cache: true, + // Passing the config path saves a little time b/c it doesn't have to find it + configFile: join(__dirname, "stylelint.config.js"), + quiet: !lint, + fix: true, + allowEmptyInput: true, + ignorePath: join(__dirname, ".stylelintignore"), + reportNeedlessDisables: lint, + reportInvalidScopeDisables: lint, + }, + /* --------------------------------------------------- */ /* ------------------- POLYFILLS --------------------- */ /** * @todo should we be documenting this for downstream users rather @@ -130,28 +162,17 @@ module.exports = ({ }, // @todo yarn add -DW css-declaration-sorter cssDeclarationSorter: false, // @todo { order: "smacss" } - normalizeWhitespace: isProduction, + normalizeWhitespace: minify || isProduction, }, ], }, - /* --------------------------------------------------- */ - /* ------------------- REPORTING --------------------- */ - stylelint: { - cache: true, - // Passing the config path saves a little time b/c it doesn't have to find it - configFile: join(__dirname, "stylelint.config.js"), - quiet: !lint, - fix: true, - allowEmptyInput: true, - ignorePath: join(__dirname, ".stylelintignore"), - reportNeedlessDisables: lint, - reportInvalidScopeDisables: lint, - }, "postcss-licensing": { filename: "COPYRIGHT", cwd: __dirname, skipIfEmpty: true, }, + /* --------------------------------------------------- */ + /* ------------------- REPORTING --------------------- */ "postcss-reporter": verbose ? { clearAllMessages: true, diff --git a/stylelint.config.js b/stylelint.config.js index b5106f152f6..d0a7e213194 100644 --- a/stylelint.config.js +++ b/stylelint.config.js @@ -201,5 +201,17 @@ module.exports = { }], }, }, + { + /* Allow "tree shaking" of unused custom properties in the bundle */ + files: ["tools/bundle/**/*.css"], + rules: { + "spectrum-tools/no-unused-custom-properties": [ + true, + { + ignoreList: [/^--mod-/], + }, + ], + } + }, ], }; diff --git a/tasks/component-builder.js b/tasks/component-builder.js index d3fca06ecca..2676f181f21 100644 --- a/tasks/component-builder.js +++ b/tasks/component-builder.js @@ -26,12 +26,12 @@ require("colors"); const { dirs, relativePrint, - bytesToSize, getPackageFromPath, cleanFolder, validateComponentName, fetchContent, copy, + writeAndReport, } = require("./utilities.js"); /** @@ -52,13 +52,26 @@ async function processCSS( { cwd, configPath = __dirname, + minify = false, + encoding = "utf-8", ...postCSSOptions } = {}, ) { - if (!content) - return Promise.reject( - new Error("This function requires content be provided"), - ); + if (!content) { + if (!input || !fs.existsSync(input)) { + return Promise.reject( + new Error("[processCSS] Content or an input file path must be provided"), + ); + } + + content = await fsp.readFile(input, encoding); + + if (!content) { + return Promise.reject( + new Error(`[processCSS] No content found for ${relativePrint(input, { cwd })}`), + ); + } + } const ctx = { cwd, @@ -67,6 +80,7 @@ async function processCSS( from: input, to: output, verbose: false, + minify, ...postCSSOptions, }; @@ -85,13 +99,13 @@ async function processCSS( if (!result.css) return Promise.resolve(); - const formatted = await prettier.format(result.css, { + const formatted = !minify ? await prettier.format(result.css, { parser: "css", filepath: input, printWidth: 500, tabWidth: 2, useTabs: true, - }); + }) : result.css; // If no output is provided, return the formatted content if (!output) return Promise.resolve(formatted); @@ -107,36 +121,12 @@ async function processCSS( } const promises = [ - fsp - .writeFile(output, formatted) - .then(() => { - const stats = fs.statSync(output); - return `${"✓".green} ${relativePrint(output, { cwd }).padEnd(20, " ").yellow} ${bytesToSize(stats.size).gray}`; - }) - .catch((err) => { - if (!err) return; - console.log( - `${"✗".red} ${relativePrint(output, { cwd }).yellow} not written`, - ); - return Promise.reject(err); - }), + writeAndReport(formatted, output, { cwd }), ]; if (result.map) { promises.push( - fsp - .writeFile(`${output}.map`, result.map.toString().trimStart()) - .then(() => { - const stats = fs.statSync(output); - return `${"✓".green} ${relativePrint(`${output}.map`, { cwd }).padEnd(20, " ").yellow} ${bytesToSize(stats.size).gray}`; - }) - .catch((err) => { - if (!err) return; - console.log( - `${"✗".red} ${relativePrint(`${output}.map`, { cwd }).yellow} not written`, - ); - return Promise.reject(err); - }), + writeAndReport(result.map.toString().trimStart(), `${output}.map`, { cwd }), ); } diff --git a/tasks/utilities.js b/tasks/utilities.js index 5868c8b2e01..52e9b00ce22 100644 --- a/tasks/utilities.js +++ b/tasks/utilities.js @@ -80,13 +80,13 @@ function getPackageFromPath(filePath = process.cwd()) { * Returns a list of all component names in the repository * @returns string[] */ -function getAllComponentNames() { +function getAllComponentNames(includeDeprecated = true) { // Get a list of all the component names in the components directory that have a package.json file // and a list of all the deprecated components in the storybook directory // then combine and deduplicate the lists to get a full list of all components return [...new Set([ ...fs.readdirSync(dirs.components).filter((file) => fs.existsSync(path.join(dirs.components, file, "package.json"))), - ...fs.readdirSync(path.join(dirs.storybook, "deprecated")), + ...(includeDeprecated ? fs.readdirSync(path.join(dirs.storybook, "deprecated")) : []), ])]; } @@ -270,12 +270,12 @@ async function copy(from, to, { cwd, isDeprecated = true } = {}) { * @param {string} [config.cwd=] - Current working directory for the component being built * @returns Promise */ -async function writeAndReport(content, output, { cwd = process.cwd() } = {}) { +async function writeAndReport(content, output, { cwd = process.cwd(), encoding = "utf-8" } = {}) { return fsp .writeFile( output, content, - { encoding: "utf-8" }, + { encoding }, ) .then(() => { const stats = fs.statSync(output); diff --git a/tools/bundle/CHANGELOG.md b/tools/bundle/CHANGELOG.md new file mode 100644 index 00000000000..420e6f23d0e --- /dev/null +++ b/tools/bundle/CHANGELOG.md @@ -0,0 +1 @@ +# Change Log diff --git a/tools/bundle/README.md b/tools/bundle/README.md new file mode 100644 index 00000000000..dcdc1784dd5 --- /dev/null +++ b/tools/bundle/README.md @@ -0,0 +1,5 @@ +# @adobe/spectrum-css bundle + +This package builds a bundle package containing backwards-compatible versions of all Spectrum CSS components. + +This package should be used for demo or development purposes only and is not designed to be used in a production environment. diff --git a/tools/bundle/package.json b/tools/bundle/package.json new file mode 100644 index 00000000000..7e8875b80d5 --- /dev/null +++ b/tools/bundle/package.json @@ -0,0 +1,120 @@ +{ + "name": "@spectrum-css/bundle", + "version": "0.0.0", + "description": "A demo-ready bundle of the components in the Spectrum CSS library.", + "license": "Apache-2.0", + "author": "Adobe", + "contributors": [ + "Larry Davis ", + "Garth Braithwaite (https://garthdb.com)", + "Steve Gill ", + "Cassondra Roberts (https://allons-y.llc)" + ], + "homepage": "https://opensource.adobe.com/spectrum-css/", + "repository": { + "type": "git", + "url": "https://github.com/adobe/spectrum-css.git", + "directory": "tools/bundle" + }, + "bugs": { + "url": "https://github.com/adobe/spectrum-css/issues" + }, + "type": "module", + "exports": { + ".": "./dist/index.css", + "./*.md": "./*.md", + "./dist/*": "./dist/*", + "./index.css": "./dist/index.css", + "./package.json": "./package.json", + "./src/*": "./src/*" + }, + "main": "dist/index.css", + "devDependencies": { + "@spectrum-css/accordion": "workspace:^", + "@spectrum-css/actionbar": "workspace:^", + "@spectrum-css/actionbutton": "workspace:^", + "@spectrum-css/actiongroup": "workspace:^", + "@spectrum-css/actionmenu": "workspace:^", + "@spectrum-css/alertbanner": "workspace:^", + "@spectrum-css/alertdialog": "workspace:^", + "@spectrum-css/asset": "workspace:^", + "@spectrum-css/assetcard": "workspace:^", + "@spectrum-css/assetlist": "workspace:^", + "@spectrum-css/avatar": "workspace:^", + "@spectrum-css/badge": "workspace:^", + "@spectrum-css/breadcrumb": "workspace:^", + "@spectrum-css/button": "workspace:^", + "@spectrum-css/buttongroup": "workspace:^", + "@spectrum-css/calendar": "workspace:^", + "@spectrum-css/card": "workspace:^", + "@spectrum-css/checkbox": "workspace:^", + "@spectrum-css/clearbutton": "workspace:^", + "@spectrum-css/closebutton": "workspace:^", + "@spectrum-css/coachindicator": "workspace:^", + "@spectrum-css/coachmark": "workspace:^", + "@spectrum-css/colorarea": "workspace:^", + "@spectrum-css/colorhandle": "workspace:^", + "@spectrum-css/colorloupe": "workspace:^", + "@spectrum-css/colorslider": "workspace:^", + "@spectrum-css/colorwheel": "workspace:^", + "@spectrum-css/combobox": "workspace:^", + "@spectrum-css/commons": "workspace:^", + "@spectrum-css/contextualhelp": "workspace:^", + "@spectrum-css/datepicker": "workspace:^", + "@spectrum-css/dial": "workspace:^", + "@spectrum-css/dialog": "workspace:^", + "@spectrum-css/divider": "workspace:^", + "@spectrum-css/dropindicator": "workspace:^", + "@spectrum-css/dropzone": "workspace:^", + "@spectrum-css/fieldgroup": "workspace:^", + "@spectrum-css/fieldlabel": "workspace:^", + "@spectrum-css/floatingactionbutton": "workspace:^", + "@spectrum-css/helptext": "workspace:^", + "@spectrum-css/icon": "workspace:^", + "@spectrum-css/illustratedmessage": "workspace:^", + "@spectrum-css/infieldbutton": "workspace:^", + "@spectrum-css/inlinealert": "workspace:^", + "@spectrum-css/link": "workspace:^", + "@spectrum-css/logicbutton": "workspace:^", + "@spectrum-css/menu": "workspace:^", + "@spectrum-css/miller": "workspace:^", + "@spectrum-css/modal": "workspace:^", + "@spectrum-css/opacitycheckerboard": "workspace:^", + "@spectrum-css/page": "workspace:^", + "@spectrum-css/pagination": "workspace:^", + "@spectrum-css/picker": "workspace:^", + "@spectrum-css/pickerbutton": "workspace:^", + "@spectrum-css/popover": "workspace:^", + "@spectrum-css/progressbar": "workspace:^", + "@spectrum-css/progresscircle": "workspace:^", + "@spectrum-css/radio": "workspace:^", + "@spectrum-css/rating": "workspace:^", + "@spectrum-css/search": "workspace:^", + "@spectrum-css/sidenav": "workspace:^", + "@spectrum-css/slider": "workspace:^", + "@spectrum-css/splitview": "workspace:^", + "@spectrum-css/statuslight": "workspace:^", + "@spectrum-css/steplist": "workspace:^", + "@spectrum-css/stepper": "workspace:^", + "@spectrum-css/swatch": "workspace:^", + "@spectrum-css/swatchgroup": "workspace:^", + "@spectrum-css/switch": "workspace:^", + "@spectrum-css/table": "workspace:^", + "@spectrum-css/tabs": "workspace:^", + "@spectrum-css/tag": "workspace:^", + "@spectrum-css/taggroup": "workspace:^", + "@spectrum-css/textfield": "workspace:^", + "@spectrum-css/thumbnail": "workspace:^", + "@spectrum-css/toast": "workspace:^", + "@spectrum-css/tokens": "workspace:^", + "@spectrum-css/tooltip": "workspace:^", + "@spectrum-css/tray": "workspace:^", + "@spectrum-css/treeview": "workspace:^", + "@spectrum-css/typography": "workspace:^", + "@spectrum-css/underlay": "workspace:^", + "@spectrum-css/well": "workspace:^", + "colors": "^1.4.0", + "postcss": "^8.4.49", + "postcss-licensing": "^2.0.0" + } +} diff --git a/tools/bundle/postcss.config.js b/tools/bundle/postcss.config.js new file mode 100644 index 00000000000..5a9f03231d1 --- /dev/null +++ b/tools/bundle/postcss.config.js @@ -0,0 +1,34 @@ +/*! + * Copyright 2024 Adobe. All rights reserved. + * + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import path from "node:path"; + +import { dirs } from "../../tasks/utilities.js"; + +/** + * This config is used only to process the source files when created; + * the dist output is processed using the postcss config in the root + * which is the same styles used for individual component processing. + * + * This only adds the licensing information to the top of the file. + */ +export default () => ({ + map: false, + plugins: { + "postcss-licensing": { + filename: "COPYRIGHT", + cwd: path.join(dirs.root), + skipIfEmpty: true, + }, + }, +}); diff --git a/tools/bundle/project.json b/tools/bundle/project.json new file mode 100644 index 00000000000..31dd6568aba --- /dev/null +++ b/tools/bundle/project.json @@ -0,0 +1,50 @@ +{ + "name": "bundle", + "tag": ["tooling"], + "namedInputs": { + "core": ["{projectRoot}/src/index.css"], + "tools": ["{projectRoot}/tasks/bundler.js"] + }, + "targets": { + "build": { + "dependsOn": ["clean", { "target": "build", "projects": "tokens" }], + "executor": "nx:run-commands", + "inputs": [ + "core", + "tools", + "{workspaceRoot}/postcss.config.js", + "{workspaceRoot}/stylelint.config.js", + { "externalDependencies": ["postcss", "stylelint"] } + ], + "options": { + "commands": ["cross-env NODE_OPTIONS=\"--no-warnings\" node -e 'import(\"./tasks/bundler.js\").then(module => module.main() )'"], + "cwd": "{projectRoot}" + }, + "outputs": [ + "{projectRoot}/dist/index.css", + "{projectRoot}/dist/index.css.map" + ] + }, + "clean": {}, + "format": {}, + "lint": {}, + "refresh": { + "cache": false, + "dependsOn": [], + "executor": "nx:run-commands", + "inputs": [ + "tools", + "{projectRoot}/package.json", + "{projectRoot}/postcss.config.js", + { "externalDependencies": ["postcss"] } + ], + "options": { + "commands": [ + "cross-env NODE_OPTIONS=\"--no-warnings\" node -e 'import(\"./tasks/bundler.js\").then(module => module.refresh() )'" + ], + "cwd": "{projectRoot}" + }, + "outputs": ["{projectRoot}/src/index.css"] + } + } +} diff --git a/tools/bundle/src/index.css b/tools/bundle/src/index.css new file mode 100644 index 00000000000..b13a660aacb --- /dev/null +++ b/tools/bundle/src/index.css @@ -0,0 +1,99 @@ +/*! + * Copyright 2024 Adobe. All rights reserved. + * + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* --- CORE TOKENS --- */ +@import "@spectrum-css/tokens"; + +/* --- COMPONENTS --- */ +@import "@spectrum-css/accordion"; +@import "@spectrum-css/actionbar"; +@import "@spectrum-css/actionbutton"; +@import "@spectrum-css/actiongroup"; +/* skip @spectrum-css/actionmenu -- does not ship CSS */ +@import "@spectrum-css/alertbanner"; +@import "@spectrum-css/alertdialog"; +@import "@spectrum-css/asset"; +@import "@spectrum-css/assetcard"; +@import "@spectrum-css/assetlist"; +@import "@spectrum-css/avatar"; +@import "@spectrum-css/badge"; +@import "@spectrum-css/breadcrumb"; +@import "@spectrum-css/button"; +@import "@spectrum-css/buttongroup"; +@import "@spectrum-css/calendar"; +@import "@spectrum-css/card"; +@import "@spectrum-css/checkbox"; +@import "@spectrum-css/clearbutton"; +@import "@spectrum-css/closebutton"; +@import "@spectrum-css/coachindicator"; +@import "@spectrum-css/coachmark"; +@import "@spectrum-css/colorarea"; +@import "@spectrum-css/colorhandle"; +@import "@spectrum-css/colorloupe"; +@import "@spectrum-css/colorslider"; +@import "@spectrum-css/colorwheel"; +@import "@spectrum-css/combobox"; +/* skip @spectrum-css/commons -- does not ship CSS */ +@import "@spectrum-css/contextualhelp"; +@import "@spectrum-css/datepicker"; +@import "@spectrum-css/dial"; +@import "@spectrum-css/dialog"; +@import "@spectrum-css/divider"; +@import "@spectrum-css/dropindicator"; +@import "@spectrum-css/dropzone"; +@import "@spectrum-css/fieldgroup"; +@import "@spectrum-css/fieldlabel"; +@import "@spectrum-css/floatingactionbutton"; +@import "@spectrum-css/helptext"; +@import "@spectrum-css/icon"; +@import "@spectrum-css/illustratedmessage"; +@import "@spectrum-css/infieldbutton"; +@import "@spectrum-css/inlinealert"; +@import "@spectrum-css/link"; +@import "@spectrum-css/logicbutton"; +@import "@spectrum-css/menu"; +@import "@spectrum-css/miller"; +@import "@spectrum-css/modal"; +@import "@spectrum-css/opacitycheckerboard"; +@import "@spectrum-css/page"; +@import "@spectrum-css/pagination"; +@import "@spectrum-css/picker"; +@import "@spectrum-css/pickerbutton"; +@import "@spectrum-css/popover"; +@import "@spectrum-css/progressbar"; +@import "@spectrum-css/progresscircle"; +@import "@spectrum-css/radio"; +@import "@spectrum-css/rating"; +@import "@spectrum-css/search"; +@import "@spectrum-css/sidenav"; +@import "@spectrum-css/slider"; +@import "@spectrum-css/splitview"; +@import "@spectrum-css/statuslight"; +@import "@spectrum-css/steplist"; +@import "@spectrum-css/stepper"; +@import "@spectrum-css/swatch"; +@import "@spectrum-css/swatchgroup"; +@import "@spectrum-css/switch"; +@import "@spectrum-css/table"; +@import "@spectrum-css/tabs"; +@import "@spectrum-css/tag"; +@import "@spectrum-css/taggroup"; +@import "@spectrum-css/textfield"; +@import "@spectrum-css/thumbnail"; +@import "@spectrum-css/toast"; +@import "@spectrum-css/tooltip"; +@import "@spectrum-css/tray"; +@import "@spectrum-css/treeview"; +@import "@spectrum-css/typography"; +@import "@spectrum-css/underlay"; +@import "@spectrum-css/well"; diff --git a/tools/bundle/tasks/bundler.js b/tools/bundle/tasks/bundler.js new file mode 100644 index 00000000000..e1b644b0be5 --- /dev/null +++ b/tools/bundle/tasks/bundler.js @@ -0,0 +1,200 @@ +/* eslint-disable no-console */ +/*! + * Copyright 2024 Adobe. All rights reserved. + * + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import fs from "node:fs"; +import path from "node:path"; + +import { processCSS } from "../../../tasks/component-builder.js"; +import { dirs, getAllComponentNames, writeAndReport } from "../../../tasks/utilities.js"; + +import "colors"; + +const bundleRoot = path.resolve(dirs.root, "tools", "bundle"); + +/** + * Validate the dependencies listed in the package.json + * match the components in the components directory + * @param {string[]} components - List of components + * @returns {Promise} + */ +async function validateDependencies(components) { + const localPackage = path.join(bundleRoot, "package.json"); + // Confirm the dependencies listed in this package.json match the components in the components directory + const packageJSON = JSON.parse(fs.readFileSync(localPackage, "utf8")); + + const dependencies = Object.keys(packageJSON.devDependencies ?? {}).filter((dependency) => dependency.startsWith("@spectrum-css/")); + + // Capture any dependencies that are missing or outdated in the components directory + const outdated = dependencies.filter((dependency) => !components.includes(dependency.replace("@spectrum-css/", ""))); + + // Capture any components that are missing from the dependencies to add them + const missing = components.filter((components) => !dependencies.includes(`@spectrum-css/${components}`)); + + // We don't need to update the package.json if nothing has changed + let hasChanged = false; + const reports = []; + + // If there are missing components, add them to the package dependencies + if (missing.length > 0) { + hasChanged = true; + + // Update the package.json dependencies + missing.forEach((dependency) => { + reports.push(`${"+".green} ${`@spectrum-css/${dependency} to package.json`.gray}`); + packageJSON.devDependencies[`@spectrum-css/${dependency}`] = "workspace:^"; + }); + } + + // If there are outdated dependencies, remove them from the package dependencies + if (outdated.length > 0) { + hasChanged = true; + + // Remove the outdated dependencies + outdated.forEach((dependency) => { + // Don't remove the tokens dependency + if (dependency === "@spectrum-css/tokens") return; + + reports.push(`${"-".red} ${`${dependency} from package.json`.gray}`); + delete packageJSON.devDependencies[dependency]; + }); + } + + // If changes were made to the dependencies, write the package.json file + if (hasChanged) { + // Sort the devDependencies alphabetically + packageJSON.devDependencies = Object.keys(packageJSON.devDependencies) + .sort() + .reduce((obj, key) => { + obj[key] = packageJSON.devDependencies[key]; + return obj; + }, {}); + + return writeAndReport(JSON.stringify(packageJSON, null, "\t"), localPackage).then((r) => [...reports, r]).catch((err) => { + return [...reports, err]; + }); + } + + return Promise.resolve("No dependency updates needed.\n".gray); +} + +/** + * Refresh the list of component imports + * @returns {Promise} + */ +export async function refresh() { + const components = getAllComponentNames(false); + + // Refresh the src/index.css file with the latest component imports + const imports = ` +/* --- CORE TOKENS --- */ +@import "@spectrum-css/tokens"; + +/* --- COMPONENTS --- */ +${components.map((component) => { + // Check if the package has an index.css file + if ( + fs.existsSync(path.join(dirs.components, component, "index.css")) && + !["commons"].includes(component) + ) { + return `@import "@spectrum-css/${component}";`; + } + return `/* skip @spectrum-css/${component} -- does not ship CSS */`; +}).join("\n")} +`; + + return Promise.all([ + validateDependencies(components), + processCSS(imports, undefined, path.join(bundleRoot, "src", "index.css"), { + cwd: bundleRoot, + env: "development", + configPath: bundleRoot, + }), + ]).then(reports => { + const logs = reports.flat(Infinity).filter(Boolean); + console.log("\n\n🔄 refresh bundle"); + console.log(`${"".padStart(30, "-")}`); + if (logs && logs.length > 0) { + logs.forEach(log => console.log(log)); + console.log(`${"".padStart(30, "-")}`); + console.log(""); + } + }) + .catch((err) => { + console.log("\n\n🔄 refresh bundle"); + console.log(`${"".padStart(30, "-")}`); + + console.trace(err); + + console.log(`${"".padStart(30, "-")}`); + console.log(""); + + process.exit(1); + }); +} + +/** + * Bundle all the components into a single CSS file + * @returns {Promise} + */ +export async function bundler() { + // Ensure the dist directory exists + if (!fs.existsSync(path.join(bundleRoot, "dist"))) { + fs.mkdirSync(path.join(bundleRoot, "dist")); + } + + return Promise.all([ + processCSS(undefined, path.join(bundleRoot, "src", "index.css"), path.join(bundleRoot, "dist", "index.css"), { cwd: bundleRoot }), + // Write the minified CSS + processCSS(undefined, path.join(bundleRoot, "src", "index.css"), path.join(bundleRoot, "dist", "index.min.css"), { cwd: bundleRoot, minify: true }), + ]); +} + +/** + * Entry point for the bundler + * @returns {Promise} + */ +export async function main() { + const key = "bundler"; + + console.time(key); + return Promise.all([ + bundler(), + ]).then((report) => { + const logs = report.flat(Infinity).filter(Boolean); + + console.log(`\n\n📦 ${key}`); + console.log(`${"".padStart(30, "-")}`); + + if (logs && logs.length > 0) { + logs.forEach((log) => console.log(log)); + } + else console.log("No assets created.".gray); + + console.log(`${"".padStart(30, "-")}`); + console.timeEnd(key); + console.log(""); + }) + .catch((err) => { + console.log(`\n\n${key} 🔨`); + console.log(`${"".padStart(30, "-")}`); + + console.trace(err); + + console.log(`${"".padStart(30, "-")}`); + console.timeEnd(key); + console.log(""); + + process.exit(1); + }); +} diff --git a/yarn.lock b/yarn.lock index 6e797dbb0e7..b5342c00654 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2924,7 +2924,7 @@ __metadata: languageName: node linkType: hard -"@spectrum-css/accordion@workspace:components/accordion": +"@spectrum-css/accordion@workspace:^, @spectrum-css/accordion@workspace:components/accordion": version: 0.0.0-use.local resolution: "@spectrum-css/accordion@workspace:components/accordion" dependencies: @@ -2936,7 +2936,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/actionbar@workspace:components/actionbar": +"@spectrum-css/actionbar@workspace:^, @spectrum-css/actionbar@workspace:components/actionbar": version: 0.0.0-use.local resolution: "@spectrum-css/actionbar@workspace:components/actionbar" dependencies: @@ -3000,7 +3000,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/alertbanner@workspace:components/alertbanner": +"@spectrum-css/alertbanner@workspace:^, @spectrum-css/alertbanner@workspace:components/alertbanner": version: 0.0.0-use.local resolution: "@spectrum-css/alertbanner@workspace:components/alertbanner" dependencies: @@ -3056,7 +3056,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/assetcard@workspace:components/assetcard": +"@spectrum-css/assetcard@workspace:^, @spectrum-css/assetcard@workspace:components/assetcard": version: 0.0.0-use.local resolution: "@spectrum-css/assetcard@workspace:components/assetcard" dependencies: @@ -3100,7 +3100,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/badge@workspace:components/badge": +"@spectrum-css/badge@workspace:^, @spectrum-css/badge@workspace:components/badge": version: 0.0.0-use.local resolution: "@spectrum-css/badge@workspace:components/badge" dependencies: @@ -3115,7 +3115,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/breadcrumb@workspace:components/breadcrumb": +"@spectrum-css/breadcrumb@workspace:^, @spectrum-css/breadcrumb@workspace:components/breadcrumb": version: 0.0.0-use.local resolution: "@spectrum-css/breadcrumb@workspace:components/breadcrumb" dependencies: @@ -3134,6 +3134,99 @@ __metadata: languageName: unknown linkType: soft +"@spectrum-css/bundle@workspace:^, @spectrum-css/bundle@workspace:tools/bundle": + version: 0.0.0-use.local + resolution: "@spectrum-css/bundle@workspace:tools/bundle" + dependencies: + "@spectrum-css/accordion": "workspace:^" + "@spectrum-css/actionbar": "workspace:^" + "@spectrum-css/actionbutton": "workspace:^" + "@spectrum-css/actiongroup": "workspace:^" + "@spectrum-css/actionmenu": "workspace:^" + "@spectrum-css/alertbanner": "workspace:^" + "@spectrum-css/alertdialog": "workspace:^" + "@spectrum-css/asset": "workspace:^" + "@spectrum-css/assetcard": "workspace:^" + "@spectrum-css/assetlist": "workspace:^" + "@spectrum-css/avatar": "workspace:^" + "@spectrum-css/badge": "workspace:^" + "@spectrum-css/breadcrumb": "workspace:^" + "@spectrum-css/button": "workspace:^" + "@spectrum-css/buttongroup": "workspace:^" + "@spectrum-css/calendar": "workspace:^" + "@spectrum-css/card": "workspace:^" + "@spectrum-css/checkbox": "workspace:^" + "@spectrum-css/clearbutton": "workspace:^" + "@spectrum-css/closebutton": "workspace:^" + "@spectrum-css/coachindicator": "workspace:^" + "@spectrum-css/coachmark": "workspace:^" + "@spectrum-css/colorarea": "workspace:^" + "@spectrum-css/colorhandle": "workspace:^" + "@spectrum-css/colorloupe": "workspace:^" + "@spectrum-css/colorslider": "workspace:^" + "@spectrum-css/colorwheel": "workspace:^" + "@spectrum-css/combobox": "workspace:^" + "@spectrum-css/commons": "workspace:^" + "@spectrum-css/contextualhelp": "workspace:^" + "@spectrum-css/datepicker": "workspace:^" + "@spectrum-css/dial": "workspace:^" + "@spectrum-css/dialog": "workspace:^" + "@spectrum-css/divider": "workspace:^" + "@spectrum-css/dropindicator": "workspace:^" + "@spectrum-css/dropzone": "workspace:^" + "@spectrum-css/fieldgroup": "workspace:^" + "@spectrum-css/fieldlabel": "workspace:^" + "@spectrum-css/floatingactionbutton": "workspace:^" + "@spectrum-css/helptext": "workspace:^" + "@spectrum-css/icon": "workspace:^" + "@spectrum-css/illustratedmessage": "workspace:^" + "@spectrum-css/infieldbutton": "workspace:^" + "@spectrum-css/inlinealert": "workspace:^" + "@spectrum-css/link": "workspace:^" + "@spectrum-css/logicbutton": "workspace:^" + "@spectrum-css/menu": "workspace:^" + "@spectrum-css/miller": "workspace:^" + "@spectrum-css/modal": "workspace:^" + "@spectrum-css/opacitycheckerboard": "workspace:^" + "@spectrum-css/page": "workspace:^" + "@spectrum-css/pagination": "workspace:^" + "@spectrum-css/picker": "workspace:^" + "@spectrum-css/pickerbutton": "workspace:^" + "@spectrum-css/popover": "workspace:^" + "@spectrum-css/progressbar": "workspace:^" + "@spectrum-css/progresscircle": "workspace:^" + "@spectrum-css/radio": "workspace:^" + "@spectrum-css/rating": "workspace:^" + "@spectrum-css/search": "workspace:^" + "@spectrum-css/sidenav": "workspace:^" + "@spectrum-css/slider": "workspace:^" + "@spectrum-css/splitview": "workspace:^" + "@spectrum-css/statuslight": "workspace:^" + "@spectrum-css/steplist": "workspace:^" + "@spectrum-css/stepper": "workspace:^" + "@spectrum-css/swatch": "workspace:^" + "@spectrum-css/swatchgroup": "workspace:^" + "@spectrum-css/switch": "workspace:^" + "@spectrum-css/table": "workspace:^" + "@spectrum-css/tabs": "workspace:^" + "@spectrum-css/tag": "workspace:^" + "@spectrum-css/taggroup": "workspace:^" + "@spectrum-css/textfield": "workspace:^" + "@spectrum-css/thumbnail": "workspace:^" + "@spectrum-css/toast": "workspace:^" + "@spectrum-css/tokens": "workspace:^" + "@spectrum-css/tooltip": "workspace:^" + "@spectrum-css/tray": "workspace:^" + "@spectrum-css/treeview": "workspace:^" + "@spectrum-css/typography": "workspace:^" + "@spectrum-css/underlay": "workspace:^" + "@spectrum-css/well": "workspace:^" + colors: "npm:^1.4.0" + postcss: "npm:^8.4.49" + postcss-licensing: "npm:^2.0.0" + languageName: unknown + linkType: soft + "@spectrum-css/button@workspace:^, @spectrum-css/button@workspace:components/button": version: 0.0.0-use.local resolution: "@spectrum-css/button@workspace:components/button" @@ -3178,7 +3271,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/card@workspace:components/card": +"@spectrum-css/card@workspace:^, @spectrum-css/card@workspace:components/card": version: 0.0.0-use.local resolution: "@spectrum-css/card@workspace:components/card" dependencies: @@ -3250,7 +3343,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/coachindicator@workspace:components/coachindicator": +"@spectrum-css/coachindicator@workspace:^, @spectrum-css/coachindicator@workspace:components/coachindicator": version: 0.0.0-use.local resolution: "@spectrum-css/coachindicator@workspace:components/coachindicator" dependencies: @@ -3260,7 +3353,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/coachmark@workspace:components/coachmark": +"@spectrum-css/coachmark@workspace:^, @spectrum-css/coachmark@workspace:components/coachmark": version: 0.0.0-use.local resolution: "@spectrum-css/coachmark@workspace:components/coachmark" dependencies: @@ -3324,7 +3417,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/colorslider@workspace:components/colorslider": +"@spectrum-css/colorslider@workspace:^, @spectrum-css/colorslider@workspace:components/colorslider": version: 0.0.0-use.local resolution: "@spectrum-css/colorslider@workspace:components/colorslider" dependencies: @@ -3338,7 +3431,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/colorwheel@workspace:components/colorwheel": +"@spectrum-css/colorwheel@workspace:^, @spectrum-css/colorwheel@workspace:components/colorwheel": version: 0.0.0-use.local resolution: "@spectrum-css/colorwheel@workspace:components/colorwheel" dependencies: @@ -3359,7 +3452,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/combobox@workspace:components/combobox": +"@spectrum-css/combobox@workspace:^, @spectrum-css/combobox@workspace:components/combobox": version: 0.0.0-use.local resolution: "@spectrum-css/combobox@workspace:components/combobox" dependencies: @@ -3392,7 +3485,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/contextualhelp@workspace:components/contextualhelp": +"@spectrum-css/contextualhelp@workspace:^, @spectrum-css/contextualhelp@workspace:components/contextualhelp": version: 0.0.0-use.local resolution: "@spectrum-css/contextualhelp@workspace:components/contextualhelp" dependencies: @@ -3421,7 +3514,7 @@ __metadata: languageName: node linkType: hard -"@spectrum-css/datepicker@workspace:components/datepicker": +"@spectrum-css/datepicker@workspace:^, @spectrum-css/datepicker@workspace:components/datepicker": version: 0.0.0-use.local resolution: "@spectrum-css/datepicker@workspace:components/datepicker" dependencies: @@ -3439,7 +3532,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/dial@workspace:components/dial": +"@spectrum-css/dial@workspace:^, @spectrum-css/dial@workspace:components/dial": version: 0.0.0-use.local resolution: "@spectrum-css/dial@workspace:components/dial" dependencies: @@ -3485,7 +3578,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/dropindicator@workspace:components/dropindicator": +"@spectrum-css/dropindicator@workspace:^, @spectrum-css/dropindicator@workspace:components/dropindicator": version: 0.0.0-use.local resolution: "@spectrum-css/dropindicator@workspace:components/dropindicator" dependencies: @@ -3497,7 +3590,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/dropzone@workspace:components/dropzone": +"@spectrum-css/dropzone@workspace:^, @spectrum-css/dropzone@workspace:components/dropzone": version: 0.0.0-use.local resolution: "@spectrum-css/dropzone@workspace:components/dropzone" dependencies: @@ -3518,7 +3611,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/fieldgroup@workspace:components/fieldgroup": +"@spectrum-css/fieldgroup@workspace:^, @spectrum-css/fieldgroup@workspace:components/fieldgroup": version: 0.0.0-use.local resolution: "@spectrum-css/fieldgroup@workspace:components/fieldgroup" dependencies: @@ -3553,7 +3646,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/floatingactionbutton@workspace:components/floatingactionbutton": +"@spectrum-css/floatingactionbutton@workspace:^, @spectrum-css/floatingactionbutton@workspace:components/floatingactionbutton": version: 0.0.0-use.local resolution: "@spectrum-css/floatingactionbutton@workspace:components/floatingactionbutton" dependencies: @@ -3623,7 +3716,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/inlinealert@workspace:components/inlinealert": +"@spectrum-css/inlinealert@workspace:^, @spectrum-css/inlinealert@workspace:components/inlinealert": version: 0.0.0-use.local resolution: "@spectrum-css/inlinealert@workspace:components/inlinealert" dependencies: @@ -3650,7 +3743,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/logicbutton@workspace:components/logicbutton": +"@spectrum-css/logicbutton@workspace:^, @spectrum-css/logicbutton@workspace:components/logicbutton": version: 0.0.0-use.local resolution: "@spectrum-css/logicbutton@workspace:components/logicbutton" dependencies: @@ -3689,7 +3782,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/miller@workspace:components/miller": +"@spectrum-css/miller@workspace:^, @spectrum-css/miller@workspace:components/miller": version: 0.0.0-use.local resolution: "@spectrum-css/miller@workspace:components/miller" dependencies: @@ -3726,7 +3819,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/page@workspace:components/page": +"@spectrum-css/page@workspace:^, @spectrum-css/page@workspace:components/page": version: 0.0.0-use.local resolution: "@spectrum-css/page@workspace:components/page" dependencies: @@ -3736,7 +3829,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/pagination@workspace:components/pagination": +"@spectrum-css/pagination@workspace:^, @spectrum-css/pagination@workspace:components/pagination": version: 0.0.0-use.local resolution: "@spectrum-css/pagination@workspace:components/pagination" dependencies: @@ -3830,9 +3923,8 @@ __metadata: "@babel/core": "npm:^7.26.0" "@chromaui/addon-visual-tests": "npm:^1.0.0" "@etchteam/storybook-addon-status": "npm:^5.0.0" - "@spectrum-css/table": "workspace:^" + "@spectrum-css/bundle": "workspace:^" "@spectrum-css/tokens": "workspace:^" - "@spectrum-css/typography": "workspace:^" "@spectrum-css/ui-icons": "workspace:^" "@storybook/addon-a11y": "npm:^8.4.7" "@storybook/addon-actions": "npm:^8.4.7" @@ -3866,7 +3958,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/progressbar@workspace:components/progressbar": +"@spectrum-css/progressbar@workspace:^, @spectrum-css/progressbar@workspace:components/progressbar": version: 0.0.0-use.local resolution: "@spectrum-css/progressbar@workspace:components/progressbar" dependencies: @@ -3914,7 +4006,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/rating@workspace:components/rating": +"@spectrum-css/rating@workspace:^, @spectrum-css/rating@workspace:components/rating": version: 0.0.0-use.local resolution: "@spectrum-css/rating@workspace:components/rating" dependencies: @@ -3926,7 +4018,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/search@workspace:components/search": +"@spectrum-css/search@workspace:^, @spectrum-css/search@workspace:components/search": version: 0.0.0-use.local resolution: "@spectrum-css/search@workspace:components/search" dependencies: @@ -3955,7 +4047,7 @@ __metadata: languageName: node linkType: hard -"@spectrum-css/sidenav@workspace:components/sidenav": +"@spectrum-css/sidenav@workspace:^, @spectrum-css/sidenav@workspace:components/sidenav": version: 0.0.0-use.local resolution: "@spectrum-css/sidenav@workspace:components/sidenav" dependencies: @@ -3970,7 +4062,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/slider@workspace:components/slider": +"@spectrum-css/slider@workspace:^, @spectrum-css/slider@workspace:components/slider": version: 0.0.0-use.local resolution: "@spectrum-css/slider@workspace:components/slider" dependencies: @@ -3996,7 +4088,7 @@ __metadata: languageName: node linkType: hard -"@spectrum-css/splitview@workspace:components/splitview": +"@spectrum-css/splitview@workspace:^, @spectrum-css/splitview@workspace:components/splitview": version: 0.0.0-use.local resolution: "@spectrum-css/splitview@workspace:components/splitview" dependencies: @@ -4006,7 +4098,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/statuslight@workspace:components/statuslight": +"@spectrum-css/statuslight@workspace:^, @spectrum-css/statuslight@workspace:components/statuslight": version: 0.0.0-use.local resolution: "@spectrum-css/statuslight@workspace:components/statuslight" dependencies: @@ -4016,7 +4108,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/steplist@workspace:components/steplist": +"@spectrum-css/steplist@workspace:^, @spectrum-css/steplist@workspace:components/steplist": version: 0.0.0-use.local resolution: "@spectrum-css/steplist@workspace:components/steplist" dependencies: @@ -4066,7 +4158,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/swatchgroup@workspace:components/swatchgroup": +"@spectrum-css/swatchgroup@workspace:^, @spectrum-css/swatchgroup@workspace:components/swatchgroup": version: 0.0.0-use.local resolution: "@spectrum-css/swatchgroup@workspace:components/swatchgroup" dependencies: @@ -4113,7 +4205,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/tabs@workspace:components/tabs": +"@spectrum-css/tabs@workspace:^, @spectrum-css/tabs@workspace:components/tabs": version: 0.0.0-use.local resolution: "@spectrum-css/tabs@workspace:components/tabs" dependencies: @@ -4153,7 +4245,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/taggroup@workspace:components/taggroup": +"@spectrum-css/taggroup@workspace:^, @spectrum-css/taggroup@workspace:components/taggroup": version: 0.0.0-use.local resolution: "@spectrum-css/taggroup@workspace:components/taggroup" dependencies: @@ -4192,7 +4284,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/toast@workspace:components/toast": +"@spectrum-css/toast@workspace:^, @spectrum-css/toast@workspace:components/toast": version: 0.0.0-use.local resolution: "@spectrum-css/toast@workspace:components/toast" dependencies: @@ -4266,7 +4358,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/treeview@workspace:components/treeview": +"@spectrum-css/treeview@workspace:^, @spectrum-css/treeview@workspace:components/treeview": version: 0.0.0-use.local resolution: "@spectrum-css/treeview@workspace:components/treeview" dependencies: @@ -4314,7 +4406,7 @@ __metadata: languageName: unknown linkType: soft -"@spectrum-css/well@workspace:components/well": +"@spectrum-css/well@workspace:^, @spectrum-css/well@workspace:components/well": version: 0.0.0-use.local resolution: "@spectrum-css/well@workspace:components/well" dependencies: