@@ -267,7 +270,9 @@ Tooltips can be controller programmatically by setting the `trigger` attribute t
```jsx:react
import { useState } from 'react';
-import { SlAvatar, SlButton, SlTooltip } from '@shoelace-style/shoelace/dist/react';
+import SlAvatar from '@shoelace-style/shoelace/dist/react/sl-avatar';
+import SlButton from '@shoelace-style/shoelace/dist/react/sl-button';
+import SlTooltip from '@shoelace-style/shoelace/dist/react/sl-tooltip';
const App = () => {
const [open, setOpen] = useState(false);
@@ -301,7 +306,8 @@ You can control the size of tooltip arrows by overriding the `--sl-tooltip-arrow
{% raw %}
```jsx:react
-import { SlButton, SlTooltip } from '@shoelace-style/shoelace/dist/react';
+import SlButton from '@shoelace-style/shoelace/dist/react/sl-button';
+import SlTooltip from '@shoelace-style/shoelace/dist/react/sl-tooltip';
const App = () => (
@@ -339,7 +345,8 @@ Use the `content` slot to create tooltips with HTML content. Tooltips are design
```
```jsx:react
-import { SlButton, SlTooltip } from '@shoelace-style/shoelace/dist/react';
+import SlButton from '@shoelace-style/shoelace/dist/react/sl-button';
+import SlTooltip from '@shoelace-style/shoelace/dist/react/sl-tooltip';
const App = () => (
@@ -365,7 +372,8 @@ Use the `--max-width` custom property to change the width the tooltip can grow t
{% raw %}
```jsx:react
-import { SlButton, SlTooltip } from '@shoelace-style/shoelace/dist/react';
+import SlButton from '@shoelace-style/shoelace/dist/react/sl-button';
+import SlTooltip from '@shoelace-style/shoelace/dist/react/sl-tooltip';
const App = () => (
@@ -402,7 +410,8 @@ Tooltips will be clipped if they're inside a container that has `overflow: auto|
```
```jsx:react
-import { SlButton, SlTooltip } from '@shoelace-style/shoelace/dist/react';
+import SlButton from '@shoelace-style/shoelace/dist/react/sl-button';
+import SlTooltip from '@shoelace-style/shoelace/dist/react/sl-tooltip';
const css = `
.tooltip-hoist {
diff --git a/docs/pages/components/tree-item.md b/docs/pages/components/tree-item.md
index 2e3cc954..d4c30bc8 100644
--- a/docs/pages/components/tree-item.md
+++ b/docs/pages/components/tree-item.md
@@ -20,7 +20,8 @@ layout: component
```jsx:react
-import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
+import SlTree from '@shoelace-style/shoelace/dist/react/sl-tree';
+import SlTreeItem from '@shoelace-style/shoelace/dist/react/sl-tree-item';
const App = () => (
@@ -62,7 +63,8 @@ A tree item can contain other tree items. This allows the node to be expanded or
```jsx:react
-import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
+import SlTree from '@shoelace-style/shoelace/dist/react/sl-tree';
+import SlTreeItem from '@shoelace-style/shoelace/dist/react/sl-tree-item';
const App = () => (
@@ -102,7 +104,8 @@ Use the `selected` attribute to select a tree item initially.
```jsx:react
-import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
+import SlTree from '@shoelace-style/shoelace/dist/react/sl-tree';
+import SlTreeItem from '@shoelace-style/shoelace/dist/react/sl-tree-item';
const App = () => (
@@ -142,7 +145,8 @@ Use the `expanded` attribute to expand a tree item initially.
```jsx:react
-import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
+import SlTree from '@shoelace-style/shoelace/dist/react/sl-tree';
+import SlTreeItem from '@shoelace-style/shoelace/dist/react/sl-tree-item';
const App = () => (
diff --git a/docs/pages/components/tree.md b/docs/pages/components/tree.md
index 23e5011e..1e950f3e 100644
--- a/docs/pages/components/tree.md
+++ b/docs/pages/components/tree.md
@@ -37,7 +37,8 @@ layout: component
```jsx:react
-import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
+import SlTree from '@shoelace-style/shoelace/dist/react/sl-tree';
+import SlTreeItem from '@shoelace-style/shoelace/dist/react/sl-tree-item';
const App = () => (
@@ -118,7 +119,8 @@ The `selection` attribute lets you change the selection behavior of the tree.
```jsx:react
-import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
+import SlTree from '@shoelace-style/shoelace/dist/react/sl-tree';
+import SlTreeItem from '@shoelace-style/shoelace/dist/react/sl-tree-item';
const App = () => {
const [selection, setSelection] = useState('single');
@@ -197,7 +199,8 @@ Indent guides can be drawn by setting `--indent-guide-width`. You can also chang
```jsx:react
-import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
+import SlTree from '@shoelace-style/shoelace/dist/react/sl-tree';
+import SlTreeItem from '@shoelace-style/shoelace/dist/react/sl-tree-item';
const App = () => (
@@ -265,7 +268,8 @@ If you want to disable this behavior after the first load, simply remove the `la
```
```jsx:react
-import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
+import SlTree from '@shoelace-style/shoelace/dist/react/sl-tree';
+import SlTreeItem from '@shoelace-style/shoelace/dist/react/sl-tree-item';
const App = () => {
const [childItems, setChildItems] = useState([]);
@@ -340,7 +344,8 @@ Use the `expand-icon` and `collapse-icon` slots to change the expand and collaps
```jsx:react
-import { SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
+import SlTree from '@shoelace-style/shoelace/dist/react/sl-tree';
+import SlTreeItem from '@shoelace-style/shoelace/dist/react/sl-tree-item';
const App = () => (
@@ -424,7 +429,9 @@ Decorative icons can be used before labels to provide hints for each node.
```
```jsx:react
-import { SlIcon, SlTree, SlTreeItem } from '@shoelace-style/shoelace/dist/react';
+import SlIcon from '@shoelace-style/shoelace/dist/react/sl-icon';
+import SlTree from '@shoelace-style/shoelace/dist/react/sl-tree';
+import SlTreeItem from '@shoelace-style/shoelace/dist/react/sl-tree-item';
const App = () => {
return (
diff --git a/docs/pages/frameworks/react.md b/docs/pages/frameworks/react.md
index b4a91473..86f208ef 100644
--- a/docs/pages/frameworks/react.md
+++ b/docs/pages/frameworks/react.md
@@ -39,13 +39,28 @@ Now you can start using components!
Every Shoelace component is available to import as a React component. Note that we're importing the `` _React component_ instead of the `` _custom element_ in the example below.
```jsx
-import { SlButton } from '@shoelace-style/shoelace/%NPMDIR%/react';
+import SlButton from '@shoelace-style/shoelace/%NPMDIR%/react/button';
const MyComponent = () => Click me;
export default MyComponent;
```
+#### Notes about tree shaking
+
+Previously, it was recommended to import from a single entrypoint like so:
+
+```jsx
+import { SlButton } from '@shoelace-style/shoelace/%NPMDIR%/react';
+```
+
+However, tree-shaking extra Shoelace components proved to be a challenge. As a result, we now recommend cherry-picking components you want to use, rather than importing from a single entrypoint.
+
+```diff
+- import { SlButton } from '@shoelace-style/shoelace/%NPMDIR%/react';
++ import SlButton from '@shoelace-style/shoelace/%NPMDIR%/react/button';
+```
+
You can find a copy + paste import for each component in the "importing" section of its documentation.
### Event Handling
@@ -56,7 +71,7 @@ Here's how you can bind the input's value to a state variable.
```jsx
import { useState } from 'react';
-import { SlInput } from '@shoelace-style/shoelace/%NPMDIR%/react';
+import SlInput from '@shoelace-style/shoelace/%NPMDIR%/react/input';
function MyComponent() {
const [value, setValue] = useState('');
@@ -71,7 +86,7 @@ If you're using TypeScript, it's important to note that `event.target` will be a
```tsx
import { useState } from 'react';
-import { SlInput } from '@shoelace-style/shoelace/%NPMDIR%/react';
+import SlInput from '@shoelace-style/shoelace/%NPMDIR%/react/input';
import type SlInputElement from '@shoelace-style/shoelace/%NPMDIR%/components/input/input';
function MyComponent() {
@@ -87,7 +102,7 @@ You can also import the event type for use in your callbacks, shown below.
```tsx
import { useCallback, useState } from 'react';
-import { SlInput, SlInputEvent } from '@shoelace-style/shoelace/%NPMDIR%/react';
+import SlInput, { type SlInputEvent } from '@shoelace-style/shoelace/%NPMDIR%/react/input';
import type SlInputElement from '@shoelace-style/shoelace/%NPMDIR%/components/input/input';
function MyComponent() {
@@ -159,7 +174,7 @@ To fix this, add the following to your `package.json` which tells the transpiler
```js
{
"jest": {
- "transformIgnorePatterns": ["node_modules/?!(@shoelace)"]
+ "transformIgnorePatterns": ["node_modules/(?!(@shoelace))"]
}
}
```
diff --git a/docs/pages/getting-started/form-controls.md b/docs/pages/getting-started/form-controls.md
index 05ebc9aa..2574e492 100644
--- a/docs/pages/getting-started/form-controls.md
+++ b/docs/pages/getting-started/form-controls.md
@@ -99,7 +99,12 @@ The form will not be submitted if a required field is incomplete.
```
```jsx:react
-import { SlButton, SlCheckbox, SlInput, SlMenuItem, SlSelect, SlTextarea } from '@shoelace-style/shoelace/dist/react';
+import SlButton from '@shoelace-style/shoelace/dist/react/sl-button';
+import SlCheckbox from '@shoelace-style/shoelace/dist/react/sl-checkbox';
+import SlInput from '@shoelace-style/shoelace/dist/react/sl-input';
+import SlMenuItem from '@shoelace-style/shoelace/dist/react/sl-menu-item';
+import SlSelect from '@shoelace-style/shoelace/dist/react/sl-select';
+import SlTextarea from '@shoelace-style/shoelace/dist/react/sl-textarea';
const App = () => {
function handleSubmit(event) {
@@ -160,7 +165,8 @@ To restrict a value to a specific [pattern](https://developer.mozilla.org/en-US/
```
```jsx:react
-import { SlButton, SlInput } from '@shoelace-style/shoelace/dist/react';
+import SlButton from '@shoelace-style/shoelace/dist/react/sl-button';
+import SlInput from '@shoelace-style/shoelace/dist/react/sl-input';
const App = () => {
function handleSubmit(event) {
@@ -211,7 +217,8 @@ Some input types will automatically trigger constraints, such as `email` and `ur
```
```jsx:react
-import { SlButton, SlInput } from '@shoelace-style/shoelace/dist/react';
+import SlButton from '@shoelace-style/shoelace/dist/react/sl-button';
+import SlInput from '@shoelace-style/shoelace/dist/react/sl-input';
const App = () => {
function handleSubmit(event) {
@@ -272,7 +279,8 @@ To create a custom validation error, pass a non-empty string to the `setCustomVa
```jsx:react
import { useRef, useState } from 'react';
-import { SlButton, SlInput } from '@shoelace-style/shoelace/dist/react';
+import SlButton from '@shoelace-style/shoelace/dist/react/sl-button';
+import SlInput from '@shoelace-style/shoelace/dist/react/sl-input';
const App = () => {
const input = useRef(null);
diff --git a/docs/pages/getting-started/installation.md b/docs/pages/getting-started/installation.md
index 2d6af34f..8cae5c29 100644
--- a/docs/pages/getting-started/installation.md
+++ b/docs/pages/getting-started/installation.md
@@ -196,7 +196,7 @@ setBasePath('/path/to/shoelace/%NPMDIR%
Component modules include side effects for registration purposes. Because of this, importing directly from `@shoelace-style/shoelace` may result in a larger bundle size than necessary. For optimal tree shaking, always cherry pick, i.e. import components and utilities from their respective files, as shown above.
:::
-### Avoiding side-effect imports
+### Avoiding auto-registering imports
By default, imports to components will auto-register themselves. This may not be ideal in all cases. To import just the component's class without auto-registering it's tag we can do the following:
diff --git a/docs/pages/resources/changelog.md b/docs/pages/resources/changelog.md
index a8d2a327..82e54c26 100644
--- a/docs/pages/resources/changelog.md
+++ b/docs/pages/resources/changelog.md
@@ -15,6 +15,7 @@ New versions of Shoelace are released as-needed and generally occur when a criti
## Next
- Fixed a bug in `` where pressing [[Up]] or [[Down]] when focused on the trigger wouldn't focus the first/last menu items [#1472]
+- Removed `sideEffects` key from `package.json`. Update React docs to use cherry-picking. [#1485]
## 2.6.0
diff --git a/package.json b/package.json
index 7c423d10..721e37c1 100644
--- a/package.json
+++ b/package.json
@@ -10,17 +10,6 @@
"type": "module",
"types": "dist/shoelace.d.ts",
"jsdelivr": "./cdn/shoelace-autoloader.js",
- "sideEffects": [
- "./dist/shoelace.js",
- "./dist/shoelace-autoloader.js",
- "./dist/components/**/*.js",
- "./dist/chunks/**/*.js",
- "./dist/translations/**/*.*",
- "./src/translations/**/*.*",
- "*.css",
- "// COMMENT: This monstrosity below isn't perfect, but its like 99% to get bundlers to recognize 'thing.component.ts' as having no side effects. Example: https://regexr.com/7grof",
- "./dist/components/**/*((? {
const tagWithoutPrefix = component.tagName.replace(/^sl-/, '');
const componentDir = path.join(reactDir, tagWithoutPrefix);
const componentFile = path.join(componentDir, 'index.ts');
- const importPath = component.path;
+ const importPath = component.path.replace(/\.js$/, '.component.js');
const eventImports = (component.events || [])
- .map(event => `import { ${event.eventName} } from '../../../src/events/events';`)
+ .map(event => `import type { ${event.eventName} } from '../../../src/events/events';`)
+ .join('\n');
+ const eventExports = (component.events || [])
+ .map(event => `export type { ${event.eventName} } from '../../../src/events/events';`)
.join('\n');
const eventNameImport =
(component.events || []).length > 0 ? `import { type EventName } from '@lit-labs/react';` : ``;
@@ -46,6 +49,7 @@ components.map(component => {
${eventNameImport}
${eventImports}
+ ${eventExports}
const tagName = '${component.tagName}'