@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.
- package/CHANGELOG.md +56 -0
- package/README.md +504 -1
- package/dist/adapters/web/controls.d.ts +19 -0
- package/dist/adapters/web/controls.js +284 -0
- package/dist/adapters/web/dom.d.ts +10 -0
- package/dist/adapters/web/dom.js +98 -0
- package/dist/adapters/web/index.d.ts +3 -0
- package/dist/adapters/web/index.js +3 -0
- package/dist/adapters/web/renderer.d.ts +18 -0
- package/dist/adapters/web/renderer.js +545 -0
- package/dist/adapters/web/styles.d.ts +3 -0
- package/dist/adapters/web/styles.js +62 -0
- package/dist/adapters/web/types.d.ts +46 -0
- package/dist/adapters/web/types.js +2 -0
- package/dist/affix.d.ts +35 -0
- package/dist/affix.js +137 -0
- package/dist/badge.d.ts +45 -0
- package/dist/badge.js +168 -0
- package/dist/border-beam.js +3 -1
- package/dist/breadcrumb.d.ts +37 -0
- package/dist/breadcrumb.js +210 -0
- package/dist/button-group.d.ts +12 -0
- package/dist/button-group.js +72 -0
- package/dist/button.d.ts +15 -1
- package/dist/button.js +101 -12
- package/dist/cascader.d.ts +65 -0
- package/dist/cascader.js +479 -0
- package/dist/collapse.d.ts +55 -0
- package/dist/collapse.js +261 -0
- package/dist/core/actions.d.ts +32 -0
- package/dist/core/actions.js +145 -0
- package/dist/core/data.d.ts +4 -0
- package/dist/core/data.js +27 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.js +6 -0
- package/dist/core/platform-view.d.ts +17 -0
- package/dist/core/platform-view.js +84 -0
- package/dist/core/selection.d.ts +14 -0
- package/dist/core/selection.js +93 -0
- package/dist/core/text.d.ts +31 -0
- package/dist/core/text.js +154 -0
- package/dist/core/types.d.ts +250 -0
- package/dist/core/types.js +2 -0
- package/dist/core/validation.d.ts +24 -0
- package/dist/core/validation.js +238 -0
- package/dist/date-picker.d.ts +60 -0
- package/dist/date-picker.js +355 -0
- package/dist/dialog.d.ts +4 -0
- package/dist/dialog.js +23 -5
- package/dist/divider.d.ts +33 -0
- package/dist/divider.js +113 -0
- package/dist/draggable.d.ts +78 -0
- package/dist/draggable.js +255 -0
- package/dist/expandable.d.ts +32 -0
- package/dist/expandable.js +136 -0
- package/dist/index.d.ts +47 -1
- package/dist/index.js +69 -0
- package/dist/input.d.ts +30 -1
- package/dist/input.js +166 -54
- package/dist/portable/index.d.ts +4 -0
- package/dist/portable/index.js +3 -0
- package/dist/portable/page.d.ts +38 -0
- package/dist/portable/page.js +361 -0
- package/dist/portable/theme.d.ts +19 -0
- package/dist/portable/theme.js +40 -0
- package/dist/portable/tree.d.ts +10 -0
- package/dist/portable/tree.js +96 -0
- package/dist/range.d.ts +3 -0
- package/dist/range.js +16 -5
- package/dist/rate.d.ts +46 -0
- package/dist/rate.js +193 -0
- package/dist/resizable.d.ts +97 -0
- package/dist/resizable.js +426 -0
- package/dist/skeleton.d.ts +41 -0
- package/dist/skeleton.js +141 -0
- package/dist/steps.d.ts +45 -0
- package/dist/steps.js +203 -0
- package/dist/table.d.ts +106 -0
- package/dist/table.js +689 -0
- package/dist/tabs.d.ts +7 -0
- package/dist/tabs.js +90 -16
- package/dist/tag.d.ts +55 -0
- package/dist/tag.js +225 -0
- package/dist/time-picker.d.ts +62 -0
- package/dist/time-picker.js +298 -0
- package/dist/timeline.d.ts +48 -0
- package/dist/timeline.js +201 -0
- package/dist/toast.d.ts +55 -0
- package/dist/toast.js +224 -0
- package/dist/tour.d.ts +89 -0
- package/dist/tour.js +306 -0
- package/dist/virtual-keyboard.d.ts +95 -0
- package/dist/virtual-keyboard.js +432 -0
- package/dist/virtual-list.js +12 -10
- package/dist/virtual-mouse.d.ts +82 -0
- package/dist/virtual-mouse.js +358 -0
- package/dist/watermark.d.ts +44 -0
- package/dist/watermark.js +148 -0
- 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
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
91
|
-
|
|
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.
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
131
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
this.
|
|
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;
|