From 25112bbf0ff7399ddd7b86c49dc77d987fea1d07 Mon Sep 17 00:00:00 2001 From: Chris Holt <13071055+chrisdholt@users.noreply.github.com> Date: Wed, 6 May 2026 23:45:37 -0700 Subject: [PATCH 01/11] fix: migrate to esbuild for CDN bundle, enable setTheme on globalThis --- ...-753b509c-f103-4d8f-8b15-4a88a784dd81.json | 7 ++ packages/web-components/.storybook/main.cjs | 2 +- .../web-components/.storybook/preview.mjs | 3 +- .../web-components/docs/web-components.api.md | 5 -- packages/web-components/package.json | 15 +++- packages/web-components/rollup.config.js | 43 ----------- packages/web-components/scripts/bundle.js | 73 +++++++++++++++++++ .../src/_docs/developer/migration.mdx | 4 +- .../src/{index-rollup.ts => index.bundle.ts} | 11 ++- packages/web-components/src/index.ts | 2 +- packages/web-components/src/theme/index.ts | 2 +- .../web-components/src/theme/set-theme.ts | 8 -- .../web-components/test/harness/src/main.ts | 2 +- yarn.lock | 12 +++ 14 files changed, 120 insertions(+), 69 deletions(-) create mode 100644 change/@fluentui-web-components-753b509c-f103-4d8f-8b15-4a88a784dd81.json delete mode 100644 packages/web-components/rollup.config.js create mode 100644 packages/web-components/scripts/bundle.js rename packages/web-components/src/{index-rollup.ts => index.bundle.ts} (80%) diff --git a/change/@fluentui-web-components-753b509c-f103-4d8f-8b15-4a88a784dd81.json b/change/@fluentui-web-components-753b509c-f103-4d8f-8b15-4a88a784dd81.json new file mode 100644 index 0000000000000..f8b8932d773ff --- /dev/null +++ b/change/@fluentui-web-components-753b509c-f103-4d8f-8b15-4a88a784dd81.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "fix: migrate to esbuild for CDN bundle, enable setTheme on globalThis", + "packageName": "@fluentui/web-components", + "email": "13071055+chrisdholt@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/web-components/.storybook/main.cjs b/packages/web-components/.storybook/main.cjs index 70cc584dac55f..5f72e881c974e 100644 --- a/packages/web-components/.storybook/main.cjs +++ b/packages/web-components/.storybook/main.cjs @@ -59,7 +59,7 @@ function createTypeScriptAliases(configPath) { /** * Creates a Vite plugin that resolves .ts files when imported with .js extension. * This matches webpack's extensionAlias behavior and is needed for imports like - * '../src/index-rollup.js' to work in production builds. + * '../src/index.bundle.js' to work in production builds. * @returns {object} Vite plugin object */ function createResolveTsAsJsPlugin() { diff --git a/packages/web-components/.storybook/preview.mjs b/packages/web-components/.storybook/preview.mjs index 00c1916f0360f..7e6d490f5b34e 100644 --- a/packages/web-components/.storybook/preview.mjs +++ b/packages/web-components/.storybook/preview.mjs @@ -1,10 +1,9 @@ import { teamsDarkTheme, teamsLightTheme, webDarkTheme, webLightTheme } from '@fluentui/tokens'; import * as prettier from 'prettier'; import prettierPluginHTML from 'prettier/parser-html.js'; -import { setTheme } from '../src/theme/set-theme.js'; import webcomponentsTheme from './theme.mjs'; -import '../src/index-rollup.js'; +import '../src/index.bundle.js'; import './docs-root.css'; const FAST_EXPRESSION_COMMENTS = //g; // Matches comments that contain FAST expressions diff --git a/packages/web-components/docs/web-components.api.md b/packages/web-components/docs/web-components.api.md index 7eb64f59ffdf1..45c4edfeca765 100644 --- a/packages/web-components/docs/web-components.api.md +++ b/packages/web-components/docs/web-components.api.md @@ -3586,11 +3586,6 @@ export const roleForMenuItem: { // @public export function setTheme(theme: Theme | null, node?: Document | HTMLElement): void; -// Warning: (ae-internal-missing-underscore) The name "setThemeFor" should be prefixed with an underscore because the declaration is marked as @internal -// -// @internal @deprecated (undocumented) -export function setThemeFor(element: HTMLElement, theme: Theme | null): void; - // @public export const shadow16 = "var(--shadow16)"; diff --git a/packages/web-components/package.json b/packages/web-components/package.json index cbed415018f1e..c1f133893ec27 100644 --- a/packages/web-components/package.json +++ b/packages/web-components/package.json @@ -30,6 +30,14 @@ ], "exports": { ".": "./dist/esm/index.js", + "./web-components.js": { + "types": "./dist/web-components.d.ts", + "default": "./dist/web-components.js" + }, + "./web-components.min.js": { + "types": "./dist/web-components.d.ts", + "default": "./dist/web-components.min.js" + }, "./utils/behaviors/*.js": "./dist/esm/utils/behaviors/*.js", "./utils/*.js": "./dist/esm/utils/*.js", "./utilities.js": "./dist/esm/utils/index.js", @@ -47,7 +55,7 @@ }, "sideEffects": [ "define.*", - "index-rollup.*", + "index.bundle.*", "./dist/esm/**/define.js", "./dist/web-components.js", "./dist/web-components.min.js" @@ -61,7 +69,7 @@ "compile:benchmark": "rollup -c rollup.bench.js", "clean": "node ./scripts/clean dist", "generate-api": "api-extractor run --local", - "build": "yarn compile && yarn rollup -c && yarn generate-api && yarn analyze", + "build": "yarn compile && node scripts/bundle.js && yarn generate-api && yarn analyze", "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", "format": "prettier -w src/**/*.{ts,html} src/*.{ts,html} --ignore-path ../../.prettierignore", @@ -85,7 +93,8 @@ "@wc-toolkit/cem-inheritance": "1.2.2", "@wc-toolkit/module-path-resolver": "1.0.0", "@wc-toolkit/type-parser": "1.0.3", - "chromedriver": "^125.0.0" + "chromedriver": "^125.0.0", + "parse-literals": "^1.2.1" }, "dependencies": { "@fluentui/tokens": "1.0.0-alpha.23", diff --git a/packages/web-components/rollup.config.js b/packages/web-components/rollup.config.js deleted file mode 100644 index f852d6179508a..0000000000000 --- a/packages/web-components/rollup.config.js +++ /dev/null @@ -1,43 +0,0 @@ -import { nodeResolve } from '@rollup/plugin-node-resolve'; -import commonJS from 'rollup-plugin-commonjs'; -import esbuild, { minify } from 'rollup-plugin-esbuild'; -import transformTaggedTemplate from 'rollup-plugin-transform-tagged-template'; -import { transformCSSFragment, transformHTMLFragment } from './scripts/transform-fragments'; - -const parserOptions = { - sourceType: 'module', -}; - -export default [ - { - input: 'src/index-rollup.ts', - output: [ - { - file: 'dist/web-components.js', - format: 'esm', - }, - { - file: 'dist/web-components.min.js', - format: 'esm', - plugins: [minify()], - }, - ], - plugins: [ - nodeResolve({ browser: true }), - commonJS(), - esbuild({ - tsconfig: './tsconfig.lib.json', - }), - transformTaggedTemplate({ - tagsToProcess: ['css'], - transformer: transformCSSFragment, - parserOptions, - }), - transformTaggedTemplate({ - tagsToProcess: ['html'], - transformer: transformHTMLFragment, - parserOptions, - }), - ], - }, -]; diff --git a/packages/web-components/scripts/bundle.js b/packages/web-components/scripts/bundle.js new file mode 100644 index 0000000000000..aee456649fc68 --- /dev/null +++ b/packages/web-components/scripts/bundle.js @@ -0,0 +1,73 @@ +import { build } from 'esbuild'; +import { readFile } from 'fs/promises'; +import { parseLiterals } from 'parse-literals'; +import { transformCSSFragment, transformHTMLFragment } from './transform-fragments.js'; + +const transforms = { + css: transformCSSFragment, + html: transformHTMLFragment, +}; + +/** + * esbuild plugin that minifies tagged template literal content (css`...` and html`...`) + * using AST-based parsing from `parse-literals` to correctly handle nested templates, + * with the existing transform functions for CSS and HTML minification. + */ +function transformTaggedTemplates() { + return { + name: 'transform-tagged-templates', + setup(build) { + build.onLoad({ filter: /src\/.*\.ts$/ }, async args => { + const source = await readFile(args.path, 'utf8'); + const literals = parseLiterals(source); + + // Collect all replacements sorted by position (descending) to splice from end to start + const replacements = []; + for (const literal of literals) { + const transform = transforms[literal.tag]; + if (!transform) continue; + + for (const part of literal.parts) { + const transformed = transform(part.text); + if (transformed !== part.text) { + replacements.push({ start: part.start, end: part.end, text: transformed }); + } + } + } + + if (replacements.length === 0) { + return { contents: source, loader: 'ts' }; + } + + // Apply replacements from end to start to preserve positions + replacements.sort((a, b) => b.start - a.start); + let result = source; + for (const { start, end, text } of replacements) { + result = result.slice(0, start) + text + result.slice(end); + } + + return { contents: result, loader: 'ts' }; + }); + }, + }; +} + +const sharedOptions = { + entryPoints: ['src/index.bundle.ts'], + bundle: true, + format: 'esm', + platform: 'browser', + tsconfig: 'tsconfig.lib.json', + plugins: [transformTaggedTemplates()], +}; + +await build({ + ...sharedOptions, + outfile: 'dist/web-components.js', +}); + +await build({ + ...sharedOptions, + outfile: 'dist/web-components.min.js', + minify: true, +}); diff --git a/packages/web-components/src/_docs/developer/migration.mdx b/packages/web-components/src/_docs/developer/migration.mdx index 557135132841e..1795d628d2779 100644 --- a/packages/web-components/src/_docs/developer/migration.mdx +++ b/packages/web-components/src/_docs/developer/migration.mdx @@ -218,9 +218,7 @@ Due to web platform labelling constraints of the ShadowDOM, the labelling API fo ### setTheme -A more powerful and simpler set-theme API that allows setting themes at the element level. - -- `setThemeFor()` is deprecated in favor of `setTheme( theme, element )` +- `setTheme()` can set themes such as `setTheme(webLightTheme)` (defaults to document) or `setTheme(webDarkTheme, element)` to theme an element and its children - `setTheme()` can unset themes with `setTheme(null)` or `setTheme( null, element )` ### Case studies diff --git a/packages/web-components/src/index-rollup.ts b/packages/web-components/src/index.bundle.ts similarity index 80% rename from packages/web-components/src/index-rollup.ts rename to packages/web-components/src/index.bundle.ts index 1c8e6dd2d1b8e..70a930cdf27a4 100644 --- a/packages/web-components/src/index-rollup.ts +++ b/packages/web-components/src/index.bundle.ts @@ -40,4 +40,13 @@ import './toggle-button/define.js'; import './tooltip/define.js'; import './tree/define.js'; import './tree-item/define.js'; -export { setTheme } from './theme/set-theme.js'; + +// import setTheme for export on globalThis for CDN +import { setTheme } from './theme/index.js'; + +// Expose all exports from index.ts +export * from './index.js'; + +// Expose setTheme on globalThis for CDN/script-tag consumers +// @ts-expect-error - CDN bundle intentionally sets globals +globalThis.setTheme = setTheme; diff --git a/packages/web-components/src/index.ts b/packages/web-components/src/index.ts index 4acba253a8463..16ce22a0c07ec 100644 --- a/packages/web-components/src/index.ts +++ b/packages/web-components/src/index.ts @@ -310,7 +310,7 @@ export { TextWeight, } from './text/index.js'; export * from './theme/design-tokens.js'; -export { setTheme, setThemeFor, type Theme } from './theme/index.js'; +export { setTheme, type Theme } from './theme/index.js'; export { ToggleButton, ToggleButtonAppearance, diff --git a/packages/web-components/src/theme/index.ts b/packages/web-components/src/theme/index.ts index 6982cbda59a2d..e23a0003232d1 100644 --- a/packages/web-components/src/theme/index.ts +++ b/packages/web-components/src/theme/index.ts @@ -384,4 +384,4 @@ export { shadow28Brand, shadow64Brand, } from './design-tokens.js'; -export { setTheme, setThemeFor, type Theme } from './set-theme.js'; +export { setTheme, type Theme } from './set-theme.js'; diff --git a/packages/web-components/src/theme/set-theme.ts b/packages/web-components/src/theme/set-theme.ts index 91acd4743e00d..8776132463a7c 100644 --- a/packages/web-components/src/theme/set-theme.ts +++ b/packages/web-components/src/theme/set-theme.ts @@ -214,11 +214,3 @@ function forceRepaint(element: HTMLElement) { element.style.setProperty(name, currentValue); } - -/** - * @internal - * @deprecated Use `setTheme(theme, element)` instead. - */ -export function setThemeFor(element: HTMLElement, theme: Theme | null) { - setThemePropertiesOnElement(theme, element); -} diff --git a/packages/web-components/test/harness/src/main.ts b/packages/web-components/test/harness/src/main.ts index 2ca1a2fa2d4eb..0299a0b2a56da 100644 --- a/packages/web-components/test/harness/src/main.ts +++ b/packages/web-components/test/harness/src/main.ts @@ -8,7 +8,7 @@ if (!CSS.supports('anchor-name: --foo')) { import { webLightTheme } from '@fluentui/tokens'; import { setTheme } from '../../../src/theme/set-theme.js'; -import '../../../src/index-rollup.js'; +import '../../../src/index.bundle.js'; setTheme(webLightTheme); diff --git a/yarn.lock b/yarn.lock index 6548596d4b514..ded1716795af8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16096,6 +16096,13 @@ parse-json@^5.0.0, parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse-literals@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/parse-literals/-/parse-literals-1.2.1.tgz#2311855a12a6e12434f44eb40fa434c48cc0560f" + integrity sha512-Ml0w104Ph2wwzuRdxrg9booVWsngXbB4bZ5T2z6WyF8b5oaNkUmBiDtahi34yUIpXD8Y13JjAK6UyIyApJ73RQ== + dependencies: + typescript "^2.9.2 || ^3.0.0 || ^4.0.0" + parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" @@ -19643,6 +19650,11 @@ typescript@5.7.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e" integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== +"typescript@^2.9.2 || ^3.0.0 || ^4.0.0": + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + typescript@~5.4.2: version "5.4.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" From cbb489024b835935ddf948454ffd57973b8a3081 Mon Sep 17 00:00:00 2001 From: Chris Holt <13071055+chrisdholt@users.noreply.github.com> Date: Thu, 7 May 2026 00:36:18 -0700 Subject: [PATCH 02/11] update to support a slim bundle and an everything bundle --- packages/web-components/package.json | 15 ++++-- packages/web-components/scripts/bundle.js | 16 +++++- .../src/_docs/developer/migration.mdx | 7 +++ .../web-components/src/index-all.bundle.ts | 52 +++++++++++++++++++ packages/web-components/src/index.bundle.ts | 3 -- 5 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 packages/web-components/src/index-all.bundle.ts diff --git a/packages/web-components/package.json b/packages/web-components/package.json index c1f133893ec27..242271bcb7b59 100644 --- a/packages/web-components/package.json +++ b/packages/web-components/package.json @@ -30,13 +30,15 @@ ], "exports": { ".": "./dist/esm/index.js", - "./web-components.js": { + "./web-components.js": "./dist/web-components.js", + "./web-components.min.js": "./dist/web-components.min.js", + "./web-components-all.js": { "types": "./dist/web-components.d.ts", - "default": "./dist/web-components.js" + "default": "./dist/web-components-all.js" }, - "./web-components.min.js": { + "./web-components-all.min.js": { "types": "./dist/web-components.d.ts", - "default": "./dist/web-components.min.js" + "default": "./dist/web-components-all.min.js" }, "./utils/behaviors/*.js": "./dist/esm/utils/behaviors/*.js", "./utils/*.js": "./dist/esm/utils/*.js", @@ -56,9 +58,12 @@ "sideEffects": [ "define.*", "index.bundle.*", + "index-all.bundle.*", "./dist/esm/**/define.js", "./dist/web-components.js", - "./dist/web-components.min.js" + "./dist/web-components.min.js", + "./dist/web-components-all.js", + "./dist/web-components-all.min.js" ], "scripts": { "analyze": "cem analyze", diff --git a/packages/web-components/scripts/bundle.js b/packages/web-components/scripts/bundle.js index aee456649fc68..123f41eccac8e 100644 --- a/packages/web-components/scripts/bundle.js +++ b/packages/web-components/scripts/bundle.js @@ -53,7 +53,6 @@ function transformTaggedTemplates() { } const sharedOptions = { - entryPoints: ['src/index.bundle.ts'], bundle: true, format: 'esm', platform: 'browser', @@ -63,11 +62,26 @@ const sharedOptions = { await build({ ...sharedOptions, + entryPoints: ['src/index.bundle.ts'], outfile: 'dist/web-components.js', }); await build({ ...sharedOptions, + entryPoints: ['src/index.bundle.ts'], outfile: 'dist/web-components.min.js', minify: true, }); + +await build({ + ...sharedOptions, + entryPoints: ['src/index-all.bundle.ts'], + outfile: 'dist/web-components-all.js', +}); + +await build({ + ...sharedOptions, + entryPoints: ['src/index-all.bundle.ts'], + outfile: 'dist/web-components-all.min.js', + minify: true, +}); diff --git a/packages/web-components/src/_docs/developer/migration.mdx b/packages/web-components/src/_docs/developer/migration.mdx index 1795d628d2779..cb9deb59ac1f5 100644 --- a/packages/web-components/src/_docs/developer/migration.mdx +++ b/packages/web-components/src/_docs/developer/migration.mdx @@ -216,6 +216,13 @@ Due to web platform labelling constraints of the ShadowDOM, the labelling API fo ``` +### Bundles + +The package ships two CDN-ready bundles, each available in minified and non-minified versions: + +- **`web-components.js`** / **`web-components.min.js`** — Registers all components and exposes `setTheme` on `globalThis`. This is the recommended bundle for most CDN and script-tag consumers. +- **`web-components-all.js`** / **`web-components-all.min.js`** — Everything in the standard bundle, plus all named exports from the package (base classes, templates, styles, design tokens, and utilities). Use this if you need programmatic access to the full API surface from a CDN context. + ### setTheme - `setTheme()` can set themes such as `setTheme(webLightTheme)` (defaults to document) or `setTheme(webDarkTheme, element)` to theme an element and its children diff --git a/packages/web-components/src/index-all.bundle.ts b/packages/web-components/src/index-all.bundle.ts new file mode 100644 index 0000000000000..70a930cdf27a4 --- /dev/null +++ b/packages/web-components/src/index-all.bundle.ts @@ -0,0 +1,52 @@ +import './accordion-item/define.js'; +import './accordion/define.js'; +import './anchor-button/define.js'; +import './avatar/define.js'; +import './badge/define.js'; +import './button/define.js'; +import './checkbox/define.js'; +import './compound-button/define.js'; +import './counter-badge/define.js'; +import './dialog/define.js'; +import './dialog-body/define.js'; +import './divider/define.js'; +import './drawer/define.js'; +import './drawer-body/define.js'; +import './dropdown/define.js'; +import './field/define.js'; +import './image/define.js'; +import './label/define.js'; +import './link/define.js'; +import './listbox/define.js'; +import './menu-button/define.js'; +import './menu-item/define.js'; +import './menu-list/define.js'; +import './menu/define.js'; +import './message-bar/define.js'; +import './option/define.js'; +import './progress-bar/define.js'; +import './radio-group/define.js'; +import './radio/define.js'; +import './rating-display/define.js'; +import './slider/define.js'; +import './spinner/define.js'; +import './switch/define.js'; +import './tab/define.js'; +import './tablist/define.js'; +import './textarea/define.js'; +import './text-input/define.js'; +import './text/define.js'; +import './toggle-button/define.js'; +import './tooltip/define.js'; +import './tree/define.js'; +import './tree-item/define.js'; + +// import setTheme for export on globalThis for CDN +import { setTheme } from './theme/index.js'; + +// Expose all exports from index.ts +export * from './index.js'; + +// Expose setTheme on globalThis for CDN/script-tag consumers +// @ts-expect-error - CDN bundle intentionally sets globals +globalThis.setTheme = setTheme; diff --git a/packages/web-components/src/index.bundle.ts b/packages/web-components/src/index.bundle.ts index 70a930cdf27a4..5e5be657d6940 100644 --- a/packages/web-components/src/index.bundle.ts +++ b/packages/web-components/src/index.bundle.ts @@ -44,9 +44,6 @@ import './tree-item/define.js'; // import setTheme for export on globalThis for CDN import { setTheme } from './theme/index.js'; -// Expose all exports from index.ts -export * from './index.js'; - // Expose setTheme on globalThis for CDN/script-tag consumers // @ts-expect-error - CDN bundle intentionally sets globals globalThis.setTheme = setTheme; From e4d2a9636b8d468b9246d890641f4ae945989d1e Mon Sep 17 00:00:00 2001 From: Chris Holt <13071055+chrisdholt@users.noreply.github.com> Date: Thu, 7 May 2026 11:39:22 -0700 Subject: [PATCH 03/11] revert back to rollup --- packages/web-components/.storybook/main.cjs | 2 +- .../web-components/.storybook/preview.mjs | 2 +- packages/web-components/package.json | 9 +- packages/web-components/rollup.config.js | 60 +++++++++++++ packages/web-components/scripts/bundle.js | 87 ------------------- ...ndex-all.bundle.ts => index-all-rollup.ts} | 0 .../src/{index.bundle.ts => index-rollup.ts} | 0 .../web-components/test/harness/src/main.ts | 2 +- yarn.lock | 12 --- 9 files changed, 67 insertions(+), 107 deletions(-) create mode 100644 packages/web-components/rollup.config.js delete mode 100644 packages/web-components/scripts/bundle.js rename packages/web-components/src/{index-all.bundle.ts => index-all-rollup.ts} (100%) rename packages/web-components/src/{index.bundle.ts => index-rollup.ts} (100%) diff --git a/packages/web-components/.storybook/main.cjs b/packages/web-components/.storybook/main.cjs index 5f72e881c974e..70cc584dac55f 100644 --- a/packages/web-components/.storybook/main.cjs +++ b/packages/web-components/.storybook/main.cjs @@ -59,7 +59,7 @@ function createTypeScriptAliases(configPath) { /** * Creates a Vite plugin that resolves .ts files when imported with .js extension. * This matches webpack's extensionAlias behavior and is needed for imports like - * '../src/index.bundle.js' to work in production builds. + * '../src/index-rollup.js' to work in production builds. * @returns {object} Vite plugin object */ function createResolveTsAsJsPlugin() { diff --git a/packages/web-components/.storybook/preview.mjs b/packages/web-components/.storybook/preview.mjs index 7e6d490f5b34e..3a2b5df2aa4c8 100644 --- a/packages/web-components/.storybook/preview.mjs +++ b/packages/web-components/.storybook/preview.mjs @@ -3,7 +3,7 @@ import * as prettier from 'prettier'; import prettierPluginHTML from 'prettier/parser-html.js'; import webcomponentsTheme from './theme.mjs'; -import '../src/index.bundle.js'; +import '../src/index-rollup.js'; import './docs-root.css'; const FAST_EXPRESSION_COMMENTS = //g; // Matches comments that contain FAST expressions diff --git a/packages/web-components/package.json b/packages/web-components/package.json index 242271bcb7b59..009000c70ea96 100644 --- a/packages/web-components/package.json +++ b/packages/web-components/package.json @@ -57,8 +57,8 @@ }, "sideEffects": [ "define.*", - "index.bundle.*", - "index-all.bundle.*", + "index-rollup.*", + "index-all-rollup.*", "./dist/esm/**/define.js", "./dist/web-components.js", "./dist/web-components.min.js", @@ -74,7 +74,7 @@ "compile:benchmark": "rollup -c rollup.bench.js", "clean": "node ./scripts/clean dist", "generate-api": "api-extractor run --local", - "build": "yarn compile && node scripts/bundle.js && yarn generate-api && yarn analyze", + "build": "yarn compile && yarn rollup -c && yarn generate-api && yarn analyze", "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", "format": "prettier -w src/**/*.{ts,html} src/*.{ts,html} --ignore-path ../../.prettierignore", @@ -98,8 +98,7 @@ "@wc-toolkit/cem-inheritance": "1.2.2", "@wc-toolkit/module-path-resolver": "1.0.0", "@wc-toolkit/type-parser": "1.0.3", - "chromedriver": "^125.0.0", - "parse-literals": "^1.2.1" + "chromedriver": "^125.0.0" }, "dependencies": { "@fluentui/tokens": "1.0.0-alpha.23", diff --git a/packages/web-components/rollup.config.js b/packages/web-components/rollup.config.js new file mode 100644 index 0000000000000..0cc26644be4c3 --- /dev/null +++ b/packages/web-components/rollup.config.js @@ -0,0 +1,60 @@ +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import commonJS from 'rollup-plugin-commonjs'; +import esbuild, { minify } from 'rollup-plugin-esbuild'; +import transformTaggedTemplate from 'rollup-plugin-transform-tagged-template'; +import { transformCSSFragment, transformHTMLFragment } from './scripts/transform-fragments.js'; + +const parserOptions = { + sourceType: 'module', +}; + +const plugins = [ + nodeResolve({ browser: true }), + commonJS(), + esbuild({ + tsconfig: './tsconfig.lib.json', + }), + transformTaggedTemplate({ + tagsToProcess: ['css'], + transformer: transformCSSFragment, + parserOptions, + }), + transformTaggedTemplate({ + tagsToProcess: ['html'], + transformer: transformHTMLFragment, + parserOptions, + }), +]; + +export default [ + { + input: 'src/index-rollup.ts', + output: [ + { + file: 'dist/web-components.js', + format: 'esm', + }, + { + file: 'dist/web-components.min.js', + format: 'esm', + plugins: [minify()], + }, + ], + plugins, + }, + { + input: 'src/index-all-rollup.ts', + output: [ + { + file: 'dist/web-components-all.js', + format: 'esm', + }, + { + file: 'dist/web-components-all.min.js', + format: 'esm', + plugins: [minify()], + }, + ], + plugins, + }, +]; diff --git a/packages/web-components/scripts/bundle.js b/packages/web-components/scripts/bundle.js deleted file mode 100644 index 123f41eccac8e..0000000000000 --- a/packages/web-components/scripts/bundle.js +++ /dev/null @@ -1,87 +0,0 @@ -import { build } from 'esbuild'; -import { readFile } from 'fs/promises'; -import { parseLiterals } from 'parse-literals'; -import { transformCSSFragment, transformHTMLFragment } from './transform-fragments.js'; - -const transforms = { - css: transformCSSFragment, - html: transformHTMLFragment, -}; - -/** - * esbuild plugin that minifies tagged template literal content (css`...` and html`...`) - * using AST-based parsing from `parse-literals` to correctly handle nested templates, - * with the existing transform functions for CSS and HTML minification. - */ -function transformTaggedTemplates() { - return { - name: 'transform-tagged-templates', - setup(build) { - build.onLoad({ filter: /src\/.*\.ts$/ }, async args => { - const source = await readFile(args.path, 'utf8'); - const literals = parseLiterals(source); - - // Collect all replacements sorted by position (descending) to splice from end to start - const replacements = []; - for (const literal of literals) { - const transform = transforms[literal.tag]; - if (!transform) continue; - - for (const part of literal.parts) { - const transformed = transform(part.text); - if (transformed !== part.text) { - replacements.push({ start: part.start, end: part.end, text: transformed }); - } - } - } - - if (replacements.length === 0) { - return { contents: source, loader: 'ts' }; - } - - // Apply replacements from end to start to preserve positions - replacements.sort((a, b) => b.start - a.start); - let result = source; - for (const { start, end, text } of replacements) { - result = result.slice(0, start) + text + result.slice(end); - } - - return { contents: result, loader: 'ts' }; - }); - }, - }; -} - -const sharedOptions = { - bundle: true, - format: 'esm', - platform: 'browser', - tsconfig: 'tsconfig.lib.json', - plugins: [transformTaggedTemplates()], -}; - -await build({ - ...sharedOptions, - entryPoints: ['src/index.bundle.ts'], - outfile: 'dist/web-components.js', -}); - -await build({ - ...sharedOptions, - entryPoints: ['src/index.bundle.ts'], - outfile: 'dist/web-components.min.js', - minify: true, -}); - -await build({ - ...sharedOptions, - entryPoints: ['src/index-all.bundle.ts'], - outfile: 'dist/web-components-all.js', -}); - -await build({ - ...sharedOptions, - entryPoints: ['src/index-all.bundle.ts'], - outfile: 'dist/web-components-all.min.js', - minify: true, -}); diff --git a/packages/web-components/src/index-all.bundle.ts b/packages/web-components/src/index-all-rollup.ts similarity index 100% rename from packages/web-components/src/index-all.bundle.ts rename to packages/web-components/src/index-all-rollup.ts diff --git a/packages/web-components/src/index.bundle.ts b/packages/web-components/src/index-rollup.ts similarity index 100% rename from packages/web-components/src/index.bundle.ts rename to packages/web-components/src/index-rollup.ts diff --git a/packages/web-components/test/harness/src/main.ts b/packages/web-components/test/harness/src/main.ts index 0299a0b2a56da..2ca1a2fa2d4eb 100644 --- a/packages/web-components/test/harness/src/main.ts +++ b/packages/web-components/test/harness/src/main.ts @@ -8,7 +8,7 @@ if (!CSS.supports('anchor-name: --foo')) { import { webLightTheme } from '@fluentui/tokens'; import { setTheme } from '../../../src/theme/set-theme.js'; -import '../../../src/index.bundle.js'; +import '../../../src/index-rollup.js'; setTheme(webLightTheme); diff --git a/yarn.lock b/yarn.lock index ded1716795af8..6548596d4b514 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16096,13 +16096,6 @@ parse-json@^5.0.0, parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse-literals@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/parse-literals/-/parse-literals-1.2.1.tgz#2311855a12a6e12434f44eb40fa434c48cc0560f" - integrity sha512-Ml0w104Ph2wwzuRdxrg9booVWsngXbB4bZ5T2z6WyF8b5oaNkUmBiDtahi34yUIpXD8Y13JjAK6UyIyApJ73RQ== - dependencies: - typescript "^2.9.2 || ^3.0.0 || ^4.0.0" - parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" @@ -19650,11 +19643,6 @@ typescript@5.7.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e" integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== -"typescript@^2.9.2 || ^3.0.0 || ^4.0.0": - version "4.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" - integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== - typescript@~5.4.2: version "5.4.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" From 29e5e1f6c2c26f91cb9a165050cc0d3d1e6797fa Mon Sep 17 00:00:00 2001 From: Chris Holt <13071055+chrisdholt@users.noreply.github.com> Date: Thu, 7 May 2026 11:47:37 -0700 Subject: [PATCH 04/11] remove use of setTheme in vr tests --- .../src/utilities/WCThemeDecorator.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/vr-tests-web-components/src/utilities/WCThemeDecorator.tsx b/apps/vr-tests-web-components/src/utilities/WCThemeDecorator.tsx index 0e0a5a739d930..9b9733bc06d80 100644 --- a/apps/vr-tests-web-components/src/utilities/WCThemeDecorator.tsx +++ b/apps/vr-tests-web-components/src/utilities/WCThemeDecorator.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import type { Decorator, StoryFn } from '@storybook/react-webpack5'; import { FASTElement, customElement, html, attr } from '@microsoft/fast-element'; import { teamsLightTheme, teamsDarkTheme, webLightTheme, webDarkTheme } from '@fluentui/tokens'; -import { setThemeFor } from '@fluentui/web-components'; +import { setTheme } from '@fluentui/web-components'; const themes = [ { id: 'web-light', label: 'Web Light', theme: webLightTheme }, @@ -36,7 +36,7 @@ export class FASTThemeDecorator extends FASTElement { connectedCallback() { super.connectedCallback(); const theme = themes.find(value => value.id === this.fluentTheme)?.theme ?? defaultTheme.theme; - setThemeFor(this, theme); + setTheme(theme); } } From b17060c54e24c0c90c3883f200ba79e754cc7270 Mon Sep 17 00:00:00 2001 From: Chris Holt <13071055+chrisdholt@users.noreply.github.com> Date: Thu, 7 May 2026 12:50:56 -0700 Subject: [PATCH 05/11] ignore setTheme types in storybook preview --- packages/web-components/.storybook/preview.mjs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/web-components/.storybook/preview.mjs b/packages/web-components/.storybook/preview.mjs index 3a2b5df2aa4c8..e3db37c0c2c14 100644 --- a/packages/web-components/.storybook/preview.mjs +++ b/packages/web-components/.storybook/preview.mjs @@ -16,8 +16,10 @@ const themes = { }; // This is needed in Playwright. +// @ts-ignore - setTheme is set on globalThis by the index-rollup bundle Object.defineProperty(window, 'setTheme', { value: setTheme }); +// @ts-ignore - setTheme is set on globalThis by the index-rollup bundle setTheme(themes['web-light']); export const globalTypes = { @@ -62,6 +64,7 @@ export const decorators = [ * @type {keyof typeof themes} */ const theme = context.globals.theme || 'web-light'; + // @ts-ignore - setTheme is set on globalThis by the index-rollup bundle setTheme(themes[theme]); // Set direction on the document body From f6ec8426343a77f0595f7c76ff931aada60571de Mon Sep 17 00:00:00 2001 From: Chris Holt <13071055+chrisdholt@users.noreply.github.com> Date: Thu, 7 May 2026 14:26:17 -0700 Subject: [PATCH 06/11] use fast-tagged-templates dep --- packages/web-components/package.json | 3 +- packages/web-components/rollup.config.js | 18 ++--------- yarn.lock | 38 ++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/packages/web-components/package.json b/packages/web-components/package.json index 009000c70ea96..1a13e2d7b9ec4 100644 --- a/packages/web-components/package.json +++ b/packages/web-components/package.json @@ -98,7 +98,8 @@ "@wc-toolkit/cem-inheritance": "1.2.2", "@wc-toolkit/module-path-resolver": "1.0.0", "@wc-toolkit/type-parser": "1.0.3", - "chromedriver": "^125.0.0" + "chromedriver": "^125.0.0", + "rollup-plugin-fast-tagged-templates": "^1.0.2" }, "dependencies": { "@fluentui/tokens": "1.0.0-alpha.23", diff --git a/packages/web-components/rollup.config.js b/packages/web-components/rollup.config.js index 0cc26644be4c3..9445148e3b6db 100644 --- a/packages/web-components/rollup.config.js +++ b/packages/web-components/rollup.config.js @@ -1,12 +1,7 @@ import { nodeResolve } from '@rollup/plugin-node-resolve'; import commonJS from 'rollup-plugin-commonjs'; import esbuild, { minify } from 'rollup-plugin-esbuild'; -import transformTaggedTemplate from 'rollup-plugin-transform-tagged-template'; -import { transformCSSFragment, transformHTMLFragment } from './scripts/transform-fragments.js'; - -const parserOptions = { - sourceType: 'module', -}; +import fastTaggedTemplates from 'rollup-plugin-fast-tagged-templates'; const plugins = [ nodeResolve({ browser: true }), @@ -14,16 +9,7 @@ const plugins = [ esbuild({ tsconfig: './tsconfig.lib.json', }), - transformTaggedTemplate({ - tagsToProcess: ['css'], - transformer: transformCSSFragment, - parserOptions, - }), - transformTaggedTemplate({ - tagsToProcess: ['html'], - transformer: transformHTMLFragment, - parserOptions, - }), + fastTaggedTemplates(), ]; export default [ diff --git a/yarn.lock b/yarn.lock index 6548596d4b514..d54c0c63d8973 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7330,7 +7330,7 @@ clean-css@4.2.3: dependencies: source-map "~0.6.0" -clean-css@^5.2.2: +clean-css@^5.2.2, clean-css@~5.3.2: version "5.3.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" integrity sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg== @@ -9052,7 +9052,7 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== -entities@^4.2.0, entities@^4.5.0: +entities@^4.2.0, entities@^4.4.0, entities@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== @@ -11469,6 +11469,19 @@ html-minifier-terser@^6.0.2: relateurl "^0.2.7" terser "^5.10.0" +html-minifier-terser@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz#18752e23a2f0ed4b0f550f217bb41693e975b942" + integrity sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA== + dependencies: + camel-case "^4.1.2" + clean-css "~5.3.2" + commander "^10.0.0" + entities "^4.4.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.15.1" + html-react-parser@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/html-react-parser/-/html-react-parser-4.0.0.tgz#a727be4539ad85b133a5071f97b8c2f835a55bdf" @@ -13991,7 +14004,7 @@ magic-string@^0.25.2: dependencies: sourcemap-codec "^1.4.4" -magic-string@^0.30.17, magic-string@^0.30.5: +magic-string@^0.30.12, magic-string@^0.30.17, magic-string@^0.30.5: version "0.30.21" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== @@ -17576,6 +17589,15 @@ rollup-plugin-esbuild@6.1.1: es-module-lexer "^1.3.1" get-tsconfig "^4.7.2" +rollup-plugin-fast-tagged-templates@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-fast-tagged-templates/-/rollup-plugin-fast-tagged-templates-1.0.2.tgz#ec4dae2819516a4e0aafa8478e85d6bc9c3a0654" + integrity sha512-faCdx89y6ggN3lcAw1YLlEszde+rcZT/EhiBQZlsqb8017jLJt4+tgZwVo0e4NF/QOa78UEeY+A2NsCj3bf2UA== + dependencies: + estree-walker "^3.0.3" + html-minifier-terser "^7.2.0" + magic-string "^0.30.12" + rollup-plugin-node-resolve@5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz#730f93d10ed202473b1fb54a5997a7db8c6d8523" @@ -19105,6 +19127,16 @@ terser@^4.6.2: source-map "~0.6.1" source-map-support "~0.5.12" +terser@^5.15.1: + version "5.47.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.47.1.tgz#99b298e51bc41214304847de1429ec92fd1f7648" + integrity sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.15.0" + commander "^2.20.0" + source-map-support "~0.5.20" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" From c444716cb1ecdf4e1b9f385355e7feecc41115ab Mon Sep 17 00:00:00 2001 From: Chris Holt <13071055+chrisdholt@users.noreply.github.com> Date: Thu, 7 May 2026 14:38:59 -0700 Subject: [PATCH 07/11] deduplicate yarn.lock --- yarn.lock | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/yarn.lock b/yarn.lock index d54c0c63d8973..629621be4153c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19108,7 +19108,7 @@ terser-webpack-plugin@^5.3.1, terser-webpack-plugin@^5.3.11: serialize-javascript "^6.0.2" terser "^5.31.1" -terser@5.39.1, terser@^5.10.0, terser@^5.16.0, terser@^5.26.0, terser@^5.31.1: +terser@5.39.1, terser@^5.10.0, terser@^5.15.1, terser@^5.16.0, terser@^5.26.0, terser@^5.31.1: version "5.39.1" resolved "https://registry.yarnpkg.com/terser/-/terser-5.39.1.tgz#1c80e6bde2b362c6f9f3e79e295c228a3882d983" integrity sha512-Mm6+uad0ZuDtcV8/4uOZQDQ8RuiC5Pu+iZRedJtF7yA/27sPL7d++In/AJKpWZlU3SYMPPkVfwetn6sgZ66pUA== @@ -19127,16 +19127,6 @@ terser@^4.6.2: source-map "~0.6.1" source-map-support "~0.5.12" -terser@^5.15.1: - version "5.47.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.47.1.tgz#99b298e51bc41214304847de1429ec92fd1f7648" - integrity sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw== - dependencies: - "@jridgewell/source-map" "^0.3.3" - acorn "^8.15.0" - commander "^2.20.0" - source-map-support "~0.5.20" - test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" From d656f4ea2943a8b612a958b8023bee48fff3fd6f Mon Sep 17 00:00:00 2001 From: Chris Holt <13071055+chrisdholt@users.noreply.github.com> Date: Thu, 7 May 2026 15:11:25 -0700 Subject: [PATCH 08/11] remove transform fragments --- .../scripts/transform-fragments.js | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 packages/web-components/scripts/transform-fragments.js diff --git a/packages/web-components/scripts/transform-fragments.js b/packages/web-components/scripts/transform-fragments.js deleted file mode 100644 index 8db1b711c9881..0000000000000 --- a/packages/web-components/scripts/transform-fragments.js +++ /dev/null @@ -1,29 +0,0 @@ -/* eslint-disable @typescript-eslint/explicit-function-return-type, @typescript-eslint/typedef */ - -/** - * Reduces extra spaces in HTML tagged templates. - * - * @param {string} data - the fragment value - * @returns string - */ -export function transformHTMLFragment(data) { - data = data.replace(/\s*([<>])\s*/g, '$1'); // remove spaces before and after angle brackets - return data.replace(/\s{2,}/g, ' '); // Collapse all sequences to 1 space -} - -/** - * Reduces extra spaces in CSS tagged templates. - * - * Breakdown of this regex: - * (?:\s*\/\*(?:.|\s)+?\*\/\s*) Remove comments (non-capturing) - * (?:;)\s+(?=\}) Remove semicolons and spaces followed by property list end (non-capturing) - * \s+(?=\{) Remove spaces before property list start (non-capturing) - * (?<=:)\s+ Remove spaces after property declarations (non-capturing) - * \s*([{};,])\s* Remove extra spaces before and after braces, semicolons, and commas (captures) - * - * @param {string} data - the fragment value - * @returns string - */ -export function transformCSSFragment(data) { - return data.replace(/(?:\s*\/\*(?:.|\s)+?\*\/\s*)|(?:;)\s+(?=\})|\s+(?=\{)|(?<=:)\s+|\s*([{};,])\s*/g, '$1'); -} From e088b3f937030f12290836b2240e95ad7654c6f0 Mon Sep 17 00:00:00 2001 From: Chris Holt <13071055+chrisdholt@users.noreply.github.com> Date: Thu, 7 May 2026 15:22:47 -0700 Subject: [PATCH 09/11] move side-effectul component registrations to new define-all.js file --- packages/web-components/package.json | 1 + packages/web-components/src/define-all.ts | 42 ++++++++++++++++++ .../web-components/src/index-all-rollup.ts | 43 +------------------ packages/web-components/src/index-rollup.ts | 43 +------------------ 4 files changed, 45 insertions(+), 84 deletions(-) create mode 100644 packages/web-components/src/define-all.ts diff --git a/packages/web-components/package.json b/packages/web-components/package.json index 1a13e2d7b9ec4..2619210a9e0f9 100644 --- a/packages/web-components/package.json +++ b/packages/web-components/package.json @@ -57,6 +57,7 @@ }, "sideEffects": [ "define.*", + "define-all.*", "index-rollup.*", "index-all-rollup.*", "./dist/esm/**/define.js", diff --git a/packages/web-components/src/define-all.ts b/packages/web-components/src/define-all.ts new file mode 100644 index 0000000000000..9835d0023159e --- /dev/null +++ b/packages/web-components/src/define-all.ts @@ -0,0 +1,42 @@ +import './accordion-item/define.js'; +import './accordion/define.js'; +import './anchor-button/define.js'; +import './avatar/define.js'; +import './badge/define.js'; +import './button/define.js'; +import './checkbox/define.js'; +import './compound-button/define.js'; +import './counter-badge/define.js'; +import './dialog/define.js'; +import './dialog-body/define.js'; +import './divider/define.js'; +import './drawer/define.js'; +import './drawer-body/define.js'; +import './dropdown/define.js'; +import './field/define.js'; +import './image/define.js'; +import './label/define.js'; +import './link/define.js'; +import './listbox/define.js'; +import './menu-button/define.js'; +import './menu-item/define.js'; +import './menu-list/define.js'; +import './menu/define.js'; +import './message-bar/define.js'; +import './option/define.js'; +import './progress-bar/define.js'; +import './radio-group/define.js'; +import './radio/define.js'; +import './rating-display/define.js'; +import './slider/define.js'; +import './spinner/define.js'; +import './switch/define.js'; +import './tab/define.js'; +import './tablist/define.js'; +import './textarea/define.js'; +import './text-input/define.js'; +import './text/define.js'; +import './toggle-button/define.js'; +import './tooltip/define.js'; +import './tree/define.js'; +import './tree-item/define.js'; diff --git a/packages/web-components/src/index-all-rollup.ts b/packages/web-components/src/index-all-rollup.ts index 70a930cdf27a4..b1adaf9202010 100644 --- a/packages/web-components/src/index-all-rollup.ts +++ b/packages/web-components/src/index-all-rollup.ts @@ -1,45 +1,4 @@ -import './accordion-item/define.js'; -import './accordion/define.js'; -import './anchor-button/define.js'; -import './avatar/define.js'; -import './badge/define.js'; -import './button/define.js'; -import './checkbox/define.js'; -import './compound-button/define.js'; -import './counter-badge/define.js'; -import './dialog/define.js'; -import './dialog-body/define.js'; -import './divider/define.js'; -import './drawer/define.js'; -import './drawer-body/define.js'; -import './dropdown/define.js'; -import './field/define.js'; -import './image/define.js'; -import './label/define.js'; -import './link/define.js'; -import './listbox/define.js'; -import './menu-button/define.js'; -import './menu-item/define.js'; -import './menu-list/define.js'; -import './menu/define.js'; -import './message-bar/define.js'; -import './option/define.js'; -import './progress-bar/define.js'; -import './radio-group/define.js'; -import './radio/define.js'; -import './rating-display/define.js'; -import './slider/define.js'; -import './spinner/define.js'; -import './switch/define.js'; -import './tab/define.js'; -import './tablist/define.js'; -import './textarea/define.js'; -import './text-input/define.js'; -import './text/define.js'; -import './toggle-button/define.js'; -import './tooltip/define.js'; -import './tree/define.js'; -import './tree-item/define.js'; +import './define-all.js'; // import setTheme for export on globalThis for CDN import { setTheme } from './theme/index.js'; diff --git a/packages/web-components/src/index-rollup.ts b/packages/web-components/src/index-rollup.ts index 5e5be657d6940..8eb3870858b3e 100644 --- a/packages/web-components/src/index-rollup.ts +++ b/packages/web-components/src/index-rollup.ts @@ -1,45 +1,4 @@ -import './accordion-item/define.js'; -import './accordion/define.js'; -import './anchor-button/define.js'; -import './avatar/define.js'; -import './badge/define.js'; -import './button/define.js'; -import './checkbox/define.js'; -import './compound-button/define.js'; -import './counter-badge/define.js'; -import './dialog/define.js'; -import './dialog-body/define.js'; -import './divider/define.js'; -import './drawer/define.js'; -import './drawer-body/define.js'; -import './dropdown/define.js'; -import './field/define.js'; -import './image/define.js'; -import './label/define.js'; -import './link/define.js'; -import './listbox/define.js'; -import './menu-button/define.js'; -import './menu-item/define.js'; -import './menu-list/define.js'; -import './menu/define.js'; -import './message-bar/define.js'; -import './option/define.js'; -import './progress-bar/define.js'; -import './radio-group/define.js'; -import './radio/define.js'; -import './rating-display/define.js'; -import './slider/define.js'; -import './spinner/define.js'; -import './switch/define.js'; -import './tab/define.js'; -import './tablist/define.js'; -import './textarea/define.js'; -import './text-input/define.js'; -import './text/define.js'; -import './toggle-button/define.js'; -import './tooltip/define.js'; -import './tree/define.js'; -import './tree-item/define.js'; +import './define-all.js'; // import setTheme for export on globalThis for CDN import { setTheme } from './theme/index.js'; From a56f50d0891d21b924690cb099e093a9f5b907e6 Mon Sep 17 00:00:00 2001 From: Chris Holt <13071055+chrisdholt@users.noreply.github.com> Date: Fri, 8 May 2026 09:48:49 -0700 Subject: [PATCH 10/11] move setTheme to globalThis.Fluent --- packages/web-components/.storybook/preview.mjs | 12 ++++++------ .../web-components/src/_docs/developer/migration.mdx | 2 +- packages/web-components/src/index-all-rollup.ts | 4 ++-- packages/web-components/src/index-rollup.ts | 4 ++-- packages/web-components/test/harness/src/main.ts | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/web-components/.storybook/preview.mjs b/packages/web-components/.storybook/preview.mjs index e3db37c0c2c14..2913b43e5b12c 100644 --- a/packages/web-components/.storybook/preview.mjs +++ b/packages/web-components/.storybook/preview.mjs @@ -16,11 +16,11 @@ const themes = { }; // This is needed in Playwright. -// @ts-ignore - setTheme is set on globalThis by the index-rollup bundle -Object.defineProperty(window, 'setTheme', { value: setTheme }); +// @ts-ignore - setTheme is set on globalThis.Fluent by the index-rollup bundle +Object.defineProperty(window, 'Fluent', { value: globalThis.Fluent }); -// @ts-ignore - setTheme is set on globalThis by the index-rollup bundle -setTheme(themes['web-light']); +// @ts-ignore - setTheme is set on globalThis.Fluent by the index-rollup bundle +Fluent.setTheme(themes['web-light']); export const globalTypes = { theme: { @@ -64,8 +64,8 @@ export const decorators = [ * @type {keyof typeof themes} */ const theme = context.globals.theme || 'web-light'; - // @ts-ignore - setTheme is set on globalThis by the index-rollup bundle - setTheme(themes[theme]); + // @ts-ignore - setTheme is set on globalThis.Fluent by the index-rollup bundle + Fluent.setTheme(themes[theme]); // Set direction on the document body const dir = context.globals.dir || 'ltr'; diff --git a/packages/web-components/src/_docs/developer/migration.mdx b/packages/web-components/src/_docs/developer/migration.mdx index cb9deb59ac1f5..2974f179848be 100644 --- a/packages/web-components/src/_docs/developer/migration.mdx +++ b/packages/web-components/src/_docs/developer/migration.mdx @@ -220,7 +220,7 @@ Due to web platform labelling constraints of the ShadowDOM, the labelling API fo The package ships two CDN-ready bundles, each available in minified and non-minified versions: -- **`web-components.js`** / **`web-components.min.js`** — Registers all components and exposes `setTheme` on `globalThis`. This is the recommended bundle for most CDN and script-tag consumers. +- **`web-components.js`** / **`web-components.min.js`** — Registers all components and exposes `Fluent.setTheme` on `globalThis`. This is the recommended bundle for most CDN and script-tag consumers. - **`web-components-all.js`** / **`web-components-all.min.js`** — Everything in the standard bundle, plus all named exports from the package (base classes, templates, styles, design tokens, and utilities). Use this if you need programmatic access to the full API surface from a CDN context. ### setTheme diff --git a/packages/web-components/src/index-all-rollup.ts b/packages/web-components/src/index-all-rollup.ts index b1adaf9202010..0c90f4d287b8c 100644 --- a/packages/web-components/src/index-all-rollup.ts +++ b/packages/web-components/src/index-all-rollup.ts @@ -6,6 +6,6 @@ import { setTheme } from './theme/index.js'; // Expose all exports from index.ts export * from './index.js'; -// Expose setTheme on globalThis for CDN/script-tag consumers +// Expose setTheme under Fluent namespace on globalThis for CDN/script-tag consumers // @ts-expect-error - CDN bundle intentionally sets globals -globalThis.setTheme = setTheme; +globalThis.Fluent = { ...globalThis.Fluent, setTheme }; diff --git a/packages/web-components/src/index-rollup.ts b/packages/web-components/src/index-rollup.ts index 8eb3870858b3e..9b35c8eb70f94 100644 --- a/packages/web-components/src/index-rollup.ts +++ b/packages/web-components/src/index-rollup.ts @@ -3,6 +3,6 @@ import './define-all.js'; // import setTheme for export on globalThis for CDN import { setTheme } from './theme/index.js'; -// Expose setTheme on globalThis for CDN/script-tag consumers +// Expose setTheme under Fluent namespace on globalThis for CDN/script-tag consumers // @ts-expect-error - CDN bundle intentionally sets globals -globalThis.setTheme = setTheme; +globalThis.Fluent = { ...globalThis.Fluent, setTheme }; diff --git a/packages/web-components/test/harness/src/main.ts b/packages/web-components/test/harness/src/main.ts index 2ca1a2fa2d4eb..5b8001e3322d5 100644 --- a/packages/web-components/test/harness/src/main.ts +++ b/packages/web-components/test/harness/src/main.ts @@ -12,6 +12,6 @@ import '../../../src/index-rollup.js'; setTheme(webLightTheme); -Object.defineProperty(window, 'setTheme', { - value: setTheme, +Object.defineProperty(window, 'Fluent', { + value: { setTheme }, }); From 2d30680c14536326204dbb5ae42f60f2383bbc4a Mon Sep 17 00:00:00 2001 From: Chris Holt <13071055+chrisdholt@users.noreply.github.com> Date: Fri, 8 May 2026 10:37:11 -0700 Subject: [PATCH 11/11] fix test harness setTheme reference on window --- packages/web-components/test/harness/src/main.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/web-components/test/harness/src/main.ts b/packages/web-components/test/harness/src/main.ts index 5b8001e3322d5..e351575b26499 100644 --- a/packages/web-components/test/harness/src/main.ts +++ b/packages/web-components/test/harness/src/main.ts @@ -12,6 +12,7 @@ import '../../../src/index-rollup.js'; setTheme(webLightTheme); -Object.defineProperty(window, 'Fluent', { - value: { setTheme }, +// Expose directly on window for Playwright test access +Object.defineProperty(window, 'setTheme', { + value: setTheme, });