Skip to content

Commit

Permalink
feat(react-output-target): add customElementsDir configuration option (
Browse files Browse the repository at this point in the history
  • Loading branch information
sean-perkins authored Aug 26, 2024
1 parent e9d35d9 commit 24de01e
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 22 deletions.
15 changes: 8 additions & 7 deletions packages/react-output-target/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@ That's it! You can now import and use your Stencil components as React component

## Output Target Options

| Property | Description |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `outDir` (required) | The directory where the React components will be generated. |
| `esModule` | If `true`, the output target will generate a separate ES module for each React component wrapper. Defaults to `false`. |
| `stencilPackageName` | The name of the package that exports the Stencil components. Defaults to the package.json detected by the Stencil compiler. |
| `excludeComponents` | An array of component tag names to exclude from the React output target. Useful if you want to prevent certain web components from being in the React library. |
| `experimentalUseClient` | If `true`, the generated output target will include the [`use client;`](https://react.dev/reference/react/use-client) directive. |
| Property | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `outDir` (required) | The directory where the React components will be generated. |
| `esModule` | If `true`, the output target will generate a separate ES module for each React component wrapper. Defaults to `false`. |
| `stencilPackageName` | The name of the package that exports the Stencil components. Defaults to the package.json detected by the Stencil compiler. |
| `excludeComponents` | An array of component tag names to exclude from the React output target. Useful if you want to prevent certain web components from being in the React library. |
| `experimentalUseClient` | If `true`, the generated output target will include the [`use client;`](https://react.dev/reference/react/use-client) directive. |
| `customElementsDir` | The directory where the custom elements are saved. This value is automatically detected from the Stencil configuration file for the `dist-custom-elements` output target. If you are working in an environment that uses absolute paths, consider setting this value manually. |
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,27 @@ describe('reactOutputTarget', () => {
).not.toThrowError();
}
});

it('uses the customElementsDir provided by the caller instead of the calculated value', () => {
const { validate, __internal_getCustomElementsDir } = reactOutputTarget({
outDir: 'dist/components',
stencilPackageName: 'my-components',
customElementsDir: 'my-custom-dir',
});

if (validate) {
const config = {
outputTargets: [
{
type: 'dist-custom-elements',
dir: 'my-components',
},
],
} as any;

validate(config, []);

expect(__internal_getCustomElementsDir()).toBe('my-custom-dir');
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,24 @@ export interface ReactOutputTargetOptions {
* Enable this option to add the `use client;` directive to the generated React components.
*/
experimentalUseClient?: boolean;
/**
* The directory where the custom elements are saved.
*
* This value is automatically detected from the Stencil configuration file for the dist-custom-elements output target.
* If you are working in an environment that uses absolute paths, consider setting this value manually.
*/
customElementsDir?: string;
}

const PLUGIN_NAME = 'react-output-target';

const DIST_CUSTOM_ELEMENTS_DEFAULT_DIR = 'components';
const DIST_CUSTOM_ELEMENTS = 'dist-custom-elements';

interface ReactOutputTarget extends OutputTargetCustom {
__internal_getCustomElementsDir: () => string;
}

/**
* Creates an output target for binding Stencil components to be used in a React context
* @public
Expand All @@ -46,7 +57,8 @@ export const reactOutputTarget = ({
stencilPackageName,
experimentalUseClient,
excludeComponents,
}: ReactOutputTargetOptions): OutputTargetCustom => {
customElementsDir: customElementsDirOverride,
}: ReactOutputTargetOptions): ReactOutputTarget => {
let customElementsDir = DIST_CUSTOM_ELEMENTS_DEFAULT_DIR;
return {
type: 'custom',
Expand All @@ -58,20 +70,24 @@ export const reactOutputTarget = ({
*
* This context is used to detect a customized output path.
*/
const customElementsOutputTarget = (config.outputTargets || []).find(
(o) => o.type === DIST_CUSTOM_ELEMENTS
) as OutputTargetDistCustomElements;
if (customElementsOutputTarget == null) {
throw new Error(
`The '${PLUGIN_NAME}' requires '${DIST_CUSTOM_ELEMENTS}' output target. Add { type: '${DIST_CUSTOM_ELEMENTS}' }, to the outputTargets config.`
);
}
if (customElementsOutputTarget.dir !== undefined) {
/**
* If the developer has configured a custom output path for the Stencil components,
* we need to use that path when importing the components in the React components.
*/
customElementsDir = customElementsOutputTarget.dir;
if (customElementsDirOverride) {
customElementsDir = customElementsDirOverride;
} else {
const customElementsOutputTarget = (config.outputTargets || []).find(
(o) => o.type === DIST_CUSTOM_ELEMENTS
) as OutputTargetDistCustomElements;
if (customElementsOutputTarget == null) {
throw new Error(
`The '${PLUGIN_NAME}' requires '${DIST_CUSTOM_ELEMENTS}' output target. Add { type: '${DIST_CUSTOM_ELEMENTS}' }, to the outputTargets config.`
);
}
if (customElementsOutputTarget.dir !== undefined) {
/**
* If the developer has configured a custom output path for the Stencil components,
* we need to use that path when importing the components in the React components.
*/
customElementsDir = customElementsOutputTarget.dir;
}
}

/**
Expand Down Expand Up @@ -114,5 +130,8 @@ export const reactOutputTarget = ({

timespan.finish(`generate ${PLUGIN_NAME} finished`);
},
__internal_getCustomElementsDir() {
return customElementsDir;
},
};
};

0 comments on commit 24de01e

Please sign in to comment.