@api-client/ui 0.5.23 → 0.5.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/.cursor/rules/lit-best-practices.mdc +12 -1
  2. package/.github/instructions/lit-best-practices.instructions.md +2 -0
  3. package/build/src/md/dropdown-list/internals/UiDropdownList.d.ts.map +1 -1
  4. package/build/src/md/dropdown-list/internals/UiDropdownList.js +4 -3
  5. package/build/src/md/dropdown-list/internals/UiDropdownList.js.map +1 -1
  6. package/build/src/md/input/Input.d.ts +8 -4
  7. package/build/src/md/input/Input.d.ts.map +1 -1
  8. package/build/src/md/input/Input.js +8 -36
  9. package/build/src/md/input/Input.js.map +1 -1
  10. package/build/src/md/list/internals/List.d.ts +3 -1
  11. package/build/src/md/list/internals/List.d.ts.map +1 -1
  12. package/build/src/md/list/internals/List.js +10 -5
  13. package/build/src/md/list/internals/List.js.map +1 -1
  14. package/build/src/md/menu/internal/Menu.d.ts +8 -7
  15. package/build/src/md/menu/internal/Menu.d.ts.map +1 -1
  16. package/build/src/md/menu/internal/Menu.js +39 -29
  17. package/build/src/md/menu/internal/Menu.js.map +1 -1
  18. package/build/src/md/menu/internal/Menu.styles.d.ts.map +1 -1
  19. package/build/src/md/menu/internal/Menu.styles.js +66 -1
  20. package/build/src/md/menu/internal/Menu.styles.js.map +1 -1
  21. package/build/src/md/select/index.d.ts +4 -0
  22. package/build/src/md/select/index.d.ts.map +1 -0
  23. package/build/src/md/select/index.js +3 -0
  24. package/build/src/md/select/index.js.map +1 -0
  25. package/build/src/md/select/internals/Option.d.ts +125 -0
  26. package/build/src/md/select/internals/Option.d.ts.map +1 -0
  27. package/build/src/md/select/internals/Option.js +242 -0
  28. package/build/src/md/select/internals/Option.js.map +1 -0
  29. package/build/src/md/select/internals/Option.styles.d.ts +3 -0
  30. package/build/src/md/select/internals/Option.styles.d.ts.map +1 -0
  31. package/build/src/md/select/internals/Option.styles.js +139 -0
  32. package/build/src/md/select/internals/Option.styles.js.map +1 -0
  33. package/build/src/md/select/internals/Select.d.ts +250 -0
  34. package/build/src/md/select/internals/Select.d.ts.map +1 -0
  35. package/build/src/md/select/internals/Select.js +606 -0
  36. package/build/src/md/select/internals/Select.js.map +1 -0
  37. package/build/src/md/select/internals/Select.styles.d.ts +3 -0
  38. package/build/src/md/select/internals/Select.styles.d.ts.map +1 -0
  39. package/build/src/md/select/internals/Select.styles.js +22 -0
  40. package/build/src/md/select/internals/Select.styles.js.map +1 -0
  41. package/build/src/md/select/ui-option.d.ts +12 -0
  42. package/build/src/md/select/ui-option.d.ts.map +1 -0
  43. package/build/src/md/select/ui-option.js +29 -0
  44. package/build/src/md/select/ui-option.js.map +1 -0
  45. package/build/src/md/select/ui-select.d.ts +12 -0
  46. package/build/src/md/select/ui-select.d.ts.map +1 -0
  47. package/build/src/md/select/ui-select.js +27 -0
  48. package/build/src/md/select/ui-select.js.map +1 -0
  49. package/build/src/md/text-field/internals/TextField.d.ts.map +1 -1
  50. package/build/src/md/text-field/internals/TextField.js +1 -0
  51. package/build/src/md/text-field/internals/TextField.js.map +1 -1
  52. package/demo/md/index.html +2 -0
  53. package/demo/md/inputs/input.ts +4 -0
  54. package/demo/md/select/index.html +16 -0
  55. package/demo/md/select/index.ts +202 -0
  56. package/package.json +1 -1
  57. package/src/md/dropdown-list/internals/UiDropdownList.ts +4 -3
  58. package/src/md/input/Input.ts +8 -37
  59. package/src/md/list/internals/List.ts +13 -6
  60. package/src/md/menu/internal/Menu.styles.ts +66 -1
  61. package/src/md/menu/internal/Menu.ts +41 -18
  62. package/src/md/select/index.ts +3 -0
  63. package/src/md/select/internals/Option.styles.ts +139 -0
  64. package/src/md/select/internals/Option.ts +210 -0
  65. package/src/md/select/internals/Select.styles.ts +22 -0
  66. package/src/md/select/internals/Select.ts +534 -0
  67. package/src/md/select/ui-option.ts +18 -0
  68. package/src/md/select/ui-select.ts +17 -0
  69. package/src/md/text-field/internals/TextField.ts +1 -0
  70. package/test/md/menu/SubMenu.test.ts +2 -3
  71. package/test/md/select/Select.test.ts +667 -0
@@ -0,0 +1,22 @@
1
+ import { css } from 'lit';
2
+ export default css `
3
+ :host {
4
+ display: inline-block;
5
+ position: relative;
6
+ outline: none;
7
+ --md-focus-ring-shape-end-end: var(--md-sys-shape-corner-extra-small);
8
+ --md-focus-ring-shape-end-start: var(--md-sys-shape-corner-extra-small);
9
+ --md-focus-ring-shape-start-end: var(--md-sys-shape-corner-extra-small);
10
+ --md-focus-ring-shape-start-start: var(--md-sys-shape-corner-extra-small);
11
+ }
12
+
13
+ .input {
14
+ anchor-name: --input;
15
+ cursor: default;
16
+ }
17
+
18
+ .menu {
19
+ position-anchor: --input;
20
+ }
21
+ `;
22
+ //# sourceMappingURL=Select.styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Select.styles.js","sourceRoot":"","sources":["../../../../../src/md/select/internals/Select.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,eAAe,GAAG,CAAA;;;;;;;;;;;;;;;;;;;CAmBjB,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport default css`\n :host {\n display: inline-block;\n position: relative;\n outline: none;\n --md-focus-ring-shape-end-end: var(--md-sys-shape-corner-extra-small);\n --md-focus-ring-shape-end-start: var(--md-sys-shape-corner-extra-small);\n --md-focus-ring-shape-start-end: var(--md-sys-shape-corner-extra-small);\n --md-focus-ring-shape-start-start: var(--md-sys-shape-corner-extra-small);\n }\n\n .input {\n anchor-name: --input;\n cursor: default;\n }\n\n .menu {\n position-anchor: --input;\n }\n`\n"]}
@@ -0,0 +1,12 @@
1
+ import type { CSSResultOrNative } from 'lit';
2
+ import Element from './internals/Option.js';
3
+ export declare class UiOptionElement extends Element {
4
+ static styles: CSSResultOrNative[];
5
+ }
6
+ declare global {
7
+ interface HTMLElementTagNameMap {
8
+ 'ui-option': Element;
9
+ }
10
+ }
11
+ export { ListItemImage, ListItemLines } from '../list/internals/ListItem.js';
12
+ //# sourceMappingURL=ui-option.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-option.d.ts","sourceRoot":"","sources":["../../../../src/md/select/ui-option.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,KAAK,CAAA;AAE5C,OAAO,OAAO,MAAM,uBAAuB,CAAA;AAI3C,qBACa,eAAgB,SAAQ,OAAO;IAC1C,OAAgB,MAAM,EAAE,iBAAiB,EAAE,CAAuB;CACnE;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,WAAW,EAAE,OAAO,CAAA;KACrB;CACF;AAED,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA"}
@@ -0,0 +1,29 @@
1
+ import { __esDecorate, __runInitializers } from "tslib";
2
+ import { customElement } from 'lit/decorators.js';
3
+ import Element from './internals/Option.js';
4
+ import styles from './internals/Option.styles.js';
5
+ import listStyles from '../list/internals/ListItem.styles.js';
6
+ let UiOptionElement = (() => {
7
+ let _classDecorators = [customElement('ui-option')];
8
+ let _classDescriptor;
9
+ let _classExtraInitializers = [];
10
+ let _classThis;
11
+ let _classSuper = Element;
12
+ var UiOptionElement = class extends _classSuper {
13
+ static { _classThis = this; }
14
+ static {
15
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
16
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
17
+ UiOptionElement = _classThis = _classDescriptor.value;
18
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
19
+ }
20
+ static styles = [styles, listStyles];
21
+ static {
22
+ __runInitializers(_classThis, _classExtraInitializers);
23
+ }
24
+ };
25
+ return UiOptionElement = _classThis;
26
+ })();
27
+ export { UiOptionElement };
28
+ export { ListItemImage, ListItemLines } from '../list/internals/ListItem.js';
29
+ //# sourceMappingURL=ui-option.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-option.js","sourceRoot":"","sources":["../../../../src/md/select/ui-option.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,OAAO,MAAM,uBAAuB,CAAA;AAC3C,OAAO,MAAM,MAAM,8BAA8B,CAAA;AACjD,OAAO,UAAU,MAAM,sCAAsC,CAAA;IAGhD,eAAe;4BAD3B,aAAa,CAAC,WAAW,CAAC;;;;sBACU,OAAO;+BAAf,SAAQ,WAAO;;;;YAA5C,6KAEC;;;;QADC,MAAM,CAAU,MAAM,GAAwB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;;YADvD,uDAAe;;;;;SAAf,eAAe;AAU5B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA","sourcesContent":["import type { CSSResultOrNative } from 'lit'\nimport { customElement } from 'lit/decorators.js'\nimport Element from './internals/Option.js'\nimport styles from './internals/Option.styles.js'\nimport listStyles from '../list/internals/ListItem.styles.js'\n\n@customElement('ui-option')\nexport class UiOptionElement extends Element {\n static override styles: CSSResultOrNative[] = [styles, listStyles]\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ui-option': Element\n }\n}\n\nexport { ListItemImage, ListItemLines } from '../list/internals/ListItem.js'\n"]}
@@ -0,0 +1,12 @@
1
+ import type { CSSResultOrNative } from 'lit';
2
+ import Element from './internals/Select.js';
3
+ export declare class UiSelectElement extends Element {
4
+ static styles: CSSResultOrNative[];
5
+ }
6
+ declare global {
7
+ interface HTMLElementTagNameMap {
8
+ 'ui-select': Element;
9
+ }
10
+ }
11
+ export type { UiSelectChangeEvent } from './internals/Select.js';
12
+ //# sourceMappingURL=ui-select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-select.d.ts","sourceRoot":"","sources":["../../../../src/md/select/ui-select.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,KAAK,CAAA;AAE5C,OAAO,OAAO,MAAM,uBAAuB,CAAA;AAG3C,qBACa,eAAgB,SAAQ,OAAO;IAC1C,OAAgB,MAAM,EAAE,iBAAiB,EAAE,CAAW;CACvD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,WAAW,EAAE,OAAO,CAAA;KACrB;CACF;AAED,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA"}
@@ -0,0 +1,27 @@
1
+ import { __esDecorate, __runInitializers } from "tslib";
2
+ import { customElement } from 'lit/decorators.js';
3
+ import Element from './internals/Select.js';
4
+ import styles from './internals/Select.styles.js';
5
+ let UiSelectElement = (() => {
6
+ let _classDecorators = [customElement('ui-select')];
7
+ let _classDescriptor;
8
+ let _classExtraInitializers = [];
9
+ let _classThis;
10
+ let _classSuper = Element;
11
+ var UiSelectElement = class extends _classSuper {
12
+ static { _classThis = this; }
13
+ static {
14
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
15
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
16
+ UiSelectElement = _classThis = _classDescriptor.value;
17
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
18
+ }
19
+ static styles = [styles];
20
+ static {
21
+ __runInitializers(_classThis, _classExtraInitializers);
22
+ }
23
+ };
24
+ return UiSelectElement = _classThis;
25
+ })();
26
+ export { UiSelectElement };
27
+ //# sourceMappingURL=ui-select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-select.js","sourceRoot":"","sources":["../../../../src/md/select/ui-select.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,OAAO,MAAM,uBAAuB,CAAA;AAC3C,OAAO,MAAM,MAAM,8BAA8B,CAAA;IAGpC,eAAe;4BAD3B,aAAa,CAAC,WAAW,CAAC;;;;sBACU,OAAO;+BAAf,SAAQ,WAAO;;;;YAA5C,6KAEC;;;;QADC,MAAM,CAAU,MAAM,GAAwB,CAAC,MAAM,CAAC,CAAA;;YAD3C,uDAAe;;;;;SAAf,eAAe","sourcesContent":["import type { CSSResultOrNative } from 'lit'\nimport { customElement } from 'lit/decorators.js'\nimport Element from './internals/Select.js'\nimport styles from './internals/Select.styles.js'\n\n@customElement('ui-select')\nexport class UiSelectElement extends Element {\n static override styles: CSSResultOrNative[] = [styles]\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ui-select': Element\n }\n}\n\nexport type { UiSelectChangeEvent } from './internals/Select.js'\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"TextField.d.ts","sourceRoot":"","sources":["../../../../../src/md/text-field/internals/TextField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,MAAM,KAAK,CAAA;AAI1C,OAAO,KAAK,MAAM,sBAAsB,CAAA;AAExC,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,KAAK;cACvB,WAAW,IAAI,cAAc;CAgEjD"}
1
+ {"version":3,"file":"TextField.d.ts","sourceRoot":"","sources":["../../../../../src/md/text-field/internals/TextField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,MAAM,KAAK,CAAA;AAI1C,OAAO,KAAK,MAAM,sBAAsB,CAAA;AAExC,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,KAAK;cACvB,WAAW,IAAI,cAAc;CAiEjD"}
@@ -50,6 +50,7 @@ export default class TextField extends Input {
50
50
  ?multiple="${this.multiple}"
51
51
  spellcheck="${ifDefined(this.spellcheck)}"
52
52
  list="input-list"
53
+ tabindex="${ifDefined(this.tabIndex)}"
53
54
  @change=${this.retargetEvent}
54
55
  @input=${this.handleInput}
55
56
  @select=${this.retargetEvent}
@@ -1 +1 @@
1
- {"version":3,"file":"TextField.js","sourceRoot":"","sources":["../../../../../src/md/text-field/internals/TextField.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, TemplateResult } from 'lit'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { live } from 'lit/directives/live.js'\nimport { StyleInfo, styleMap } from 'lit/directives/style-map.js'\nimport Input from '../../input/Input.js'\n\nexport default class TextField extends Input {\n protected override renderInput(): TemplateResult {\n const placeholderValue = this.placeholder || undefined\n const maxValue = this.max || undefined\n const maxLengthValue = this.maxLength > -1 ? this.maxLength : undefined\n const minValue = this.min || undefined\n const patternValue = this.pattern || undefined\n const roleValue = this.dataRole || undefined\n const stepValue = this.step || undefined\n const { disabled } = this\n\n const style: StyleInfo = {}\n if (this.textDirection) {\n style.direction = this.textDirection\n }\n\n const ariaActiveDescendantValue = this.ariaActiveDescendant || undefined\n const ariaAutoCompleteValue = this.ariaAutoComplete || undefined\n const ariaControlsValue = this.ariaControls || undefined\n const ariaDescribedByValue = this.getAriaDescribedBy() || undefined\n const ariaExpandedValue = this.ariaExpanded || undefined\n const ariaLabelValue = this.ariaLabel || this.label || undefined\n const ariaLabelledByValue = this.ariaLabelledBy || undefined\n\n return html`\n <input\n class=\"input\"\n style=${styleMap(style)}\n type=${this.effectiveType}\n name=\"${ifDefined(this.name)}\"\n .value=${live(this.getInputValue())}\n max=${ifDefined(maxValue)}\n maxlength=${ifDefined(maxLengthValue)}\n min=${ifDefined(minValue)}\n minlength=${ifDefined(this.minLength)}\n pattern=${ifDefined(patternValue)}\n placeholder=${ifDefined(placeholderValue)}\n role=${ifDefined(roleValue as 'textbox')}\n ?disabled=${disabled}\n ?readonly=${this.readOnly}\n ?required=${this.required}\n step=${ifDefined(stepValue)}\n autocomplete=\"${ifDefined(this.autocomplete)}\"\n autocapitalize=\"${ifDefined(this.autocapitalize)}\"\n inputmode=\"${ifDefined(this.inputMode)}\"\n size=\"${ifDefined(this.size)}\"\n accept=\"${ifDefined(this.accept)}\"\n ?multiple=\"${this.multiple}\"\n spellcheck=\"${ifDefined(this.spellcheck)}\"\n list=\"input-list\"\n @change=${this.retargetEvent}\n @input=${this.handleInput}\n @select=${this.retargetEvent}\n @invalid=${this.invalidHandler}\n aria-activedescendant=${ifDefined(ariaActiveDescendantValue)}\n aria-autocomplete=${ifDefined(ariaAutoCompleteValue)}\n aria-controls=${ifDefined(ariaControlsValue)}\n aria-describedby=${ifDefined(ariaDescribedByValue)}\n aria-expanded=${ifDefined(ariaExpandedValue)}\n aria-invalid=${this.getError()}\n aria-label=${ifDefined(ariaLabelValue)}\n aria-labelledby=${ifDefined(ariaLabelledByValue)}\n />\n `\n }\n}\n"]}
1
+ {"version":3,"file":"TextField.js","sourceRoot":"","sources":["../../../../../src/md/text-field/internals/TextField.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, TemplateResult } from 'lit'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { live } from 'lit/directives/live.js'\nimport { StyleInfo, styleMap } from 'lit/directives/style-map.js'\nimport Input from '../../input/Input.js'\n\nexport default class TextField extends Input {\n protected override renderInput(): TemplateResult {\n const placeholderValue = this.placeholder || undefined\n const maxValue = this.max || undefined\n const maxLengthValue = this.maxLength > -1 ? this.maxLength : undefined\n const minValue = this.min || undefined\n const patternValue = this.pattern || undefined\n const roleValue = this.dataRole || undefined\n const stepValue = this.step || undefined\n const { disabled } = this\n\n const style: StyleInfo = {}\n if (this.textDirection) {\n style.direction = this.textDirection\n }\n\n const ariaActiveDescendantValue = this.ariaActiveDescendant || undefined\n const ariaAutoCompleteValue = this.ariaAutoComplete || undefined\n const ariaControlsValue = this.ariaControls || undefined\n const ariaDescribedByValue = this.getAriaDescribedBy() || undefined\n const ariaExpandedValue = this.ariaExpanded || undefined\n const ariaLabelValue = this.ariaLabel || this.label || undefined\n const ariaLabelledByValue = this.ariaLabelledBy || undefined\n\n return html`\n <input\n class=\"input\"\n style=${styleMap(style)}\n type=${this.effectiveType}\n name=\"${ifDefined(this.name)}\"\n .value=${live(this.getInputValue())}\n max=${ifDefined(maxValue)}\n maxlength=${ifDefined(maxLengthValue)}\n min=${ifDefined(minValue)}\n minlength=${ifDefined(this.minLength)}\n pattern=${ifDefined(patternValue)}\n placeholder=${ifDefined(placeholderValue)}\n role=${ifDefined(roleValue as 'textbox')}\n ?disabled=${disabled}\n ?readonly=${this.readOnly}\n ?required=${this.required}\n step=${ifDefined(stepValue)}\n autocomplete=\"${ifDefined(this.autocomplete)}\"\n autocapitalize=\"${ifDefined(this.autocapitalize)}\"\n inputmode=\"${ifDefined(this.inputMode)}\"\n size=\"${ifDefined(this.size)}\"\n accept=\"${ifDefined(this.accept)}\"\n ?multiple=\"${this.multiple}\"\n spellcheck=\"${ifDefined(this.spellcheck)}\"\n list=\"input-list\"\n tabindex=\"${ifDefined(this.tabIndex)}\"\n @change=${this.retargetEvent}\n @input=${this.handleInput}\n @select=${this.retargetEvent}\n @invalid=${this.invalidHandler}\n aria-activedescendant=${ifDefined(ariaActiveDescendantValue)}\n aria-autocomplete=${ifDefined(ariaAutoCompleteValue)}\n aria-controls=${ifDefined(ariaControlsValue)}\n aria-describedby=${ifDefined(ariaDescribedByValue)}\n aria-expanded=${ifDefined(ariaExpandedValue)}\n aria-invalid=${this.getError()}\n aria-label=${ifDefined(ariaLabelValue)}\n aria-labelledby=${ifDefined(ariaLabelledByValue)}\n />\n `\n }\n}\n"]}
@@ -47,6 +47,8 @@
47
47
  <dd>A Material 3 listbox.</dd>
48
48
  <dt><a href="menu/index.html">menu</a></dt>
49
49
  <dd>A Material 3 menu.</dd>
50
+ <dt><a href="select/index.html">select</a></dt>
51
+ <dd>A Material 3 select.</dd>
50
52
  <dt><a href="inputs/switch.html">switch</a></dt>
51
53
  <dd>A Material 3 switch.</dd>
52
54
 
@@ -177,6 +177,10 @@ class ComponentDemoPage extends DemoPage {
177
177
  <span class="column-title title-medium">Filled</span>
178
178
  <span class="column-title title-medium">Outlined</span>
179
179
 
180
+ <span class="row-name title-small">Password</span>
181
+ <ui-filled-text-field label="Enter password" name="pwd-filled" type="password"></ui-filled-text-field>
182
+ <ui-outlined-text-field label="Enter password" name="pwd-outlined" type="password"></ui-outlined-text-field>
183
+
180
184
  <span class="row-name title-small">Color</span>
181
185
  <ui-filled-text-field label="Select a color" name="color-filled" type="color"></ui-filled-text-field>
182
186
  <ui-outlined-text-field label="Select a color" name="color-outlined" type="color"></ui-outlined-text-field>
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>UI Select</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
8
+ <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&icon_names=arrow_drop_down,check" rel="stylesheet" />
9
+ <link href="../../../src/styles/m3/tokens.css" rel="stylesheet" type="text/css" />
10
+ <link href="../../../src/styles/m3/theme.css" rel="stylesheet" type="text/css" />
11
+ </head>
12
+ <body>
13
+ <div id="app"></div>
14
+ <script type="module" src="/.tmp/demo/md/select/index.js"></script>
15
+ </body>
16
+ </html>
@@ -0,0 +1,202 @@
1
+ import { html, TemplateResult } from 'lit'
2
+ import { DemoPage } from '../../../src/demo/DemoPage.js'
3
+ import { reactive } from '../../../src/decorators/index.js'
4
+ import '../../../src/md/select/ui-select.js'
5
+ import '../../../src/md/select/ui-option.js'
6
+ import '../../../src/md/button/ui-button.js'
7
+ import '../../../src/md/icons/ui-icon.js'
8
+
9
+ class ComponentDemoPage extends DemoPage {
10
+ override accessor componentName = 'UI Select'
11
+
12
+ @reactive() accessor basicSelected: string | undefined
13
+
14
+ @reactive() accessor iconSelected: string | undefined
15
+
16
+ @reactive() accessor supportingSelected: string | undefined
17
+
18
+ @reactive() accessor noIconSelected: string | undefined
19
+
20
+ @reactive() accessor programmaticSelected: string | undefined
21
+
22
+ contentTemplate(): TemplateResult {
23
+ return html`
24
+ <a href="../">Back</a>
25
+ <h1>UI Select</h1>
26
+ <p>A Material Design 3 select component that behaves like an outlined text field with dropdown.</p>
27
+
28
+ <section>
29
+ <h2>Basic Select</h2>
30
+ <p>Select a fruit from the list:</p>
31
+ <ui-select id="basic-select" @change="${this.handleBasicSelectChange}" label="Select a fruit">
32
+ <ui-option value="apple">Apple</ui-option>
33
+ <ui-option value="banana">Banana</ui-option>
34
+ <ui-option value="cherry">Cherry</ui-option>
35
+ <ui-option value="date">Date</ui-option>
36
+ <ui-option value="elderberry">Elderberry</ui-option>
37
+ </ui-select>
38
+ <p>Selected: <span id="basic-result">None</span></p>
39
+ </section>
40
+
41
+ <section>
42
+ <h2>Select with Icons</h2>
43
+ <p>Select a country with icons:</p>
44
+ <ui-select id="icon-select" @change="${this.handleIconSelectChange}" value="us" label="Select a country">
45
+ <ui-option value="us">
46
+ <ui-icon slot="start">🇺🇸</ui-icon>
47
+ United States
48
+ </ui-option>
49
+ <ui-option value="gb">
50
+ <ui-icon slot="start">🇬🇧</ui-icon>
51
+ United Kingdom
52
+ </ui-option>
53
+ <ui-option value="de">
54
+ <ui-icon slot="start">🇩🇪</ui-icon>
55
+ Germany
56
+ </ui-option>
57
+ <ui-option value="fr">
58
+ <ui-icon slot="start">🇫🇷</ui-icon>
59
+ France
60
+ </ui-option>
61
+ <ui-option value="jp">
62
+ <ui-icon slot="start">🇯🇵</ui-icon>
63
+ Japan
64
+ </ui-option>
65
+ </ui-select>
66
+ <p>Selected: <span id="icon-result">None</span></p>
67
+ </section>
68
+
69
+ <section>
70
+ <h2>Select with Supporting Text</h2>
71
+ <p>Select a user with additional information:</p>
72
+ <ui-select id="supporting-select" @change="${this.handleSupportingSelectChange}">
73
+ <ui-option value="alice" lines="two">
74
+ Alice Johnson
75
+ <span slot="supporting-text">alice@example.com</span>
76
+ </ui-option>
77
+ <ui-option value="bob" lines="two">
78
+ Bob Smith
79
+ <span slot="supporting-text">bob@example.com</span>
80
+ </ui-option>
81
+ <ui-option value="carol" lines="two">
82
+ Carol Davis
83
+ <span slot="supporting-text">carol@example.com</span>
84
+ </ui-option>
85
+ <ui-option value="dave" lines="two">
86
+ Dave Wilson
87
+ <span slot="supporting-text">dave@example.com</span>
88
+ </ui-option>
89
+ </ui-select>
90
+ <p>Selected: <span id="supporting-result">None</span></p>
91
+ </section>
92
+
93
+ <section>
94
+ <h2>Disabled Select</h2>
95
+ <p>This select is disabled:</p>
96
+ <ui-select id="disabled-select" disabled>
97
+ <ui-option value="option1">Option 1</ui-option>
98
+ <ui-option value="option2">Option 2</ui-option>
99
+ <ui-option value="option3">Option 3</ui-option>
100
+ </ui-select>
101
+ </section>
102
+
103
+ <section>
104
+ <h2>Select without Selection Icon</h2>
105
+ <p>Select without the check icon:</p>
106
+ <ui-select id="no-icon-select" @change="${this.handleNoIconSelectChange}">
107
+ <ui-option value="red">Red</ui-option>
108
+ <ui-option value="green">Green</ui-option>
109
+ <ui-option value="blue">Blue</ui-option>
110
+ <ui-option value="yellow">Yellow</ui-option>
111
+ </ui-select>
112
+ <p>Selected: <span id="no-icon-result">None</span></p>
113
+ </section>
114
+
115
+ <section>
116
+ <h2>Programmatic Control</h2>
117
+ <p>Control the select value programmatically:</p>
118
+ <ui-select id="programmatic-select" @change="${this.handleProgrammaticSelectChange}">
119
+ <ui-option value="one">One</ui-option>
120
+ <ui-option value="two">Two</ui-option>
121
+ <ui-option value="three">Three</ui-option>
122
+ <ui-option value="four">Four</ui-option>
123
+ </ui-select>
124
+ <p>Selected: <span id="programmatic-result">None</span></p>
125
+ <div class="button-group">
126
+ <ui-button @click="${this.setValueOne}">Set to "One"</ui-button>
127
+ <ui-button @click="${this.setValueTwo}">Set to "Two"</ui-button>
128
+ <ui-button @click="${this.clearValue}">Clear</ui-button>
129
+ </div>
130
+ </section>
131
+ `
132
+ }
133
+
134
+ handleBasicSelectChange(e: CustomEvent): void {
135
+ const { value } = e.detail
136
+ this.basicSelected = value
137
+ const resultElement = document.querySelector('#basic-result')
138
+ if (resultElement) {
139
+ resultElement.textContent = value || 'None'
140
+ }
141
+ }
142
+
143
+ handleIconSelectChange(e: CustomEvent): void {
144
+ const { value } = e.detail
145
+ this.iconSelected = value
146
+ const resultElement = document.querySelector('#icon-result')
147
+ if (resultElement) {
148
+ resultElement.textContent = value || 'None'
149
+ }
150
+ }
151
+
152
+ handleSupportingSelectChange(e: CustomEvent): void {
153
+ const { value } = e.detail
154
+ this.supportingSelected = value
155
+ const resultElement = document.querySelector('#supporting-result')
156
+ if (resultElement) {
157
+ resultElement.textContent = value || 'None'
158
+ }
159
+ }
160
+
161
+ handleNoIconSelectChange(e: CustomEvent): void {
162
+ const { value } = e.detail
163
+ this.noIconSelected = value
164
+ const resultElement = document.querySelector('#no-icon-result')
165
+ if (resultElement) {
166
+ resultElement.textContent = value || 'None'
167
+ }
168
+ }
169
+
170
+ handleProgrammaticSelectChange(e: CustomEvent): void {
171
+ const { value } = e.detail
172
+ this.programmaticSelected = value
173
+ const resultElement = document.querySelector('#programmatic-result')
174
+ if (resultElement) {
175
+ resultElement.textContent = value || 'None'
176
+ }
177
+ }
178
+
179
+ setValueOne(): void {
180
+ const select = document.querySelector('#programmatic-select') as HTMLElement & { value: string }
181
+ if (select) {
182
+ select.value = 'one'
183
+ }
184
+ }
185
+
186
+ setValueTwo(): void {
187
+ const select = document.querySelector('#programmatic-select') as HTMLElement & { value: string }
188
+ if (select) {
189
+ select.value = 'two'
190
+ }
191
+ }
192
+
193
+ clearValue(): void {
194
+ const select = document.querySelector('#programmatic-select') as HTMLElement & { value: string }
195
+ if (select) {
196
+ select.value = ''
197
+ }
198
+ }
199
+ }
200
+
201
+ const instance = new ComponentDemoPage()
202
+ instance.render()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@api-client/ui",
3
- "version": "0.5.23",
3
+ "version": "0.5.25",
4
4
  "description": "Internal UI component library for the API Client ecosystem.",
5
5
  "license": "UNLICENSED",
6
6
  "main": "build/src/index.js",
@@ -368,9 +368,10 @@ export default class UiDropdownList extends LitElement {
368
368
  }
369
369
 
370
370
  protected activate(e: Event): void {
371
- if (e.defaultPrevented) {
372
- return
373
- }
371
+ // if (e.defaultPrevented) {
372
+ // We now cancel the event in the menu list
373
+ // return
374
+ // }
374
375
  const path = e.composedPath()
375
376
  let item: HTMLElement | undefined
376
377
  while (!item) {
@@ -1,11 +1,11 @@
1
- import { html, nothing, PropertyValues, TemplateResult } from 'lit'
1
+ import { html, LitElement, nothing, PropertyValues, TemplateResult } from 'lit'
2
2
  import { property, queryAssignedElements, state } from 'lit/decorators.js'
3
3
  import { classMap } from 'lit/directives/class-map.js'
4
4
  import { ifDefined } from 'lit/directives/if-defined.js'
5
5
  import { SupportedAutocapitalize, SupportedAutocomplete, SupportedInputTypes } from '../../types/input.js'
6
6
  import { ARIAAutoComplete, ARIAExpanded, ARIARole } from '../../types/role.js'
7
- import { isDisabled, setDisabled } from '../../lib/disabled.js'
8
7
  import { UiElement } from '../UiElement.js'
8
+ import { isDisabled, setDisabled } from '../../lib/disabled.js'
9
9
  import '../icon-button/ui-icon-button.js'
10
10
  import '../icons/ui-icon.js'
11
11
 
@@ -16,6 +16,7 @@ const floatTypes = ['date', 'color', 'datetime-local', 'file', 'month', 'time',
16
16
  * @slot suffix - A slot in which to render suffixes of the input
17
17
  */
18
18
  export default abstract class Input extends UiElement {
19
+ static override shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }
19
20
  #_userInteracted: boolean
20
21
 
21
22
  // static override shadowRootOptions: ShadowRootInit = {mode: 'open', delegatesFocus: true};
@@ -33,28 +34,20 @@ export default abstract class Input extends UiElement {
33
34
  */
34
35
  @property({ type: String, reflect: true }) accessor type: SupportedInputTypes
35
36
 
36
- /**
37
- * Disables the input.
38
- * @attribute
39
- */
40
37
  get disabled(): boolean {
41
38
  return isDisabled(this)
42
39
  }
43
40
 
41
+ /**
42
+ * When set, the input is a disabled state.
43
+ * @attribute
44
+ */
44
45
  @property({ reflect: true, type: Boolean })
45
46
  set disabled(value: boolean) {
46
47
  const old = isDisabled(this)
47
48
  setDisabled(this, value)
48
49
  this.requestUpdate('disabled', old)
49
50
  this._updateFormValue()
50
- if (value) {
51
- this.dataset.tabindex = this.getAttribute('tabindex') || '0'
52
- this.removeAttribute('tabindex')
53
- } else {
54
- const index = this.dataset.tabindex || '0'
55
- this.setAttribute('tabindex', index)
56
- this.blur()
57
- }
58
51
  }
59
52
 
60
53
  /**
@@ -433,8 +426,6 @@ export default abstract class Input extends UiElement {
433
426
  */
434
427
  #showPassword = false
435
428
 
436
- protected removingTabindex = false
437
-
438
429
  get files(): FileList | null {
439
430
  return this.getNativeValue('files') as FileList | null
440
431
  }
@@ -750,34 +741,14 @@ export default abstract class Input extends UiElement {
750
741
  return
751
742
  }
752
743
  this.focused = true
753
- this.removingTabindex = true
754
- // Note, the input is automatically focused when form is being submitted and
755
- // it won't pass validation. In this case the form will throw an error
756
- // as the input is not focusable. In overall, this still works with forms and validation.
757
- if (this.checkNativeValidity()) {
758
- this.dataset.tabindex = this.getAttribute('tabindex') || '0'
759
- this.removeAttribute('tabindex')
760
- }
761
- input.focus()
762
- this.#_userInteracted = true
763
- setTimeout(() => {
764
- this.removingTabindex = false
765
- }, 1)
766
744
  }
767
745
 
768
746
  protected handleBlur(): void {
769
- if (this.matches(':focus-within') || this.removingTabindex) {
747
+ if (this.matches(':focus-within')) {
770
748
  // Changing focus to another child within the text field, like a button
771
749
  return
772
750
  }
773
751
  this.focused = false
774
- const index = this.dataset.tabindex || '0'
775
- delete this.dataset.tabindex
776
- this.setAttribute('tabindex', index)
777
- }
778
-
779
- private checkNativeValidity(): boolean {
780
- return this.input?.validity.valid ?? true
781
752
  }
782
753
 
783
754
  private checkValidityAndDispatch(): { valid: boolean; canceled: boolean } {
@@ -28,6 +28,8 @@ export interface UiListItemsChange {
28
28
  * The `event.detail` object contains the `item` and `index` properties.
29
29
  * @fires itemschange - Dispatched when the list items change, e.g. when the slot changes.
30
30
  * The `event.detail` object contains the `items` property with the list of items.
31
+ * @fires highlightchange - Dispatched when the highlighted item changes.
32
+ * The `event.detail` object contains the `items` property with the list of items.
31
33
  */
32
34
  export default class UiList extends LitElement {
33
35
  /**
@@ -210,7 +212,7 @@ export default class UiList extends LitElement {
210
212
  }
211
213
  this.removeAttribute('tabindex')
212
214
  item.activate()
213
- item.scrollIntoView({ block: 'end', inline: 'nearest' })
215
+ item.scrollIntoView({ block: 'nearest', inline: 'nearest', behavior: 'smooth' })
214
216
  }
215
217
 
216
218
  handleKeydown(event: KeyboardEvent): void {
@@ -311,15 +313,21 @@ export default class UiList extends LitElement {
311
313
  this.activateFromEvent(event)
312
314
  }
313
315
 
314
- protected highlightItem(item?: UiListItem | null): void {
316
+ highlightItem(item?: UiListItem | null): void {
317
+ if (this.highlightListItem === item) {
318
+ return
319
+ }
315
320
  if (this.highlightListItem) {
316
321
  this.highlightListItem.classList.remove('highlight')
317
322
  }
318
323
  this.highlightListItem = item || null
319
324
  if (this.highlightListItem) {
320
325
  this.highlightListItem.classList.add('highlight')
321
- this.highlightListItem.scrollIntoView({ block: 'end', inline: 'nearest' })
326
+ this.highlightListItem.scrollIntoView({ block: 'nearest', inline: 'nearest', behavior: 'smooth' })
322
327
  }
328
+ this.dispatchEvent(
329
+ new CustomEvent('highlightchange', { bubbles: false, composed: false, detail: { item: this.highlightListItem } })
330
+ )
323
331
  }
324
332
 
325
333
  /**
@@ -345,9 +353,8 @@ export default class UiList extends LitElement {
345
353
  this.manageSelection(item)
346
354
  item.activate()
347
355
  this.activeListItem = item
348
- if (this.notifySelect(item)) {
349
- e.preventDefault()
350
- }
356
+ e.preventDefault()
357
+ this.notifySelect(item)
351
358
  }
352
359
 
353
360
  /**