@vollowx/seele 0.13.7 → 0.13.9

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 (94) hide show
  1. package/README.md +33 -15
  2. package/package.json +2 -2
  3. package/src/all.d.ts +5 -0
  4. package/src/all.js +5 -0
  5. package/src/base/autocomplete.js +13 -13
  6. package/src/base/button.d.ts +4 -2
  7. package/src/base/button.js +15 -11
  8. package/src/base/checkbox.js +3 -8
  9. package/src/base/controllers/popover-controller.js +1 -1
  10. package/src/base/experimental/popup-styles.css.js +2 -0
  11. package/src/base/experimental/popup.d.ts +40 -0
  12. package/src/base/experimental/popup.js +278 -0
  13. package/src/base/mixins/attachable.d.ts +5 -2
  14. package/src/base/mixins/attachable.js +63 -23
  15. package/src/base/mixins/button-toggle-mixin.d.ts +7 -0
  16. package/src/base/mixins/button-toggle-mixin.js +101 -0
  17. package/src/base/mixins/internals-attached.d.ts +4 -0
  18. package/src/base/mixins/internals-attached.js +6 -0
  19. package/src/base/radio.d.ts +3 -0
  20. package/src/base/radio.js +28 -16
  21. package/src/base/tab-panel.d.ts +3 -3
  22. package/src/base/tab-panel.js +9 -11
  23. package/src/base/tab.d.ts +2 -8
  24. package/src/base/tab.js +16 -35
  25. package/src/base/tabs.d.ts +6 -6
  26. package/src/base/tabs.js +101 -99
  27. package/src/base/toggle-button.d.ts +6 -45
  28. package/src/base/toggle-button.js +6 -135
  29. package/src/base/tooltip.d.ts +2 -1
  30. package/src/base/tooltip.js +2 -2
  31. package/src/core/ensure-ready.d.ts +2 -1
  32. package/src/core/ensure-ready.js +12 -7
  33. package/src/m3/button/common-button-toggle.d.ts +4 -10
  34. package/src/m3/button/common-button-toggle.js +6 -40
  35. package/src/m3/button/icon-button-toggle.d.ts +4 -6
  36. package/src/m3/button/icon-button-toggle.js +6 -33
  37. package/src/m3/button/shared-button-styles.css.js +1 -1
  38. package/src/m3/button/shared-button-toggle-styles.css.js +1 -1
  39. package/src/m3/button-group/standard-button-group-styles.css.js +1 -1
  40. package/src/m3/button-group/standard-button-group.d.ts +2 -0
  41. package/src/m3/button-group/standard-button-group.js +44 -38
  42. package/src/m3/checkbox/checkbox-styles.css.js +1 -1
  43. package/src/m3/checkbox/checkbox.d.ts +1 -1
  44. package/src/m3/checkbox/checkbox.js +2 -5
  45. package/src/m3/dialog/dialog-styles.css.js +1 -1
  46. package/src/m3/dialog/dialog.d.ts +3 -1
  47. package/src/m3/dialog/dialog.js +6 -4
  48. package/src/m3/experimental/popup-styles.css.js +2 -0
  49. package/src/m3/experimental/popup.d.ts +9 -0
  50. package/src/m3/experimental/popup.js +11 -0
  51. package/src/m3/fab/fab-styles.css.js +1 -1
  52. package/src/m3/field/field-styles.css.js +1 -1
  53. package/src/m3/field/filled-field-styles.css.js +1 -1
  54. package/src/m3/focus-ring/focus-ring-styles.css.js +1 -1
  55. package/src/m3/focus-ring/focus-ring.d.ts +2 -1
  56. package/src/m3/focus-ring/focus-ring.js +4 -7
  57. package/src/m3/list/list-item-styles.css.js +1 -1
  58. package/src/m3/menu/menu-styles.css.js +1 -1
  59. package/src/m3/nagivation/navigation-rail-item-styles.css.js +2 -0
  60. package/src/m3/nagivation/navigation-rail-item.d.ts +21 -0
  61. package/src/m3/nagivation/navigation-rail-item.js +44 -0
  62. package/src/m3/nagivation/navigation-rail-styles.css.js +2 -0
  63. package/src/m3/nagivation/navigation-rail.d.ts +12 -0
  64. package/src/m3/nagivation/navigation-rail.js +17 -0
  65. package/src/m3/radio/radio-styles.css.js +1 -1
  66. package/src/m3/radio/radio.d.ts +3 -0
  67. package/src/m3/radio/radio.js +12 -4
  68. package/src/m3/ripple/ripple-styles.css.js +1 -1
  69. package/src/m3/ripple/ripple.d.ts +3 -13
  70. package/src/m3/ripple/ripple.js +28 -31
  71. package/src/m3/{system → styles}/defaults.css +1 -1
  72. package/src/m3/styles/motion-expressive.css +15 -0
  73. package/src/m3/styles/motion-standard.css +15 -0
  74. package/src/m3/styles/typography.css +24 -0
  75. package/src/m3/switch/switch-styles.css.js +1 -1
  76. package/src/m3/switch/switch.d.ts +4 -2
  77. package/src/m3/switch/switch.js +14 -12
  78. package/src/m3/tab/secondary-tab-styles.css.js +2 -0
  79. package/src/m3/tab/secondary-tab.d.ts +5 -0
  80. package/src/m3/tab/secondary-tab.js +15 -0
  81. package/src/m3/tab/tab-panel-styles.css.js +1 -1
  82. package/src/m3/tab/tab-styles.css.js +1 -1
  83. package/src/m3/tab/tab.d.ts +3 -0
  84. package/src/m3/tab/tab.js +68 -3
  85. package/src/m3/tab/tabs-styles.css.js +1 -1
  86. package/src/m3/tab/tabs.d.ts +1 -7
  87. package/src/m3/tab/tabs.js +6 -39
  88. package/src/m3/toolbar/toolbar-styles.css.js +1 -1
  89. package/src/win98/button/button-styles.css.js +1 -1
  90. package/src/m3/system/typography.css +0 -34
  91. /package/src/m3/{system → styles}/base.css +0 -0
  92. /package/src/m3/{system → styles}/elevation.css +0 -0
  93. /package/src/m3/{system → styles}/motion.d.ts +0 -0
  94. /package/src/m3/{system → styles}/motion.js +0 -0
@@ -1,18 +1,23 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { property } from 'lit/decorators.js';
3
+ export const autoAttachToParent = Symbol('autoAttachToParent');
4
+ export const handleControlChange = Symbol('handleControlChange');
3
5
  export const Attachable = (superClass) => {
6
+ var _a;
4
7
  class AttachableElement extends superClass {
5
8
  constructor() {
6
9
  super(...arguments);
7
- this.currentControl = null;
8
- }
9
- connectedCallback() {
10
- super.connectedCallback();
11
- this.setCurrentControl(this.$control);
12
- }
13
- disconnectedCallback() {
14
- this.setCurrentControl(null);
15
- super.disconnectedCallback();
10
+ /**
11
+ * The control element currently attached to
12
+ */
13
+ this.#$control = null;
14
+ /**
15
+ * Whether `parentNode` is a candidate of `$control`.
16
+ *
17
+ * When false, only `id` is considered without manually setting `$control`
18
+ * or `attach()`
19
+ */
20
+ this[_a] = true;
16
21
  }
17
22
  /**
18
23
  * If has `for` attribute, use it to find the control element.
@@ -23,9 +28,19 @@ export const Attachable = (superClass) => {
23
28
  if (!this.htmlFor || !this.isConnected) {
24
29
  return null;
25
30
  }
26
- return this.getRootNode().querySelector(`#${this.htmlFor}`);
31
+ const root = this.getRootNode();
32
+ if (!root || !('querySelector' in root)) {
33
+ return null;
34
+ }
35
+ return root.querySelector(`#${CSS.escape(this.htmlFor)}`);
36
+ }
37
+ if (this.#$control) {
38
+ return this.#$control;
39
+ }
40
+ if (!this[autoAttachToParent]) {
41
+ return null;
27
42
  }
28
- return this.currentControl || this.parentNode instanceof ShadowRoot
43
+ return this.parentNode instanceof ShadowRoot
29
44
  ? this.parentNode.host
30
45
  : this.parentElement;
31
46
  }
@@ -37,32 +52,57 @@ export const Attachable = (superClass) => {
37
52
  this.detach();
38
53
  }
39
54
  }
55
+ connectedCallback() {
56
+ super.connectedCallback();
57
+ this.#setControl(this.$control);
58
+ }
59
+ disconnectedCallback() {
60
+ this.#setControl(null);
61
+ super.disconnectedCallback();
62
+ }
63
+ firstUpdated(changed) {
64
+ super.firstUpdated(changed);
65
+ // When the control element is placed after `this` and wasn't parsed yet
66
+ // at `connectedCallback`.
67
+ if (!this.#$control && this.htmlFor) {
68
+ this.#setControl(this.$control);
69
+ }
70
+ }
40
71
  updated(changed) {
41
72
  super.updated(changed);
42
73
  if (changed.has('htmlFor')) {
43
74
  // Will be triggered when first render using `for` attribute, will be
44
- // prevented in setCurrentControl since it's unnecessary.
45
- this.setCurrentControl(this.$control);
75
+ // prevented in #setControl since it's unnecessary.
76
+ this.#setControl(this.$control);
46
77
  }
47
78
  }
48
- setCurrentControl(control, force = false) {
49
- if (control === this.currentControl && !force)
50
- return;
51
- this.handleControlChange(this.currentControl, control);
52
- this.currentControl = control;
53
- }
54
79
  attach(control, force = false) {
55
- this.setCurrentControl(control, force);
80
+ this.#setControl(control, force);
56
81
  this.removeAttribute('for');
57
82
  }
58
83
  detach() {
59
- this.setCurrentControl(null);
60
- this.setAttribute('for', '');
84
+ this.#setControl(null);
85
+ this.removeAttribute('for');
86
+ this[autoAttachToParent] = false;
87
+ // That is to prevent attaching automatically on a `$control` access.
88
+ // (yet, I don't even know who would call `detach()`) :/
89
+ }
90
+ /**
91
+ * The control element currently attached to
92
+ */
93
+ #$control;
94
+ #setControl(control, force = false) {
95
+ if (control === this.#$control && !force)
96
+ return;
97
+ this[handleControlChange](this.#$control, control);
98
+ this.#$control = control;
61
99
  }
62
100
  /**
63
101
  * Handles the first attaching and actual control element changing
64
102
  */
65
- handleControlChange(prev = null, next = null) { }
103
+ [(_a = autoAttachToParent, handleControlChange)](_prev = null, _next = null) {
104
+ console.warn('[seele] You should implement [onControlChange] on any class that mixes Attachable');
105
+ }
66
106
  }
67
107
  __decorate([
68
108
  property({ attribute: 'for', type: String })
@@ -0,0 +1,7 @@
1
+ import { Button } from '../button.js';
2
+ export declare class ToggleableInterface {
3
+ checked: boolean;
4
+ _ignoreClick: boolean;
5
+ _toggle(): void;
6
+ }
7
+ export declare const ButtonToggleMixin: <T extends Constructor<Button>>(superClass: T) => Constructor<ToggleableInterface> & T;
@@ -0,0 +1,101 @@
1
+ import { __decorate } from "tslib";
2
+ import { property } from 'lit/decorators.js';
3
+ import { internals, updateInternals, replaceStates, } from './internals-attached.js';
4
+ const PROPERTY_FROM_ARIA_PRESSED = {
5
+ true: 'checked',
6
+ false: 'unchecked',
7
+ };
8
+ export const ButtonToggleMixin = (superClass) => {
9
+ class ButtonToggle extends superClass {
10
+ constructor(...args) {
11
+ super();
12
+ this.checked = false;
13
+ /**
14
+ * --> Drag-and-drop to the other side
15
+ *
16
+ * `checked` is supposed to be changed once
17
+ *
18
+ * 1. `pointerdown`: _ignoreClick = false
19
+ * 2. `pointermove`: _ignoreClick = true
20
+ * 3. `pointerup`: `checked` changed
21
+ * 4. `click`: ignored, _ignoreClick = false
22
+ *
23
+ * --> Drag-and-drop to the other side, then click
24
+ *
25
+ * `checked` is supposed to be changed twice
26
+ *
27
+ * 1. `pointerdown`: _ignoreClick = false
28
+ * 2. `pointermove`: _ignoreClick = true
29
+ * 3. `pointerup`: `checked` changed(1)
30
+ * 4. `click`: ignored, _ignoreClick = false
31
+ * 5. `click`: `checked` changed(2)
32
+ *
33
+ * --> Drag-and-drop to the other side, then click the label
34
+ *
35
+ * `checked` is supposed to be changed twice
36
+ *
37
+ * 1. `pointerdown`: _ignoreClick = false
38
+ * 2. `pointermove`: _ignoreClick = true
39
+ * 3. `pointerup`: `checked` changed(1)
40
+ * 4. `click` on label: _ignoreClick = false
41
+ * 5. `click` on switch: `checked` changed(2)
42
+ */
43
+ this._ignoreClick = false;
44
+ this.checked = this.hasAttribute('checked');
45
+ }
46
+ connectedCallback() {
47
+ super.connectedCallback();
48
+ this.labels.forEach((label) => {
49
+ label.addEventListener('click', this.#handleLabelClick);
50
+ });
51
+ }
52
+ disconnectedCallback() {
53
+ this.labels.forEach((label) => {
54
+ label.removeEventListener('click', this.#handleLabelClick);
55
+ });
56
+ super.disconnectedCallback();
57
+ }
58
+ updated(changed) {
59
+ if (changed.has('checked'))
60
+ this[updateInternals]();
61
+ }
62
+ [updateInternals]() {
63
+ super[updateInternals]();
64
+ this[internals].ariaPressed = this.checked ? 'true' : 'false';
65
+ this[replaceStates](['unchecked', 'checked'], [PROPERTY_FROM_ARIA_PRESSED[this[internals].ariaPressed]]);
66
+ this[internals].setFormValue(this.checked ? 'on' : null);
67
+ }
68
+ #handleLabelClick() {
69
+ this._ignoreClick = false;
70
+ }
71
+ _handleClick(e) {
72
+ e.stopPropagation();
73
+ e.preventDefault();
74
+ if (this._ignoreClick) {
75
+ this._ignoreClick = false;
76
+ return;
77
+ }
78
+ this._toggle();
79
+ }
80
+ _toggle() {
81
+ if (this.disabled)
82
+ return;
83
+ this.checked = !this.checked;
84
+ this.dispatchEvent(new CustomEvent('change', {
85
+ bubbles: true,
86
+ composed: true,
87
+ detail: this.checked,
88
+ }));
89
+ }
90
+ formResetCallback() {
91
+ this.checked = this.hasAttribute('checked');
92
+ }
93
+ formStateRestoreCallback(state, _reason) {
94
+ this.checked = state === 'on';
95
+ }
96
+ }
97
+ __decorate([
98
+ property({ type: Boolean })
99
+ ], ButtonToggle.prototype, "checked", void 0);
100
+ return ButtonToggle;
101
+ };
@@ -1,6 +1,10 @@
1
1
  import { LitElement } from 'lit';
2
2
  export declare const internals: unique symbol;
3
+ export declare const updateInternals: unique symbol;
4
+ export declare const replaceStates: unique symbol;
3
5
  export declare class InternalsAttachedInterface {
4
6
  [internals]: ElementInternals;
7
+ [updateInternals]?(): void;
8
+ [replaceStates](del: Array<string>, add: Array<string>): void;
5
9
  }
6
10
  export declare const InternalsAttached: <T extends Constructor<LitElement>>(superClass: T) => Constructor<InternalsAttachedInterface> & T;
@@ -1,5 +1,7 @@
1
1
  export const internals = Symbol('internals');
2
2
  const privateInternals = Symbol('privateInternals');
3
+ export const updateInternals = Symbol('updateInternals');
4
+ export const replaceStates = Symbol('replaceStates');
3
5
  export const InternalsAttached = (superClass) => {
4
6
  class InternalsAttachedElement extends superClass {
5
7
  get [internals]() {
@@ -8,6 +10,10 @@ export const InternalsAttached = (superClass) => {
8
10
  }
9
11
  return this[privateInternals];
10
12
  }
13
+ [replaceStates](del, add) {
14
+ del.forEach((state) => this[internals].states.delete(state));
15
+ add.forEach((state) => this[internals].states.add(state));
16
+ }
11
17
  }
12
18
  return InternalsAttachedElement;
13
19
  };
@@ -1,4 +1,5 @@
1
1
  import { LitElement, PropertyValues } from 'lit';
2
+ import { updateInternals } from './mixins/internals-attached.js';
2
3
  declare const Radio_base: Constructor<import("./mixins/form-associated.js").FormAssociatedInterface> & Constructor<import("./mixins/internals-attached.js").InternalsAttachedInterface> & typeof LitElement;
3
4
  export declare class Radio extends Radio_base {
4
5
  #private;
@@ -8,6 +9,8 @@ export declare class Radio extends Radio_base {
8
9
  connectedCallback(): void;
9
10
  disconnectedCallback(): void;
10
11
  protected updated(changedProperties: PropertyValues<this>): void;
12
+ [updateInternals](): void;
11
13
  formResetCallback(): void;
14
+ formStateRestoreCallback(state: string | null): void;
12
15
  }
13
16
  export {};
package/src/base/radio.js CHANGED
@@ -3,7 +3,7 @@ import { __decorate } from "tslib";
3
3
  import { LitElement } from 'lit';
4
4
  import { property } from 'lit/decorators.js';
5
5
  import { FormAssociated } from './mixins/form-associated.js';
6
- import { InternalsAttached, internals } from './mixins/internals-attached.js';
6
+ import { InternalsAttached, internals, replaceStates, updateInternals, } from './mixins/internals-attached.js';
7
7
  export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
8
8
  // Static hidden registry: Scope (Form or RootNode) -> Name -> Set<Radio>
9
9
  static #registry = new Map();
@@ -19,7 +19,7 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
19
19
  connectedCallback() {
20
20
  super.connectedCallback();
21
21
  this.#registerToGroup();
22
- this.#updateAriaState();
22
+ this[updateInternals]();
23
23
  this.addEventListener('click', this.#handleClick);
24
24
  this.addEventListener('keydown', this.#handleKeyDown);
25
25
  }
@@ -41,16 +41,16 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
41
41
  }
42
42
  this[internals].setFormValue(this.checked ? this.value : null);
43
43
  this.#updateGroupTabIndices();
44
- this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
45
44
  }
46
45
  if (changedProperties.has('disabled') || changedProperties.has('checked'))
47
- this.#updateAriaState();
46
+ this[updateInternals]();
48
47
  }
49
48
  #handleClick() {
50
49
  if (this.disabled || this.checked)
51
50
  return;
52
51
  this.checked = true;
53
52
  this.focus();
53
+ this.#dispatchEvents();
54
54
  }
55
55
  #handleKeyDown(event) {
56
56
  if (this.disabled)
@@ -58,8 +58,10 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
58
58
  switch (event.key) {
59
59
  case ' ':
60
60
  event.preventDefault();
61
- if (!this.checked)
61
+ if (!this.checked) {
62
62
  this.checked = true;
63
+ this.#dispatchEvents();
64
+ }
63
65
  break;
64
66
  case 'ArrowDown':
65
67
  case 'ArrowRight':
@@ -117,11 +119,9 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
117
119
  this.#currentName = '';
118
120
  }
119
121
  #getGroupRadios() {
120
- if (!this.name)
122
+ if (!this.#currentName || !this.#currentScope)
121
123
  return [this];
122
- const scope = this.#getScope();
123
- const group = _a.#registry.get(scope)?.get(this.name);
124
- return group ? Array.from(group) : [this];
124
+ return (_a.#registry.get(this.#currentScope)?.get(this.#currentName) ?? [this]);
125
125
  }
126
126
  #uncheckSiblings() {
127
127
  const radios = this.#getGroupRadios();
@@ -130,10 +130,14 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
130
130
  radio.checked = false;
131
131
  }
132
132
  #updateGroupTabIndices(groupSet) {
133
- const radios = groupSet ? Array.from(groupSet) : this.#getGroupRadios();
134
- if (radios.length === 0)
135
- return;
136
- const hasChecked = radios.some((r) => r.checked && !r.disabled);
133
+ const radios = groupSet ?? this.#getGroupRadios();
134
+ let hasChecked = false;
135
+ for (const r of radios) {
136
+ if (r.checked && !r.disabled) {
137
+ hasChecked = true;
138
+ break;
139
+ }
140
+ }
137
141
  let enabledFound = false;
138
142
  for (const radio of radios) {
139
143
  const active = !radio.disabled && (hasChecked ? radio.checked : !enabledFound);
@@ -143,7 +147,7 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
143
147
  }
144
148
  }
145
149
  #navigateGroup(direction) {
146
- const radios = this.#getGroupRadios().filter((r) => !r.disabled);
150
+ const radios = Array.from(this.#getGroupRadios()).filter((r) => !r.disabled);
147
151
  if (radios.length <= 1)
148
152
  return;
149
153
  const currentIndex = radios.indexOf(this);
@@ -152,18 +156,26 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
152
156
  targetRadio.checked = true;
153
157
  targetRadio.focus();
154
158
  }
155
- #updateAriaState() {
159
+ [updateInternals]() {
156
160
  this[internals].ariaChecked = String(this.checked);
157
161
  this[internals].ariaDisabled = String(this.disabled);
162
+ this[replaceStates](['checked'], [this.checked ? 'checked' : null]);
163
+ }
164
+ #dispatchEvents() {
165
+ this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
166
+ this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
158
167
  }
159
168
  formResetCallback() {
160
169
  this.checked = this.hasAttribute('checked');
161
170
  }
171
+ formStateRestoreCallback(state) {
172
+ this.checked = state === this.value;
173
+ }
162
174
  }
163
175
  _a = Radio;
164
176
  __decorate([
165
177
  property({ type: String })
166
178
  ], Radio.prototype, "value", void 0);
167
179
  __decorate([
168
- property({ type: Boolean, reflect: true })
180
+ property({ type: Boolean })
169
181
  ], Radio.prototype, "checked", void 0);
@@ -1,9 +1,9 @@
1
1
  import { LitElement } from 'lit';
2
2
  declare const TabPanel_base: Constructor<import("./mixins/internals-attached.js").InternalsAttachedInterface> & typeof LitElement;
3
3
  export declare class TabPanel extends TabPanel_base {
4
- protected _role: string;
5
- render(): import("lit-html").TemplateResult<1>;
6
4
  value: string;
7
- connectedCallback(): void;
5
+ selected: boolean;
6
+ render(): import("lit-html").TemplateResult<1>;
7
+ constructor();
8
8
  }
9
9
  export {};
@@ -2,24 +2,22 @@ import { __decorate } from "tslib";
2
2
  import { LitElement, html } from 'lit';
3
3
  import { property } from 'lit/decorators.js';
4
4
  import { InternalsAttached, internals } from './mixins/internals-attached.js';
5
- import { genUniqueId } from '../core/unique-id.js';
6
5
  export class TabPanel extends InternalsAttached(LitElement) {
7
- constructor() {
8
- super(...arguments);
9
- this._role = 'tabpanel';
10
- this.value = '';
11
- }
12
6
  render() {
13
7
  return html `<slot></slot>`;
14
8
  }
15
- connectedCallback() {
16
- super.connectedCallback();
9
+ constructor() {
10
+ super();
11
+ this.value = '';
12
+ this.selected = false;
13
+ this[internals].role = 'tabpanel';
17
14
  this.setAttribute('seele-base', 'tabpanel');
18
- this[internals].role = this._role;
19
- if (!this.id)
20
- this.id = genUniqueId('tabpanel');
15
+ this.setAttribute('slot', 'panels');
21
16
  }
22
17
  }
23
18
  __decorate([
24
19
  property({ type: String, reflect: true })
25
20
  ], TabPanel.prototype, "value", void 0);
21
+ __decorate([
22
+ property({ type: Boolean, reflect: true })
23
+ ], TabPanel.prototype, "selected", void 0);
package/src/base/tab.d.ts CHANGED
@@ -1,18 +1,12 @@
1
1
  import { LitElement } from 'lit';
2
2
  declare const Tab_base: Constructor<import("./mixins/internals-attached.js").InternalsAttachedInterface> & typeof LitElement;
3
- /**
4
- * TODO: disabled
5
- */
6
3
  export declare class Tab extends Tab_base {
7
4
  #private;
8
- protected _role: string;
5
+ disabled: boolean;
9
6
  selected: boolean;
10
- focused: boolean;
11
7
  value: string;
12
8
  render(): import("lit-html").TemplateResult<1>;
13
- connectedCallback(): void;
9
+ constructor();
14
10
  protected updated(changed: Map<string, any>): void;
15
- focus(): void;
16
- blur(): void;
17
11
  }
18
12
  export {};
package/src/base/tab.js CHANGED
@@ -1,60 +1,41 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { LitElement, html } from 'lit';
3
3
  import { property } from 'lit/decorators.js';
4
- import { InternalsAttached, internals } from './mixins/internals-attached.js';
5
- import { genUniqueId } from '../core/unique-id.js';
6
- /**
7
- * TODO: disabled
8
- */
4
+ import { InternalsAttached, internals, replaceStates, } from './mixins/internals-attached.js';
9
5
  export class Tab extends InternalsAttached(LitElement) {
10
- constructor() {
11
- super(...arguments);
12
- this._role = 'tab';
13
- this.selected = false;
14
- this.focused = false;
15
- this.value = '';
16
- }
17
6
  render() {
18
7
  return html `<slot></slot>`;
19
8
  }
20
- connectedCallback() {
21
- super.connectedCallback();
9
+ constructor() {
10
+ super();
11
+ this.disabled = false;
12
+ this.selected = false;
13
+ this.value = '';
22
14
  this.setAttribute('seele-base', 'tab');
23
- this[internals].role = this._role;
24
- if (!this.id)
25
- this.id = genUniqueId('tab');
15
+ this[internals].role = 'tab';
26
16
  this.#updateInternals();
27
17
  }
28
18
  updated(changed) {
29
19
  super.updated(changed);
30
- if (changed.has('selected') || changed.has('focused')) {
20
+ if (changed.has('selected') ||
21
+ changed.has('focused') ||
22
+ changed.has('disabled')) {
31
23
  this.#updateInternals();
32
24
  }
33
25
  }
34
26
  #updateInternals() {
35
- this[internals].ariaSelected = this.selected ? 'true' : 'false';
36
- this.focused
37
- ? this[internals].states.add('focused')
38
- : this[internals].states.delete('focused');
39
- this.selected
40
- ? this[internals].states.add('selected')
41
- : this[internals].states.delete('selected');
42
- }
43
- focus() {
44
- this.focused = true;
45
- super.focus();
46
- }
47
- blur() {
48
- this.focused = false;
49
- super.blur();
27
+ this.tabIndex = this.disabled ? -1 : this.selected ? 0 : -1;
28
+ this[internals].ariaSelected = String(this.selected);
29
+ this[internals].ariaDisabled = String(this.disabled);
30
+ this[replaceStates](['selected', 'disabled'], [this.selected ? 'selected' : null, this.disabled ? 'disabled' : null]);
50
31
  }
51
32
  }
52
33
  __decorate([
53
34
  property({ type: Boolean, reflect: true })
54
- ], Tab.prototype, "selected", void 0);
35
+ ], Tab.prototype, "disabled", void 0);
55
36
  __decorate([
56
37
  property({ type: Boolean, reflect: true })
57
- ], Tab.prototype, "focused", void 0);
38
+ ], Tab.prototype, "selected", void 0);
58
39
  __decorate([
59
40
  property({ type: String, reflect: true })
60
41
  ], Tab.prototype, "value", void 0);
@@ -1,19 +1,19 @@
1
1
  import { LitElement } from 'lit';
2
2
  import type { Tab } from './tab.js';
3
+ import type { TabPanel } from './tab-panel.js';
3
4
  /**
4
- * @fires {CustomEvent} tab-select
5
+ * @fires {CustomEvent} select
5
6
  */
6
7
  export declare class Tabs extends LitElement {
7
8
  #private;
8
- protected _role: string;
9
9
  switch: 'auto' | 'manual';
10
10
  selected: string;
11
- $slotItems: Array<HTMLElement>;
12
- get $tabs(): Tab[];
13
- get $parent(): HTMLElement;
11
+ get $tabs(): Array<Tab>;
12
+ get $panels(): Array<TabPanel>;
14
13
  render(): import("lit-html").TemplateResult<1>;
14
+ constructor();
15
15
  connectedCallback(): void;
16
16
  protected updated(changed: Map<string, any>): void;
17
17
  focusTab(tab: Tab): void;
18
- selectTab(selectedTab: Tab): void;
18
+ protected _selectTab(selectedTab: Tab, dispatchEvent?: boolean): void;
19
19
  }