mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-19 23:44:15 +00:00
Compare commits
4 Commits
konnorroge
...
react-impo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77f6991e59 | ||
|
|
0efb9b2f78 | ||
|
|
39677bf37d | ||
|
|
8535883152 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,4 +6,3 @@ docs/assets/images/sprite.svg
|
||||
node_modules
|
||||
src/react
|
||||
cdn
|
||||
web-types.json
|
||||
@@ -7,7 +7,6 @@ docs/search.json
|
||||
src/components/icon/icons
|
||||
src/react/index.ts
|
||||
node_modules
|
||||
package.json
|
||||
package-lock.json
|
||||
tsconfig.json
|
||||
cdn
|
||||
|
||||
@@ -160,7 +160,6 @@
|
||||
"unbundles",
|
||||
"unbundling",
|
||||
"unicons",
|
||||
"unsanitized",
|
||||
"unsupportive",
|
||||
"valpha",
|
||||
"valuenow",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as path from 'path';
|
||||
import { customElementJetBrainsPlugin } from 'custom-element-jet-brains-integration';
|
||||
import { customElementVsCodePlugin } from 'custom-element-vs-code-integration';
|
||||
import { parse } from 'comment-parser';
|
||||
import { pascalCase } from 'pascal-case';
|
||||
@@ -201,15 +200,6 @@ export default {
|
||||
url: `https://shoelace.style/components/${tag.replace('sl-', '')}`
|
||||
}
|
||||
]
|
||||
}),
|
||||
customElementJetBrainsPlugin({
|
||||
excludeCss: true,
|
||||
referencesTemplate: (_, tag) => {
|
||||
return {
|
||||
name: 'Documentation',
|
||||
url: `https://shoelace.style/components/${tag.replace('sl-', '')}`
|
||||
};
|
||||
}
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
@@ -250,9 +250,7 @@ Note that multi-select options may wrap, causing the control to expand verticall
|
||||
|
||||
### Setting Initial Values
|
||||
|
||||
Use the `value` attribute to set the initial selection.
|
||||
|
||||
When using `multiple`, the `value` _attribute_ uses space-delimited values to select more than one option. Because of this, `<sl-option>` values cannot contain spaces. If you're accessing the `value` _property_ through Javascript, it will be an array.
|
||||
Use the `value` attribute to set the initial selection. When using `multiple`, use space-delimited values to select more than one option.
|
||||
|
||||
```html:preview
|
||||
<sl-select value="option-1 option-2" multiple clearable>
|
||||
@@ -454,53 +452,3 @@ const App = () => (
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Custom Tags
|
||||
|
||||
When multiple options can be selected, you can provide custom tags by passing a function to the `getTag` property. Your function can return a string of HTML, a <a href="https://lit.dev/docs/templates/overview/">Lit Template</a>, or an [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement). The `getTag()` function will be called for each option. The first argument is an `<sl-option>` element and the second argument is the tag's index (its position in the tag list).
|
||||
|
||||
Remember that custom tags are rendered in a shadow root. To style them, you can use the `style` attribute in your template or you can add your own [parts](/getting-started/customizing/#css-parts) and target them with the [`::part()`](https://developer.mozilla.org/en-US/docs/Web/CSS/::part) selector.
|
||||
|
||||
```html:preview
|
||||
<sl-select
|
||||
placeholder="Select one"
|
||||
value="email phone"
|
||||
multiple
|
||||
clearable
|
||||
class="custom-tag"
|
||||
>
|
||||
<sl-option value="email">
|
||||
<sl-icon slot="prefix" name="envelope"></sl-icon>
|
||||
Email
|
||||
</sl-option>
|
||||
<sl-option value="phone">
|
||||
<sl-icon slot="prefix" name="telephone"></sl-icon>
|
||||
Phone
|
||||
</sl-option>
|
||||
<sl-option value="chat">
|
||||
<sl-icon slot="prefix" name="chat-dots"></sl-icon>
|
||||
Chat
|
||||
</sl-option>
|
||||
</sl-select>
|
||||
|
||||
<script type="module">
|
||||
const select = document.querySelector('.custom-tag');
|
||||
|
||||
select.getTag = (option, index) => {
|
||||
// Use the same icon used in the <sl-option>
|
||||
const name = option.querySelector('sl-icon[slot="prefix"]').name;
|
||||
|
||||
// You can return a string, a Lit Template, or an HTMLElement here
|
||||
return `
|
||||
<sl-tag removable>
|
||||
<sl-icon name="${name}" style="padding-inline-end: .5rem;"></sl-icon>
|
||||
${option.getTextLabel()}
|
||||
</sl-tag>
|
||||
`;
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
:::warning
|
||||
Be sure you trust the content you are outputting! Passing unsanitized user input to `getTag()` can result in XSS vulnerabilities.
|
||||
:::
|
||||
|
||||
@@ -462,7 +462,7 @@ To disable the browser's error messages, you need to cancel the `sl-invalid` eve
|
||||
<sl-button type="reset" variant="default">Reset</sl-button>
|
||||
</form>
|
||||
|
||||
<script type="module">
|
||||
<script>
|
||||
const form = document.querySelector('.inline-validation');
|
||||
const nameError = document.querySelector('#name-error');
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ 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/%NPMDIR%');
|
||||
setBasePath('/path/to/shoelace/%NPMDIR%
|
||||
|
||||
// <sl-button>, <sl-icon>, <sl-input>, and <sl-rating> are ready to use!
|
||||
```
|
||||
|
||||
@@ -210,12 +210,6 @@ Shoelace ships with a file called `vscode.html-custom-data.json` that can be use
|
||||
|
||||
If `settings.json` already exists, simply add the above line to the root of the object. Note that you may need to restart VS Code for the changes to take affect.
|
||||
|
||||
## JetBrains IDEs
|
||||
|
||||
If you are using a [JetBrains IDE](https://www.jetbrains.com/) and you are installing Shoelace from NPM, the editor will automatically detect the `web-types.json` file from the package and you should immediately see component information in your editor.
|
||||
|
||||
If you are installing from the CDN, you can [download a local copy](https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace/cdn/web-types.json) and add it to the root of your project.
|
||||
|
||||
### Other Editors
|
||||
|
||||
Most popular editors support custom code completion with a bit of configuration. Please [submit a feature request](https://github.com/shoelace-style/shoelace/issues/new/choose) for your editor of choice. PRs are also welcome!
|
||||
|
||||
@@ -14,13 +14,7 @@ New versions of Shoelace are released as-needed and generally occur when a criti
|
||||
|
||||
## Next
|
||||
|
||||
- Fixed type issues with the `ref` attribute in React Wrappers. [#1526]
|
||||
- Fixed a regression that caused `<sl-radio-button>` to render incorrectly with gaps [#1523]
|
||||
- Improved expand/collapse behavior of `<sl-tree>` to work more like users expect [#1521]
|
||||
|
||||
## 2.7.0
|
||||
|
||||
- Added the experimental `<sl-copy-button>` component [#1473]
|
||||
- Added the `<sl-copy-button>` component [#1473]
|
||||
- Fixed a bug in `<sl-dropdown>` where pressing [[Up]] or [[Down]] when focused on the trigger wouldn't focus the first/last menu items [#1472]
|
||||
- Fixed a bug that caused key presses in text fields to be hijacked when used inside `<sl-tree>` [#1492]
|
||||
- Fixed an upstream bug that caused React CodePen examples to stop working
|
||||
|
||||
37
package-lock.json
generated
37
package-lock.json
generated
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"name": "@shoelace-style/shoelace",
|
||||
"version": "2.7.0",
|
||||
"version": "2.6.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@shoelace-style/shoelace",
|
||||
"version": "2.7.0",
|
||||
"version": "2.6.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ctrl/tinycolor": "^3.5.0",
|
||||
"@floating-ui/dom": "^1.2.1",
|
||||
"@lit-labs/react": "^1.2.1",
|
||||
"@lit-labs/react": "^1.1.1",
|
||||
"@shoelace-style/animations": "^1.1.0",
|
||||
"@shoelace-style/localize": "^3.1.1",
|
||||
"composed-offset-position": "^0.0.4",
|
||||
@@ -37,7 +37,6 @@
|
||||
"command-line-args": "^5.2.1",
|
||||
"comment-parser": "^1.3.1",
|
||||
"cspell": "^6.18.1",
|
||||
"custom-element-jet-brains-integration": "^1.1.0",
|
||||
"custom-element-vs-code-integration": "^1.1.0",
|
||||
"del": "^7.0.0",
|
||||
"download": "^8.0.0",
|
||||
@@ -1474,9 +1473,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lit-labs/react": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lit-labs/react/-/react-1.2.1.tgz",
|
||||
"integrity": "sha512-DiZdJYFU0tBbdQkfwwRSwYyI/mcWkg3sWesKRsHUd4G+NekTmmeq9fzsurvcKTNVa0comNljwtg4Hvi1ds3V+A=="
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@lit-labs/react/-/react-1.1.1.tgz",
|
||||
"integrity": "sha512-9TC+/ZWb6BJlWCyUr14FKFlaGnyKpeEDorufXozQgke/VoVrslUQNaL7nBmrAWdNrmzx5jWgi8lFmWwrxMjnlA=="
|
||||
},
|
||||
"node_modules/@lit-labs/ssr-dom-shim": {
|
||||
"version": "1.1.1",
|
||||
@@ -5688,15 +5687,6 @@
|
||||
"integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/custom-element-jet-brains-integration": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/custom-element-jet-brains-integration/-/custom-element-jet-brains-integration-1.1.0.tgz",
|
||||
"integrity": "sha512-wesa4OEvRQdxNzynk5ugU7ZRy0Ghkoaa6NmRGTqOASIng1hVaE3EKKO3rK11b4Y/pR3HUPIPKs1mRSnRCjHBfg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"prettier": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/custom-element-vs-code-integration": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/custom-element-vs-code-integration/-/custom-element-vs-code-integration-1.1.0.tgz",
|
||||
@@ -18291,9 +18281,9 @@
|
||||
}
|
||||
},
|
||||
"@lit-labs/react": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lit-labs/react/-/react-1.2.1.tgz",
|
||||
"integrity": "sha512-DiZdJYFU0tBbdQkfwwRSwYyI/mcWkg3sWesKRsHUd4G+NekTmmeq9fzsurvcKTNVa0comNljwtg4Hvi1ds3V+A=="
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@lit-labs/react/-/react-1.1.1.tgz",
|
||||
"integrity": "sha512-9TC+/ZWb6BJlWCyUr14FKFlaGnyKpeEDorufXozQgke/VoVrslUQNaL7nBmrAWdNrmzx5jWgi8lFmWwrxMjnlA=="
|
||||
},
|
||||
"@lit-labs/ssr-dom-shim": {
|
||||
"version": "1.1.1",
|
||||
@@ -21517,15 +21507,6 @@
|
||||
"integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==",
|
||||
"dev": true
|
||||
},
|
||||
"custom-element-jet-brains-integration": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/custom-element-jet-brains-integration/-/custom-element-jet-brains-integration-1.1.0.tgz",
|
||||
"integrity": "sha512-wesa4OEvRQdxNzynk5ugU7ZRy0Ghkoaa6NmRGTqOASIng1hVaE3EKKO3rK11b4Y/pR3HUPIPKs1mRSnRCjHBfg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"prettier": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"custom-element-vs-code-integration": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/custom-element-vs-code-integration/-/custom-element-vs-code-integration-1.1.0.tgz",
|
||||
|
||||
23
package.json
23
package.json
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@shoelace-style/shoelace",
|
||||
"description": "A forward-thinking library of web components.",
|
||||
"version": "2.7.0",
|
||||
"version": "2.6.0",
|
||||
"homepage": "https://github.com/shoelace-style/shoelace",
|
||||
"author": "Cory LaViska",
|
||||
"license": "MIT",
|
||||
"customElements": "dist/custom-elements.json",
|
||||
"web-types": "./web-types.json",
|
||||
"web-types": "dist/web-types.json",
|
||||
"type": "module",
|
||||
"types": "dist/shoelace.d.ts",
|
||||
"jsdelivr": "./cdn/shoelace-autoloader.js",
|
||||
@@ -25,8 +25,15 @@
|
||||
"./dist/react/*": "./dist/react/*",
|
||||
"./dist/translations/*": "./dist/translations/*"
|
||||
},
|
||||
"files": ["dist", "cdn"],
|
||||
"keywords": ["web components", "custom elements", "components"],
|
||||
"files": [
|
||||
"dist",
|
||||
"cdn"
|
||||
],
|
||||
"keywords": [
|
||||
"web components",
|
||||
"custom elements",
|
||||
"components"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/shoelace-style/shoelace.git"
|
||||
@@ -62,7 +69,7 @@
|
||||
"dependencies": {
|
||||
"@ctrl/tinycolor": "^3.5.0",
|
||||
"@floating-ui/dom": "^1.2.1",
|
||||
"@lit-labs/react": "^1.2.1",
|
||||
"@lit-labs/react": "^1.1.1",
|
||||
"@shoelace-style/animations": "^1.1.0",
|
||||
"@shoelace-style/localize": "^3.1.1",
|
||||
"composed-offset-position": "^0.0.4",
|
||||
@@ -88,7 +95,6 @@
|
||||
"command-line-args": "^5.2.1",
|
||||
"comment-parser": "^1.3.1",
|
||||
"cspell": "^6.18.1",
|
||||
"custom-element-jet-brains-integration": "^1.1.0",
|
||||
"custom-element-vs-code-integration": "^1.1.0",
|
||||
"del": "^7.0.0",
|
||||
"download": "^8.0.0",
|
||||
@@ -133,6 +139,9 @@
|
||||
"user-agent-data-types": "^0.3.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,js}": ["eslint --max-warnings 0 --cache --fix", "prettier --write"]
|
||||
"*.{ts,js}": [
|
||||
"eslint --max-warnings 0 --cache --fix",
|
||||
"prettier --write"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,6 +188,10 @@ await nextTask('Wrapping components for React', () => {
|
||||
return execPromise(`node scripts/make-react.js --outdir "${outdir}"`, { stdio: 'inherit' });
|
||||
});
|
||||
|
||||
await nextTask('Generating Web Types', () => {
|
||||
return execPromise(`node scripts/make-web-types.js --outdir "${outdir}"`, { stdio: 'inherit' });
|
||||
});
|
||||
|
||||
await nextTask('Generating themes', () => {
|
||||
return execPromise(`node scripts/make-themes.js --outdir "${outdir}"`, { stdio: 'inherit' });
|
||||
});
|
||||
@@ -203,7 +207,6 @@ await nextTask('Running the TypeScript compiler', () => {
|
||||
// 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('./web-types.json', `${outdir}/web-types.json`);
|
||||
await copy(outdir, cdndir);
|
||||
});
|
||||
|
||||
|
||||
@@ -51,15 +51,6 @@ components.map(component => {
|
||||
${eventImports}
|
||||
${eventExports}
|
||||
|
||||
export type ForwardComponent<
|
||||
Element extends HTMLElement,
|
||||
ReactComponent extends React.ElementType
|
||||
> = React.JSXElementConstructor<
|
||||
React.ComponentPropsWithoutRef<ReactComponent> & {
|
||||
ref?: React.ForwardedRef<Element>;
|
||||
}
|
||||
> & { displayName?: string }
|
||||
|
||||
const tagName = '${component.tagName}'
|
||||
|
||||
const component = createComponent({
|
||||
@@ -85,7 +76,7 @@ components.map(component => {
|
||||
}
|
||||
}
|
||||
|
||||
export default SlComponent as ForwardComponent<Component, typeof SlComponent>;
|
||||
export default SlComponent;
|
||||
`,
|
||||
Object.assign(prettierConfig, {
|
||||
parser: 'babel-ts'
|
||||
|
||||
68
scripts/make-web-types.js
Normal file
68
scripts/make-web-types.js
Normal file
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// This script generates a web-types.json file from custom-elements.json for use with WebStorm/PHPStorm
|
||||
//
|
||||
// Docs: https://github.com/JetBrains/web-types
|
||||
//
|
||||
import commandLineArgs from 'command-line-args';
|
||||
import jsonata from 'jsonata';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const { outdir } = commandLineArgs({ name: 'outdir', type: String });
|
||||
const metadata = JSON.parse(fs.readFileSync(path.join(outdir, 'custom-elements.json'), 'utf8'));
|
||||
|
||||
const jsonataExprString = `{
|
||||
"$schema": "http://json.schemastore.org/web-types",
|
||||
"name": package.name,
|
||||
"version": package.version,
|
||||
"description-markup": "markdown",
|
||||
"framework-config": {
|
||||
"enable-when": {
|
||||
"node-packages": [
|
||||
package.name
|
||||
]
|
||||
}
|
||||
},
|
||||
"contributions": {
|
||||
"html": {
|
||||
"elements": [
|
||||
modules.declarations.{
|
||||
"name": tagName,
|
||||
"description": description,
|
||||
"doc-url": $join(["https://shoelace.style/components/", $substringAfter(tagName, 'sl-')]),
|
||||
"js": {
|
||||
"properties": [
|
||||
members.{
|
||||
"name": name,
|
||||
"description": description,
|
||||
"value": {
|
||||
"type": type.text
|
||||
}
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
events.{
|
||||
"name": name,
|
||||
"description": description
|
||||
}
|
||||
]
|
||||
},
|
||||
"attributes": [
|
||||
attributes.{
|
||||
"name": name,
|
||||
"description": description,
|
||||
"value": {
|
||||
"type": type.text
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
const expression = jsonata(jsonataExprString);
|
||||
const result = await expression.evaluate(metadata);
|
||||
|
||||
fs.writeFileSync(path.join(outdir, 'web-types.json'), JSON.stringify(result, null, 2), 'utf8');
|
||||
@@ -54,7 +54,7 @@ export default class SlButtonGroup extends ShoelaceElement {
|
||||
const index = slottedElements.indexOf(el);
|
||||
const button = findButton(el);
|
||||
|
||||
if (button) {
|
||||
if (button !== null) {
|
||||
button.classList.add('sl-button-group__button');
|
||||
button.classList.toggle('sl-button-group__button--first', index === 0);
|
||||
button.classList.toggle('sl-button-group__button--inner', index > 0 && index < slottedElements.length - 1);
|
||||
|
||||
@@ -882,7 +882,7 @@ export default class SlColorPicker extends ShoelaceElement implements ShoelaceFo
|
||||
style=${styleMap({
|
||||
backgroundImage: `linear-gradient(
|
||||
to right,
|
||||
${this.getHexString(this.hue, this.saturation, this.brightness, 0)} 0%,
|
||||
${this.getHexString(this.hue, this.saturation, this.brightness, 0)} 0%
|
||||
${this.getHexString(this.hue, this.saturation, this.brightness, 100)} 100%
|
||||
)`
|
||||
})}
|
||||
|
||||
@@ -90,15 +90,15 @@ export default class SlDetails extends ShoelaceElement {
|
||||
this.detailsObserver.disconnect();
|
||||
}
|
||||
|
||||
private handleSummaryClick(event: MouseEvent) {
|
||||
event.preventDefault();
|
||||
|
||||
private handleSummaryClick(ev: MouseEvent) {
|
||||
ev.preventDefault();
|
||||
if (!this.disabled) {
|
||||
if (this.open) {
|
||||
this.hide();
|
||||
} else {
|
||||
this.show();
|
||||
}
|
||||
|
||||
this.header.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,26 +20,4 @@ describe('<sl-radio-button>', () => {
|
||||
expect(radio1.checked).to.be.true;
|
||||
expect(radio2.checked).to.be.false;
|
||||
});
|
||||
|
||||
it('should receive positional classes from <sl-button-group>', async () => {
|
||||
const radioGroup = await fixture<SlRadioGroup>(html`
|
||||
<sl-radio-group value="1">
|
||||
<sl-radio-button id="radio-1" value="1"></sl-radio-button>
|
||||
<sl-radio-button id="radio-2" value="2"></sl-radio-button>
|
||||
<sl-radio-button id="radio-3" value="3"></sl-radio-button>
|
||||
</sl-radio-group>
|
||||
`);
|
||||
const radio1 = radioGroup.querySelector<SlRadioButton>('#radio-1')!;
|
||||
const radio2 = radioGroup.querySelector<SlRadioButton>('#radio-2')!;
|
||||
const radio3 = radioGroup.querySelector<SlRadioButton>('#radio-3')!;
|
||||
|
||||
await Promise.all([radioGroup.updateComplete, radio1.updateComplete, radio2.updateComplete, radio3.updateComplete]);
|
||||
|
||||
expect(radio1.classList.contains('sl-button-group__button')).to.be.true;
|
||||
expect(radio1.classList.contains('sl-button-group__button--first')).to.be.true;
|
||||
expect(radio2.classList.contains('sl-button-group__button')).to.be.true;
|
||||
expect(radio2.classList.contains('sl-button-group__button--inner')).to.be.true;
|
||||
expect(radio3.classList.contains('sl-button-group__button')).to.be.true;
|
||||
expect(radio3.classList.contains('sl-button-group__button--last')).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -327,8 +327,11 @@ export default class SlRadioGroup extends ShoelaceElement implements ShoelaceFor
|
||||
const hasHelpTextSlot = this.hasSlotController.test('help-text');
|
||||
const hasLabel = this.label ? true : !!hasLabelSlot;
|
||||
const hasHelpText = this.helpText ? true : !!hasHelpTextSlot;
|
||||
|
||||
const defaultSlot = html`
|
||||
<slot @slotchange=${this.syncRadios} @click=${this.handleRadioClick} @keydown=${this.handleKeyDown}></slot>
|
||||
<span @click=${this.handleRadioClick} @keydown=${this.handleKeyDown} role="presentation">
|
||||
<slot @slotchange=${this.syncRadios}></slot>
|
||||
</span>
|
||||
`;
|
||||
|
||||
return html`
|
||||
@@ -375,7 +378,7 @@ export default class SlRadioGroup extends ShoelaceElement implements ShoelaceFor
|
||||
|
||||
${this.hasButtonGroup
|
||||
? html`
|
||||
<sl-button-group part="button-group" exportparts="base:button-group__base" role="presentation">
|
||||
<sl-button-group part="button-group" exportparts="base:button-group__base">
|
||||
${defaultSlot}
|
||||
</sl-button-group>
|
||||
`
|
||||
@@ -392,5 +395,6 @@ export default class SlRadioGroup extends ShoelaceElement implements ShoelaceFor
|
||||
</div>
|
||||
</fieldset>
|
||||
`;
|
||||
/* eslint-enable lit-a11y/click-events-have-key-events */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import { html } from 'lit';
|
||||
import { LocalizeController } from '../../utilities/localize.js';
|
||||
import { property, query, state } from 'lit/decorators.js';
|
||||
import { scrollIntoView } from '../../internal/scroll.js';
|
||||
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
||||
import { waitForEvent } from '../../internal/event.js';
|
||||
import { watch } from '../../internal/watch.js';
|
||||
import ShoelaceElement from '../../internal/shoelace-element.js';
|
||||
@@ -16,7 +15,7 @@ import SlIcon from '../icon/icon.component.js';
|
||||
import SlPopup from '../popup/popup.component.js';
|
||||
import SlTag from '../tag/tag.component.js';
|
||||
import styles from './select.styles.js';
|
||||
import type { CSSResultGroup, TemplateResult } from 'lit';
|
||||
import type { CSSResultGroup } from 'lit';
|
||||
import type { ShoelaceFormControl } from '../../internal/shoelace-element.js';
|
||||
import type SlOption from '../option/option.component.js';
|
||||
import type SlRemoveEvent from '../../events/sl-remove.js';
|
||||
@@ -173,31 +172,6 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
|
||||
/** The select's required attribute. */
|
||||
@property({ type: Boolean, reflect: true }) required = false;
|
||||
|
||||
/**
|
||||
* A function that customizes the tags to be rendered when multiple=true. The first argument is the option, the second
|
||||
* is the current tag's index. The function should return either a Lit TemplateResult or a string containing trusted HTML of the symbol to render at
|
||||
* the specified value.
|
||||
*/
|
||||
@property() getTag: (option: SlOption, index: number) => TemplateResult | string | HTMLElement = option => {
|
||||
return html`
|
||||
<sl-tag
|
||||
part="tag"
|
||||
exportparts="
|
||||
base:tag__base,
|
||||
content:tag__content,
|
||||
remove-button:tag__remove-button,
|
||||
remove-button__base:tag__remove-button__base
|
||||
"
|
||||
?pill=${this.pill}
|
||||
size=${this.size}
|
||||
removable
|
||||
@sl-remove=${(event: SlRemoveEvent) => this.handleTagRemove(event, option)}
|
||||
>
|
||||
${option.getTextLabel()}
|
||||
</sl-tag>
|
||||
`;
|
||||
};
|
||||
|
||||
/** Gets the validity state object */
|
||||
get validity() {
|
||||
return this.valueInput.validity;
|
||||
@@ -573,21 +547,6 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
|
||||
this.formControlController.updateValidity();
|
||||
});
|
||||
}
|
||||
protected get tags() {
|
||||
return this.selectedOptions.map((option, index) => {
|
||||
if (index < this.maxOptionsVisible || this.maxOptionsVisible <= 0) {
|
||||
const tag = this.getTag(option, index);
|
||||
// Wrap so we can handle the remove
|
||||
return html`<div @sl-remove=${(e: SlRemoveEvent) => this.handleTagRemove(e, option)}>
|
||||
${typeof tag === 'string' ? unsafeHTML(tag) : tag}
|
||||
</div>`;
|
||||
} else if (index === this.maxOptionsVisible) {
|
||||
// Hit tag limit
|
||||
return html`<sl-tag>+${this.selectedOptions.length - index}</sl-tag>`;
|
||||
}
|
||||
return html``;
|
||||
});
|
||||
}
|
||||
|
||||
private handleInvalid(event: Event) {
|
||||
this.formControlController.setValidity(false);
|
||||
@@ -796,7 +755,37 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
|
||||
@blur=${this.handleBlur}
|
||||
/>
|
||||
|
||||
${this.multiple ? html`<div part="tags" class="select__tags">${this.tags}</div>` : ''}
|
||||
${this.multiple
|
||||
? html`
|
||||
<div part="tags" class="select__tags">
|
||||
${this.selectedOptions.map((option, index) => {
|
||||
if (index < this.maxOptionsVisible || this.maxOptionsVisible <= 0) {
|
||||
return html`
|
||||
<sl-tag
|
||||
part="tag"
|
||||
exportparts="
|
||||
base:tag__base,
|
||||
content:tag__content,
|
||||
remove-button:tag__remove-button,
|
||||
remove-button__base:tag__remove-button__base
|
||||
"
|
||||
?pill=${this.pill}
|
||||
size=${this.size}
|
||||
removable
|
||||
@sl-remove=${(event: SlRemoveEvent) => this.handleTagRemove(event, option)}
|
||||
>
|
||||
${option.getTextLabel()}
|
||||
</sl-tag>
|
||||
`;
|
||||
} else if (index === this.maxOptionsVisible) {
|
||||
return html` <sl-tag size=${this.size}> +${this.selectedOptions.length - index} </sl-tag> `;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
`
|
||||
: ''}
|
||||
|
||||
<input
|
||||
class="select__value-input"
|
||||
|
||||
@@ -168,6 +168,20 @@ export default class SlTree extends ShoelaceElement {
|
||||
}
|
||||
};
|
||||
|
||||
private syncTreeItems(selectedItem: SlTreeItem) {
|
||||
const items = this.getAllTreeItems();
|
||||
|
||||
if (this.selection === 'multiple') {
|
||||
syncCheckboxes(selectedItem);
|
||||
} else {
|
||||
for (const item of items) {
|
||||
if (item !== selectedItem) {
|
||||
item.selected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private selectItem(selectedItem: SlTreeItem) {
|
||||
const previousSelection = [...this.selectedItems];
|
||||
|
||||
@@ -176,12 +190,12 @@ export default class SlTree extends ShoelaceElement {
|
||||
if (selectedItem.lazy) {
|
||||
selectedItem.expanded = true;
|
||||
}
|
||||
syncCheckboxes(selectedItem);
|
||||
this.syncTreeItems(selectedItem);
|
||||
} else if (this.selection === 'single' || selectedItem.isLeaf) {
|
||||
const items = this.getAllTreeItems();
|
||||
for (const item of items) {
|
||||
item.selected = item === selectedItem;
|
||||
}
|
||||
selectedItem.expanded = !selectedItem.expanded;
|
||||
selectedItem.selected = true;
|
||||
|
||||
this.syncTreeItems(selectedItem);
|
||||
} else if (this.selection === 'leaf') {
|
||||
selectedItem.expanded = !selectedItem.expanded;
|
||||
}
|
||||
@@ -297,7 +311,7 @@ export default class SlTree extends ShoelaceElement {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isExpandButton) {
|
||||
if (this.selection === 'multiple' && isExpandButton) {
|
||||
treeItem.expanded = !treeItem.expanded;
|
||||
} else {
|
||||
this.selectItem(treeItem);
|
||||
|
||||
@@ -275,6 +275,7 @@ describe('<sl-tree>', () => {
|
||||
// Assert
|
||||
expect(el.selectedItems.length).to.eq(1);
|
||||
expect(el.children[2]).to.have.attribute('selected');
|
||||
expect(el.children[2]).to.have.attribute('expanded');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -438,6 +439,7 @@ describe('<sl-tree>', () => {
|
||||
await el.updateComplete;
|
||||
|
||||
// Assert
|
||||
expect(node).to.have.attribute('selected');
|
||||
expect(node).to.have.attribute('expanded');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -133,10 +133,10 @@ before(async () => {
|
||||
|
||||
relevantMetadata.forEach(({ tagName, path }) => {
|
||||
it(`Should not register any components: ${tagName}`, async () => {
|
||||
// Check if importing the files automatically registers any components
|
||||
await import('../../dist/' + path);
|
||||
|
||||
// Need to make sure we remove the current tag from the tagNames and *then* see whats been registered.
|
||||
const registeredTags = tagNames.filter(tag => tag !== tagName && Boolean(window.customElements.get(tag)));
|
||||
const registeredTags = tagNames.filter(tag => Boolean(window.customElements.get(tag)));
|
||||
|
||||
const errorMessage =
|
||||
`Expected ${path} to not register any tags, but it registered the following tags: ` +
|
||||
|
||||
Reference in New Issue
Block a user