From 0d5fd4fb2e56b5e5863a9af3f6618a1f74f495e2 Mon Sep 17 00:00:00 2001 From: Boris Diakur Date: Tue, 22 Aug 2023 14:34:45 +0200 Subject: [PATCH] feat(ld-select): option groups --- screenshot/builds/master.json | 78 ++ .../7e6872acb848e765226bb806f850eff6.png | Bin 0 -> 19248 bytes .../877daacf066fca131b6d8046e80e7400.png | Bin 0 -> 8296 bytes .../9c3af8ce7cb3378b397e909c0477ceba.png | Bin 0 -> 16906 bytes .../b12bed03b74cd4a3fc989bd1da4d663d.png | Bin 0 -> 8710 bytes .../cabd1ff3f7feb8fe0964ce3174802820.png | Bin 0 -> 8732 bytes .../d9a7e7afd21923aa6f5d59922bf6ef1b.png | Bin 0 -> 8745 bytes src/docs/utils/copyToClipboard.ts | 4 +- src/liquid/components/ld-checkbox/readme.md | 2 + .../ld-optgroup-internal.shadow.css | 183 +++ .../ld-optgroup-internal.tsx | 170 +++ .../ld-optgroup/ld-optgroup.shadow.css | 0 .../ld-select/ld-optgroup/ld-optgroup.tsx | 28 + .../ld-select/ld-optgroup/readme.md | 34 + .../ld-option-internal.shadow.css | 44 +- .../ld-option-internal/ld-option-internal.tsx | 56 +- .../ld-select-popper/ld-select-popper.tsx | 3 +- src/liquid/components/ld-select/ld-select.css | 163 +-- src/liquid/components/ld-select/ld-select.tsx | 447 +++++-- src/liquid/components/ld-select/readme.md | 433 ++++-- .../test/__snapshots__/ld-select.spec.ts.snap | 4 +- .../ld-select/test/ld-select.e2e.ts | 148 +++ .../ld-select/test/ld-select.spec.ts | 1173 ++++++++++++++++- 23 files changed, 2528 insertions(+), 442 deletions(-) create mode 100644 screenshot/images/7e6872acb848e765226bb806f850eff6.png create mode 100644 screenshot/images/877daacf066fca131b6d8046e80e7400.png create mode 100644 screenshot/images/9c3af8ce7cb3378b397e909c0477ceba.png create mode 100644 screenshot/images/b12bed03b74cd4a3fc989bd1da4d663d.png create mode 100644 screenshot/images/cabd1ff3f7feb8fe0964ce3174802820.png create mode 100644 screenshot/images/d9a7e7afd21923aa6f5d59922bf6ef1b.png create mode 100644 src/liquid/components/ld-select/ld-optgroup-internal/ld-optgroup-internal.shadow.css create mode 100644 src/liquid/components/ld-select/ld-optgroup-internal/ld-optgroup-internal.tsx create mode 100644 src/liquid/components/ld-select/ld-optgroup/ld-optgroup.shadow.css create mode 100644 src/liquid/components/ld-select/ld-optgroup/ld-optgroup.tsx create mode 100644 src/liquid/components/ld-select/ld-optgroup/readme.md diff --git a/screenshot/builds/master.json b/screenshot/builds/master.json index e6be126cc3..d7b76df431 100644 --- a/screenshot/builds/master.json +++ b/screenshot/builds/master.json @@ -18893,6 +18893,58 @@ "isLandscape": false, "isMobile": false }, + { + "id": "a59384a1", + "image": "b12bed03b74cd4a3fc989bd1da4d663d.png", + "userAgent": "default", + "desc": "ld-select css component multiple", + "testPath": "./src/liquid/components/ld-select/test/ld-select.e2e.ts", + "width": 600, + "height": 600, + "deviceScaleFactor": 1, + "hasTouch": false, + "isLandscape": false, + "isMobile": false + }, + { + "id": "1407fb72", + "image": "cabd1ff3f7feb8fe0964ce3174802820.png", + "userAgent": "default", + "desc": "ld-select css component multiple focus", + "testPath": "./src/liquid/components/ld-select/test/ld-select.e2e.ts", + "width": 600, + "height": 600, + "deviceScaleFactor": 1, + "hasTouch": false, + "isLandscape": false, + "isMobile": false + }, + { + "id": "8c672c8c", + "image": "d9a7e7afd21923aa6f5d59922bf6ef1b.png", + "userAgent": "default", + "desc": "ld-select css component multiple hover", + "testPath": "./src/liquid/components/ld-select/test/ld-select.e2e.ts", + "width": 600, + "height": 600, + "deviceScaleFactor": 1, + "hasTouch": false, + "isLandscape": false, + "isMobile": false + }, + { + "id": "276525f4", + "image": "877daacf066fca131b6d8046e80e7400.png", + "userAgent": "default", + "desc": "ld-select css component multiple with option groups", + "testPath": "./src/liquid/components/ld-select/test/ld-select.e2e.ts", + "width": 600, + "height": 600, + "deviceScaleFactor": 1, + "hasTouch": false, + "isLandscape": false, + "isMobile": false + }, { "id": "789d7a75", "image": "a196eb723f60598e0f8f30411b4e869b.png", @@ -19114,6 +19166,32 @@ "isLandscape": false, "isMobile": false }, + { + "id": "168f9248", + "image": "9c3af8ce7cb3378b397e909c0477ceba.png", + "userAgent": "default", + "desc": "ld-select multiple option groups default", + "testPath": "./src/liquid/components/ld-select/test/ld-select.e2e.ts", + "width": 600, + "height": 600, + "deviceScaleFactor": 1, + "hasTouch": false, + "isLandscape": false, + "isMobile": false + }, + { + "id": "a989ddcd", + "image": "7e6872acb848e765226bb806f850eff6.png", + "userAgent": "default", + "desc": "ld-select multiple option groups multiple", + "testPath": "./src/liquid/components/ld-select/test/ld-select.e2e.ts", + "width": 600, + "height": 600, + "deviceScaleFactor": 1, + "hasTouch": false, + "isLandscape": false, + "isMobile": false + }, { "id": "e0c87412", "image": "d6b9b880e9fd716599e54363f8574a9e.png", diff --git a/screenshot/images/7e6872acb848e765226bb806f850eff6.png b/screenshot/images/7e6872acb848e765226bb806f850eff6.png new file mode 100644 index 0000000000000000000000000000000000000000..2db995830865512501c11a5f914dcb836a98b821 GIT binary patch literal 19248 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 HaO-~n^gc^x literal 0 HcmV?d00001 diff --git a/screenshot/images/9c3af8ce7cb3378b397e909c0477ceba.png b/screenshot/images/9c3af8ce7cb3378b397e909c0477ceba.png new file mode 100644 index 0000000000000000000000000000000000000000..8ba4f3f610cd423361b541cbb395235731411d17 GIT binary patch literal 16906 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 literal 0 HcmV?d00001 diff --git a/screenshot/images/b12bed03b74cd4a3fc989bd1da4d663d.png b/screenshot/images/b12bed03b74cd4a3fc989bd1da4d663d.png new file mode 100644 index 0000000000000000000000000000000000000000..fd9fda1a7d2c655f130e1c9edf0dfac3ece88a19 GIT binary patch literal 8710 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 GpZ*I@-(aNx literal 0 HcmV?d00001 diff --git a/screenshot/images/d9a7e7afd21923aa6f5d59922bf6ef1b.png b/screenshot/images/d9a7e7afd21923aa6f5d59922bf6ef1b.png new file mode 100644 index 0000000000000000000000000000000000000000..16e1463e6ee79986dbc9e3becdef40eb2cb0e9a8 GIT binary patch literal 8745 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 literal 0 HcmV?d00001 diff --git a/src/docs/utils/copyToClipboard.ts b/src/docs/utils/copyToClipboard.ts index 7bd02e0343..8504f25bc3 100644 --- a/src/docs/utils/copyToClipboard.ts +++ b/src/docs/utils/copyToClipboard.ts @@ -1,7 +1,7 @@ export async function copyToClipboard(textToCopy: string) { // navigator clipboard api needs a secure context (https) if (navigator.clipboard && window.isSecureContext) { - navigator.clipboard.writeText(textToCopy) + await navigator.clipboard.writeText(textToCopy) } else { const activeElement = document.activeElement as HTMLElement // text area method @@ -11,7 +11,7 @@ export async function copyToClipboard(textToCopy: string) { document.body.appendChild(textArea) textArea.focus({ preventScroll: true }) textArea.select() - await document.execCommand('copy') + document.execCommand('copy') textArea.remove() activeElement.focus({ preventScroll: true }) } diff --git a/src/liquid/components/ld-checkbox/readme.md b/src/liquid/components/ld-checkbox/readme.md index 122cafb9ba..0b9d51e46e 100644 --- a/src/liquid/components/ld-checkbox/readme.md +++ b/src/liquid/components/ld-checkbox/readme.md @@ -585,12 +585,14 @@ Type: `Promise` ### Used by + - ld-optgroup-internal - ld-option-internal - [ld-table-row](../ld-table/ld-table-row) ### Graph ```mermaid graph TD; + ld-optgroup-internal --> ld-checkbox ld-option-internal --> ld-checkbox ld-table-row --> ld-checkbox style ld-checkbox fill:#f9f,stroke:#333,stroke-width:4px diff --git a/src/liquid/components/ld-select/ld-optgroup-internal/ld-optgroup-internal.shadow.css b/src/liquid/components/ld-select/ld-optgroup-internal/ld-optgroup-internal.shadow.css new file mode 100644 index 0000000000..b843e4b739 --- /dev/null +++ b/src/liquid/components/ld-select/ld-optgroup-internal/ld-optgroup-internal.shadow.css @@ -0,0 +1,183 @@ +:host, +.ld-optgroup-internal { + /* layout */ + --ld-optgroup-padding-left-sm: 0.625rem; + --ld-optgroup-padding-left-lg: 0.875rem; + --ld-optgroup-option-padding-left: 1rem; + + /* colors */ + --ld-optgroup-bg-col: var(--ld-col-neutral-010); + --ld-optgroup-border-col: var(--ld-col-neutral-100); + --ld-optgroup-disabled-text-col: var(--ld-col-neutral-100); + --ld-optgroup-text-col: var(--ld-col-neutral-900); + + /* themable colors */ + --ld-optgroup-thm-col: var(--ld-thm-primary); + --ld-optgroup-thm-col-hover: var(--ld-thm-primary-hover); + --ld-optgroup-thm-col-focus: var(--ld-thm-primary-focus); + --ld-optgroup-thm-col-active: var(--ld-thm-primary-active); + --ld-optgroup-thm-bg-col-hover: var(--ld-thm-primary-highlight); + --ld-optgroup-thm-bg-col-focus: var(--ld-thm-primary-highlight); + --ld-optgroup-thm-bg-col-active: var(--ld-thm-primary-highlight); +} + +:host(:not(:last-child)) { + .ld-optgroup-internal__slot-container { + border-bottom: solid var(--ld-optgroup-border-col) var(--ld-sp-1); + } +} + +.ld-optgroup-internal { + background-color: var(--ld-optgroup-bg-col); + border: 0; + box-sizing: border-box; + color: var(--ld-optgroup-text-col); + display: flex; + font: var(--ld-typo-label-m); + min-height: 2.5rem; + outline: none; + padding: var(--ld-sp-8) var(--ld-sp-12); + position: relative; + touch-action: manipulation; + user-select: none; + white-space: nowrap; + -webkit-touch-callout: none; + + &::after { + content: ''; + inset-block: calc(-1 * var(--ld-sp-1)) 0; + inset-inline: calc(-1 * var(--ld-sp-1)); + position: absolute; + pointer-events: none; + box-shadow: inset 0 0 0 var(--ld-sp-1) var(--ld-col-neutral-100); + } + + &--sm { + padding-left: var(--ld-optgroup-padding-left-sm); + } + + &--lg { + padding-left: var(--ld-optgroup-padding-left-lg); + } + + &--filtered { + display: none; + } + + *, + *::before, + *::after { + box-sizing: inherit; + } + + [data-popper-placement*='bottom'] & { + &:last-of-type { + border-bottom-left-radius: var(--ld-br-m); + border-bottom-right-radius: var(--ld-br-m); + } + } + [data-popper-placement*='top'] & { + &:first-of-type { + border-top-left-radius: var(--ld-br-m); + border-top-right-radius: var(--ld-br-m); + } + } + + &:not([aria-disabled='true']) { + cursor: pointer; + } + + &[aria-disabled='true'] { + color: var(--ld-optgroup-disabled-text-col); + } + + /* Pseudo element for focus outline */ + &::before { + content: ''; + position: absolute; + inset: 0; + border-radius: var(--ld-br-m); + pointer-events: none; + } + + &:where(:focus), + &:where(:focus:focus-visible) { + &::before { + box-shadow: inset 0 0 0 var(--ld-sp-2) var(--ld-optgroup-thm-col); + } + } + + &:where(:focus:not(:focus-visible)) { + &::before { + box-shadow: none; + } + } + + &:where(:not(.ld-optgroup-internal--disabled, [aria-disabled='true'])) { + :where(.ld-optgroup-internal__check) { + color: var(--ld-optgroup-thm-col); + } + + &:where(:focus), + &:where(:focus:focus-visible) { + background-color: var(--ld-optgroup-thm-bg-col-focus); + + :where(.ld-optgroup-internal__check) { + color: var(--ld-optgroup-thm-col-focus); + } + } + + &:where(:focus:not(:focus-visible)) { + background-color: var(--ld-optgroup-bg-col); + + :where(.ld-optgroup-internal__check) { + color: var(--ld-optgroup-thm-col); + } + } + + @media (hover: hover) { + &:where(:hover) { + background-color: var(--ld-optgroup-thm-bg-col-hover); + + :where(.ld-optgroup-internal__check) { + color: var(--ld-optgroup-thm-col-hover); + } + } + } + + &:where(:active), + &:where(:active:focus-visible) { + background-color: var(--ld-optgroup-thm-bg-col-active); + + :where(.ld-optgroup-internal__check) { + color: var(--ld-optgroup-thm-col-active); + } + } + } +} + +.ld-optgroup-internal__checkbox-wrapper { + display: inline-flex; + flex-shrink: 0; +} + +.ld-optgroup-internal__check, +.ld-optgroup-internal__checkbox { + align-self: center; + flex-shrink: 0; + transform: translateX(calc(-1 * var(--ld-sp-2))); +} + +.ld-optgroup-internal__check { + margin-right: var(--ld-sp-4); +} + +.ld-optgroup-internal__checkbox { + margin-left: var(--ld-sp-2); + margin-right: var(--ld-sp-6); +} + +.ld-optgroup-internal__label { + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/src/liquid/components/ld-select/ld-optgroup-internal/ld-optgroup-internal.tsx b/src/liquid/components/ld-select/ld-optgroup-internal/ld-optgroup-internal.tsx new file mode 100644 index 0000000000..a2b6be321f --- /dev/null +++ b/src/liquid/components/ld-select/ld-optgroup-internal/ld-optgroup-internal.tsx @@ -0,0 +1,170 @@ +import { + Component, + Element, + Event, + EventEmitter, + h, + Host, + Listen, + Method, + Prop, + State, + Watch, +} from '@stencil/core' +import { getClassNames } from '../../../utils/getClassNames' + +/** @internal **/ +@Component({ + tag: 'ld-optgroup-internal', + styleUrl: 'ld-optgroup-internal.shadow.css', + shadow: true, +}) +export class LdOptgroupInternal implements InnerFocusable { + @Element() el: HTMLElement + + private optgroupRef: HTMLElement + + /** Disables the whole option group. */ + @Prop() disabled?: boolean + + /** Set to true on filtering via select input. */ + @Prop() filtered? = false + + /** The name of the group of options. */ + @Prop() label!: string + + /** Tab index of the option. */ + @Prop() ldTabindex? = -1 + + /** Display mode. */ + @Prop() mode?: 'checkbox' | undefined + + /** Size of the option. */ + @Prop() size?: 'sm' | 'lg' + + @State() hasFocus: boolean + @State() hasHover: boolean + @State() selected?: boolean | 'indeterminate' = false + + /** + * @internal + * Emitted on either selection or de-selection of the option. + */ + @Event() ldoptgroupselect: EventEmitter + + /** + * Sets focus internally. + */ + @Method() + async focusInner() { + this.optgroupRef.focus() + } + + @Listen('ldoptionselect') + handleOptionSelect() { + if (this.mode !== 'checkbox') return + + const options = Array.from( + this.el.children + ) as HTMLLdOptionInternalElement[] + const totalOptions = options.length + const totalSelected = options.filter((o) => o.selected).length + + if (totalOptions === 0 || totalSelected === 0) { + this.selected = false + return + } + + if (totalOptions === totalSelected) { + this.selected = true + return + } + + this.selected = 'indeterminate' + } + + @Listen('keydown', { passive: false }) + handleKeyDown(ev: KeyboardEvent) { + if (ev.key === ' ' || ev.key === 'Enter') { + ev.preventDefault() + ev.stopImmediatePropagation() + this.handleClick() + } + } + + private handleClick = () => { + if (this.disabled) return + if (this.mode !== 'checkbox') return + + const options = Array.from( + this.el.children + ) as HTMLLdOptionInternalElement[] + const newSelectedState = + this.selected === false || this.selected === 'indeterminate' + options + .filter((o) => o.selected !== newSelectedState) + .forEach((o) => { + o.selected = newSelectedState + }) + } + + @Watch('selected') + handleSelectedChange() { + this.ldoptgroupselect.emit(this.selected) + } + + componentWillLoad() { + this.handleOptionSelect() + } + + render() { + return ( + +
(this.optgroupRef = el as HTMLElement)} + aria-disabled={this.disabled ? 'true' : undefined} + onClick={this.handleClick} + tabIndex={this.ldTabindex} + part="option focusable" + > + {this.mode === 'checkbox' && ( + + )} + + + {this.label} + +
+ +
+ +
+
+ ) + } +} diff --git a/src/liquid/components/ld-select/ld-optgroup/ld-optgroup.shadow.css b/src/liquid/components/ld-select/ld-optgroup/ld-optgroup.shadow.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/liquid/components/ld-select/ld-optgroup/ld-optgroup.tsx b/src/liquid/components/ld-select/ld-optgroup/ld-optgroup.tsx new file mode 100644 index 0000000000..910c29914e --- /dev/null +++ b/src/liquid/components/ld-select/ld-optgroup/ld-optgroup.tsx @@ -0,0 +1,28 @@ +import { Component, h, Host, Prop, Element } from '@stencil/core' + +/** + * @virtualProp ref - reference to component + * @virtualProp {string | number} key - for tracking the node's identity when working with lists + */ +@Component({ + tag: 'ld-optgroup', + styleUrl: 'ld-optgroup.shadow.css', + shadow: true, +}) +export class LdOptgroup { + @Element() el: HTMLElement + + /** The name of the group of options. */ + @Prop() label!: string + + /** Disables the whole option group. */ + @Prop() disabled?: boolean + + render() { + return ( + + + + ) + } +} diff --git a/src/liquid/components/ld-select/ld-optgroup/readme.md b/src/liquid/components/ld-select/ld-optgroup/readme.md new file mode 100644 index 0000000000..a095ec0d5d --- /dev/null +++ b/src/liquid/components/ld-select/ld-optgroup/readme.md @@ -0,0 +1,34 @@ +--- +eleventyNavigation: + key: Option Group + parent: Select +layout: layout.njk +title: Option Group +permalink: components/ld-select/ld-optgroup/ +--- + +# ld-optgroup + +The `ld-optgroup` component is a subcomponent for `ld-select`. + +Please refer to the [`ld-select` documentation](components/ld-select#with-option-groups) for usage examples. + +--- + + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| -------------------- | ---------- | -------------------------------------------------------- | ------------------ | ----------- | +| `disabled` | `disabled` | Disables the whole option group. | `boolean` | `undefined` | +| `key` | `key` | for tracking the node's identity when working with lists | `string \| number` | `undefined` | +| `label` _(required)_ | `label` | The name of the group of options. | `string` | `undefined` | +| `ref` | `ref` | reference to component | `any` | `undefined` | + + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/src/liquid/components/ld-select/ld-option-internal/ld-option-internal.shadow.css b/src/liquid/components/ld-select/ld-option-internal/ld-option-internal.shadow.css index 82f2d0848d..a960438f68 100644 --- a/src/liquid/components/ld-select/ld-option-internal/ld-option-internal.shadow.css +++ b/src/liquid/components/ld-select/ld-option-internal/ld-option-internal.shadow.css @@ -1,11 +1,7 @@ -:host(:not(:last-of-type)) { - .ld-option-internal { - border-bottom: solid var(--ld-option-border-col) var(--ld-sp-1); - } -} - +:host, .ld-option-internal { /* layout */ + --ld-option-padding-left: var(--ld-sp-12); --ld-option-padding-left-sm: 0.625rem; --ld-option-padding-left-lg: 0.875rem; @@ -23,13 +19,37 @@ --ld-option-thm-bg-col-hover: var(--ld-thm-primary-highlight); --ld-option-thm-bg-col-focus: var(--ld-thm-primary-highlight); --ld-option-thm-bg-col-active: var(--ld-thm-primary-highlight); +} + +:host(:not(:last-of-type)) { + .ld-option-internal { + border-bottom: solid var(--ld-option-border-col) var(--ld-sp-1); + } +} + +.ld-option-internal { + &--sm { + --ld-option-padding-left: var(--ld-option-padding-left-sm); + } + + &--lg { + --ld-option-padding-left: var(--ld-option-padding-left-lg); + } + + &--indent { + --ld-option-indent: 1.75rem; + } outline: none; display: flex; position: relative; color: var(--ld-option-text-col); background-color: var(--ld-option-bg-col); - padding: var(--ld-sp-8) var(--ld-sp-12); + padding-block: var(--ld-sp-8); + padding-right: var(--ld-sp-12); + padding-left: calc( + var(--ld-option-padding-left) + var(--ld-option-indent, 0px) + ); font: var(--ld-typo-label-m); min-height: 2.5rem; white-space: nowrap; @@ -39,14 +59,6 @@ -webkit-touch-callout: none; box-sizing: border-box; - &--sm { - padding-left: var(--ld-option-padding-left-sm); - } - - &--lg { - padding-left: var(--ld-option-padding-left-lg); - } - &--filtered { display: none; } @@ -100,7 +112,7 @@ } } - &:where(:not(.ld-option-internal--disabled, [aria-disabled='true'])) { + &:where(:not([aria-disabled='true'])) { :where(.ld-option-internal__check) { color: var(--ld-option-thm-col); } diff --git a/src/liquid/components/ld-select/ld-option-internal/ld-option-internal.tsx b/src/liquid/components/ld-select/ld-option-internal/ld-option-internal.tsx index ffbcbe3eb4..c3481b2645 100644 --- a/src/liquid/components/ld-select/ld-option-internal/ld-option-internal.tsx +++ b/src/liquid/components/ld-select/ld-option-internal/ld-option-internal.tsx @@ -9,6 +9,7 @@ import { Listen, State, Method, + Watch, } from '@stencil/core' import { getClassNames } from '../../../utils/getClassNames' @@ -49,7 +50,7 @@ export class LdOptionInternal implements InnerFocusable { /** * Display mode. */ - @Prop() mode?: 'checkbox' | undefined + @Prop() mode?: 'checkbox' /** Size of the option. */ @Prop() size?: 'sm' | 'lg' @@ -60,23 +61,12 @@ export class LdOptionInternal implements InnerFocusable { /** Tab index of the option. */ @Prop() ldTabindex? = -1 - /** - * Sets focus internally. - */ + /** Sets focus internally. */ @Method() async focusInner() { this.optionRef.focus() } - /** - * Sets focus internally. - * @deprecated - */ - @Method() - async focusOption() { - await this.focusInner() - } - /** * @internal * Emitted on either selection or de-selection of the option. @@ -87,8 +77,14 @@ export class LdOptionInternal implements InnerFocusable { @State() hasFocus: boolean @State() hasHover: boolean + @State() indent?: boolean = false - private handleClick() { + @Watch('selected') + handleSelectedChange() { + this.ldoptionselect.emit(this.selected) + } + + private handleClick = () => { if (this.disabled) return if ( @@ -98,13 +94,6 @@ export class LdOptionInternal implements InnerFocusable { ) { this.selected = !this.selected } - - if (this.mode !== 'checkbox') { - this.hasFocus = false - this.hasHover = false - } - - this.ldoptionselect.emit(this.selected) } @Listen('keydown', { passive: false }) @@ -114,33 +103,26 @@ export class LdOptionInternal implements InnerFocusable { ev.stopImmediatePropagation() this.handleClick() } - - if (ev.key === 'Escape') { - this.hasFocus = false - this.hasHover = false - } } componentWillLoad() { if (typeof this.value === 'undefined') { - requestAnimationFrame(() => { + setTimeout(() => { this.value = this.el.innerText }) } + if (this.mode === 'checkbox' && this.el.closest('ld-optgroup-internal')) { + this.indent = true + } } render() { return ( - +
(this.optionRef = el as HTMLElement)} aria-selected={this.selected ? 'true' : undefined} aria-disabled={this.disabled ? 'true' : undefined} - onClick={this.handleClick.bind(this)} - onFocus={() => (this.hasFocus = true)} - onBlur={() => (this.hasFocus = false)} - onMouseOver={() => (this.hasHover = true)} - onMouseOut={() => (this.hasHover = false)} + onClick={this.handleClick} tabindex={this.ldTabindex} part="option focusable" > diff --git a/src/liquid/components/ld-select/ld-select-popper/ld-select-popper.tsx b/src/liquid/components/ld-select/ld-select-popper/ld-select-popper.tsx index 8766333455..66eee0f622 100644 --- a/src/liquid/components/ld-select/ld-select-popper/ld-select-popper.tsx +++ b/src/liquid/components/ld-select/ld-select-popper/ld-select-popper.tsx @@ -87,8 +87,9 @@ export class LdSelectPopper { private handleCreate = (ev) => { ev.preventDefault() - this.ldselectfiltercreate.emit(this.filterInputValue) + const value = this.filterInputValue this.filterInputValue = '' + this.ldselectfiltercreate.emit(value) } @Watch('creatable') diff --git a/src/liquid/components/ld-select/ld-select.css b/src/liquid/components/ld-select/ld-select.css index e68fb196ca..311a3088e8 100644 --- a/src/liquid/components/ld-select/ld-select.css +++ b/src/liquid/components/ld-select/ld-select.css @@ -8,26 +8,54 @@ } :host, +.ld-select { + /* reset */ + *, + *::before, + *::after { + box-sizing: border-box; + } + ul { + list-style: none; + } +} + .ld-select { /* layout */ --ld-select-min-width: 12.8125rem; + --ld-select-min-height: 2.5rem; --ld-select-min-height-sm: 2rem; - --ld-select-min-height-md: 2.5rem; --ld-select-min-height-lg: 3.125rem; + --ld-select-padding-x: 0.75rem; --ld-select-padding-x-sm: 0.625rem; - --ld-select-padding-x-md: 0.75rem; --ld-select-padding-x-lg: 0.875rem; + --ld-select-padding-y: 0.5rem; --ld-select-padding-y-sm: 0.25rem; - --ld-select-padding-y-md: 0.5rem; --ld-select-padding-y-lg: 0.5rem; + --ld-select-padding-right: calc(2.5rem + 0.75rem); --ld-select-padding-right-sm: calc(2.5rem + 0.625rem); - --ld-select-padding-right-md: calc(2.5rem + 0.75rem); --ld-select-padding-right-lg: calc(2.5rem + 0.875rem); + --ld-select-icon-size: 1.25rem; --ld-select-icon-size-sm: 1rem; - --ld-select-icon-size-md: 1.25rem; --ld-select-icon-size-lg: 1.5rem; --ld-select-trigger-line-height: 1.25; + &--sm { + --ld-select-min-height: var(--ld-select-min-height-sm); + --ld-select-padding-x: var(--ld-select-padding-x-sm); + --ld-select-padding-y: var(--ld-select-padding-y-sm); + --ld-select-padding-right: var(--ld-select-padding-right-sm); + --ld-select-icon-size: var(--ld-select-icon-size-sm); + } + + &--lg { + --ld-select-min-height: var(--ld-select-min-height-lg); + --ld-select-padding-x: var(--ld-select-padding-x-lg); + --ld-select-padding-y: var(--ld-select-padding-y-lg); + --ld-select-padding-right: var(--ld-select-padding-right-lg); + --ld-select-icon-size: var(--ld-select-icon-size-lg); + } + /* colors */ --ld-select-col: var(--ld-col-neutral-900); --ld-select-col-disabled: var(--ld-col-neutral-100); @@ -49,25 +77,13 @@ --ld-select-ghost-trigger-bg-col-hover: var(--ld-thm-primary-alpha-lowest); --ld-select-ghost-trigger-bg-col-focus: var(--ld-thm-primary-alpha-low); - /* reset */ - *, - *::before, - *::after { - box-sizing: border-box; - } - ul { - list-style: none; - } -} - -.ld-select { display: inline-flex; position: relative; select + .ld-icon, ::slotted(ld-icon) { - width: var(--ld-select-icon-size-md); - height: var(--ld-select-icon-size-md); + width: var(--ld-select-icon-size); + height: var(--ld-select-icon-size); } ::slotted(ld-icon) { @@ -78,53 +94,36 @@ + .ld-icon, + .ld-select__icon { position: absolute; - right: var(--ld-select-padding-x-md); + right: var(--ld-select-padding-x); top: 50%; transform: translateY(-50%); } - + .ld-icon { - width: var(--ld-select-icon-size-md); - height: var(--ld-select-icon-size-md); + &[multiple] + .ld-icon, + &[multiple] + .ld-select__icon { + display: none; } - &:where(:not[multiple]) { - padding-right: var(--ld-select-padding-right-md); + + .ld-icon { + width: var(--ld-select-icon-size); + height: var(--ld-select-icon-size); } } - &.ld-select--sm { - select { - + .ld-icon, - + .ld-select__icon { - right: var(--ld-select-padding-x-sm); - } - - + .ld-icon { - width: var(--ld-select-icon-size-sm); - height: var(--ld-select-icon-size-sm); - } - - &:where(:not[multiple]) { - padding-right: var(--ld-select-padding-right-sm); - } - } + > select[multiple] { + overflow: auto; } - &.ld-select--lg { - select { - + .ld-icon, - + .ld-select__icon { - right: var(--ld-select-padding-x-lg); - } +} - + .ld-icon { - width: var(--ld-select-icon-size-lg); - height: var(--ld-select-icon-size-lg); - } +/* Mobile Safari (iOS only) */ +/* stylelint-disable-next-line media-feature-range-notation, media-feature-name-no-vendor-prefix */ +@media screen and (max-width: 767px) and (-webkit-min-device-pixel-ratio: 0) { + .ld-select > select[multiple] { + padding-right: calc(var(--ld-select-padding-x) + var(--ld-sp-24)); - &:where(:not[multiple]) { - padding-right: var(--ld-select-padding-right-lg); - } + + .ld-icon, + + .ld-select__icon { + display: flex; } } } @@ -157,7 +156,7 @@ font: var(--ld-typo-body-m); line-height: var(--ld-select-trigger-line-height); border: 0; - padding: var(--ld-select-padding-y-md) var(--ld-select-padding-x-md); + padding: var(--ld-select-padding-y) var(--ld-select-padding-x); border-radius: var(--ld-br-m); height: 100%; user-select: none; @@ -170,23 +169,10 @@ &:where(select) { width: 100%; + } - &[multiple] { - optgroup { - padding: var(--ld-sp-8) 0; - font-style: normal; - } - - option { - padding: var(--ld-sp-6) var(--ld-sp-6); - margin: 0 calc(-1 * var(--ld-sp-6)); - border-radius: var(--ld-br-m); - - &:not(:last-of-type) { - margin-bottom: var(--ld-sp-2); - } - } - } + &:where(select:not([multiple])) { + padding-right: calc(var(--ld-select-padding-x) + var(--ld-sp-24)); } &:where(select:not(:disabled, [aria-disabled='true'])), @@ -218,27 +204,7 @@ :where(.ld-select), :where(.ld-select) > select { - min-height: var(--ld-select-min-height-md); -} - -:where(.ld-select--sm), -:where(.ld-select--sm) > select { - min-height: var(--ld-select-min-height-sm); -} - -:where(.ld-select--lg), -:where(.ld-select--lg) > select { - min-height: var(--ld-select-min-height-lg); -} - -.ld-select--sm > select, -.ld-select--sm .ld-select__btn-trigger { - padding: var(--ld-select-padding-y-sm) var(--ld-select-padding-x-sm); -} - -.ld-select--lg > select, -.ld-select--lg .ld-select__btn-trigger { - padding: var(--ld-select-padding-y-lg) var(--ld-select-padding-x-lg); + min-height: var(--ld-select-min-height); } .ld-select--ghost { @@ -365,19 +331,6 @@ overflow: hidden; } -.ld-select--sm > select, -.ld-select--sm .ld-select__btn-trigger-input, -.ld-select--sm .ld-select__btn-trigger-text-wrapper { - font: var(--ld-typo-body-s); - line-height: var(--ld-select-trigger-line-height); -} -.ld-select--lg > select, -.ld-select--lg .ld-select__btn-trigger-input, -.ld-select--lg .ld-select__btn-trigger-text-wrapper { - font: var(--ld-typo-body-l); - line-height: var(--ld-select-trigger-line-height); -} - .ld-select > select, .ld-select__btn-trigger-text, .ld-select__selection-label-text { diff --git a/src/liquid/components/ld-select/ld-select.tsx b/src/liquid/components/ld-select/ld-select.tsx index ce5609705b..29b0ee4dc2 100644 --- a/src/liquid/components/ld-select/ld-select.tsx +++ b/src/liquid/components/ld-select/ld-select.tsx @@ -17,6 +17,7 @@ import { registerAutofocus } from '../../utils/focus' import { closest } from '../../utils/closest' import { TypeAheadHandler } from '../../utils/typeahead' import { isAriaDisabled } from '../../utils/ariaDisabled' +import { sanitize } from '../../utils/sanitize' type SelectOption = { value: string; text: string } @@ -43,6 +44,7 @@ export class LdSelect implements InnerFocusable { private slotChangeObserver: MutationObserver private popperObserver: MutationObserver private isObserverEnabled = true + private optionSelectListenerEnabled = true /** Alternative disabled state that keeps element focusable */ @Prop() ariaDisabled: string @@ -112,6 +114,13 @@ export class LdSelect implements InnerFocusable { /** A Boolean attribute indicating that an option with a non-empty string value must be selected. */ @Prop() required?: boolean + /** + * Sanitize config passed to DOMPurify's sanitize method. + * If passed as string, the component will try to parse the string as JSON. + * See https://github.com/cure53/DOMPurify#can-i-configure-dompurify + */ + @Prop() sanitizeConfig?: SanitizeConfig | string + /** Currently selected option(s) (read only!) */ @Prop({ mutable: true }) selected?: SelectOption[] = [] @@ -121,8 +130,8 @@ export class LdSelect implements InnerFocusable { /** Tether options object to be merged with the default options (optionally stringified). */ @Prop() tetherOptions?: Partial | string - @State() allOptionsFiltered = false - @State() filterMatchesOption = false + @State() allOptsFiltered = false + @State() filterMatchesOpt = false @State() expanded = false @State() hasCustomIcon = false @State() hasMore = false @@ -130,7 +139,9 @@ export class LdSelect implements InnerFocusable { @State() internalOptionsHTML: string @State() renderHiddenInput = false @State() theme: string - @State() typeAheadHandler: TypeAheadHandler + @State() typeAheadHandler: TypeAheadHandler< + HTMLLdOptionInternalElement | HTMLLdOptgroupInternalElement + > /** * Emitted with an array of selected values @@ -171,7 +182,7 @@ export class LdSelect implements InnerFocusable { const newValues = newSelection.map((option) => option.value) const oldValues = oldSelection.map((option) => option.value) - if (newValues.join() === oldValues.join()) return + if (JSON.stringify(newValues) === JSON.stringify(oldValues)) return this.updateTriggerMoreIndicator(true) @@ -301,6 +312,23 @@ export class LdSelect implements InnerFocusable { ): el is HTMLLdOptionElement | HTMLLdOptionInternalElement => ['LD-OPTION', 'LD-OPTION-INTERNAL'].includes((el as HTMLElement)?.tagName) + private isLdOptgroup = ( + el: HTMLElement | Node | EventTarget + ): el is HTMLLdOptgroupElement | HTMLLdOptgroupInternalElement => + ['LD-OPTGROUP', 'LD-OPTGROUP-INTERNAL'].includes( + (el as HTMLElement)?.tagName + ) + + private isLdOptionInternal = ( + el: HTMLElement | Node | EventTarget + ): el is HTMLLdOptionInternalElement => + ['LD-OPTION-INTERNAL'].includes((el as HTMLElement)?.tagName) + + private isLdOptgroupInternal = ( + el: HTMLElement | Node | EventTarget + ): el is HTMLLdOptgroupInternalElement => + ['LD-OPTGROUP-INTERNAL'].includes((el as HTMLElement)?.tagName) + private updatePopperWidth = () => { this.listboxRef.style.setProperty( 'width', @@ -368,55 +396,90 @@ export class LdSelect implements InnerFocusable { private initOptions = () => { const initialized = this.initialized - const children = initialized - ? this.internalOptionsContainerRef.querySelectorAll('ld-option-internal') - : this.el.querySelectorAll('ld-option') + const children = Array.from( + initialized ? this.internalOptionsContainerRef.children : this.el.children + ) - if (!children.length) { + const options = children.flatMap((child) => { + if (this.isLdOption(child)) { + return child + } + return Array.from(child.children) + }) + + if (!options.length) { throw new TypeError( 'ld-select requires at least one ld-option element as a child, but found none.' ) } - const selectedChildren = Array.from< - HTMLLdOptionInternalElement | HTMLLdOptionElement - >(children).filter((child) => { - return child.selected - }) + const selectedOptions = options.filter( + (child: HTMLLdOptionInternalElement | HTMLLdOptionElement) => { + return child.selected + } + ) - if (selectedChildren.length > 1 && !this.multiple) { + if (selectedOptions.length > 1 && !this.multiple) { throw new TypeError( 'Multiple selected options are not allowed, if multiple option is not set.' ) } + const getInternalOptionHTML = ( + ldOption: HTMLLdOptionElement, + optgroupDisabled = false + ) => { + const classStr = ldOption.classList.toString() + return `${ldOption.innerHTML.replaceAll( + /(.|\n|\r)*<\/ld-icon>/g, + '' + )}` + } + + const getInternalOptgroupHTML = (ldOptgroup: HTMLLdOptgroupElement) => { + const classStr = ldOptgroup.classList.toString() + return `${Array.from(ldOptgroup.children) + .map((ldOption: HTMLLdOptionElement) => + getInternalOptionHTML(ldOption, ldOptgroup.disabled) + ) + .join('')}` + } + if (!initialized) { let internalOptionsHTML = '' - children.forEach((ldOption: HTMLLdOptionElement) => { - const classStr = ldOption.classList.toString() - internalOptionsHTML += `${ldOption.innerHTML.replaceAll( - /(.|\n|\r)*<\/ld-icon>/g, - '' - )}` + children.forEach((child: HTMLLdOptgroupElement | HTMLLdOptionElement) => { + if (this.isLdOption(child)) { + internalOptionsHTML += getInternalOptionHTML(child) + } else if (this.isLdOptgroup(child)) { + internalOptionsHTML += getInternalOptgroupHTML(child) + } // else it's the slotted icon which we ignore. }) this.internalOptionsHTML = internalOptionsHTML } - this.selected = selectedChildren.map((child) => { - return { - value: child.value, - text: child.innerHTML, + this.selected = selectedOptions.map( + (child: HTMLLdOptionInternalElement | HTMLLdOptionElement) => { + return { + value: child.value, + text: child.innerHTML, + } } - }) + ) if (this.listboxRef) { this.typeAheadHandler.options = @@ -493,7 +556,12 @@ export class LdSelect implements InnerFocusable { private handleSlotChange = (mutationsList: MutationRecord[]) => { if (!this.isObserverEnabled) return - if (!mutationsList.some((record) => this.isLdOption(record.target))) { + if ( + !mutationsList.some( + (record) => + this.isLdOption(record.target) || this.isLdOptgroup(record.target) + ) + ) { return } @@ -599,6 +667,9 @@ export class LdSelect implements InnerFocusable { @Listen('ldoptionselect', { target: 'window', passive: true }) handleSelect(ev: CustomEvent) { + if (!this.optionSelectListenerEnabled) return + this.optionSelectListenerEnabled = false + const target = ev.target as HTMLLdOptionInternalElement // Ignore events which are not fired on current instance. @@ -620,6 +691,8 @@ export class LdSelect implements InnerFocusable { } } this.initOptions() + + this.optionSelectListenerEnabled = true } private handleHome = (ev) => { @@ -630,63 +703,69 @@ export class LdSelect implements InnerFocusable { private handleEnd = (ev) => { // Move focus to the last option. ev.preventDefault() - const options = Array.from( + const visibleOptions = Array.from( this.listboxRef.querySelectorAll('ld-option-internal') - ) - if (document.activeElement !== options[options.length - 1]) { - options[options.length - 1].focusOption() + ).filter((option) => !this.optHidden(option)) + if (document.activeElement !== visibleOptions[visibleOptions.length - 1]) { + visibleOptions[visibleOptions.length - 1].focusInner() } } private selectAndFocus = ( ev: KeyboardEvent, - ldOption: HTMLLdOptionInternalElement + opt: HTMLLdOptionInternalElement | HTMLLdOptgroupInternalElement ) => { - if (!ldOption) return + if (!opt) return if (this.multiple && ev.shiftKey) { if ( - this.isLdOption(document.activeElement) && + this.isLdOptionInternal(document.activeElement) && + !this.isLdOptgroupInternal(document.activeElement) && !document.activeElement.hasAttribute('selected') ) { document.activeElement.dispatchEvent( new KeyboardEvent('keydown', { key: ' ' }) ) } - ldOption.focusOption() - if (!ldOption.hasAttribute('selected')) { - ldOption.dispatchEvent(new KeyboardEvent('keydown', { key: ' ' })) + opt.focusInner() + if (!opt.hasAttribute('selected') && !this.isLdOptgroupInternal(opt)) { + opt.dispatchEvent(new KeyboardEvent('keydown', { key: ' ' })) } } else { - ldOption.focusOption() + opt.focusInner() } } private handleFilterChange = (ev: CustomEvent) => { // Hide options which do not match the filter query. - const options = - this.internalOptionsContainerRef.querySelectorAll('ld-option-internal') + const opts: NodeListOf< + HTMLLdOptionInternalElement | HTMLLdOptgroupInternalElement + > = this.internalOptionsContainerRef.querySelectorAll( + 'ld-option-internal, ld-optgroup-internal' + ) const query = ev.detail.trim().toLowerCase() let allFiltered = true - let filterMatchesOption = false - const filteredOptions = Array.from(options).filter((ldOption) => { - const optionTextLower = ldOption.textContent.toLowerCase() - const filtered = Boolean(query) && !optionTextLower.includes(query) - - ldOption.filtered = filtered - if (optionTextLower === query) { - filterMatchesOption = true + let filterMatchesOpt = false + const filteredOpts = Array.from(opts).filter((opt) => { + const optTextLower = this.isLdOptionInternal(opt) + ? opt.textContent.toLowerCase() + : (opt as HTMLLdOptgroupInternalElement).label.toLowerCase() + const filtered = Boolean(query) && !optTextLower.includes(query) + + opt.filtered = filtered + if (optTextLower === query) { + filterMatchesOpt = true } - if (!ldOption.filtered) { + if (!opt.filtered) { allFiltered = false } return !filtered }) - this.typeAheadHandler.options = filteredOptions - this.allOptionsFiltered = allFiltered - this.filterMatchesOption = filterMatchesOption + this.typeAheadHandler.options = filteredOpts + this.allOptsFiltered = allFiltered + this.filterMatchesOpt = filterMatchesOpt // Re-position popper after new height has been applied. requestAnimationFrame(() => { @@ -703,20 +782,162 @@ export class LdSelect implements InnerFocusable { }) } - this.ldoptioncreate.emit(this.getFilterInput().value) + const value = this.getFilterInput().value this.resetFilter() + this.ldoptioncreate.emit(value) } private canCreate = () => { return Boolean( - this.creatable && !this.filterMatchesOption && this.getFilterInput().value + this.creatable && !this.filterMatchesOpt && this.getFilterInput().value ) } + private optHidden = ( + opt: HTMLLdOptionInternalElement | HTMLLdOptgroupInternalElement + ) => { + return opt.hidden || opt.filtered + } + + private focusPrev = ( + current: HTMLLdOptionInternalElement | HTMLLdOptgroupInternalElement, + ev: KeyboardEvent + ) => { + // Focus previous visible option, if any. + // If the previous is an option, we check if it's visible. + if (this.isLdOptionInternal(current.previousElementSibling)) { + if (this.optHidden(current.previousElementSibling)) { + // If it's hidden, we repeat with the hidden option. + this.focusPrev(current.previousElementSibling, ev) + return + } + // If it's not hidden we focus it. + this.selectAndFocus(ev, current.previousElementSibling) + return + } + + // If the previous is an optgroup, we try to focus the last option in it. + if (this.isLdOptgroupInternal(current.previousElementSibling)) { + const lastInOptgroup = Array.from( + current.previousElementSibling.children + ).at(-1) as HTMLLdOptionInternalElement + + // If it's hidden, we repeat with the hidden option. + if (this.optHidden(lastInOptgroup)) { + this.focusPrev(lastInOptgroup, ev) + return + } + // If it's not hidden we focus it. + this.selectAndFocus(ev, lastInOptgroup) + return + } + + // If there is no previous element, we check if we are currently in an optgroup. + const closestOptgroup = + this.isLdOptionInternal(current) && + current.closest( + 'ld-optgroup-internal' + ) + // If we are in an optgroup, we try to focus the optgroup. + if (closestOptgroup) { + // If the optgroup is not visible, we set current to the optgroup and repeat. + if (this.optHidden(closestOptgroup)) { + this.focusPrev(closestOptgroup, ev) + return + } + closestOptgroup.focusInner() + return + } + + // Otherwise we focus either the filter input or the trigger button. + if (this.filter) { + this.getFilterInput().focus() + return + } + this.handleHome(ev) + } + + private focusNext = ( + current: HTMLLdOptionInternalElement | HTMLLdOptgroupInternalElement, + ev: KeyboardEvent + ) => { + // Focus next visible option, if any. + // If current is an optgroup, try to focus the first option in it. + if (this.isLdOptgroupInternal(current)) { + const firstInOptgroup = current.children[0] as HTMLLdOptionInternalElement + // If it's hidden, we repeat with the hidden option. + if (this.optHidden(firstInOptgroup)) { + this.focusNext(firstInOptgroup, ev) + return + } + // If it's not hidden we focus it. + this.selectAndFocus(ev, firstInOptgroup) + return + } + + // If the next is an option, we check if it's visible. + if (this.isLdOptionInternal(current.nextElementSibling)) { + if (this.optHidden(current.nextElementSibling)) { + // If it's hidden, we repeat with the hidden option. + this.focusNext(current.nextElementSibling, ev) + return + } + // If it's not hidden we focus it. + this.selectAndFocus(ev, current.nextElementSibling) + return + } + + // If the next is an optgroup, we try to focus the optgroup. + if (this.isLdOptgroupInternal(current.nextElementSibling)) { + // If it's hidden, we repeat with first input within the hidden optgroup. + if (this.optHidden(current.nextElementSibling)) { + const firstInOptgroup = current.nextElementSibling + .children[0] as HTMLLdOptionInternalElement + // If the first is not visible, we continue with it as current. + if (this.optHidden(firstInOptgroup)) { + this.focusNext(firstInOptgroup, ev) + return + } + // Otherwise we focus it. + this.selectAndFocus(ev, firstInOptgroup) + return + } + // If it's not hidden we focus it. + this.selectAndFocus(ev, current.nextElementSibling) + return + } + + // If there is no next element, we check if we are currently in an optgroup. + const closestOptgroup = + this.isLdOptionInternal(current) && + current.closest( + 'ld-optgroup-internal' + ) + // If we are in an optgroup, we try to focus its next sibling. + if (closestOptgroup) { + const next = closestOptgroup.nextElementSibling as + | HTMLLdOptionInternalElement + | HTMLLdOptgroupInternalElement + | undefined + if (!next) return + + // If the next sibling is not visible, we repeat with the next sibling. + if (this.optHidden(next)) { + this.focusNext(next, ev) + return + } + // If it's visible, we focus it. + next.focusInner() + } + } + @Listen('keydown', { passive: false, target: 'window' }) handleKeyDown(ev: KeyboardEvent) { if (this.isDisabled()) return + // Ignore page special meta key combos. + if (ev.metaKey && !['ArrowDown', 'ArrowUp'].includes(ev.key)) return + // Ignore events if current instance has no focus. if ( document.activeElement.closest('[role="listbox"]') !== this.listboxRef && @@ -780,29 +1001,20 @@ export class LdSelect implements InnerFocusable { if (this.filter && !filterHasFocus) { this.getFilterInput().focus() } else { - const nextLdOption = Array.from( - this.listboxRef.querySelectorAll('ld-option-internal') - ).find((ldOption) => !ldOption.filtered) - this.selectAndFocus(ev, nextLdOption) + const nextOpt = Array.from( + this.listboxRef.querySelectorAll< + HTMLLdOptionInternalElement | HTMLLdOptgroupInternalElement + >('ld-option-internal, ld-optgroup-internal') + ).find((opt) => !this.optHidden(opt)) + this.selectAndFocus(ev, nextOpt) } } else { - let current = document.activeElement - let nextLdOption - while (nextLdOption === undefined) { - if (this.isLdOption(current.nextElementSibling)) { - if ( - current.nextElementSibling.filtered || - current.nextElementSibling.hidden - ) { - current = current.nextElementSibling - } else { - nextLdOption = current.nextElementSibling - } - } else { - nextLdOption = null - } - } - this.selectAndFocus(ev, nextLdOption) + this.focusNext( + document.activeElement as + | HTMLLdOptionInternalElement + | HTMLLdOptgroupInternalElement, + ev + ) } break } @@ -824,32 +1036,11 @@ export class LdSelect implements InnerFocusable { } // Focus previous visible option, if any. - if (this.isLdOption(document.activeElement)) { - let prevLdOption - let current = document.activeElement - while (prevLdOption === undefined) { - if (this.isLdOption(current.previousElementSibling)) { - if ( - current.previousElementSibling.hidden || - current.previousElementSibling.filtered - ) { - current = current.previousElementSibling - } else { - prevLdOption = current.previousElementSibling - } - } else { - prevLdOption = null - } - } - if (prevLdOption) { - this.selectAndFocus(ev, prevLdOption) - } else { - if (this.filter) { - this.getFilterInput().focus() - } else { - this.handleHome(ev) - } - } + if ( + this.isLdOptionInternal(document.activeElement) || + this.isLdOptgroupInternal(document.activeElement) + ) { + this.focusPrev(document.activeElement, ev) } break } @@ -941,22 +1132,25 @@ export class LdSelect implements InnerFocusable { } private resetFilter = () => { - this.allOptionsFiltered = false - this.filterMatchesOption = false + this.allOptsFiltered = false + this.filterMatchesOpt = false if (!this.filter) return const filterInput = this.getFilterInput() if (!filterInput) return filterInput.value = '' - const options = - this.internalOptionsContainerRef.querySelectorAll('ld-option-internal') + const opts: NodeListOf< + HTMLLdOptionInternalElement | HTMLLdOptgroupInternalElement + > = this.internalOptionsContainerRef.querySelectorAll( + 'ld-option-internal, ld-optgroup-internal' + ) - options.forEach((ldOption) => { - ldOption.filtered = false + opts.forEach((opt) => { + opt.filtered = false }) - this.typeAheadHandler.options = options + this.typeAheadHandler.options = opts this.listboxRef.resetFilter() } @@ -966,6 +1160,7 @@ export class LdSelect implements InnerFocusable { ev.relatedTarget === null || ev.relatedTarget === this.listboxRef || this.isLdOption(ev.relatedTarget) || + this.isLdOptgroup(ev.relatedTarget) || closest('ld-select', ev.relatedTarget as HTMLElement) === this.el ) { ev.stopImmediatePropagation() @@ -1170,7 +1365,10 @@ export class LdSelect implements InnerFocusable { class="ld-select__selection-label-text" title={selection.text} part="selection-label-text" - innerHTML={selection.text} + innerHTML={sanitize( + selection.text, + this.sanitizeConfig + )} >
(this.internalOptionsContainerRef = el)} - innerHTML={this.internalOptionsHTML} + innerHTML={sanitize(this.internalOptionsHTML, { + ...(typeof this.sanitizeConfig === 'string' + ? JSON.parse(this.sanitizeConfig) + : this.sanitizeConfig), + ADD_ATTR: ['prevent-deselection'], + })} part="options-container" >
diff --git a/src/liquid/components/ld-select/readme.md b/src/liquid/components/ld-select/readme.md index ff471c48a7..ae104da4b6 100644 --- a/src/liquid/components/ld-select/readme.md +++ b/src/liquid/components/ld-select/readme.md @@ -33,7 +33,7 @@ The feature set of the `ld-select` Web Component differs from its CSS Component Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -53,7 +53,7 @@ The feature set of the `ld-select` Web Component differs from its CSS Component Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -75,7 +75,7 @@ The feature set of the `ld-select` Web Component differs from its CSS Component - + @@ -113,7 +113,7 @@ You can prevent a state with no options selected after initial selection in sing Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -133,7 +133,7 @@ You can prevent a state with no options selected after initial selection in sing Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -155,7 +155,7 @@ You can prevent a state with no options selected after initial selection in sing Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -175,7 +175,7 @@ You can prevent a state with no options selected after initial selection in sing Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -189,6 +189,41 @@ You can prevent a state with no options selected after initial selection in sing Pineapple Plum + + + +
+ + + + +
{% endexample %} #### Width @@ -199,7 +234,7 @@ You may have noticed, that in multiple mode the component grows horizontally wit Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -217,7 +252,7 @@ You may have noticed, that in multiple mode the component grows horizontally wit Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -237,7 +272,7 @@ You may have noticed, that in multiple mode the component grows horizontally wit Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -255,7 +290,7 @@ You may have noticed, that in multiple mode the component grows horizontally wit Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -279,7 +314,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -297,7 +332,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -317,7 +352,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -335,7 +370,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -357,7 +392,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -375,7 +410,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -393,7 +428,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -411,7 +446,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -431,7 +466,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -449,7 +484,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -467,7 +502,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -485,7 +520,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -507,7 +542,7 @@ If you have limited vertical space (this may especially be the case on mobile de - + @@ -543,7 +578,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -561,7 +596,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -579,7 +614,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -597,7 +632,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -617,7 +652,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -635,7 +670,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -653,7 +688,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -671,7 +706,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -693,7 +728,7 @@ If you have limited vertical space (this may especially be the case on mobile de - + @@ -733,7 +768,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -751,7 +786,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -771,7 +806,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -789,7 +824,7 @@ If you have limited vertical space (this may especially be the case on mobile de Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -811,7 +846,7 @@ If you have limited vertical space (this may especially be the case on mobile de - + @@ -849,7 +884,7 @@ In detached mode the component positions the popper element with a small vertica Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -869,7 +904,7 @@ In detached mode the component positions the popper element with a small vertica Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -893,7 +928,7 @@ In inline mode, while the popper element has a minimum width, the component's tr Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -911,7 +946,7 @@ In inline mode, while the popper element has a minimum width, the component's tr Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -929,7 +964,7 @@ In inline mode, while the popper element has a minimum width, the component's tr Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -949,7 +984,7 @@ In inline mode, while the popper element has a minimum width, the component's tr Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -967,7 +1002,7 @@ In inline mode, while the popper element has a minimum width, the component's tr Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -985,7 +1020,7 @@ In inline mode, while the popper element has a minimum width, the component's tr Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1009,7 +1044,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1029,7 +1064,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1051,7 +1086,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1069,7 +1104,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1087,7 +1122,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1105,7 +1140,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1123,7 +1158,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1141,7 +1176,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1161,7 +1196,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1179,7 +1214,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1197,7 +1232,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1215,7 +1250,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1233,7 +1268,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1251,7 +1286,7 @@ In ghost mode the component works the same way as it does in inline mode while a Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1273,7 +1308,7 @@ In ghost mode the component works the same way as it does in inline mode while a - + @@ -1307,7 +1342,7 @@ In ghost mode the component works the same way as it does in inline mode while a - + @@ -1341,7 +1376,7 @@ In ghost mode the component works the same way as it does in inline mode while a - + @@ -1379,7 +1414,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1398,7 +1433,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1417,7 +1452,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1438,7 +1473,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1457,7 +1492,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1476,7 +1511,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1499,7 +1534,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo - + @@ -1524,7 +1559,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo - + @@ -1549,7 +1584,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo - + @@ -1576,7 +1611,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1594,7 +1629,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1614,7 +1649,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1632,7 +1667,7 @@ For both, the ld-select Web Component and the CSS Component, you can use a custo Apple Banana - Strawberry + Papaya Watermelon Honeymelon Rasberry @@ -1662,7 +1697,7 @@ This mode allows the user to create new options using the filter input field. > Apple Banana - Strawberry + Papaya