@haiyue/ui 0.1.1 → 0.2.1

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 (99) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +504 -1
  3. package/dist/adapters/web/controls.d.ts +19 -0
  4. package/dist/adapters/web/controls.js +284 -0
  5. package/dist/adapters/web/dom.d.ts +10 -0
  6. package/dist/adapters/web/dom.js +98 -0
  7. package/dist/adapters/web/index.d.ts +3 -0
  8. package/dist/adapters/web/index.js +3 -0
  9. package/dist/adapters/web/renderer.d.ts +18 -0
  10. package/dist/adapters/web/renderer.js +545 -0
  11. package/dist/adapters/web/styles.d.ts +3 -0
  12. package/dist/adapters/web/styles.js +62 -0
  13. package/dist/adapters/web/types.d.ts +46 -0
  14. package/dist/adapters/web/types.js +2 -0
  15. package/dist/affix.d.ts +35 -0
  16. package/dist/affix.js +137 -0
  17. package/dist/badge.d.ts +45 -0
  18. package/dist/badge.js +168 -0
  19. package/dist/border-beam.js +3 -1
  20. package/dist/breadcrumb.d.ts +37 -0
  21. package/dist/breadcrumb.js +210 -0
  22. package/dist/button-group.d.ts +12 -0
  23. package/dist/button-group.js +72 -0
  24. package/dist/button.d.ts +15 -1
  25. package/dist/button.js +101 -12
  26. package/dist/cascader.d.ts +65 -0
  27. package/dist/cascader.js +479 -0
  28. package/dist/collapse.d.ts +55 -0
  29. package/dist/collapse.js +261 -0
  30. package/dist/core/actions.d.ts +32 -0
  31. package/dist/core/actions.js +145 -0
  32. package/dist/core/data.d.ts +4 -0
  33. package/dist/core/data.js +27 -0
  34. package/dist/core/index.d.ts +7 -0
  35. package/dist/core/index.js +6 -0
  36. package/dist/core/platform-view.d.ts +17 -0
  37. package/dist/core/platform-view.js +84 -0
  38. package/dist/core/selection.d.ts +14 -0
  39. package/dist/core/selection.js +93 -0
  40. package/dist/core/text.d.ts +31 -0
  41. package/dist/core/text.js +154 -0
  42. package/dist/core/types.d.ts +250 -0
  43. package/dist/core/types.js +2 -0
  44. package/dist/core/validation.d.ts +24 -0
  45. package/dist/core/validation.js +238 -0
  46. package/dist/date-picker.d.ts +60 -0
  47. package/dist/date-picker.js +355 -0
  48. package/dist/dialog.d.ts +4 -0
  49. package/dist/dialog.js +23 -5
  50. package/dist/divider.d.ts +33 -0
  51. package/dist/divider.js +113 -0
  52. package/dist/draggable.d.ts +78 -0
  53. package/dist/draggable.js +255 -0
  54. package/dist/expandable.d.ts +32 -0
  55. package/dist/expandable.js +136 -0
  56. package/dist/index.d.ts +47 -1
  57. package/dist/index.js +69 -0
  58. package/dist/input.d.ts +30 -1
  59. package/dist/input.js +166 -54
  60. package/dist/portable/index.d.ts +4 -0
  61. package/dist/portable/index.js +3 -0
  62. package/dist/portable/page.d.ts +38 -0
  63. package/dist/portable/page.js +361 -0
  64. package/dist/portable/theme.d.ts +19 -0
  65. package/dist/portable/theme.js +40 -0
  66. package/dist/portable/tree.d.ts +10 -0
  67. package/dist/portable/tree.js +96 -0
  68. package/dist/range.d.ts +3 -0
  69. package/dist/range.js +16 -5
  70. package/dist/rate.d.ts +46 -0
  71. package/dist/rate.js +193 -0
  72. package/dist/resizable.d.ts +97 -0
  73. package/dist/resizable.js +426 -0
  74. package/dist/skeleton.d.ts +41 -0
  75. package/dist/skeleton.js +141 -0
  76. package/dist/steps.d.ts +45 -0
  77. package/dist/steps.js +203 -0
  78. package/dist/table.d.ts +106 -0
  79. package/dist/table.js +689 -0
  80. package/dist/tabs.d.ts +7 -0
  81. package/dist/tabs.js +90 -16
  82. package/dist/tag.d.ts +55 -0
  83. package/dist/tag.js +225 -0
  84. package/dist/time-picker.d.ts +62 -0
  85. package/dist/time-picker.js +298 -0
  86. package/dist/timeline.d.ts +48 -0
  87. package/dist/timeline.js +201 -0
  88. package/dist/toast.d.ts +55 -0
  89. package/dist/toast.js +224 -0
  90. package/dist/tour.d.ts +89 -0
  91. package/dist/tour.js +306 -0
  92. package/dist/virtual-keyboard.d.ts +95 -0
  93. package/dist/virtual-keyboard.js +432 -0
  94. package/dist/virtual-list.js +12 -10
  95. package/dist/virtual-mouse.d.ts +82 -0
  96. package/dist/virtual-mouse.js +358 -0
  97. package/dist/watermark.d.ts +44 -0
  98. package/dist/watermark.js +148 -0
  99. package/package.json +135 -7
package/dist/tabs.d.ts CHANGED
@@ -11,7 +11,9 @@ export declare class HYTabs extends HTMLElement {
11
11
  private readonly _style;
12
12
  private readonly _tabs;
13
13
  private readonly _panels;
14
+ private readonly _instanceId;
14
15
  private _options;
16
+ private _pendingFocusValue;
15
17
  static get observedAttributes(): string[];
16
18
  constructor();
17
19
  connectedCallback(): void;
@@ -20,9 +22,14 @@ export declare class HYTabs extends HTMLElement {
20
22
  set options(value: HYTabOption[]);
21
23
  get value(): string;
22
24
  set value(value: string);
25
+ /** Opt-in application ownership, including a disabled authoritative selection. */
26
+ get controlled(): boolean;
27
+ set controlled(value: boolean);
23
28
  private _syncFromAttributes;
24
29
  private _readOptionsAttribute;
25
30
  private _render;
31
+ private _focusTab;
32
+ private _resolveValue;
26
33
  private _select;
27
34
  }
28
35
  export declare function defineTabsComponents(): void;
package/dist/tabs.js CHANGED
@@ -2,9 +2,11 @@ export class HYTabs extends HTMLElement {
2
2
  _style = document.createElement('style');
3
3
  _tabs = document.createElement('div');
4
4
  _panels = document.createElement('div');
5
+ _instanceId = `hy-tabs-${globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2)}`;
5
6
  _options = [];
7
+ _pendingFocusValue = null;
6
8
  static get observedAttributes() {
7
- return ['options', 'value'];
9
+ return ['options', 'value', 'aria-label', 'controlled'];
8
10
  }
9
11
  constructor() {
10
12
  super();
@@ -27,6 +29,9 @@ export class HYTabs extends HTMLElement {
27
29
  align-items: end;
28
30
  gap: 2px;
29
31
  min-width: 0;
32
+ overflow-x: auto;
33
+ overflow-y: hidden;
34
+ scrollbar-width: none;
30
35
  padding: 4px 6px 0;
31
36
  border-bottom: 1px solid var(--hy-border-color, #303746);
32
37
  background: var(--hy-tabs-bar-bg-color, var(--hy-menu-bg-color, var(--hy-surface-elevated-color, #1b2230)));
@@ -34,6 +39,8 @@ export class HYTabs extends HTMLElement {
34
39
  button {
35
40
  height: 28px;
36
41
  min-width: 0;
42
+ flex-shrink: 0;
43
+ white-space: nowrap;
37
44
  padding: 0 10px;
38
45
  border: 1px solid transparent;
39
46
  border-bottom: 0;
@@ -61,11 +68,17 @@ export class HYTabs extends HTMLElement {
61
68
  min-height: 0;
62
69
  overflow: auto;
63
70
  }
71
+ .panels > [role="tabpanel"] {
72
+ height: 100%;
73
+ min-width: 0;
74
+ min-height: 0;
75
+ }
64
76
  ::slotted(*) {
65
77
  box-sizing: border-box;
66
78
  }
67
79
  `;
68
80
  this._tabs.className = 'tabs';
81
+ this._tabs.setAttribute('role', 'tablist');
69
82
  this._panels.className = 'panels';
70
83
  root.append(this._style, this._tabs, this._panels);
71
84
  }
@@ -74,11 +87,16 @@ export class HYTabs extends HTMLElement {
74
87
  this._render();
75
88
  }
76
89
  attributeChangedCallback(name, _oldValue, newValue) {
90
+ if (_oldValue === newValue)
91
+ return;
77
92
  if (name === 'options')
78
93
  this._readOptionsAttribute();
79
- if (name === 'value' && newValue === null && this._options[0]) {
80
- this.setAttribute('value', this._options[0].value);
81
- return;
94
+ if (name === 'value' && newValue === null) {
95
+ const value = this._resolveValue();
96
+ if (value) {
97
+ this.setAttribute('value', value);
98
+ return;
99
+ }
82
100
  }
83
101
  this._render();
84
102
  }
@@ -87,9 +105,9 @@ export class HYTabs extends HTMLElement {
87
105
  }
88
106
  set options(value) {
89
107
  this._options = Array.isArray(value) ? value : [];
90
- if (!this._options.some(item => item.value === this.value)) {
91
- this.value = this._options[0]?.value ?? '';
92
- }
108
+ const resolved = this._resolveValue();
109
+ if (resolved !== this.value)
110
+ this.value = resolved;
93
111
  this._render();
94
112
  }
95
113
  get value() {
@@ -97,12 +115,16 @@ export class HYTabs extends HTMLElement {
97
115
  }
98
116
  set value(value) {
99
117
  this.setAttribute('value', value);
100
- this._render();
101
118
  }
119
+ /** Opt-in application ownership, including a disabled authoritative selection. */
120
+ get controlled() { return this.hasAttribute('controlled'); }
121
+ set controlled(value) { this.toggleAttribute('controlled', value); }
102
122
  _syncFromAttributes() {
103
- this._readOptionsAttribute();
104
- if (!this.value && this._options[0])
105
- this.setAttribute('value', this._options[0].value);
123
+ if (this.hasAttribute('options'))
124
+ this._readOptionsAttribute();
125
+ const value = this._resolveValue();
126
+ if (value !== this.value)
127
+ this.setAttribute('value', value);
106
128
  }
107
129
  _readOptionsAttribute() {
108
130
  const raw = this.getAttribute('options');
@@ -125,25 +147,77 @@ export class HYTabs extends HTMLElement {
125
147
  }
126
148
  }
127
149
  _render() {
150
+ const focusedValue = this._pendingFocusValue
151
+ ?? [...this._tabs.querySelectorAll('button')].find(button => button === this.shadowRoot?.activeElement)?.dataset.value
152
+ ?? null;
153
+ this._pendingFocusValue = null;
128
154
  this._tabs.replaceChildren();
129
155
  this._panels.replaceChildren();
130
- const value = this.value || this._options[0]?.value || '';
131
- for (const option of this._options) {
156
+ this._tabs.setAttribute('aria-label', this.getAttribute('aria-label') ?? 'Tabs');
157
+ const enabled = this._options.filter(option => !option.disabled);
158
+ const value = this._resolveValue(enabled);
159
+ if (value !== this.value) {
160
+ this.setAttribute('value', value);
161
+ return;
162
+ }
163
+ const focusValue = enabled.some(option => option.value === value) ? value : enabled[0]?.value;
164
+ this._options.forEach((option, index) => {
132
165
  const button = document.createElement('button');
166
+ const panel = document.createElement('div');
133
167
  button.type = 'button';
168
+ button.id = `${this._instanceId}-tab-${index}`;
169
+ button.dataset.value = option.value;
170
+ button.setAttribute('role', 'tab');
171
+ button.setAttribute('aria-selected', String(option.value === value));
172
+ panel.id = `${this._instanceId}-panel-${index}`;
173
+ panel.hidden = option.value !== value;
174
+ panel.setAttribute('role', 'tabpanel');
175
+ panel.setAttribute('aria-labelledby', button.id);
176
+ button.setAttribute('aria-controls', panel.id);
177
+ button.tabIndex = option.value === focusValue && !option.disabled ? 0 : -1;
134
178
  button.textContent = option.label;
135
179
  button.disabled = Boolean(option.disabled);
136
180
  button.classList.toggle('active', option.value === value);
137
181
  button.addEventListener('click', () => this._select(option.value));
182
+ button.addEventListener('keydown', event => {
183
+ if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key) || !enabled.length)
184
+ return;
185
+ event.preventDefault();
186
+ const position = enabled.findIndex(item => item.value === option.value);
187
+ const next = event.key === 'Home' ? 0 : event.key === 'End' ? enabled.length - 1
188
+ : (position + (event.key === 'ArrowLeft' ? -1 : 1) + enabled.length) % enabled.length;
189
+ this._pendingFocusValue = enabled[next].value;
190
+ this._select(enabled[next].value);
191
+ });
192
+ const slot = document.createElement('slot');
193
+ slot.name = option.value;
194
+ panel.append(slot);
138
195
  this._tabs.append(button);
196
+ this._panels.append(panel);
197
+ });
198
+ if (focusedValue) {
199
+ const restoreValue = enabled.some(option => option.value === focusedValue) ? focusedValue : focusValue;
200
+ if (restoreValue)
201
+ this._focusTab(restoreValue);
139
202
  }
140
- const slot = document.createElement('slot');
141
- slot.name = value;
142
- this._panels.append(slot);
203
+ }
204
+ _focusTab(value) {
205
+ [...this._tabs.querySelectorAll('button')].find(button => button.dataset.value === value)?.focus();
206
+ }
207
+ _resolveValue(enabled = this._options.filter(option => !option.disabled)) {
208
+ if (this.controlled && this._options.some(option => option.value === this.value))
209
+ return this.value;
210
+ if (enabled.some(option => option.value === this.value))
211
+ return this.value;
212
+ if (enabled[0])
213
+ return enabled[0].value;
214
+ return '';
143
215
  }
144
216
  _select(value) {
145
217
  if (value === this.value)
146
218
  return;
219
+ if (!this._options.some(option => option.value === value && !option.disabled))
220
+ return;
147
221
  this.setAttribute('value', value);
148
222
  const option = this._options.find(item => item.value === value) ?? null;
149
223
  this.dispatchEvent(new CustomEvent('tab-change', {
package/dist/tag.d.ts ADDED
@@ -0,0 +1,55 @@
1
+ export type HYTagVariant = 'default' | 'primary' | 'success' | 'warning' | 'error';
2
+ export type HYTagSize = 'small' | 'medium' | 'large';
3
+ export interface HYTagCloseDetail {
4
+ readonly value: string;
5
+ }
6
+ export interface HYTagCheckedChangeDetail {
7
+ readonly checked: boolean;
8
+ readonly value: string;
9
+ }
10
+ /** Compact semantic label with optional close and checked interactions. */
11
+ export declare class HYTag extends HTMLElement {
12
+ private readonly _tag;
13
+ private readonly _icon;
14
+ private readonly _iconSlot;
15
+ private readonly _iconText;
16
+ private readonly _labelSlot;
17
+ private readonly _labelText;
18
+ private readonly _label;
19
+ private readonly _close;
20
+ static get observedAttributes(): string[];
21
+ constructor();
22
+ connectedCallback(): void;
23
+ disconnectedCallback(): void;
24
+ attributeChangedCallback(): void;
25
+ get variant(): HYTagVariant;
26
+ set variant(value: HYTagVariant);
27
+ get color(): string;
28
+ set color(value: string);
29
+ get size(): HYTagSize;
30
+ set size(value: HYTagSize);
31
+ get label(): string;
32
+ set label(value: string);
33
+ get icon(): string;
34
+ set icon(value: string);
35
+ get value(): string;
36
+ set value(value: string);
37
+ get closable(): boolean;
38
+ set closable(value: boolean);
39
+ get checkable(): boolean;
40
+ set checkable(value: boolean);
41
+ get checked(): boolean;
42
+ set checked(value: boolean);
43
+ get disabled(): boolean;
44
+ set disabled(value: boolean);
45
+ close(): boolean;
46
+ private _toggleChecked;
47
+ private _sync;
48
+ private _syncIcon;
49
+ private _syncLabel;
50
+ private _setOptionalAttribute;
51
+ private _onTagClick;
52
+ private _onCloseClick;
53
+ private _onKeydown;
54
+ }
55
+ export declare function defineTagComponents(): void;
package/dist/tag.js ADDED
@@ -0,0 +1,225 @@
1
+ const VARIANTS = ['default', 'primary', 'success', 'warning', 'error'];
2
+ const SIZES = ['small', 'medium', 'large'];
3
+ function isVariant(value) {
4
+ return typeof value === 'string' && VARIANTS.includes(value);
5
+ }
6
+ function isSize(value) {
7
+ return typeof value === 'string' && SIZES.includes(value);
8
+ }
9
+ /** Compact semantic label with optional close and checked interactions. */
10
+ export class HYTag extends HTMLElement {
11
+ _tag = document.createElement('span');
12
+ _icon = document.createElement('span');
13
+ _iconSlot = document.createElement('slot');
14
+ _iconText = document.createElement('span');
15
+ _labelSlot = document.createElement('slot');
16
+ _labelText = document.createElement('span');
17
+ _label = document.createElement('span');
18
+ _close = document.createElement('button');
19
+ static get observedAttributes() {
20
+ return ['variant', 'color', 'size', 'label', 'icon', 'closable', 'checkable', 'checked', 'disabled', 'value'];
21
+ }
22
+ constructor() {
23
+ super();
24
+ const root = this.attachShadow({ mode: 'open' });
25
+ const style = document.createElement('style');
26
+ style.textContent = `
27
+ :host { display: inline-flex; max-width: 100%; vertical-align: middle; }
28
+ :host([hidden]) { display: none !important; }
29
+ .tag {
30
+ --_tone: var(--hy-secondary-text-color, #9aa8ba);
31
+ --_surface: color-mix(in srgb, var(--_tone) 12%, var(--hy-surface-color, #121822));
32
+ display: inline-flex;
33
+ max-width: 100%;
34
+ min-height: var(--hy-tag-height, 24px);
35
+ box-sizing: border-box;
36
+ align-items: center;
37
+ gap: var(--hy-tag-gap, 5px);
38
+ padding: 2px var(--hy-tag-padding-inline, 8px);
39
+ border: 1px solid color-mix(in srgb, var(--_tone) 42%, var(--hy-border-color, #303746));
40
+ border-radius: var(--hy-tag-radius, 5px);
41
+ color: var(--_tone);
42
+ background: var(--_surface);
43
+ font: 600 var(--hy-tag-font-size, 11px)/1.35 system-ui, sans-serif;
44
+ transition: border-color 120ms ease, box-shadow 120ms ease, color 120ms ease, background 120ms ease;
45
+ }
46
+ .tag[data-variant="primary"] { --_tone: var(--hy-accent-color, #79a8ff); }
47
+ .tag[data-variant="success"] { --_tone: var(--hy-success-color, #55c98a); }
48
+ .tag[data-variant="warning"] { --_tone: var(--hy-warning-color, #e7b75a); }
49
+ .tag[data-variant="error"] { --_tone: var(--hy-error-color, #ef6b78); }
50
+ :host([checkable]) .tag { cursor: pointer; user-select: none; }
51
+ :host([checkable][checked]) .tag {
52
+ color: var(--hy-selected-text-color, #fff);
53
+ background: var(--_tone);
54
+ border-color: var(--_tone);
55
+ }
56
+ :host(:focus-visible) { outline: none; }
57
+ :host(:focus-visible) .tag { box-shadow: 0 0 0 2px var(--hy-focus-ring-color, rgba(61, 111, 168, .24)); }
58
+ :host([disabled]) { pointer-events: none; opacity: .5; }
59
+ :host([size="small"]) .tag { --hy-tag-height: 20px; --hy-tag-padding-inline: 6px; --hy-tag-font-size: 10px; }
60
+ :host([size="large"]) .tag { --hy-tag-height: 30px; --hy-tag-padding-inline: 11px; --hy-tag-font-size: 12px; }
61
+ .icon { display: inline-flex; flex: 0 0 auto; align-items: center; justify-content: center; }
62
+ .icon[hidden] { display: none; }
63
+ .label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
64
+ .close {
65
+ display: none;
66
+ width: 16px;
67
+ height: 16px;
68
+ margin-inline-end: -3px;
69
+ padding: 0;
70
+ border: 0;
71
+ border-radius: 50%;
72
+ place-items: center;
73
+ color: currentColor;
74
+ background: transparent;
75
+ cursor: pointer;
76
+ font: 15px/1 system-ui, sans-serif;
77
+ }
78
+ :host([closable]) .close { display: grid; }
79
+ .close:hover { background: color-mix(in srgb, currentColor 16%, transparent); }
80
+ .close:focus-visible { outline: 2px solid currentColor; outline-offset: 1px; }
81
+ ::slotted([slot="icon"]) { width: 1em; height: 1em; }
82
+ @media (prefers-reduced-motion: reduce) { .tag { transition: none; } }
83
+ `;
84
+ this._tag.className = 'tag';
85
+ this._tag.part.add('tag');
86
+ this._icon.className = 'icon';
87
+ this._icon.part.add('icon');
88
+ this._iconSlot.name = 'icon';
89
+ this._iconText.className = 'icon-text';
90
+ this._icon.append(this._iconSlot, this._iconText);
91
+ this._label.className = 'label';
92
+ this._label.part.add('label');
93
+ this._labelText.className = 'label-text';
94
+ this._label.append(this._labelSlot, this._labelText);
95
+ this._close.className = 'close';
96
+ this._close.part.add('close-button');
97
+ this._close.type = 'button';
98
+ this._close.textContent = '×';
99
+ this._close.setAttribute('aria-label', 'Close tag');
100
+ this._tag.append(this._icon, this._label, this._close);
101
+ root.append(style, this._tag);
102
+ }
103
+ connectedCallback() {
104
+ this._tag.addEventListener('click', this._onTagClick);
105
+ this._close.addEventListener('click', this._onCloseClick);
106
+ this.addEventListener('keydown', this._onKeydown);
107
+ this._iconSlot.addEventListener('slotchange', this._syncIcon);
108
+ this._labelSlot.addEventListener('slotchange', this._syncLabel);
109
+ this._sync();
110
+ }
111
+ disconnectedCallback() {
112
+ this._tag.removeEventListener('click', this._onTagClick);
113
+ this._close.removeEventListener('click', this._onCloseClick);
114
+ this.removeEventListener('keydown', this._onKeydown);
115
+ this._iconSlot.removeEventListener('slotchange', this._syncIcon);
116
+ this._labelSlot.removeEventListener('slotchange', this._syncLabel);
117
+ }
118
+ attributeChangedCallback() { this._sync(); }
119
+ get variant() { return isVariant(this.getAttribute('variant')) ? this.getAttribute('variant') : 'default'; }
120
+ set variant(value) { this.setAttribute('variant', isVariant(value) ? value : 'default'); }
121
+ get color() { return this.getAttribute('color')?.trim() ?? ''; }
122
+ set color(value) { this._setOptionalAttribute('color', value); }
123
+ get size() { return isSize(this.getAttribute('size')) ? this.getAttribute('size') : 'medium'; }
124
+ set size(value) { this.setAttribute('size', isSize(value) ? value : 'medium'); }
125
+ get label() { return this.getAttribute('label') ?? ''; }
126
+ set label(value) { this._setOptionalAttribute('label', value); }
127
+ get icon() { return this.getAttribute('icon') ?? ''; }
128
+ set icon(value) { this._setOptionalAttribute('icon', value); }
129
+ get value() { return this.getAttribute('value') ?? ''; }
130
+ set value(value) { this.setAttribute('value', String(value ?? '')); }
131
+ get closable() { return this.hasAttribute('closable'); }
132
+ set closable(value) { this.toggleAttribute('closable', Boolean(value)); }
133
+ get checkable() { return this.hasAttribute('checkable'); }
134
+ set checkable(value) { this.toggleAttribute('checkable', Boolean(value)); }
135
+ get checked() { return this.hasAttribute('checked'); }
136
+ set checked(value) { this.toggleAttribute('checked', Boolean(value)); }
137
+ get disabled() { return this.hasAttribute('disabled'); }
138
+ set disabled(value) { this.toggleAttribute('disabled', Boolean(value)); }
139
+ close() {
140
+ if (!this.closable || this.disabled)
141
+ return false;
142
+ const accepted = this.dispatchEvent(new CustomEvent('tag-close', {
143
+ detail: { value: this.value },
144
+ bubbles: true,
145
+ composed: true,
146
+ cancelable: true,
147
+ }));
148
+ if (accepted)
149
+ this.hidden = true;
150
+ return accepted;
151
+ }
152
+ _toggleChecked() {
153
+ if (!this.checkable || this.disabled)
154
+ return;
155
+ this.checked = !this.checked;
156
+ this.dispatchEvent(new CustomEvent('checked-change', {
157
+ detail: { checked: this.checked, value: this.value },
158
+ bubbles: true,
159
+ composed: true,
160
+ }));
161
+ }
162
+ _sync() {
163
+ this._tag.dataset.variant = this.variant;
164
+ const color = this.color;
165
+ if (color)
166
+ this._tag.style.setProperty('--_tone', color);
167
+ else
168
+ this._tag.style.removeProperty('--_tone');
169
+ this._close.disabled = this.disabled;
170
+ this._close.tabIndex = this.closable ? 0 : -1;
171
+ if (this.checkable) {
172
+ this.setAttribute('role', 'checkbox');
173
+ this.setAttribute('aria-checked', String(this.checked));
174
+ this.setAttribute('aria-disabled', String(this.disabled));
175
+ if (!this.hasAttribute('tabindex'))
176
+ this.tabIndex = this.disabled ? -1 : 0;
177
+ }
178
+ else {
179
+ this.removeAttribute('role');
180
+ this.removeAttribute('aria-checked');
181
+ this.removeAttribute('aria-disabled');
182
+ if (this.getAttribute('tabindex') === '0' || this.getAttribute('tabindex') === '-1')
183
+ this.removeAttribute('tabindex');
184
+ }
185
+ this._syncIcon();
186
+ this._syncLabel();
187
+ }
188
+ _syncIcon = () => {
189
+ const assigned = this._iconSlot.assignedNodes({ flatten: true }).some(node => node.nodeType === Node.ELEMENT_NODE || Boolean(node.textContent?.trim()));
190
+ this._iconText.textContent = assigned ? '' : this.icon;
191
+ this._icon.hidden = !assigned && !this.icon;
192
+ };
193
+ _syncLabel = () => {
194
+ const assigned = this._labelSlot.assignedNodes({ flatten: true }).some(node => node.nodeType === Node.ELEMENT_NODE || Boolean(node.textContent?.trim()));
195
+ this._labelText.textContent = assigned ? '' : this.label;
196
+ this._labelText.hidden = assigned || !this.label;
197
+ };
198
+ _setOptionalAttribute(name, value) {
199
+ const normalized = String(value ?? '').trim();
200
+ if (normalized)
201
+ this.setAttribute(name, normalized);
202
+ else
203
+ this.removeAttribute(name);
204
+ }
205
+ _onTagClick = (event) => {
206
+ if (event.composedPath().includes(this._close))
207
+ return;
208
+ this._toggleChecked();
209
+ };
210
+ _onCloseClick = (event) => {
211
+ event.stopPropagation();
212
+ this.close();
213
+ };
214
+ _onKeydown = (event) => {
215
+ if (!this.checkable || this.disabled || (event.key !== 'Enter' && event.key !== ' '))
216
+ return;
217
+ event.preventDefault();
218
+ this._toggleChecked();
219
+ };
220
+ }
221
+ export function defineTagComponents() {
222
+ if (!customElements.get('hy-tag'))
223
+ customElements.define('hy-tag', HYTag);
224
+ }
225
+ //# sourceMappingURL=tag.js.map
@@ -0,0 +1,62 @@
1
+ export interface HYTimePickerChangeDetail {
2
+ readonly value: string;
3
+ readonly hour: number | null;
4
+ readonly minute: number | null;
5
+ readonly second: number | null;
6
+ }
7
+ export interface HYTimePickerOpenChangeDetail {
8
+ readonly open: boolean;
9
+ }
10
+ /** Accessible column-based time picker with stable 24-hour values. */
11
+ export declare class HYTimePicker extends HTMLElement {
12
+ private readonly _control;
13
+ private readonly _trigger;
14
+ private readonly _label;
15
+ private readonly _arrow;
16
+ private readonly _clear;
17
+ private readonly _panel;
18
+ private readonly _panelId;
19
+ private _value;
20
+ private _draft;
21
+ private _reflecting;
22
+ private _outsideAbort;
23
+ static get observedAttributes(): string[];
24
+ constructor();
25
+ connectedCallback(): void;
26
+ disconnectedCallback(): void;
27
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
28
+ get value(): string;
29
+ set value(value: string);
30
+ get open(): boolean;
31
+ set open(value: boolean);
32
+ get disabled(): boolean;
33
+ set disabled(value: boolean);
34
+ get clearable(): boolean;
35
+ set clearable(value: boolean);
36
+ get placeholder(): string;
37
+ set placeholder(value: string);
38
+ get showSeconds(): boolean;
39
+ set showSeconds(value: boolean);
40
+ get minuteStep(): number;
41
+ set minuteStep(value: number);
42
+ get secondStep(): number;
43
+ set secondStep(value: number);
44
+ get min(): string;
45
+ set min(value: string);
46
+ get max(): string;
47
+ set max(value: string);
48
+ private _syncAttributes;
49
+ private _normalizeValue;
50
+ private _reflectValue;
51
+ private _isAllowed;
52
+ private _setDraft;
53
+ private _render;
54
+ private _renderPanel;
55
+ private _createColumn;
56
+ private _handleOptionKeydown;
57
+ private _focusSelected;
58
+ private _commit;
59
+ private _syncOutsideListener;
60
+ private _dispatchOpenChange;
61
+ }
62
+ export declare function defineTimePickerComponents(): void;