feat(accordion): add exclusive option (#2372)

* Added exclusive feature for accordion

* Changed position of exclusive accordion

* chore: accordion [exclusive] option

* chore: accordion [exclusive] option

* chore: fixes and cleanups

* chore: get docs of accordion back

---------

Co-authored-by: Thijs Louisse <Thijs.Louisse@ing.com>
Co-authored-by: gerjanvangeest <Gerjan.van.Geest@ing.com>
This commit is contained in:
John Clifford 2024-10-03 19:22:39 +05:30 committed by GitHub
parent 5ce7fee5f2
commit 4696ad72c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 492 additions and 468 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': patch
---
[accordion] new "exclusive" feature, allowing one opened collapsible at a time

View file

@ -15,7 +15,7 @@ All accordion panels are collapsed by default.
<h3 slot="invoker">
<button>Sensory Factors</button>
</h3>
<div slot="content" class="lion-paragraph-container">
<div slot="content">
<p>
The taste of oranges is determined mainly by the relative ratios of sugars and acids, whereas
orange aroma derives from volatile organic compounds, including alcohols, aldehydes, ketones,
@ -52,7 +52,7 @@ Multiple accordion panels can be expanded at the same time. When content drops o
<h3 slot="invoker">
<button>Sensory Factors</button>
</h3>
<div slot="content" class="lion-paragraph-container">
<div slot="content">
<p>
The taste of oranges is determined mainly by the relative ratios of sugars and acids, whereas
orange aroma derives from volatile organic compounds, including alcohols, aldehydes, ketones,
@ -92,7 +92,7 @@ The invoker and content slots are ordered by DOM order. This means you can put a
<h3 slot="invoker">
<button>Nutritional value</button>
</h3>
<div slot="content" class="lion-paragraph-container">
<div slot="content">
<p>
The taste of oranges is determined mainly by the relative ratios of sugars and acids, whereas
orange aroma derives from volatile organic compounds, including alcohols, aldehydes, ketones,
@ -129,7 +129,7 @@ A header can be multiline.
<small>or the experience of taste</small>
</button>
</h3>
<div slot="content" class="lion-paragraph-container">
<div slot="content">
<p>
The taste of oranges is determined mainly by the relative ratios of sugars and acids, whereas
orange aroma derives from volatile organic compounds, including alcohols, aldehydes, ketones,
@ -160,6 +160,45 @@ A header can be multiline.
</lion-accordion>
```
## Exclusive
Sometimes, it might be required to show only one expanded slot of the accordion at a time. For such instances, we have a feature called 'exclusive'. This allows the accordion to open only one and a time and closes the open slot when a new slot is clicked upon.
This field takes in a Boolean value, which by default is false.
```html preview-story
<lion-accordion exclusive>
<h3 slot="invoker">
<button>This collapsible closes all other ones</button>
</h3>
<div slot="content">
<p>
The taste of oranges is determined mainly by the relative ratios of sugars and acids, whereas
orange aroma derives from volatile organic compounds, including alcohols, aldehydes, ketones,
terpenes, and esters. Bitter limonoid compounds, such as limonin, decrease gradually during
development, whereas volatile aroma compounds tend to peak in mid to lateseason development.
Taste quality tends to improve later in harvests when there is a higher sugar/acid ratio with
less bitterness. As a citrus fruit, the orange is acidic, with pH levels ranging from 2.9 to
4.0.
</p>
<p>
Sensory qualities vary according to genetic background, environmental conditions during
development, ripeness at harvest, postharvest conditions, and storage duration.
</p>
</div>
<h3 slot="invoker">
<button>Same for this collapsible</button>
</h3>
<div slot="content">
Orange flesh is 87% water, 12% carbohydrates, 1% protein, and contains negligible fat (table).
In a 100 gram reference amount, orange flesh provides 47 calories, and is a rich source of
vitamin C, providing 64% of the Daily Value. No other micronutrients are present in significant
amounts (table).
</div>
</lion-accordion>
```
## Distribute New Elements
Below, we demonstrate how you could dynamically add a new invoker + content.

View file

@ -31,10 +31,7 @@ Our recommendation would be to set the `name` attribute only on the `lion-checkb
## Example
```html
<lion-checkbox-group
name="scientists[]"
label="Favorite scientists"
>
<lion-checkbox-group name="scientists[]" label="Favorite scientists">
<lion-checkbox label="Archimedes" .choiceValue="${'Archimedes'}"></lion-checkbox>
<lion-checkbox label="Francis Bacon" .choiceValue="${'Francis Bacon'}"></lion-checkbox>
<lion-checkbox label="Marie Curie" .choiceValue="${'Marie Curie'}"></lion-checkbox>
@ -145,25 +142,13 @@ A `checkbox-indeterminate`'s value is neither true nor false, but is instead ind
```html preview-story
<lion-checkbox-group name="scientists[]" label="Favorite scientists">
<lion-checkbox-indeterminate label="Old Greek scientists">
<lion-checkbox
label="Archimedes"
.choiceValue="${'Archimedes'}"
></lion-checkbox>
<lion-checkbox label="Archimedes" .choiceValue="${'Archimedes'}"></lion-checkbox>
<lion-checkbox label="Plato" .choiceValue="${'Plato'}"></lion-checkbox>
<lion-checkbox
label="Pythagoras"
.choiceValue="${'Pythagoras'}"
></lion-checkbox>
<lion-checkbox label="Pythagoras" .choiceValue="${'Pythagoras'}"></lion-checkbox>
</lion-checkbox-indeterminate>
<lion-checkbox-indeterminate label="17th Century scientists">
<lion-checkbox
label="Isaac Newton"
.choiceValue="${'Isaac Newton'}"
></lion-checkbox>
<lion-checkbox
label="Galileo Galilei"
.choiceValue="${'Galileo Galilei'}"
></lion-checkbox>
<lion-checkbox label="Isaac Newton" .choiceValue="${'Isaac Newton'}"></lion-checkbox>
<lion-checkbox label="Galileo Galilei" .choiceValue="${'Galileo Galilei'}"></lion-checkbox>
</lion-checkbox-indeterminate>
</lion-checkbox-group>
```
@ -173,24 +158,12 @@ The `checkbox-indeterminate` can have another `checkbox-indeterminate` as a chil
```html preview-story
<lion-checkbox-group name="scientists[]" label="Favorite scientists">
<lion-checkbox-indeterminate label="Scientists">
<lion-checkbox
label="Isaac Newton"
.choiceValue="${'Isaac Newton'}"
></lion-checkbox>
<lion-checkbox
label="Galileo Galilei"
.choiceValue="${'Galileo Galilei'}"
></lion-checkbox>
<lion-checkbox label="Isaac Newton" .choiceValue="${'Isaac Newton'}"></lion-checkbox>
<lion-checkbox label="Galileo Galilei" .choiceValue="${'Galileo Galilei'}"></lion-checkbox>
<lion-checkbox-indeterminate label="Old Greek scientists">
<lion-checkbox
label="Archimedes"
.choiceValue="${'Archimedes'}"
></lion-checkbox>
<lion-checkbox label="Archimedes" .choiceValue="${'Archimedes'}"></lion-checkbox>
<lion-checkbox label="Plato" .choiceValue="${'Plato'}"></lion-checkbox>
<lion-checkbox
label="Pythagoras"
.choiceValue="${'Pythagoras'}"
></lion-checkbox>
<lion-checkbox label="Pythagoras" .choiceValue="${'Pythagoras'}"></lion-checkbox>
</lion-checkbox-indeterminate>
</lion-checkbox-indeterminate>
</lion-checkbox-group>
@ -201,24 +174,12 @@ You can also use `mixed-state` attribute so your indeterminate checkbox toggles
```html preview-story
<lion-checkbox-group name="scientists[]" label="Favorite scientists">
<lion-checkbox-indeterminate mixed-state label="Scientists">
<lion-checkbox
label="Isaac Newton"
.choiceValue="${'Isaac Newton'}"
></lion-checkbox>
<lion-checkbox
label="Galileo Galilei"
.choiceValue="${'Galileo Galilei'}"
></lion-checkbox>
<lion-checkbox label="Isaac Newton" .choiceValue="${'Isaac Newton'}"></lion-checkbox>
<lion-checkbox label="Galileo Galilei" .choiceValue="${'Galileo Galilei'}"></lion-checkbox>
<lion-checkbox-indeterminate mixed-state label="Old Greek scientists">
<lion-checkbox
label="Archimedes"
.choiceValue="${'Archimedes'}"
></lion-checkbox>
<lion-checkbox label="Archimedes" .choiceValue="${'Archimedes'}"></lion-checkbox>
<lion-checkbox label="Plato" .choiceValue="${'Plato'}"></lion-checkbox>
<lion-checkbox
label="Pythagoras"
.choiceValue="${'Pythagoras'}"
></lion-checkbox>
<lion-checkbox label="Pythagoras" .choiceValue="${'Pythagoras'}"></lion-checkbox>
</lion-checkbox-indeterminate>
</lion-checkbox-indeterminate>
</lion-checkbox-group>

View file

@ -41,7 +41,12 @@ export const disabled = () => {
<lion-input name="FirstName" label="First Name" .modelValue="${'Foo'}"></lion-input>
<lion-input name="LastName" label="Last Name" .modelValue="${'Bar'}"></lion-input>
<lion-fieldset name="nameGroup2" label="Name">
<lion-input name="FirstName2" label="First Name" .modelValue="${'Foo'}" disabled></lion-input>
<lion-input
name="FirstName2"
label="First Name"
.modelValue="${'Foo'}"
disabled
></lion-input>
<lion-input name="LastName2" label="Last Name" .modelValue="${'Bar'}"></lion-input>
</lion-fieldset>
</lion-fieldset>
@ -70,7 +75,9 @@ export const nestingFieldsets = () => html`
Log everything to Action Logger
</button>
<br />
<button @click="${ev => console.log(ev.target.parentElement.formElements.nameGroup.modelValue)}">
<button
@click="${ev => console.log(ev.target.parentElement.formElements.nameGroup.modelValue)}"
>
Log only Name fieldset to Action Logger
</button>
</lion-fieldset>

View file

@ -55,7 +55,8 @@ export const formSubmit = () => {
<button>Submit</button>
<button
type="button"
@click="${ev => ev.currentTarget.parentElement.parentElement.parentElement.resetGroup()}"
@click="${ev =>
ev.currentTarget.parentElement.parentElement.parentElement.resetGroup()}"
>
Reset
</button>

View file

@ -96,10 +96,10 @@ export const noDecimals = () => html`
<lion-input-amount
label="Amount"
help-text="Prefilled and formatted"
.formatOptions="${({
.formatOptions="${{
minimumFractionDigits: 0,
maximumFractionDigits: 0,
})}"
}}"
.modelValue="${20}"
>
</lion-input-amount>

View file

@ -58,7 +58,9 @@ export const withMinimumAndMaximumDate = () => {
<lion-input-date
label="MinMaxDate"
.modelValue="${new Date('2018/05/30')}"
.validators="${[new MinMaxDate({ min: new Date('2018/05/24'), max: new Date('2018/06/24') })]}"
.validators="${[
new MinMaxDate({ min: new Date('2018/05/24'), max: new Date('2018/06/24') }),
]}"
>
<div slot="help-text">
Enter a date between ${formatDate(new Date('2018/05/24'))} and ${formatDate(

View file

@ -58,7 +58,9 @@ export const methods = ({ shadowRoot }) => {
<button @click="${() => shadowRoot.getElementById('pagination-method').next()}">Next</button>
<br />
<br />
<button @click="${() => shadowRoot.getElementById('pagination-method').first()}">First</button>
<button @click="${() => shadowRoot.getElementById('pagination-method').first()}">
First
</button>
<button @click="${() => shadowRoot.getElementById('pagination-method').last()}">Last</button>
<br />
<br />

View file

@ -13,14 +13,18 @@ export const main = () => html`
<lion-steps>
<lion-step initial-step>
Step 1
<button type="button" @click="${ev => ev.target.parentElement.controller.next()}">Next</button>
<button type="button" @click="${ev => ev.target.parentElement.controller.next()}">
Next
</button>
</lion-step>
<lion-step>
<button type="button" @click="${ev => ev.target.parentElement.controller.previous()}">
Previous
</button>
Step 2
<button type="button" @click="${ev => ev.target.parentElement.controller.next()}">Next</button>
<button type="button" @click="${ev => ev.target.parentElement.controller.next()}">
Next
</button>
</lion-step>
<lion-step>
<button type="button" @click="${ev => ev.target.parentElement.controller.previous()}">

View file

@ -12,7 +12,9 @@ export const main = () => html`
<lion-step initial-step>
<p>Welcome</p>
<button disabled>previous</button> &nbsp;
<button type="button" @click="${ev => ev.target.parentElement.controller.next()}">Next</button>
<button type="button" @click="${ev => ev.target.parentElement.controller.next()}">
Next
</button>
</lion-step>
<lion-step>
<p>Are you single?</p>
@ -46,7 +48,9 @@ export const main = () => html`
Previous
</button>
&nbsp;
<button type="button" @click="${ev => ev.target.parentElement.controller.next()}">Next</button>
<button type="button" @click="${ev => ev.target.parentElement.controller.next()}">
Next
</button>
</lion-step>
<lion-step id="is-not-single" .condition="${data => data.isSingle}" invert-condition>
<p>You are NOT single.</p>
@ -54,7 +58,9 @@ export const main = () => html`
Previous
</button>
&nbsp;
<button type="button" @click="${ev => ev.target.parentElement.controller.next()}">Next</button>
<button type="button" @click="${ev => ev.target.parentElement.controller.next()}">
Next
</button>
</lion-step>
<lion-step>
<p>Finish</p>

View file

@ -162,7 +162,8 @@ export const main = () => {
<div class="buttons">
<lion-button-submit>Submit</lion-button-submit>
<lion-button-reset
@click="${ev => ev.currentTarget.parentElement.parentElement.parentElement.resetGroup()}"
@click="${ev =>
ev.currentTarget.parentElement.parentElement.parentElement.resetGroup()}"
>Reset</lion-button-reset
>
</div>

View file

@ -309,7 +309,9 @@ localize.setupNamespaceLoader('my-hello-component', async locale => {
// for all components which have a prefix in their names
localize.setupNamespaceLoader(/my-.+/, async (locale, namespace) => {
const response = await fetch(`https://api.example.com/?namespace="${namespace}&locale=${locale}"`);
const response = await fetch(
`https://api.example.com/?namespace="${namespace}&locale=${locale}"`,
);
return response.json();
});
```

View file

@ -29,7 +29,9 @@ export const main = () => html`
<button slot="invoker">Click me to open the overlay!</button>
<div slot="content" class="demo-overlay">
Hello! You can close this notification here:
<button @click="${e => e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}">
<button
@click="${e => e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}"
>
</button>
</div>

637
package-lock.json generated
View file

@ -159,6 +159,47 @@
"url": "https://opencollective.com/11ty"
}
},
"node_modules/@11ty/eleventy-img/node_modules/color": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
"integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^1.9.3",
"color-string": "^1.6.0"
}
},
"node_modules/@11ty/eleventy-img/node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-name": "1.1.3"
}
},
"node_modules/@11ty/eleventy-img/node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"dev": true,
"license": "MIT"
},
"node_modules/@11ty/eleventy-img/node_modules/decompress-response": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
"dev": true,
"license": "MIT",
"dependencies": {
"mimic-response": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@11ty/eleventy-img/node_modules/fs-extra": {
"version": "9.1.0",
"dev": true,
@ -184,6 +225,110 @@
"graceful-fs": "^4.1.6"
}
},
"node_modules/@11ty/eleventy-img/node_modules/mimic-response": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@11ty/eleventy-img/node_modules/node-abi": {
"version": "2.30.1",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz",
"integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"semver": "^5.4.1"
}
},
"node_modules/@11ty/eleventy-img/node_modules/node-abi/node_modules/semver": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver"
}
},
"node_modules/@11ty/eleventy-img/node_modules/node-addon-api": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz",
"integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==",
"dev": true,
"license": "MIT"
},
"node_modules/@11ty/eleventy-img/node_modules/prebuild-install": {
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz",
"integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"detect-libc": "^1.0.3",
"expand-template": "^2.0.3",
"github-from-package": "0.0.0",
"minimist": "^1.2.3",
"mkdirp-classic": "^0.5.3",
"napi-build-utils": "^1.0.1",
"node-abi": "^2.21.0",
"npmlog": "^4.0.1",
"pump": "^3.0.0",
"rc": "^1.2.7",
"simple-get": "^3.0.3",
"tar-fs": "^2.0.0",
"tunnel-agent": "^0.6.0"
},
"bin": {
"prebuild-install": "bin.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@11ty/eleventy-img/node_modules/sharp": {
"version": "0.28.3",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.28.3.tgz",
"integrity": "sha512-21GEP45Rmr7q2qcmdnjDkNP04Ooh5v0laGS5FDpojOO84D1DJwUijLiSq8XNNM6e8aGXYtoYRh3sVNdm8NodMA==",
"dev": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"color": "^3.1.3",
"detect-libc": "^1.0.3",
"node-addon-api": "^3.2.0",
"prebuild-install": "^6.1.2",
"semver": "^7.3.5",
"simple-get": "^3.1.0",
"tar-fs": "^2.1.1",
"tunnel-agent": "^0.6.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@11ty/eleventy-img/node_modules/simple-get": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
"integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
"dev": true,
"license": "MIT",
"dependencies": {
"decompress-response": "^4.2.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"node_modules/@11ty/eleventy-img/node_modules/universalify": {
"version": "2.0.0",
"dev": true,
@ -7235,6 +7380,13 @@
"node": ">= 8"
}
},
"node_modules/aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
"dev": true,
"license": "ISC"
},
"node_modules/archiver": {
"version": "7.0.1",
"dev": true,
@ -7419,6 +7571,18 @@
"streamx": "^2.15.0"
}
},
"node_modules/are-we-there-yet": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
"integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
"deprecated": "This package is no longer supported.",
"dev": true,
"license": "ISC",
"dependencies": {
"delegates": "^1.0.0",
"readable-stream": "^2.0.6"
}
},
"node_modules/argparse": {
"version": "1.0.10",
"dev": true,
@ -8826,16 +8990,14 @@
"type-is": "^1.6.16"
}
},
"node_modules/color": {
"version": "4.2.3",
"node_modules/code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
},
"engines": {
"node": ">=12.5.0"
"node": ">=0.10.0"
}
},
"node_modules/color-convert": {
@ -9167,6 +9329,13 @@
"dev": true,
"license": "MIT"
},
"node_modules/console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
"dev": true,
"license": "ISC"
},
"node_modules/constantinople": {
"version": "3.1.2",
"dev": true,
@ -11657,6 +11826,75 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
"deprecated": "This package is no longer supported.",
"dev": true,
"license": "ISC",
"dependencies": {
"aproba": "^1.0.3",
"console-control-strings": "^1.0.0",
"has-unicode": "^2.0.0",
"object-assign": "^4.1.0",
"signal-exit": "^3.0.0",
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wide-align": "^1.1.0"
}
},
"node_modules/gauge/node_modules/ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/gauge/node_modules/is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
"dev": true,
"license": "MIT",
"dependencies": {
"number-is-nan": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/gauge/node_modules/string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==",
"dev": true,
"license": "MIT",
"dependencies": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/gauge/node_modules/strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/geckodriver": {
"version": "4.4.0",
"dev": true,
@ -12251,6 +12489,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
"dev": true,
"license": "ISC"
},
"node_modules/hash-string": {
"version": "1.0.0",
"dev": true,
@ -16339,22 +16584,6 @@
"tslib": "^2.0.3"
}
},
"node_modules/node-abi": {
"version": "3.33.0",
"dev": true,
"license": "MIT",
"dependencies": {
"semver": "^7.3.5"
},
"engines": {
"node": ">=10"
}
},
"node_modules/node-addon-api": {
"version": "4.3.0",
"dev": true,
"license": "MIT"
},
"node_modules/node-domexception": {
"version": "1.0.0",
"dev": true,
@ -16644,6 +16873,20 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"deprecated": "This package is no longer supported.",
"dev": true,
"license": "ISC",
"dependencies": {
"are-we-there-yet": "~1.1.2",
"console-control-strings": "~1.1.0",
"gauge": "~2.7.3",
"set-blocking": "~2.0.0"
}
},
"node_modules/nth-check": {
"version": "2.1.1",
"license": "BSD-2-Clause",
@ -16654,6 +16897,16 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/nunjucks": {
"version": "3.2.3",
"dev": true,
@ -17661,39 +17914,6 @@
"hasInstallScript": true,
"license": "MIT"
},
"node_modules/prebuild-install": {
"version": "7.1.1",
"dev": true,
"license": "MIT",
"dependencies": {
"detect-libc": "^2.0.0",
"expand-template": "^2.0.3",
"github-from-package": "0.0.0",
"minimist": "^1.2.3",
"mkdirp-classic": "^0.5.3",
"napi-build-utils": "^1.0.1",
"node-abi": "^3.3.0",
"pump": "^3.0.0",
"rc": "^1.2.7",
"simple-get": "^4.0.0",
"tar-fs": "^2.0.0",
"tunnel-agent": "^0.6.0"
},
"bin": {
"prebuild-install": "bin.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/prebuild-install/node_modules/detect-libc": {
"version": "2.0.1",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">=8"
}
},
"node_modules/preferred-pm": {
"version": "3.0.3",
"dev": true,
@ -19962,28 +20182,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/sharp": {
"version": "0.29.3",
"dev": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"color": "^4.0.1",
"detect-libc": "^1.0.3",
"node-addon-api": "^4.2.0",
"prebuild-install": "^7.0.0",
"semver": "^7.3.5",
"simple-get": "^4.0.0",
"tar-fs": "^2.1.1",
"tunnel-agent": "^0.6.0"
},
"engines": {
"node": ">=12.13.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"dev": true,
@ -20066,30 +20264,6 @@
],
"license": "MIT"
},
"node_modules/simple-get": {
"version": "4.0.1",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT",
"dependencies": {
"decompress-response": "^6.0.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"node_modules/simple-swizzle": {
"version": "0.2.2",
"dev": true,
@ -22152,6 +22326,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/wide-align": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
"dev": true,
"license": "ISC",
"dependencies": {
"string-width": "^1.0.2 || 2 || 3 || 4"
}
},
"node_modules/window-size": {
"version": "0.1.0",
"dev": true,
@ -23008,111 +23192,6 @@
"node": ">=18.0.0"
}
},
"packages-node/providence-analytics/node_modules/@babel/compat-data": {
"version": "7.23.2",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
},
"packages-node/providence-analytics/node_modules/@babel/core": {
"version": "7.23.2",
"license": "MIT",
"peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.23.0",
"@babel/helper-compilation-targets": "^7.22.15",
"@babel/helper-module-transforms": "^7.23.0",
"@babel/helpers": "^7.23.2",
"@babel/parser": "^7.23.0",
"@babel/template": "^7.22.15",
"@babel/traverse": "^7.23.2",
"@babel/types": "^7.23.0",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.2.3",
"semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/babel"
}
},
"packages-node/providence-analytics/node_modules/@babel/core/node_modules/semver": {
"version": "6.3.1",
"license": "ISC",
"peer": true,
"bin": {
"semver": "bin/semver.js"
}
},
"packages-node/providence-analytics/node_modules/@babel/helper-compilation-targets": {
"version": "7.22.15",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/compat-data": "^7.22.9",
"@babel/helper-validator-option": "^7.22.15",
"browserslist": "^4.21.9",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"packages-node/providence-analytics/node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
"version": "5.1.1",
"license": "ISC",
"peer": true,
"dependencies": {
"yallist": "^3.0.2"
}
},
"packages-node/providence-analytics/node_modules/@babel/helper-compilation-targets/node_modules/semver": {
"version": "6.3.1",
"license": "ISC",
"peer": true,
"bin": {
"semver": "bin/semver.js"
}
},
"packages-node/providence-analytics/node_modules/@babel/helper-module-imports": {
"version": "7.22.15",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/types": "^7.22.15"
},
"engines": {
"node": ">=6.9.0"
}
},
"packages-node/providence-analytics/node_modules/@babel/helper-module-transforms": {
"version": "7.23.0",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-module-imports": "^7.22.15",
"@babel/helper-simple-access": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/helper-validator-identifier": "^7.22.20"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
}
},
"packages-node/providence-analytics/node_modules/@babel/helper-plugin-utils": {
"version": "7.24.5",
"license": "MIT",
@ -23120,38 +23199,6 @@
"node": ">=6.9.0"
}
},
"packages-node/providence-analytics/node_modules/@babel/helper-simple-access": {
"version": "7.22.5",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"packages-node/providence-analytics/node_modules/@babel/helper-validator-option": {
"version": "7.22.15",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
},
"packages-node/providence-analytics/node_modules/@babel/helpers": {
"version": "7.23.2",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/template": "^7.22.15",
"@babel/traverse": "^7.23.2",
"@babel/types": "^7.23.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"packages-node/providence-analytics/node_modules/@babel/plugin-syntax-import-assertions": {
"version": "7.24.1",
"license": "MIT",
@ -23165,19 +23212,6 @@
"@babel/core": "^7.0.0-0"
}
},
"packages-node/providence-analytics/node_modules/@babel/template": {
"version": "7.22.15",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.22.15",
"@babel/types": "^7.22.15"
},
"engines": {
"node": ">=6.9.0"
}
},
"packages-node/providence-analytics/node_modules/@lit/reactive-element": {
"version": "2.0.4",
"dev": true,
@ -23520,56 +23554,6 @@
"dev": true,
"license": "MIT"
},
"packages-node/providence-analytics/node_modules/browserslist": {
"version": "4.22.1",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001541",
"electron-to-chromium": "^1.4.535",
"node-releases": "^2.0.13",
"update-browserslist-db": "^1.0.13"
},
"bin": {
"browserslist": "cli.js"
},
"engines": {
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"packages-node/providence-analytics/node_modules/caniuse-lite": {
"version": "1.0.30001561",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "CC-BY-4.0",
"peer": true
},
"packages-node/providence-analytics/node_modules/command-line-args": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz",
@ -23618,16 +23602,6 @@
"node": ">=12.20.0"
}
},
"packages-node/providence-analytics/node_modules/convert-source-map": {
"version": "2.0.0",
"license": "MIT",
"peer": true
},
"packages-node/providence-analytics/node_modules/electron-to-chromium": {
"version": "1.4.578",
"license": "ISC",
"peer": true
},
"packages-node/providence-analytics/node_modules/es-module-lexer": {
"version": "1.5.2",
"dev": true,
@ -23676,11 +23650,6 @@
"node": ">=16.14"
}
},
"packages-node/providence-analytics/node_modules/node-releases": {
"version": "2.0.13",
"license": "MIT",
"peer": true
},
"packages-node/providence-analytics/node_modules/rollup": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz",
@ -23766,35 +23735,6 @@
"node": ">=12.17"
}
},
"packages-node/providence-analytics/node_modules/update-browserslist-db": {
"version": "1.0.13",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"escalade": "^3.1.1",
"picocolors": "^1.0.0"
},
"bin": {
"update-browserslist-db": "cli.js"
},
"peerDependencies": {
"browserslist": ">= 4.21.0"
}
},
"packages-node/providence-analytics/node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
@ -23826,11 +23766,6 @@
"node": ">=12.17"
}
},
"packages-node/providence-analytics/node_modules/yallist": {
"version": "3.1.1",
"license": "ISC",
"peer": true
},
"packages-node/publish-docs": {
"version": "0.2.1",
"license": "MIT",

View file

@ -25,15 +25,15 @@ export class LionAccordion extends LitElement {
/**
* index number of the focused accordion
*/
focusedIndex: {
type: Number,
},
focusedIndex: { type: Number },
/**
* array of indices of the expanded accordions
*/
expanded: {
type: Array,
},
expanded: { type: Array },
/**
* exclusive property allows only one accordion slot to be open at a time
*/
exclusive: { type: Boolean },
};
}
@ -101,6 +101,11 @@ export class LionAccordion extends LitElement {
super();
this.styles = {};
/**
* @type {boolean}
*/
this.exclusive = false;
/**
* @type {StoreEntry[]}
* @private
@ -437,20 +442,21 @@ export class LionAccordion extends LitElement {
}
/**
* @param {number} value
* @param {number} indexClicked
* @private
*/
__toggleExpanded(value) {
const expanded = [...this.expanded];
const index = expanded.indexOf(value);
__toggleExpanded(indexClicked) {
const indexFound = this.expanded.indexOf(indexClicked);
const expandedNewValues = this.exclusive ? [] : [...this.expanded];
if (index === -1) {
expanded.push(value);
} else {
expanded.splice(index, 1);
if (indexFound === -1) {
expandedNewValues.push(indexClicked);
} else if (expandedNewValues.includes(indexFound)) {
expandedNewValues.splice(indexFound, 1);
}
this.expanded = expanded;
// trigger a render
this.expanded = expandedNewValues;
}
/**

View file

@ -33,14 +33,14 @@ function getAccordionChildren(el) {
}
/**
* @param {Element} el
* @param {LionAccordion} el
*/
function getInvokers(el) {
return getAccordionChildren(el).filter(child => child.classList.contains('invoker'));
}
/**
* @param {Element} el
* @param {LionAccordion} el
*/
function getContents(el) {
return getAccordionChildren(el).filter(child => child.classList.contains('content'));
@ -112,6 +112,51 @@ describe('<lion-accordion>', () => {
expect(invokers[1].firstElementChild).to.have.attribute('expanded');
});
it('supports [exclusive] attribute, allowing one collapsible to be open at a time', async () => {
const el = /** @type {LionAccordion} */ (
await fixture(html`
<lion-accordion exclusive>
<h2 slot="invoker"><button>invoker 1</button></h2>
<div slot="content">content 1</div>
<h2 slot="invoker"><button>invoker 2</button></h2>
<div slot="content">content 2</div>
<h2 slot="invoker"><button>invoker 3</button></h2>
<div slot="content">content 3</div>
</lion-accordion>
`)
);
const invokerButtons = Array.from(getInvokers(el)).map(
invokerHeadingEl => /** @type {HTMLButtonElement} */ (invokerHeadingEl.firstElementChild),
);
// We open the first... (nothing different from not [exclusive] so far)
invokerButtons[0].click();
expect(invokerButtons[0]).to.have.attribute('expanded');
expect(invokerButtons[1]).to.not.have.attribute('expanded');
expect(invokerButtons[2]).to.not.have.attribute('expanded');
// We click the second...
invokerButtons[1].click();
expect(invokerButtons[0]).to.not.have.attribute('expanded');
expect(invokerButtons[1]).to.have.attribute('expanded');
expect(invokerButtons[2]).to.not.have.attribute('expanded');
// We click the third...
invokerButtons[2].click();
expect(invokerButtons[0]).to.not.have.attribute('expanded');
expect(invokerButtons[1]).to.not.have.attribute('expanded');
expect(invokerButtons[2]).to.have.attribute('expanded');
el.exclusive = false;
// We open the first... (behaving as default (not [exclusive]) again)
invokerButtons[0].click();
expect(invokerButtons[0]).to.have.attribute('expanded');
expect(invokerButtons[1]).to.not.have.attribute('expanded');
expect(invokerButtons[2]).to.have.attribute('expanded');
});
it('sends event "expanded-changed" for every expanded state change', async () => {
const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
const spy = sinon.spy();
@ -467,14 +512,16 @@ describe('<lion-accordion>', () => {
describe('Invokers', () => {
it('links ids of content items to invoker first child via [aria-controls]', async () => {
const el = await fixture(html`
const el = /** @type {LionAccordion} */ (
await fixture(html`
<lion-accordion>
<h2 id="h1" slot="invoker"><button>invoker 1</button></h2>
<div id="p1" slot="content">content 1</div>
<h2 id="h2" slot="invoker"><button>invoker 2</button></h2>
<div id="p2" slot="content">content 2</div>
</lion-accordion>
`);
`)
);
const invokers = getInvokers(el);
const contents = getContents(el);
expect(invokers[0].firstElementChild?.getAttribute('aria-controls')).to.equal(
@ -486,12 +533,14 @@ describe('<lion-accordion>', () => {
});
it('adds aria-expanded="false" to invoker when its content is not expanded', async () => {
const el = await fixture(html`
const el = /** @type {LionAccordion} */ (
await fixture(html`
<lion-accordion>
<h2 slot="invoker"><button>invoker</button></h2>
<div slot="content">content</div>
</lion-accordion>
`);
`)
);
expect(Array.from(getInvokers(el))[0]?.firstElementChild).to.have.attribute(
'aria-expanded',
'false',
@ -517,14 +566,16 @@ describe('<lion-accordion>', () => {
describe('Contents', () => {
it('adds aria-labelledby referring to invoker ids', async () => {
const el = await fixture(html`
const el = /** @type {LionAccordion} */ (
await fixture(html`
<lion-accordion>
<h2 slot="invoker"><button>invoker 1</button></h2>
<div slot="content">content 1</div>
<h2 slot="invoker"><button>invoker 2</button></h2>
<div slot="content">content 2</div>
</lion-accordion>
`);
`)
);
const contents = getContents(el);
const invokers = getInvokers(el);
expect(contents[0]).to.have.attribute('aria-labelledby', invokers[0].firstElementChild?.id);