Merge branch 'konnorrogers/modify-build-script-for-npm-2' into next

pull/1370/head
Cory LaViska 2023-06-13 10:05:00 -04:00
commit 7404e496cb
22 zmienionych plików z 201 dodań i 108 usunięć

1
.gitignore vendored
Wyświetl plik

@ -5,3 +5,4 @@ dist
docs/assets/images/sprite.svg
node_modules
src/react
cdn

Wyświetl plik

@ -18,6 +18,7 @@
"CACHEABLE",
"callout",
"callouts",
"cdndir",
"chatbubble",
"checkmark",
"claviska",
@ -104,6 +105,7 @@
"noopener",
"noreferrer",
"novalidate",
"npmdir",
"outdir",
"ParamagicDev",
"peta",

Wyświetl plik

@ -39,15 +39,15 @@
{% if component.summary %}
{{ component.summary | markdownInline | safe }}
{% endif %}
</p>
</p>
{# Markdown content #}
{{ content | safe }}
{# Importing #}
<h2>Importing</h2>
<p>
If you're using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use
If you're using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use
any of the following snippets to <a href="/getting-started/installation#cherry-picking">cherry pick</a> this component.
</p>
@ -59,32 +59,32 @@
<sl-tab-panel name="script">
<p>
To import this component from <a href="https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace">the CDN</a>
To import this component from <a href="https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace">the CDN</a>
using a script tag:
</p>
<pre><code class="language-html">&lt;script type=&quot;module&quot; src=&quot;https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/dist/{{ component.path }}&quot;&gt;&lt;/script&gt;</code></pre>
<pre><code class="language-html">&lt;script type=&quot;module&quot; src=&quot;https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/{{ meta.cdndir }}/{{ component.path }}&quot;&gt;&lt;/script&gt;</code></pre>
</sl-tab-panel>
<sl-tab-panel name="import">
<p>
To import this component from <a href="https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace">the CDN</a>
To import this component from <a href="https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace">the CDN</a>
using a JavaScript import:
</p>
<pre><code class="language-js">import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/dist/{{ component.path }}';</code></pre>
<pre><code class="language-js">import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@{{ meta.version }}/{{ meta.cdndir }}/{{ component.path }}';</code></pre>
</sl-tab-panel>
<sl-tab-panel name="bundler">
<p>
To import this component using <a href="{{ rootUrl('/getting-started/installation#bundling') }}">a bundler</a>:
</p>
<pre><code class="language-js">import '@shoelace-style/shoelace/dist/{{ component.path }}';</code></pre>
<pre><code class="language-js">import '@shoelace-style/shoelace/{{ meta.npmdir }}/{{ component.path }}';</code></pre>
</sl-tab-panel>
<sl-tab-panel name="react">
<p>
To import this component as a <a href="/frameworks/react">React component</a>:
</p>
<pre><code class="language-js">import { {{ component.name }} } from '@shoelace-style/shoelace/dist/react';</code></pre>
<pre><code class="language-js">import { {{ component.name }} } from '@shoelace-style/shoelace/{{ meta.npmdir }}/react';</code></pre>
</sl-tab-panel>
</sl-tab-group>
@ -337,11 +337,11 @@
<h2>Dependencies</h2>
<p>This component automatically imports the following dependencies.</p>
<ul>
{% for dependency in component.dependencies %}
<li><code>&lt;{{ dependency }}&gt;</code></li>
{% endfor %}
</ul>
{% endif %}
{% endblock %}
{% endblock %}

Wyświetl plik

@ -34,9 +34,9 @@
<meta property="og:image" content="{{ assetUrl(meta.image, true) }}" />
{# Shoelace #}
<link rel="stylesheet" href="/dist/themes/light.css" />
<link rel="stylesheet" href="/dist/themes/dark.css" />
<script type="module" src="/dist/shoelace-autoloader.js"></script>
<link rel="stylesheet" href="/cdn/themes/light.css" />
<link rel="stylesheet" href="/cdn/themes/dark.css" />
<script type="module" src="/cdn/shoelace-autoloader.js"></script>
{# Set the initial theme and menu states here to prevent flashing #}
<script>

Wyświetl plik

@ -0,0 +1,19 @@
/**
* @typedef {object} Replacement
* @property {string | RegExp} pattern
* @property {string} replacement
*/
/**
* @typedef {Array<Replacement>} Replacements
*/
/**
* @param {Document} content
* @param {Replacements} replacements
*/
module.exports = function (content, replacements) {
replacements.forEach(replacement => {
content.body.innerHTML = content.body.innerHTML.replaceAll(replacement.pattern, replacement.replacement);
});
};

Wyświetl plik

@ -180,7 +180,7 @@
// HTML templates
if (!isReact) {
htmlTemplate =
`<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${shoelaceVersion}/dist/shoelace.js"></script>\n` +
`<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${shoelaceVersion}/%CDNDIR%/shoelace.js"></script>\n` +
`\n${htmlExample}`;
jsTemplate = '';
}
@ -191,10 +191,10 @@
jsTemplate =
`import React from 'https://cdn.skypack.dev/react@${reactVersion}';\n` +
`import ReactDOM from 'https://cdn.skypack.dev/react-dom@${reactVersion}';\n` +
`import { setBasePath } from 'https://cdn.skypack.dev/@shoelace-style/shoelace@${shoelaceVersion}/dist/utilities/base-path';\n` +
`import { setBasePath } from 'https://cdn.skypack.dev/@shoelace-style/shoelace@${shoelaceVersion}/%CDNDIR%/utilities/base-path';\n` +
`\n` +
`// Set the base path for Shoelace assets\n` +
`setBasePath('https://cdn.skypack.dev/@shoelace-style/shoelace@${shoelaceVersion}/dist/')\n` +
`setBasePath('https://cdn.skypack.dev/@shoelace-style/shoelace@${shoelaceVersion}/%NPMDIR%/')\n` +
`\n${convertModuleLinks(reactExample)}\n` +
`\n` +
`ReactDOM.render(<App />, document.getElementById('root'));`;
@ -202,7 +202,7 @@
// CSS templates
cssTemplate =
`@import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${shoelaceVersion}/dist/themes/${
`@import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@${shoelaceVersion}/%CDNDIR%/themes/${
isDark ? 'dark' : 'light'
}.css';\n` +
'\n' +

Wyświetl plik

@ -16,8 +16,11 @@ const tableOfContents = require('./_utilities/table-of-contents.cjs');
const prettier = require('./_utilities/prettier.cjs');
const scrollingTables = require('./_utilities/scrolling-tables.cjs');
const typography = require('./_utilities/typography.cjs');
const replacer = require('./_utilities/replacer.cjs');
const assetsDir = 'assets';
const cdndir = 'cdn';
const npmdir = 'dist';
const allComponents = getAllComponents();
let hasBuiltSearchIndex = false;
@ -33,7 +36,9 @@ module.exports = function (eleventyConfig) {
description: 'A forward-thinking library of web components.',
image: 'images/og-image.png',
version: customElementsManifest.package.version,
components: allComponents
components: allComponents,
cdndir,
npmdir
});
//
@ -129,6 +134,11 @@ module.exports = function (eleventyConfig) {
scrollingTables(doc);
copyCodeButtons(doc); // must be after codePreviews + highlightCodeBlocks
typography(doc, '#content');
replacer(doc, [
{ pattern: '%VERSION%', replacement: customElementsManifest.package.version },
{ pattern: '%CDNDIR%', replacement: cdndir },
{ pattern: '%NPMDIR%', replacement: npmdir }
]);
// Serialize the Document object to an HTML string and prepend the doctype
content = `<!DOCTYPE html>\n${doc.documentElement.outerHTML}`;
@ -208,7 +218,7 @@ module.exports = function (eleventyConfig) {
eleventyConfig.setServerOptions({
domDiff: false, // disable dom diffing so custom elements don't break on reload,
port: 4000, // if port 4000 is taken, 11ty will use the next one available
watch: ['dist/**/*'] // additional files to watch that will trigger server updates (array of paths or globs)
watch: ['cdn/**/*'] // additional files to watch that will trigger server updates (array of paths or globs)
});
//

Wyświetl plik

@ -19,14 +19,14 @@ npm install @shoelace-style/shoelace
Next, [include a theme](/getting-started/themes) and set the [base path](/getting-started/installation#setting-the-base-path) for icons and other assets. In this example, we'll import the light theme and use the CDN as a base path.
```jsx
import '@shoelace-style/shoelace/dist/themes/light.css';
import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path';
import '@shoelace-style/shoelace/%NPMDIR%/themes/light.css';
import { setBasePath } from '@shoelace-style/shoelace/%NPMDIR%/utilities/base-path';
setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/');
setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/');
```
:::tip
If you'd rather not use the CDN for assets, you can create a build task that copies `node_modules/@shoelace-style/shoelace/dist/assets` into a public folder in your app. Then you can point the base path to that folder instead.
If you'd rather not use the CDN for assets, you can create a build task that copies `node_modules/@shoelace-style/shoelace/%NPMDIR%/assets` into a public folder in your app. Then you can point the base path to that folder instead.
:::
## Configuration

Wyświetl plik

@ -20,14 +20,14 @@ Next, [include a theme](/getting-started/themes) and set the [base path](/gettin
```jsx
// App.jsx
import '@shoelace-style/shoelace/dist/themes/light.css';
import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path';
import '@shoelace-style/shoelace/%NPMDIR%/themes/light.css';
import { setBasePath } from '@shoelace-style/shoelace/%NPMDIR%/utilities/base-path';
setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/');
setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/');
```
:::tip
If you'd rather not use the CDN for assets, you can create a [build task](https://webpack.js.org/plugins/copy-webpack-plugin/) that copies `node_modules/@shoelace-style/shoelace/dist/assets` into your app's `public` directory. Then you can point the base path to that folder instead.
If you'd rather not use the CDN for assets, you can create a [build task](https://webpack.js.org/plugins/copy-webpack-plugin/) that copies `node_modules/@shoelace-style/shoelace/%NPMDIR%/assets` into your app's `public` directory. Then you can point the base path to that folder instead.
:::
Now you can start using components!
@ -39,7 +39,7 @@ Now you can start using components!
Every Shoelace component is available to import as a React component. Note that we're importing the `<SlButton>` _React component_ instead of the `<sl-button>` _custom element_ in the example below.
```jsx
import { SlButton } from '@shoelace-style/shoelace/dist/react';
import { SlButton } from '@shoelace-style/shoelace/%NPMDIR%/react';
const MyComponent = () => <SlButton variant="primary">Click me</SlButton>;
@ -56,7 +56,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/dist/react';
import { SlInput } from '@shoelace-style/shoelace/%NPMDIR%/react';
function MyComponent() {
const [value, setValue] = useState('');
@ -71,8 +71,8 @@ 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/dist/react';
import type SlInputElement from '@shoelace-style/shoelace/dist/components/input/input';
import { SlInput } from '@shoelace-style/shoelace/%NPMDIR%/react';
import type SlInputElement from '@shoelace-style/shoelace/%NPMDIR%/components/input/input';
function MyComponent() {
const [value, setValue] = useState('');

Wyświetl plik

@ -23,10 +23,10 @@ npm install @shoelace-style/shoelace
Next, [include a theme](/getting-started/themes) and set the [base path](/getting-started/installation#setting-the-base-path) for icons and other assets. In this example, we'll import the light theme and use the CDN as a base path.
```jsx
import '@shoelace-style/shoelace/dist/themes/light.css';
import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path';
import '@shoelace-style/shoelace/%NPMDIR%/themes/light.css';
import { setBasePath } from '@shoelace-style/shoelace/%NPMDIR%/utilities/base-path';
setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/');
setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/');
```
:::tip

Wyświetl plik

@ -26,7 +26,7 @@ Next, [include a theme](/getting-started/themes) and set the [base path](/gettin
import '@shoelace-style/shoelace/dist/themes/light.css';
import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path';
setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/');
setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/');
```
:::tip

Wyświetl plik

@ -22,8 +22,8 @@ While convenient, autoloading may lead to a [Flash of Undefined Custom Elements]
<!-- prettier-ignore -->
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/light.css" />
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/shoelace-autoloader.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/themes/light.css" />
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/shoelace-autoloader.js"></script>
```
</sl-tab-panel>
@ -32,9 +32,10 @@ While convenient, autoloading may lead to a [Flash of Undefined Custom Elements]
The traditional CDN loader registers all Shoelace elements up front. Note that, if you're only using a handful of components, it will be much more efficient to stick with the autoloader. However, you can also [cherry pick](#cherry-picking) components if you want to load specific ones up front.
<!-- prettier-ignore -->
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/light.css" />
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/shoelace.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/themes/light.css" />
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/shoelace.js" ></script>
```
</sl-tab-panel>
@ -44,8 +45,9 @@ The traditional CDN loader registers all Shoelace elements up front. Note that,
The code above will load the light theme. If you want to use the [dark theme](/getting-started/themes#dark-theme) instead, update the stylesheet as shown below and add `<html class="sl-theme-dark">` to your page.
<!-- prettier-ignore -->
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/dark.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/themes/dark.css" />
```
### Light & Dark Theme
@ -56,21 +58,21 @@ If you want to load the light or dark theme based on the user's `prefers-color-s
<link
rel="stylesheet"
media="(prefers-color-scheme:light)"
href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/light.css"
href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/themes/light.css"
/>
<link
rel="stylesheet"
media="(prefers-color-scheme:dark)"
href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/dark.css"
href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/themes/dark.css"
onload="document.documentElement.classList.add('sl-theme-dark');"
/>
```
Now you can [start using Shoelace!](/getting-started/usage)
## Local Installation
## npm installation
If you don't want to use the CDN, you can install Shoelace locally with the following command.
If you don't want to use the CDN, you can install Shoelace from npm with the following command.
```bash
npm install @shoelace-style/shoelace
@ -81,8 +83,8 @@ It's up to you to make the source files available to your app. One way to do thi
Once you've done that, add the following tags to your page. Make sure to update `href` and `src` so they point to the route you created.
```html
<link rel="stylesheet" href="/shoelace/dist/themes/light.css" />
<script type="module" src="/shoelace/dist/shoelace.js"></script>
<link rel="stylesheet" href="/shoelace/%NPMDIR%/themes/light.css" />
<script type="module" src="/shoelace/%NPMDIR%/shoelace.js"></script>
```
Alternatively, [you can use a bundler](#bundling).
@ -99,31 +101,37 @@ However, if you're [cherry picking](#cherry-picking) or [bundling](#bundling) Sh
```html
<!-- Option 1: the data-shoelace attribute -->
<script src="bundle.js" data-shoelace="/path/to/shoelace/dist"></script>
<script src="bundle.js" data-shoelace="/path/to/shoelace/%NPMDIR%"></script>
<!-- Option 2: the setBasePath() method -->
<script src="bundle.js"></script>
<script type="module">
import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path.js';
setBasePath('/path/to/shoelace/dist');
import { setBasePath } from '@shoelace-style/shoelace/%NPMDIR%/utilities/base-path.js';
setBasePath('/path/to/shoelace/%NPMDIR%');
</script>
```
:::tip
The library also exports a `getBasePath()` method you can use to reference assets.
When setting a basePath, and easy way to check if it was down properly is by checking if an icon exists.
For example, if I set the basePath to `/dist`, I should be able to go to:
`https://<my-site>/dist/assets/icons/arrow-left.svg` and the browser should show me the SVG.
Shoelace also exports a `getBasePath()` method you can use to reference assets.
:::
## Cherry Picking
Cherry picking can be done from [the CDN](#cdn-installation-easiest) or your [local installation](#local-installation). This approach will load only the components you need up front, while limiting the number of files the browser has to download. The disadvantage is that you need to import each individual component.
Cherry picking can be done from [the CDN](#cdn-installation-easiest) or from [npm](#npm-installation). This approach will load only the components you need up front, while limiting the number of files the browser has to download. The disadvantage is that you need to import each individual component.
Here's an example that loads only the button component. Again, if you're not using a module resolver, you'll need to adjust the path to point to the folder Shoelace is in.
```html
<link rel="stylesheet" href="/path/to/shoelace/dist/themes/light.css" />
<link rel="stylesheet" href="/path/to/shoelace/%NPMDIR%/themes/light.css" />
<script type="module" data-shoelace="/path/to/shoelace/dist">
import '@shoelace-style/shoelace/dist/components/button/button.js';
<script type="module" data-shoelace="/path/to/shoelace/%NPMDIR%">
import '@shoelace-style/shoelace/%NPMDIR%/components/button/button.js';
// <sl-button> is ready to use!
</script>
@ -157,15 +165,15 @@ Now it's time to configure your bundler. Configurations vary for each tool, but
Once your bundler is configured, you'll be able to import Shoelace components and utilities.
```js
import '@shoelace-style/shoelace/dist/themes/light.css';
import '@shoelace-style/shoelace/dist/components/button/button.js';
import '@shoelace-style/shoelace/dist/components/icon/icon.js';
import '@shoelace-style/shoelace/dist/components/input/input.js';
import '@shoelace-style/shoelace/dist/components/rating/rating.js';
import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path.js';
import '@shoelace-style/shoelace/%NPMDIR%/themes/light.css';
import '@shoelace-style/shoelace/%NPMDIR%/components/button/button.js';
import '@shoelace-style/shoelace/%NPMDIR%/components/icon/icon.js';
import '@shoelace-style/shoelace/%NPMDIR%/components/input/input.js';
import '@shoelace-style/shoelace/%NPMDIR%/components/rating/rating.js';
import { setBasePath } from '@shoelace-style/shoelace/%NPMDIR%/utilities/base-path.js';
// Set the base path to the folder you copied Shoelace's assets to
setBasePath('/path/to/shoelace/dist');
setBasePath('/path/to/shoelace/%NPMDIR%
// <sl-button>, <sl-icon>, <sl-input>, and <sl-rating> are ready to use!
```
@ -173,3 +181,14 @@ setBasePath('/path/to/shoelace/dist');
:::warning
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.
:::
## The difference between CDN and npm
You'll notice that the CDN links all start with `/%CDNDIR%/<path>` and npm imports use `/%NPMDIR%/<path>`. The `/%CDNDIR%` files are bundled separately from the `/%NPMDIR%` files. The `/%CDNDIR%` files come pre-bundled, which means all dependencies are inlined so you do not need to worry about loading additional libraries. The `/%NPMDIR%` files **DO NOT** come pre-bundled, allowing your bundler of choice to more efficiently deduplicate dependencies, resulting in smaller bundles and optimal code sharing.
TL;DR:
- `@shoelace-style/shoelace/%CDNDIR%` is for CDN users
- `@shoelace-style/shoelace/%NPMDIR%` is for npm users
This change was introduced in `v2.5.0` to address issues around installations from npm loading multiple versions of libraries (such as the Lit) that Shoelace uses internally.

Wyświetl plik

@ -28,8 +28,8 @@ Shoelace ships with a number of translations. The default is English (US), which
The location of translations depends on how you're consuming Shoelace.
- If you're using the CDN, [import them from the CDN](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace?path=dist%2Ftranslations)
- If you're using a bundler, import them from `@shoelace-style/shoelace/dist/translations/[lang].js`
- If you're using the CDN, [import them from the CDN](https://www.jsdelivr.com/package/npm/@shoelace-style/shoelace?path=%CDNDIR%%2Ftranslations)
- If you're using a bundler, import them from `@shoelace-style/shoelace/%NPMDIR%/translations/[lang].js`
You do not need to load translations up front. You can import them dynamically even after updating the `lang` attribute. Once a translation is registered, localized components will update automatically.

Wyświetl plik

@ -11,7 +11,7 @@ Shoelace is designed to be highly customizable through pure CSS. Out of the box,
A theme is nothing more than a stylesheet that uses the Shoelace API to define design tokens and apply custom styles to components. To create a theme, you will need a decent understanding of CSS, including [CSS Custom Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) and the [`::part` selector](https://developer.mozilla.org/en-US/docs/Web/CSS/::part).
:::tip
For component developers, built-in themes are also available as JavaScript modules that export [Lit CSSResult](https://lit.dev/docs/api/styles/#CSSResult) objects. You can find them in `dist/themes/*.styles.js`.
For component developers, built-in themes are also available as JavaScript modules that export [Lit CSSResult](https://lit.dev/docs/api/styles/#CSSResult) objects. You can find them in `%NPMDIR%/themes/*.styles.js`.
:::
## Theme Basics
@ -34,7 +34,7 @@ To activate a theme, import it and apply the theme's class to the `<html>` eleme
```html
<html class="sl-theme-dark">
<head>
<link rel="stylesheet" href="path/to/shoelace/dist/themes/dark.css" />
<link rel="stylesheet" href="path/to/shoelace/%NPMDIR%/themes/dark.css" />
</head>
<body>
@ -54,8 +54,8 @@ You can activate themes on various containers throughout the page. This example
```html
<html>
<head>
<link rel="stylesheet" href="path/to/shoelace/dist/themes/light.css" />
<link rel="stylesheet" href="path/to/shoelace/dist/themes/dark.css" />
<link rel="stylesheet" href="path/to/shoelace/%NPMDIR%/themes/light.css" />
<link rel="stylesheet" href="path/to/shoelace/%NPMDIR%/themes/dark.css" />
</head>
<body>
@ -127,7 +127,10 @@ The dark theme works by taking the light theme's [color tokens](/tokens/color) a
To install the dark theme, add the following to the `<head>` section of your page.
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/dark.css" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/themes/dark.css"
/>
```
To activate the theme, apply the `sl-theme-dark` class to the `<html>` element.

Wyświetl plik

@ -41,8 +41,8 @@ Add the following code to your page.
<!-- prettier-ignore -->
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/themes/light.css" />
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/dist/shoelace-autoloader.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/themes/light.css" />
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/%CDNDIR%/shoelace-autoloader.js"></script>
```
Now you have access to all of Shoelace's components! Try adding a button:

Wyświetl plik

@ -14,6 +14,16 @@ New versions of Shoelace are released as-needed and generally occur when a criti
## Next
This release [unbundles Lit](https://github.com/shoelace-style/shoelace/issues/559) (and other dependencies) from Shoelace. There are now two distributions for the project:
1. `cdn/` a bundled, CDN-ready distribution
2. `dist/` – an unbundled, npm-ready distribution
:::warning
If you're a CDN user, you must update your path to point to `cdn/` instead of `dist/`. You can copy and paste the latest paths from the [installation page](/getting-started/installation).
:::
- Added a `cdn/` distribution for bundled dependencies (imports for npm users remain the same) [#1369](https://github.com/shoelace-style/shoelace/pull/1369)
- Added the `checkbox` part and related exported parts to `<sl-tree-item>` so you can target it with CSS [#1318](https://github.com/shoelace-style/shoelace/discussions/1318)
- Added the `submenu-icon` part to `<sl-menu-item>` (submenus have not been implemented yet, but this part is required to allow customizations)
- Added tests for `<sl-split-panel>` [#1343](https://github.com/shoelace-style/shoelace/pull/1343)

Wyświetl plik

@ -23,7 +23,8 @@
"./dist/translations/*": "./dist/translations/*"
},
"files": [
"dist"
"dist",
"cdn"
],
"keywords": [
"web components",
@ -42,8 +43,8 @@
"url": "https://github.com/sponsors/claviska"
},
"scripts": {
"start": "node scripts/build.js --bundle --serve",
"build": "node scripts/build.js --bundle --types --copydir \"_site/dist\"",
"start": "node scripts/build.js --serve",
"build": "node scripts/build.js",
"verify": "npm run prettier:check && npm run lint && npm run build && npm run test",
"prepublishOnly": "npm run verify",
"prettier": "prettier --write --loglevel warn .",

Wyświetl plik

@ -11,18 +11,16 @@ import getPort, { portNumbers } from 'get-port';
import ora from 'ora';
import util from 'util';
const { bundle, copydir, dir, serve, types } = commandLineArgs([
{ name: 'bundle', type: Boolean },
{ name: 'copydir', type: String },
{ name: 'serve', type: Boolean },
{ name: 'types', type: Boolean }
]);
const { serve } = commandLineArgs([{ name: 'serve', type: Boolean }]);
const outdir = 'dist';
const cdndir = 'cdn';
const sitedir = '_site';
const spinner = ora({ hideCursor: false }).start();
const execPromise = util.promisify(exec);
let childProcess;
let buildResult;
let buildResults;
const bundleDirectories = [cdndir, outdir];
//
// Runs 11ty and builds the docs. The returned promise resolves after the initial publish has completed. The child
@ -71,8 +69,13 @@ async function buildTheDocs(watch = false) {
//
async function buildTheSource() {
const alwaysExternal = ['@lit-labs/react', 'react'];
const packageJSON = await fs.readFile('./package.json');
const dependencies = [
...Object.keys(packageJSON.dependencies || {}),
...Object.keys(packageJSON.peerDependencies || {})
];
return await esbuild.build({
const cdnConfig = {
format: 'esm',
target: 'es2017',
entryPoints: [
@ -94,7 +97,7 @@ async function buildTheSource() {
// React wrappers
...(await globby('./src/react/**/*.ts'))
],
outdir,
outdir: cdndir,
chunkNames: 'chunks/[name].[hash]',
incremental: serve,
define: {
@ -108,19 +111,26 @@ async function buildTheSource() {
//
// We never bundle React or @lit-labs/react though!
//
external: bundle
? alwaysExternal
: [...alwaysExternal, '@floating-ui/dom', '@shoelace-style/animations', 'lit', 'qr-creator'],
external: alwaysExternal,
splitting: true,
plugins: []
});
};
const npmConfig = {
...cdnConfig,
bundle: false,
external: undefined,
outdir
};
return await Promise.all([esbuild.build(cdnConfig), esbuild.build(npmConfig)]);
}
//
// Called on SIGINT or SIGTERM to cleanup the build and child processes.
//
function handleCleanup() {
buildResult.rebuild.dispose();
buildResults.forEach(result => result.rebuild.dispose());
if (childProcess) {
childProcess.kill('SIGINT');
@ -150,12 +160,16 @@ async function nextTask(label, action) {
}
await nextTask('Cleaning up the previous build', async () => {
await Promise.all([deleteAsync(outdir), deleteAsync(sitedir)]);
await Promise.all([deleteAsync(sitedir), ...bundleDirectories.map(dir => deleteAsync(dir))]);
await fs.mkdir(outdir, { recursive: true });
});
await nextTask('Generating component metadata', () => {
return execPromise(`node scripts/make-metadata.js --outdir "${outdir}"`, { stdio: 'inherit' });
return Promise.all(
bundleDirectories.map(dir => {
return execPromise(`node scripts/make-metadata.js --outdir "${dir}"`, { stdio: 'inherit' });
})
);
});
await nextTask('Wrapping components for React', () => {
@ -178,17 +192,23 @@ await nextTask('Running the TypeScript compiler', () => {
return execPromise(`tsc --project ./tsconfig.prod.json --outdir "${outdir}"`, { stdio: 'inherit' });
});
await nextTask('Building source files', async () => {
buildResult = await buildTheSource();
// Copy the above steps to the CDN directory directly so we don't need to twice the work for nothing.
await nextTask(`Copying Web Types, Themes, Icons, and TS Types to "${cdndir}"`, async () => {
await deleteAsync(cdndir);
await copy(outdir, cdndir);
});
if (copydir) {
// Copy the build output to an additional directory
await nextTask(`Copying the build to "${copydir}"`, async () => {
await deleteAsync(copydir);
await copy(outdir, copydir);
});
}
await nextTask('Building source files', async () => {
buildResults = await buildTheSource();
});
// Copy the CDN build to the docs
await nextTask(`Copying the build to "${sitedir}"`, async () => {
await deleteAsync(sitedir);
// We copy the CDN build because that has everything bundled.
await copy(cdndir, sitedir);
});
// Launch the dev server
if (serve) {
@ -215,7 +235,7 @@ if (serve) {
server: {
baseDir: sitedir,
routes: {
'/dist': './dist'
'/cdn': './cdn'
}
}
};
@ -243,16 +263,24 @@ if (serve) {
const isStylesheet = /(\.css|\.styles\.ts)$/.test(filename);
// Rebuild the source
await buildResult.rebuild();
await Promise.all([buildResults.map(result => result.rebuild())]);
// Rebuild stylesheets when a theme file changes
if (isTheme) {
await execPromise(`node scripts/make-themes.js --outdir "${outdir}"`, { stdio: 'inherit' });
await Promise.all(
bundleDirectories.map(dir => {
execPromise(`node scripts/make-themes.js --outdir "${dir}"`, { stdio: 'inherit' });
})
);
}
// Rebuild metadata (but not when styles are changed)
if (!isStylesheet) {
await execPromise(`node scripts/make-metadata.js --outdir "${outdir}"`, { stdio: 'inherit' });
await Promise.all(
bundleDirectories.map(dir => {
return execPromise(`node scripts/make-metadata.js --outdir "${dir}"`, { stdio: 'inherit' });
})
);
}
bs.reload();

Wyświetl plik

@ -23,7 +23,7 @@ const url = `https://github.com/twbs/icons/archive/v${version}.zip`;
try {
await fs.stat(`${srcPath}/LICENSE.md`);
} catch {
// Download the source from GitHub (since not everything is published to NPM)
// Download the source from GitHub (since not everything is published to npm)
await download(url, './.cache/icons', { extract: true });
}

Wyświetl plik

@ -1,4 +1,4 @@
import { registerTranslation } from '../utilities/localize';
import { registerTranslation } from '@shoelace-style/localize';
import type { Translation } from '../utilities/localize';
const translation: Translation = {

Wyświetl plik

@ -1,4 +1,4 @@
import '../translations/en';
import '../translations/en.js';
import { LocalizeController as DefaultLocalizationController } from '@shoelace-style/localize'; // Register English as the default/fallback language
import type { Translation as DefaultTranslation } from '@shoelace-style/localize';

Wyświetl plik

@ -28,8 +28,8 @@ export default {
<html lang="en-US">
<head></head>
<body>
<link rel="stylesheet" href="dist/themes/light.css">
<script type="module" src="dist/shoelace.js"></script>
<link rel="stylesheet" href="cdn/themes/light.css">
<script type="module" src="cdn/shoelace.js"></script>
<script type="module" src="${testFramework}"></script>
</body>
</html>