diff --git a/.changeset/css-exports.md b/.changeset/css-exports.md
new file mode 100644
index 00000000..4cbea343
--- /dev/null
+++ b/.changeset/css-exports.md
@@ -0,0 +1,41 @@
+---
+'@crackle/core': minor
+---
+
+Crackle now supports importing external CSS.
+
+This is useful when consuming packages which come with their own CSS, such as [Pure React Carousel](https://github.com/express-labs/pure-react-carousel).
+
+External CSS can be imported with a side-effect `import`, same as how you would import a JavaScript or TypeScript module:
+
+```tsx
+// src/components/MyComponent.tsx
+import 'package-with-styles/dist/styles.css';
+
+import { Component } from 'package-with-styles';
+
+export const MyComponent = (props) => {
+ ;
+};
+```
+
+The side-effect import will be preserved in the output bundles.
+
+External CSS can also be imported with a CSS `@import` rule:
+
+```css
+/* src/components/MyComponent/third-party.css */
+@import 'package-with-styles/dist/styles.css';
+```
+
+```tsx
+// src/components/MyComponent.tsx
+import './third-party.css';
+
+export const MyComponent = () => {
+ // ...
+};
+```
+
+When importing with a CSS `@import` rule, Crackle will bundle all external CSS into one file and output it to the `dist` directory.
+Package exports will also be updated so consumers can import the bundled CSS.
diff --git a/.eslintignore b/.eslintignore
index c86768c9..6b060393 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -58,6 +58,10 @@ fixtures/with-side-effects/dist
fixtures/with-side-effects/reset
# end managed by crackle
+# managed by crackle
+fixtures/with-styles/dist
+# end managed by crackle
+
# managed by crackle
fixtures/with-vocab/dist
# end managed by crackle
diff --git a/.prettierignore b/.prettierignore
index 0cd1ed68..dea72d6e 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -61,6 +61,10 @@ fixtures/with-side-effects/dist
fixtures/with-side-effects/reset
# end managed by crackle
+# managed by crackle
+fixtures/with-styles/dist
+# end managed by crackle
+
# managed by crackle
fixtures/with-vocab/dist
# end managed by crackle
diff --git a/fixtures/with-styles/.gitignore b/fixtures/with-styles/.gitignore
new file mode 100644
index 00000000..7303c616
--- /dev/null
+++ b/fixtures/with-styles/.gitignore
@@ -0,0 +1,3 @@
+# managed by crackle
+/dist
+# end managed by crackle
diff --git a/fixtures/with-styles/package-with-styles/package.json b/fixtures/with-styles/package-with-styles/package.json
new file mode 100644
index 00000000..6c7072db
--- /dev/null
+++ b/fixtures/with-styles/package-with-styles/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "@sku-fixtures/package-with-styles"
+}
diff --git a/fixtures/with-styles/package-with-styles/styles.css b/fixtures/with-styles/package-with-styles/styles.css
new file mode 100644
index 00000000..77234b20
--- /dev/null
+++ b/fixtures/with-styles/package-with-styles/styles.css
@@ -0,0 +1,4 @@
+.external {
+ display: none;
+ font-size: 9px;
+}
diff --git a/fixtures/with-styles/package.json b/fixtures/with-styles/package.json
new file mode 100644
index 00000000..6ca43b75
--- /dev/null
+++ b/fixtures/with-styles/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "@crackle-fixtures/with-styles",
+ "version": "1.0.0",
+ "private": true,
+ "license": "MIT",
+ "author": "SEEK",
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.mjs",
+ "require": "./dist/index.cjs"
+ },
+ "./dist/style.css": "./dist/style.css",
+ "./package.json": "./package.json"
+ },
+ "main": "./dist/index.cjs",
+ "module": "./dist/index.mjs",
+ "types": "./dist/index.d.ts",
+ "files": [
+ "dist",
+ "init"
+ ],
+ "scripts": {
+ "dev": "crackle dev",
+ "fix": "crackle fix",
+ "package": "crackle package"
+ },
+ "dependencies": {
+ "@crackle-fixtures/package-with-styles": "link:./package-with-styles",
+ "@vanilla-extract/css": "^1.12.0",
+ "react": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.21"
+ }
+}
diff --git a/fixtures/with-styles/src/Component.css.ts b/fixtures/with-styles/src/Component.css.ts
new file mode 100644
index 00000000..8bb67160
--- /dev/null
+++ b/fixtures/with-styles/src/Component.css.ts
@@ -0,0 +1,5 @@
+import { style } from '@vanilla-extract/css';
+
+export const redBorder = style({
+ border: '5px solid red',
+});
diff --git a/fixtures/with-styles/src/Component.tsx b/fixtures/with-styles/src/Component.tsx
new file mode 100644
index 00000000..f4d326fe
--- /dev/null
+++ b/fixtures/with-styles/src/Component.tsx
@@ -0,0 +1,11 @@
+import '@crackle-fixtures/package-with-styles/styles.css';
+
+import './thirdparty.css';
+
+import * as styles from './Component.css';
+
+export default () => (
+
+
+
+);
diff --git a/fixtures/with-styles/src/index.ts b/fixtures/with-styles/src/index.ts
new file mode 100644
index 00000000..efedd0c1
--- /dev/null
+++ b/fixtures/with-styles/src/index.ts
@@ -0,0 +1 @@
+export { default as Component } from './Component';
diff --git a/fixtures/with-styles/src/thirdparty.css b/fixtures/with-styles/src/thirdparty.css
new file mode 100644
index 00000000..4976cc2d
--- /dev/null
+++ b/fixtures/with-styles/src/thirdparty.css
@@ -0,0 +1 @@
+@import '@crackle-fixtures/package-with-styles/styles.css';
diff --git a/packages/core/src/entries/package.ts b/packages/core/src/entries/package.ts
index 8019b3c4..d906e938 100644
--- a/packages/core/src/entries/package.ts
+++ b/packages/core/src/entries/package.ts
@@ -2,8 +2,10 @@ import fs from 'fs/promises';
import path from 'path';
import chalk from 'chalk';
+import type { RollupOutput } from 'rollup';
import { type EnhancedConfig, type PartialConfig, getConfig } from '../config';
+import { distDir } from '../constants';
import { createBundle } from '../package-utils/bundle';
import { createDtsBundle } from '../package-utils/dts';
import { renderPackageJsonValidationError } from '../reporters/package';
@@ -15,7 +17,10 @@ import {
getPackageEntryPoints,
} from '../utils/entry-points';
import { updateGitignore } from '../utils/gitignore';
-import { validatePackageJson } from '../utils/setup-package-json';
+import {
+ updatePackageJsonExports,
+ validatePackageJson,
+} from '../utils/setup-package-json';
import { fix } from './fix';
import { logger } from './logger';
@@ -62,11 +67,12 @@ const build = async (config: EnhancedConfig, packageName: string) => {
label: string,
) => {
logger.info(`⚙️ Creating ${chalk.bold(label)} bundle...`);
- await bundle(config, entries);
+ const result = await bundle(config, entries);
logger.info(`⚙️ Finished creating ${chalk.bold(label)} bundle`);
+ return result;
};
- await Promise.all([
+ const [bundles] = await Promise.all([
withLogging(createBundle, 'esm/cjs'),
withLogging(createDtsBundle, 'dts'),
]);
@@ -75,6 +81,14 @@ const build = async (config: EnhancedConfig, packageName: string) => {
await updateGitignore(config.root, entries);
+ const cssExports = (bundles as RollupOutput[])
+ .flatMap((bundle) => bundle.output)
+ .map((output) => output.fileName)
+ .filter((fileName) => fileName.endsWith('.css'))
+ .map((fileName) => path.join(distDir, fileName));
+
+ await updatePackageJsonExports(config.root, cssExports);
+
logger.info(`✅ Successfully built ${chalk.bold.green(packageName)}!`);
};
diff --git a/packages/core/src/package-utils/bundle.ts b/packages/core/src/package-utils/bundle.ts
index 9e3e268d..d6188c37 100644
--- a/packages/core/src/package-utils/bundle.ts
+++ b/packages/core/src/package-utils/bundle.ts
@@ -3,7 +3,7 @@ import path from 'path';
import { cssFileFilter as vanillaCssFileFilter } from '@vanilla-extract/integration';
import fse from 'fs-extra';
-import type { OutputOptions } from 'rollup';
+import type { OutputOptions, RollupOutput } from 'rollup';
import { normalizePath, build as viteBuild } from 'vite';
import type { EnhancedConfig } from '../config';
@@ -82,7 +82,7 @@ export const createBundle = async (
} satisfies OutputOptions;
};
- await viteBuild({
+ const result = (await viteBuild({
...commonViteConfig,
esbuild: {
jsx: 'automatic',
@@ -105,7 +105,8 @@ export const createBundle = async (
minify: false,
rollupOptions: {
treeshake: {
- moduleSideEffects: 'no-external',
+ // keep only CSS side-effect imports
+ moduleSideEffects: (id, external) => !external || id.endsWith('.css'),
},
output: formats.map((format) => createOutputOptionsForFormat(format)),
onLog(level, log, defaultHandler) {
@@ -114,5 +115,7 @@ export const createBundle = async (
},
},
},
- });
+ })) as RollupOutput[]; // because we know that we're building esm and cjs
+
+ return result;
};
diff --git a/packages/core/src/package-utils/dts.ts b/packages/core/src/package-utils/dts.ts
index 30469174..8fd2c55f 100644
--- a/packages/core/src/package-utils/dts.ts
+++ b/packages/core/src/package-utils/dts.ts
@@ -15,8 +15,11 @@ export const createDtsBundle = async (
const bundle = await rollup({
input: entries.map((entry) => entry.entryPath),
plugins: [
- // patching imports is not needed for dts, as TypeScript can handle it (for now)
- externals(config, 'cjs'),
+ externals(
+ config,
+ 'cjs', // patching imports is not needed for dts, as TypeScript can handle it (for now)
+ /\.css$/, // ignore CSS files
+ ),
dts({
respectExternal: true,
compilerOptions: config.dtsOptions as any,
@@ -41,7 +44,7 @@ export const createDtsBundle = async (
preserveEntrySignatures: 'strict',
});
- await bundle.write({
+ const result = await bundle.write({
...commonOutputOptions(config, entries, 'dts'),
exports: 'named',
format: 'esm',
@@ -55,4 +58,6 @@ export const createDtsBundle = async (
});
await bundle.close();
+
+ return result;
};
diff --git a/packages/core/src/plugins/rollup/externals.ts b/packages/core/src/plugins/rollup/externals.ts
index 29ee2066..098a4bd3 100644
--- a/packages/core/src/plugins/rollup/externals.ts
+++ b/packages/core/src/plugins/rollup/externals.ts
@@ -91,7 +91,11 @@ async function findDependencies(options: ExternalsOptions) {
return packagesById;
}
-export function externals(config: EnhancedConfig, format?: Format): Plugin {
+export function externals(
+ config: EnhancedConfig,
+ format?: Format,
+ forceExternal?: RegExp,
+): Plugin {
const packageRoot = config.root;
const packagePath = path.join(packageRoot, 'package.json');
// eslint-disable-next-line no-sync
@@ -138,12 +142,12 @@ export function externals(config: EnhancedConfig, format?: Format): Plugin {
resolveId: {
order: 'pre',
- async handler(id, ...rest) {
- // `resolveId` is async in Rollup 3
+ async handler(id, importer, hookOptions) {
const resolved = await (plugin as FunctionPluginHooks).resolveId.call(
this,
id,
- ...rest,
+ importer,
+ hookOptions,
);
if (
@@ -166,6 +170,20 @@ export function externals(config: EnhancedConfig, format?: Format): Plugin {
return patched;
}
+
+ if (forceExternal) {
+ const resolvedByRollup = await this.resolve(id, importer, {
+ skipSelf: true,
+ ...hookOptions,
+ });
+ if (resolvedByRollup && forceExternal.test(resolvedByRollup.id)) {
+ return {
+ id: resolvedByRollup.id,
+ external: true,
+ };
+ }
+ }
+
if (!id.match(ABSOLUTE_OR_RELATIVE)) {
logDebugOnce(`Internalized dependency ${id}`);
}
diff --git a/packages/core/src/utils/__snapshots__/setup-package-json.test.ts.snap b/packages/core/src/utils/__snapshots__/setup-package-json.test.ts.snap
index 8cb8112d..09e77c0e 100644
--- a/packages/core/src/utils/__snapshots__/setup-package-json.test.ts.snap
+++ b/packages/core/src/utils/__snapshots__/setup-package-json.test.ts.snap
@@ -98,37 +98,6 @@ Snapshot Diff:
"main": "./dist/index.cjs",
`;
-exports[`diffPackageJson > incorrect package.json > exports out of order > diffs 1`] = `
-[
- {
- "key": "exports",
- },
-]
-`;
-
-exports[`diffPackageJson > incorrect package.json > exports out of order > package.json 1`] = `
-Snapshot Diff:
-- Diff A
-+ Diff B
-
-@@ --- --- @@
- "exports": {
-+ ".": {
-+ "types": "./dist/index.d.ts",
-+ "import": "./dist/index.mjs",
-+ "require": "./dist/index.cjs",
-+ },
- "./css": {
-@@ --- --- @@
- "./package.json": "./package.json",
-- ".": {
-- "types": "./dist/index.d.ts",
-- "import": "./dist/index.mjs",
-- "require": "./dist/index.cjs",
-- },
- },
-`;
-
exports[`diffPackageJson > incorrect package.json > files missing > diffs 1`] = `
[
{
diff --git a/packages/core/src/utils/setup-package-json.test.ts b/packages/core/src/utils/setup-package-json.test.ts
index 278dc5a6..97af44f8 100644
--- a/packages/core/src/utils/setup-package-json.test.ts
+++ b/packages/core/src/utils/setup-package-json.test.ts
@@ -1,14 +1,18 @@
import path from 'path';
+import { fs, vol } from 'memfs';
import { sortPackageJson } from 'sort-package-json';
-import { describe, expect, test } from 'vitest';
+import { beforeEach, describe, expect, test, vi } from 'vitest';
import packageJsonSerializer from '~utils/pkg-serializer';
import { createSerializer } from '~utils/snapshot-diff-serializer';
import type { PackageEntryPoint, PackageJson } from '../types';
import { extensionForFormat } from './files';
-import { diffPackageJson } from './setup-package-json';
+import {
+ diffPackageJson,
+ updatePackageJsonExports,
+} from './setup-package-json';
expect.addSnapshotSerializer(createSerializer({ contextLines: 1 })); // override default config
expect.addSnapshotSerializer(packageJsonSerializer);
@@ -158,23 +162,6 @@ describe('diffPackageJson', () => {
expectSnapshots({ diffs, packageJson, expectedPackageJson });
});
- test('exports out of order', () => {
- const packageJson = structuredClone(correctPackageJson);
- const { '.': index, ...otherExports } = packageJson.exports;
- packageJson.exports = {
- ...otherExports,
- '.': index,
- };
-
- const { diffs, expectedPackageJson } = diffPackageJson(
- packageRoot,
- packageJson,
- entries,
- );
-
- expectSnapshots({ diffs, packageJson, expectedPackageJson });
- });
-
test('files missing', () => {
const packageJson = structuredClone(correctPackageJson);
// @ts-ignore
@@ -352,3 +339,85 @@ describe('diffPackageJson', () => {
});
});
});
+
+// we use a mix of `fs`, `fs/promises` and `fs-extra` across the codebase, so the mocks must cover all of them
+vi.mock('fs', () => ({ default: fs }));
+vi.mock('fs/promises', () => ({ default: fs.promises }));
+vi.mock('fs-extra', async () => {
+ const fse = await vi.importActual('fs-extra');
+ return {
+ default: {
+ ...fs,
+ ...fs.promises,
+ // readJson is not available in `memfs`, but it can use a provided `fs` mock
+ readJson: fse.readJson,
+ },
+ };
+});
+
+describe('updatePackageJsonExports', () => {
+ const packageRoot = '/___';
+
+ beforeEach(() => {
+ vol.reset();
+ vol.fromJSON(
+ {
+ 'package.json': JSON.stringify(
+ {
+ exports: {
+ '.': './dist/index.js',
+ './entry': {
+ import: './dist/entry.mjs',
+ require: './dist/entry.cjs',
+ },
+ './package.json': './package.json',
+ },
+ },
+ null,
+ 2,
+ ),
+ },
+ packageRoot,
+ );
+ });
+
+ test('no exports provided', async () => {
+ await updatePackageJsonExports(packageRoot, []);
+
+ expect(vol.toJSON()).toMatchInlineSnapshot(`
+ {
+ "/___/package.json": "{
+ "exports": {
+ ".": "./dist/index.js",
+ "./entry": {
+ "import": "./dist/entry.mjs",
+ "require": "./dist/entry.cjs"
+ },
+ "./package.json": "./package.json"
+ }
+ }",
+ }
+ `);
+ });
+
+ test('with exports', async () => {
+ await updatePackageJsonExports(packageRoot, ['dist/some/thing.css']);
+
+ expect(vol.toJSON()).toMatchInlineSnapshot(`
+ {
+ "/___/package.json": "{
+ "exports": {
+ ".": "./dist/index.js",
+ "./entry": {
+ "import": "./dist/entry.mjs",
+ "require": "./dist/entry.cjs"
+ },
+ "./dist/some/thing.css": "./dist/some/thing.css",
+ "./package.json": "./package.json"
+ }
+ }
+ ",
+ }
+ `);
+ });
+});
diff --git a/packages/core/src/utils/setup-package-json.ts b/packages/core/src/utils/setup-package-json.ts
index 5d551893..801201e5 100644
--- a/packages/core/src/utils/setup-package-json.ts
+++ b/packages/core/src/utils/setup-package-json.ts
@@ -28,6 +28,7 @@ type ExportObject = {
import: ExportString;
require: ExportString;
};
+type Exports = Record;
const structuredClone = global.structuredClone ?? structuredClonePolyfill;
@@ -44,19 +45,31 @@ const arrayDiff = (array: T[], comparison: T[] | undefined) => {
return missingItems;
};
+const exportsDiff = (expected: Exports, actual: Exports) => {
+ // Compare only keys which are the same in both objects.
+ // This allows exports to be injected by `updatePackageJsonExports`
+ const actualEntries = Object.entries(actual).filter(
+ ([key]) => key in expected,
+ );
+ return !isDeepStrictEqual(Object.entries(expected), actualEntries);
+};
+
+const makeRelative = (value: string): ExportString =>
+ value.startsWith('./') ? (value as ExportString) : `./${value}`;
+
const getExportsForPackage = (entries: Entry[], options: { from: string }) => {
const [$default, other] = partition(entries, (entry) => entry.isDefaultEntry);
const sortedEntries = [...$default, ...sort(other, 'entryName')];
- const exports: Record = {};
+ const exports: Exports = {};
for (const entry of sortedEntries) {
- exports[entry.isDefaultEntry ? '.' : `./${entry.entryName}`] = {
- types: `./${entry.getOutputPath('dts', options)}`,
- import: `./${entry.getOutputPath('esm', options)}`,
- require: `./${entry.getOutputPath('cjs', options)}`,
+ exports[entry.isDefaultEntry ? '.' : makeRelative(entry.entryName)] = {
+ types: makeRelative(entry.getOutputPath('dts', options)),
+ import: makeRelative(entry.getOutputPath('esm', options)),
+ require: makeRelative(entry.getOutputPath('cjs', options)),
};
}
- exports['./package.json'] = './package.json';
+ exports[makeRelative('package.json')] = makeRelative('package.json');
return exports;
};
@@ -128,21 +141,21 @@ export const diffPackageJson = (
// create expected package.json
- let expectedPackageJson: PackageJson = structuredClone(packageJson);
+ let expected = structuredClone(packageJson);
const options = { from: packageRoot };
- expectedPackageJson.exports = getExportsForPackage(entries, options);
+ expected.exports = getExportsForPackage(entries, options);
const files = new Set(packageJson.files);
for (const entry of entries) {
if (entry.isDefaultEntry) {
- expectedPackageJson.main = `./${entry.getOutputPath('cjs', options)}`;
- expectedPackageJson.module = `./${entry.getOutputPath('esm', options)}`;
- expectedPackageJson.types = `./${entry.getOutputPath('dts', options)}`;
+ expected.main = makeRelative(entry.getOutputPath('cjs', options));
+ expected.module = makeRelative(entry.getOutputPath('esm', options));
+ expected.types = makeRelative(entry.getOutputPath('dts', options));
}
files.add(entry.entryName);
}
- expectedPackageJson.files = sort(files);
+ expected.files = sort(files);
const { sideEffects, missingSideEffects } = getSideEffectsForPackage(
entries,
@@ -150,42 +163,40 @@ export const diffPackageJson = (
options,
);
if (missingSideEffects.length) {
- expectedPackageJson.sideEffects = sideEffects;
+ expected.sideEffects = sideEffects;
}
- expectedPackageJson = sortPackageJson(expectedPackageJson);
+ expected = sortPackageJson(expected);
// do checks against expected package.json
(['main', 'module', 'types'] as const).forEach((key) => {
- if (expectedPackageJson[key] !== packageJson[key]) {
- diffs.push({ key, from: packageJson[key], to: expectedPackageJson[key] });
+ if (expected[key] !== packageJson[key]) {
+ diffs.push({ key, from: packageJson[key], to: expected[key] });
}
});
if (
- !isDeepStrictEqual(
- Object.entries(expectedPackageJson.exports!),
- Object.entries(packageJson.exports ?? {}),
+ exportsDiff(
+ expected.exports as Exports,
+ (packageJson.exports ?? {}) as Exports,
)
) {
diffs.push({ key: 'exports' });
}
- if (!isDeepStrictEqual(expectedPackageJson.files, packageJson.files)) {
+ if (!isDeepStrictEqual(expected.files, packageJson.files)) {
diffs.push({
key: 'files',
- additions: arrayDiff(expectedPackageJson.files!, packageJson.files),
+ additions: arrayDiff(expected.files!, packageJson.files),
});
}
- if (
- !isDeepStrictEqual(expectedPackageJson.sideEffects, packageJson.sideEffects)
- ) {
+ if (!isDeepStrictEqual(expected.sideEffects, packageJson.sideEffects)) {
diffs.push({ key: 'sideEffects', additions: missingSideEffects });
}
- const expectedPackageJsonKeys = Object.keys(expectedPackageJson);
+ const expectedPackageJsonKeys = Object.keys(expected);
const packageJsonKeys = Object.keys(packageJson);
if (
expectedPackageJsonKeys.length === packageJsonKeys.length &&
@@ -196,7 +207,7 @@ export const diffPackageJson = (
return {
diffs,
- expectedPackageJson,
+ expectedPackageJson: expected,
};
};
@@ -224,3 +235,31 @@ const setupPackageJson =
export const validatePackageJson = setupPackageJson(false);
export const fixPackageJson = setupPackageJson(true);
+
+export const updatePackageJsonExports = async (
+ packageRoot: string,
+ exports: string[],
+) => {
+ if (exports.length === 0) return;
+
+ const packagePath = path.join(packageRoot, 'package.json');
+ const packageJson: PackageJson = await fse.readJson(packagePath, { fs });
+
+ const packageExports = packageJson.exports as Exports;
+
+ const lastKey = Object.keys(packageExports).pop()!;
+ const lastExport = packageExports[lastKey];
+
+ delete packageExports[lastKey];
+ for (const entry of exports) {
+ packageExports[makeRelative(entry)] = makeRelative(entry);
+ }
+ packageExports[lastKey] = lastExport;
+
+ packageJson.exports = packageExports;
+
+ await writePackageJson({
+ dir: packageRoot,
+ contents: packageJson,
+ });
+};
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ebf5d04c..4516d514 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -252,6 +252,22 @@ importers:
specifier: ^1.5.1
version: 1.5.2(@vanilla-extract/css@1.12.0)
+ fixtures/with-styles:
+ dependencies:
+ '@crackle-fixtures/package-with-styles':
+ specifier: link:./package-with-styles
+ version: link:package-with-styles
+ '@vanilla-extract/css':
+ specifier: ^1.12.0
+ version: 1.12.0
+ react:
+ specifier: ^18.2.0
+ version: 18.2.0
+ devDependencies:
+ '@types/react':
+ specifier: ^18.0.21
+ version: 18.0.28
+
fixtures/with-vocab:
dependencies:
'@vocab/core':
diff --git a/tests/__snapshots__/package/with-styles/dist/index.ts.snap b/tests/__snapshots__/package/with-styles/dist/index.ts.snap
new file mode 100644
index 00000000..9197d82a
--- /dev/null
+++ b/tests/__snapshots__/package/with-styles/dist/index.ts.snap
@@ -0,0 +1,29 @@
+/* #region dist/index.cjs */
+"use strict";
+Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
+const jsxRuntime = require("react/jsx-runtime");
+require("@crackle-fixtures/package-with-styles/styles.css");
+const styles_Component_css_cjs = require("./styles/Component.css.cjs");
+const thirdparty = "";
+const Component = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles_Component_css_cjs.redBorder, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "external" }) });
+exports.Component = Component;
+/* #endregion */
+
+
+/* #region dist/index.d.ts */
+declare const _default: () => JSX.Element;
+
+export { _default as Component };
+/* #endregion */
+
+
+/* #region dist/index.mjs */
+import { jsx } from "react/jsx-runtime";
+import "@crackle-fixtures/package-with-styles/styles.css";
+import { redBorder } from "./styles/Component.css.mjs";
+const thirdparty = "";
+const Component = () => /* @__PURE__ */ jsx("div", { className: redBorder, children: /* @__PURE__ */ jsx("span", { className: "external" }) });
+export {
+ Component
+};
+/* #endregion */
diff --git a/tests/__snapshots__/package/with-styles/dist/style.css.snap b/tests/__snapshots__/package/with-styles/dist/style.css.snap
new file mode 100644
index 00000000..be1d5c04
--- /dev/null
+++ b/tests/__snapshots__/package/with-styles/dist/style.css.snap
@@ -0,0 +1,6 @@
+/* #region dist/style.css */
+.external {
+ display: none;
+ font-size: 9px;
+}
+/* #endregion */
diff --git a/tests/__snapshots__/package/with-styles/dist/styles/Component.css.ts.snap b/tests/__snapshots__/package/with-styles/dist/styles/Component.css.ts.snap
new file mode 100644
index 00000000..7c092820
--- /dev/null
+++ b/tests/__snapshots__/package/with-styles/dist/styles/Component.css.ts.snap
@@ -0,0 +1,25 @@
+/* #region dist/styles/Component.css.cjs */
+"use strict";
+const fileScope = require("@vanilla-extract/css/fileScope");
+const css = require("@vanilla-extract/css");
+fileScope.setFileScope("src/Component.css.ts?used", "with-styles");
+const redBorder = css.style({
+ border: "5px solid red"
+}, "redBorder");
+fileScope.endFileScope();
+exports.redBorder = redBorder;
+/* #endregion */
+
+
+/* #region dist/styles/Component.css.mjs */
+import { setFileScope, endFileScope } from "@vanilla-extract/css/fileScope";
+import { style } from "@vanilla-extract/css";
+setFileScope("src/Component.css.ts?used", "with-styles");
+const redBorder = style({
+ border: "5px solid red"
+}, "redBorder");
+endFileScope();
+export {
+ redBorder
+};
+/* #endregion */
diff --git a/tests/package.test.ts b/tests/package.test.ts
index 15e11c9a..68bc7492 100644
--- a/tests/package.test.ts
+++ b/tests/package.test.ts
@@ -20,6 +20,7 @@ test.each([
'with-dep-hidden-package-json',
'with-graphql-schema-types',
'with-side-effects',
+ 'with-styles',
'with-vocab',
])(
'fixture %s',