@haiyue/ui 0.1.0 → 0.1.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/LICENSE +1 -1
- package/README.md +166 -2
- package/dist/border-beam.d.ts +26 -0
- package/dist/border-beam.js +172 -0
- package/dist/button.d.ts +10 -0
- package/dist/button.js +85 -0
- package/dist/checkbox.d.ts +2 -2
- package/dist/checkbox.js +11 -11
- package/dist/context-menu.d.ts +6 -6
- package/dist/context-menu.js +11 -9
- package/dist/dialog.d.ts +5 -5
- package/dist/dialog.js +18 -18
- package/dist/drawer.d.ts +49 -0
- package/dist/drawer.js +377 -0
- package/dist/dropdown.d.ts +9 -9
- package/dist/dropdown.js +9 -9
- package/dist/history-controls.d.ts +40 -0
- package/dist/history-controls.js +123 -0
- package/dist/index.d.ts +34 -31
- package/dist/index.js +32 -85
- package/dist/input.d.ts +5 -5
- package/dist/input.js +13 -13
- package/dist/menu-shared.d.ts +4 -4
- package/dist/menu-shared.js +4 -4
- package/dist/notification.d.ts +55 -0
- package/dist/notification.js +357 -0
- package/dist/radio.d.ts +2 -2
- package/dist/radio.js +12 -12
- package/dist/range.d.ts +74 -0
- package/dist/range.js +393 -0
- package/dist/select.d.ts +6 -6
- package/dist/select.js +20 -20
- package/dist/split.d.ts +6 -6
- package/dist/split.js +14 -14
- package/dist/tabs.d.ts +6 -6
- package/dist/tabs.js +14 -14
- package/dist/tooltip.d.ts +4 -4
- package/dist/tooltip.js +9 -9
- package/dist/tree-model.d.ts +15 -7
- package/dist/tree-model.js +93 -80
- package/dist/tree-node.d.ts +3 -3
- package/dist/tree-node.js +3 -3
- package/dist/tree-types.d.ts +14 -14
- package/dist/tree.d.ts +9 -7
- package/dist/tree.js +68 -66
- package/dist/virtual-list.d.ts +61 -0
- package/dist/virtual-list.js +322 -0
- package/package.json +87 -11
- package/themes/haiyue-dark.css +46 -0
- package/themes/haiyue-light.css +46 -0
- package/src/checkbox.ts +0 -215
- package/src/context-menu.ts +0 -248
- package/src/dialog.ts +0 -195
- package/src/dropdown.ts +0 -249
- package/src/index.ts +0 -192
- package/src/input.ts +0 -150
- package/src/menu-shared.ts +0 -65
- package/src/radio.ts +0 -216
- package/src/select.ts +0 -271
- package/src/split.ts +0 -306
- package/src/tabs.ts +0 -182
- package/src/tooltip.ts +0 -321
- package/src/tree-model.ts +0 -305
- package/src/tree-node.ts +0 -67
- package/src/tree-types.ts +0 -47
- package/src/tree.ts +0 -1002
package/dist/dialog.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Accessible modal surface with slotted body/footer content and reflected open state. */
|
|
2
|
-
export class
|
|
2
|
+
export class HYDialog extends HTMLElement {
|
|
3
3
|
_dialog = document.createElement('dialog');
|
|
4
4
|
_title = document.createElement('h2');
|
|
5
5
|
_closeButton = document.createElement('button');
|
|
@@ -14,31 +14,31 @@ export class GEDialog extends HTMLElement {
|
|
|
14
14
|
const style = document.createElement('style');
|
|
15
15
|
style.textContent = `
|
|
16
16
|
:host {
|
|
17
|
-
color: var(--
|
|
17
|
+
color: var(--hy-text-color, #e6edf7);
|
|
18
18
|
font: 13px system-ui, sans-serif;
|
|
19
19
|
}
|
|
20
20
|
dialog {
|
|
21
|
-
width: min(var(--
|
|
21
|
+
width: min(var(--hy-dialog-width, 460px), calc(100vw - 32px));
|
|
22
22
|
max-height: calc(100vh - 32px);
|
|
23
23
|
margin: auto;
|
|
24
24
|
padding: 0;
|
|
25
25
|
overflow: hidden;
|
|
26
|
-
border: 1px solid var(--
|
|
27
|
-
border-radius: var(--
|
|
26
|
+
border: 1px solid var(--hy-border-color, #303746);
|
|
27
|
+
border-radius: var(--hy-dialog-radius, 8px);
|
|
28
28
|
color: inherit;
|
|
29
|
-
background: var(--
|
|
30
|
-
box-shadow: 0 22px 70px var(--
|
|
29
|
+
background: var(--hy-dialog-bg-color, var(--hy-surface-elevated-color, #171e2a));
|
|
30
|
+
box-shadow: 0 22px 70px var(--hy-dialog-shadow-color, rgba(0, 0, 0, 0.52));
|
|
31
31
|
}
|
|
32
32
|
dialog::backdrop {
|
|
33
|
-
background: var(--
|
|
34
|
-
backdrop-filter: blur(var(--
|
|
33
|
+
background: var(--hy-dialog-backdrop-color, rgba(3, 7, 12, 0.66));
|
|
34
|
+
backdrop-filter: blur(var(--hy-dialog-backdrop-blur, 2px));
|
|
35
35
|
}
|
|
36
36
|
.header {
|
|
37
37
|
display: flex;
|
|
38
38
|
align-items: center;
|
|
39
39
|
min-height: 49px;
|
|
40
40
|
padding: 0 12px 0 16px;
|
|
41
|
-
border-bottom: 1px solid var(--
|
|
41
|
+
border-bottom: 1px solid var(--hy-border-color, #303746);
|
|
42
42
|
}
|
|
43
43
|
h2 {
|
|
44
44
|
flex: 1;
|
|
@@ -56,18 +56,18 @@ export class GEDialog extends HTMLElement {
|
|
|
56
56
|
height: 28px;
|
|
57
57
|
border: 0;
|
|
58
58
|
border-radius: 5px;
|
|
59
|
-
color: var(--
|
|
59
|
+
color: var(--hy-secondary-text-color, #8b99ad);
|
|
60
60
|
background: transparent;
|
|
61
61
|
cursor: pointer;
|
|
62
62
|
font: 20px/1 system-ui, sans-serif;
|
|
63
63
|
}
|
|
64
64
|
:host([dismissible]) .close { display: grid; place-items: center; }
|
|
65
|
-
.close:hover { color: inherit; background: var(--
|
|
65
|
+
.close:hover { color: inherit; background: var(--hy-hover-bg-color, #242d3b); }
|
|
66
66
|
.body {
|
|
67
67
|
max-height: calc(100vh - 160px);
|
|
68
68
|
overflow: auto;
|
|
69
|
-
padding: var(--
|
|
70
|
-
color: var(--
|
|
69
|
+
padding: var(--hy-dialog-body-padding, 16px);
|
|
70
|
+
color: var(--hy-dialog-body-color, var(--hy-secondary-text-color, #a8b4c5));
|
|
71
71
|
line-height: 1.55;
|
|
72
72
|
}
|
|
73
73
|
.footer {
|
|
@@ -76,8 +76,8 @@ export class GEDialog extends HTMLElement {
|
|
|
76
76
|
gap: 8px;
|
|
77
77
|
min-height: 54px;
|
|
78
78
|
padding: 10px 14px;
|
|
79
|
-
border-top: 1px solid var(--
|
|
80
|
-
background: var(--
|
|
79
|
+
border-top: 1px solid var(--hy-border-color, #303746);
|
|
80
|
+
background: var(--hy-dialog-footer-bg-color, rgba(9, 13, 19, 0.22));
|
|
81
81
|
}
|
|
82
82
|
slot[name="footer"]::slotted(*) { margin: 0; }
|
|
83
83
|
`;
|
|
@@ -177,7 +177,7 @@ export class GEDialog extends HTMLElement {
|
|
|
177
177
|
};
|
|
178
178
|
}
|
|
179
179
|
export function defineDialogComponents() {
|
|
180
|
-
if (!customElements.get('
|
|
181
|
-
customElements.define('
|
|
180
|
+
if (!customElements.get('hy-dialog'))
|
|
181
|
+
customElements.define('hy-dialog', HYDialog);
|
|
182
182
|
}
|
|
183
183
|
//# sourceMappingURL=dialog.js.map
|
package/dist/drawer.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type HYDrawerPlacement = 'top' | 'right' | 'bottom' | 'left';
|
|
2
|
+
export type HYDrawerCloseReason = 'action' | 'mask' | 'escape' | 'programmatic';
|
|
3
|
+
export interface HYDrawerCloseDetail {
|
|
4
|
+
readonly reason: HYDrawerCloseReason | string;
|
|
5
|
+
}
|
|
6
|
+
/** Sliding dialog surface with optional mask and hidden-content unmounting. */
|
|
7
|
+
export declare class HYDrawer extends HTMLElement {
|
|
8
|
+
private readonly _panel;
|
|
9
|
+
private readonly _title;
|
|
10
|
+
private readonly _closeButton;
|
|
11
|
+
private readonly _footer;
|
|
12
|
+
private readonly _footerSlot;
|
|
13
|
+
private readonly _detachedContent;
|
|
14
|
+
private _documentListenerAbort;
|
|
15
|
+
private _destroyTimer;
|
|
16
|
+
private _returnFocus;
|
|
17
|
+
private _closeReason;
|
|
18
|
+
private _wasOpen;
|
|
19
|
+
static get observedAttributes(): string[];
|
|
20
|
+
constructor();
|
|
21
|
+
connectedCallback(): void;
|
|
22
|
+
disconnectedCallback(): void;
|
|
23
|
+
attributeChangedCallback(name: string): void;
|
|
24
|
+
get open(): boolean;
|
|
25
|
+
set open(value: boolean);
|
|
26
|
+
get heading(): string;
|
|
27
|
+
set heading(value: string);
|
|
28
|
+
get placement(): HYDrawerPlacement;
|
|
29
|
+
set placement(value: HYDrawerPlacement);
|
|
30
|
+
/** The mask defaults to true; use mask="false" or set the property to false to disable it. */
|
|
31
|
+
get mask(): boolean;
|
|
32
|
+
set mask(value: boolean);
|
|
33
|
+
get destroyOnHidden(): boolean;
|
|
34
|
+
set destroyOnHidden(value: boolean);
|
|
35
|
+
show(): void;
|
|
36
|
+
close(reason?: HYDrawerCloseDetail['reason']): void;
|
|
37
|
+
private _syncHeading;
|
|
38
|
+
private _syncPlacement;
|
|
39
|
+
private _syncFooter;
|
|
40
|
+
private _syncPanelSemantics;
|
|
41
|
+
private _syncOpen;
|
|
42
|
+
private _attachDocumentListener;
|
|
43
|
+
private _detachDocumentListener;
|
|
44
|
+
private _onDocumentKeyDown;
|
|
45
|
+
private _scheduleContentDestroy;
|
|
46
|
+
private _cancelContentDestroy;
|
|
47
|
+
private _restoreContent;
|
|
48
|
+
}
|
|
49
|
+
export declare function defineDrawerComponents(): void;
|
package/dist/drawer.js
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
const CONTENT_DESTROY_DELAY = 220;
|
|
2
|
+
const FOCUSABLE_SELECTOR = [
|
|
3
|
+
'a[href]',
|
|
4
|
+
'button:not([disabled])',
|
|
5
|
+
'input:not([disabled])',
|
|
6
|
+
'select:not([disabled])',
|
|
7
|
+
'textarea:not([disabled])',
|
|
8
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
9
|
+
].join(',');
|
|
10
|
+
const DRAWER_STYLES = `
|
|
11
|
+
:host {
|
|
12
|
+
position: fixed;
|
|
13
|
+
z-index: var(--hy-drawer-z-index, 1000);
|
|
14
|
+
inset: 0;
|
|
15
|
+
display: block;
|
|
16
|
+
pointer-events: none;
|
|
17
|
+
color: var(--hy-text-color, #e6edf7);
|
|
18
|
+
font: 13px/1.5 system-ui, sans-serif;
|
|
19
|
+
--_duration: var(--hy-drawer-duration, 200ms);
|
|
20
|
+
}
|
|
21
|
+
.root {
|
|
22
|
+
position: absolute;
|
|
23
|
+
inset: 0;
|
|
24
|
+
visibility: hidden;
|
|
25
|
+
transition: visibility 0s linear var(--_duration);
|
|
26
|
+
}
|
|
27
|
+
:host([open]) .root {
|
|
28
|
+
visibility: visible;
|
|
29
|
+
transition-delay: 0s;
|
|
30
|
+
}
|
|
31
|
+
.mask {
|
|
32
|
+
position: absolute;
|
|
33
|
+
inset: 0;
|
|
34
|
+
opacity: 0;
|
|
35
|
+
pointer-events: none;
|
|
36
|
+
background: var(--hy-drawer-mask-color, rgba(3, 7, 18, 0.58));
|
|
37
|
+
backdrop-filter: blur(var(--hy-drawer-mask-blur, 1px));
|
|
38
|
+
transition: opacity var(--_duration) ease;
|
|
39
|
+
}
|
|
40
|
+
:host([open]) .mask { opacity: 1; pointer-events: auto; }
|
|
41
|
+
:host([mask="false"]) .mask { display: none; }
|
|
42
|
+
.panel {
|
|
43
|
+
position: absolute;
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
width: min(var(--hy-drawer-width, 378px), calc(100vw - 24px));
|
|
47
|
+
height: 100%;
|
|
48
|
+
max-width: 100vw;
|
|
49
|
+
max-height: 100vh;
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
pointer-events: auto;
|
|
52
|
+
outline: none;
|
|
53
|
+
color: inherit;
|
|
54
|
+
background: var(--hy-drawer-bg-color, var(--hy-surface-elevated-color, #171e2a));
|
|
55
|
+
box-shadow: 0 0 54px var(--hy-drawer-shadow-color, rgba(0, 0, 0, 0.42));
|
|
56
|
+
transition: transform var(--_duration) cubic-bezier(0.22, 1, 0.36, 1);
|
|
57
|
+
box-sizing: border-box;
|
|
58
|
+
}
|
|
59
|
+
:host(:not([placement])) .panel, :host([placement="right"]) .panel {
|
|
60
|
+
inset: 0 0 0 auto;
|
|
61
|
+
border-left: 1px solid var(--hy-border-color, #303746);
|
|
62
|
+
transform: translateX(100%);
|
|
63
|
+
}
|
|
64
|
+
:host([placement="left"]) .panel {
|
|
65
|
+
inset: 0 auto 0 0;
|
|
66
|
+
border-right: 1px solid var(--hy-border-color, #303746);
|
|
67
|
+
transform: translateX(-100%);
|
|
68
|
+
}
|
|
69
|
+
:host([placement="top"]) .panel,
|
|
70
|
+
:host([placement="bottom"]) .panel {
|
|
71
|
+
width: 100%;
|
|
72
|
+
height: min(var(--hy-drawer-height, 320px), calc(100vh - 24px));
|
|
73
|
+
}
|
|
74
|
+
:host([placement="top"]) .panel {
|
|
75
|
+
inset: 0 0 auto;
|
|
76
|
+
border-bottom: 1px solid var(--hy-border-color, #303746);
|
|
77
|
+
transform: translateY(-100%);
|
|
78
|
+
}
|
|
79
|
+
:host([placement="bottom"]) .panel {
|
|
80
|
+
inset: auto 0 0;
|
|
81
|
+
border-top: 1px solid var(--hy-border-color, #303746);
|
|
82
|
+
transform: translateY(100%);
|
|
83
|
+
}
|
|
84
|
+
:host([open]) .panel { transform: translate(0); }
|
|
85
|
+
.header {
|
|
86
|
+
display: flex;
|
|
87
|
+
flex: 0 0 auto;
|
|
88
|
+
align-items: center;
|
|
89
|
+
min-height: 52px;
|
|
90
|
+
padding: 0 12px 0 18px;
|
|
91
|
+
border-bottom: 1px solid var(--hy-border-color, #303746);
|
|
92
|
+
}
|
|
93
|
+
h2 {
|
|
94
|
+
flex: 1;
|
|
95
|
+
min-width: 0;
|
|
96
|
+
margin: 0;
|
|
97
|
+
overflow: hidden;
|
|
98
|
+
font-size: 14px;
|
|
99
|
+
font-weight: 650;
|
|
100
|
+
text-overflow: ellipsis;
|
|
101
|
+
white-space: nowrap;
|
|
102
|
+
}
|
|
103
|
+
.close {
|
|
104
|
+
display: grid;
|
|
105
|
+
width: 30px;
|
|
106
|
+
height: 30px;
|
|
107
|
+
padding: 0;
|
|
108
|
+
border: 0;
|
|
109
|
+
border-radius: 5px;
|
|
110
|
+
place-items: center;
|
|
111
|
+
color: var(--hy-secondary-text-color, #8b99ad);
|
|
112
|
+
background: transparent;
|
|
113
|
+
cursor: pointer;
|
|
114
|
+
font: 20px/1 system-ui, sans-serif;
|
|
115
|
+
}
|
|
116
|
+
.close:hover { color: inherit; background: var(--hy-hover-bg-color, #242d3b); }
|
|
117
|
+
.close:focus-visible, .panel:focus-visible {
|
|
118
|
+
outline: 2px solid var(--hy-focus-border-color, #79a8ff);
|
|
119
|
+
outline-offset: -2px;
|
|
120
|
+
}
|
|
121
|
+
.body {
|
|
122
|
+
flex: 1 1 auto;
|
|
123
|
+
min-height: 0;
|
|
124
|
+
overflow: auto;
|
|
125
|
+
padding: var(--hy-drawer-body-padding, 18px);
|
|
126
|
+
color: var(--hy-secondary-text-color, #a8b4c5);
|
|
127
|
+
}
|
|
128
|
+
.footer {
|
|
129
|
+
display: flex;
|
|
130
|
+
flex: 0 0 auto;
|
|
131
|
+
justify-content: flex-end;
|
|
132
|
+
gap: 8px;
|
|
133
|
+
min-height: 56px;
|
|
134
|
+
padding: 10px 16px;
|
|
135
|
+
border-top: 1px solid var(--hy-border-color, #303746);
|
|
136
|
+
background: var(--hy-drawer-footer-bg-color, rgba(9, 13, 19, 0.22));
|
|
137
|
+
box-sizing: border-box;
|
|
138
|
+
}
|
|
139
|
+
.footer[hidden] { display: none; }
|
|
140
|
+
slot[name="footer"]::slotted(*) { margin: 0; }
|
|
141
|
+
@media (prefers-reduced-motion: reduce) {
|
|
142
|
+
:host { --_duration: 1ms; }
|
|
143
|
+
}
|
|
144
|
+
`;
|
|
145
|
+
/** Sliding dialog surface with optional mask and hidden-content unmounting. */
|
|
146
|
+
export class HYDrawer extends HTMLElement {
|
|
147
|
+
_panel = document.createElement('section');
|
|
148
|
+
_title = document.createElement('h2');
|
|
149
|
+
_closeButton = document.createElement('button');
|
|
150
|
+
_footer = document.createElement('footer');
|
|
151
|
+
_footerSlot = document.createElement('slot');
|
|
152
|
+
_detachedContent = document.createDocumentFragment();
|
|
153
|
+
_documentListenerAbort = null;
|
|
154
|
+
_destroyTimer = null;
|
|
155
|
+
_returnFocus = null;
|
|
156
|
+
_closeReason = 'programmatic';
|
|
157
|
+
_wasOpen = false;
|
|
158
|
+
static get observedAttributes() {
|
|
159
|
+
return ['open', 'heading', 'placement', 'mask', 'destroy-on-hidden'];
|
|
160
|
+
}
|
|
161
|
+
constructor() {
|
|
162
|
+
super();
|
|
163
|
+
const root = this.attachShadow({ mode: 'open' });
|
|
164
|
+
const style = document.createElement('style');
|
|
165
|
+
style.textContent = DRAWER_STYLES;
|
|
166
|
+
const container = document.createElement('div');
|
|
167
|
+
container.className = 'root';
|
|
168
|
+
const mask = document.createElement('div');
|
|
169
|
+
mask.className = 'mask';
|
|
170
|
+
mask.part.add('mask');
|
|
171
|
+
mask.setAttribute('aria-hidden', 'true');
|
|
172
|
+
this._panel.className = 'panel';
|
|
173
|
+
this._panel.part.add('panel');
|
|
174
|
+
this._panel.setAttribute('role', 'dialog');
|
|
175
|
+
this._panel.setAttribute('aria-labelledby', 'drawer-title');
|
|
176
|
+
this._panel.setAttribute('aria-hidden', 'true');
|
|
177
|
+
this._panel.tabIndex = -1;
|
|
178
|
+
const header = document.createElement('header');
|
|
179
|
+
header.className = 'header';
|
|
180
|
+
header.part.add('header');
|
|
181
|
+
this._title.id = 'drawer-title';
|
|
182
|
+
this._closeButton.className = 'close';
|
|
183
|
+
this._closeButton.part.add('close-button');
|
|
184
|
+
this._closeButton.type = 'button';
|
|
185
|
+
this._closeButton.setAttribute('aria-label', 'Close drawer');
|
|
186
|
+
this._closeButton.textContent = '×';
|
|
187
|
+
header.append(this._title, this._closeButton);
|
|
188
|
+
const body = document.createElement('div');
|
|
189
|
+
body.className = 'body';
|
|
190
|
+
body.part.add('body');
|
|
191
|
+
body.append(document.createElement('slot'));
|
|
192
|
+
this._footer.className = 'footer';
|
|
193
|
+
this._footer.part.add('footer');
|
|
194
|
+
this._footerSlot.name = 'footer';
|
|
195
|
+
this._footer.append(this._footerSlot);
|
|
196
|
+
this._panel.append(header, body, this._footer);
|
|
197
|
+
container.append(mask, this._panel);
|
|
198
|
+
root.append(style, container);
|
|
199
|
+
mask.addEventListener('click', () => this.close('mask'));
|
|
200
|
+
this._closeButton.addEventListener('click', () => this.close('action'));
|
|
201
|
+
this._footerSlot.addEventListener('slotchange', () => this._syncFooter());
|
|
202
|
+
}
|
|
203
|
+
connectedCallback() {
|
|
204
|
+
this._syncPlacement();
|
|
205
|
+
this._syncHeading();
|
|
206
|
+
this._syncFooter();
|
|
207
|
+
this._syncOpen();
|
|
208
|
+
}
|
|
209
|
+
disconnectedCallback() {
|
|
210
|
+
this._detachDocumentListener();
|
|
211
|
+
this._cancelContentDestroy();
|
|
212
|
+
this._returnFocus = null;
|
|
213
|
+
this._wasOpen = false;
|
|
214
|
+
}
|
|
215
|
+
attributeChangedCallback(name) {
|
|
216
|
+
if (name === 'heading')
|
|
217
|
+
this._syncHeading();
|
|
218
|
+
if (name === 'placement')
|
|
219
|
+
this._syncPlacement();
|
|
220
|
+
if (name === 'mask')
|
|
221
|
+
this._syncPanelSemantics();
|
|
222
|
+
if (name === 'open' && this.isConnected)
|
|
223
|
+
this._syncOpen();
|
|
224
|
+
if (name === 'destroy-on-hidden' && this.isConnected && !this.open) {
|
|
225
|
+
if (this.destroyOnHidden)
|
|
226
|
+
this._scheduleContentDestroy(0);
|
|
227
|
+
else
|
|
228
|
+
this._restoreContent();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
get open() { return this.hasAttribute('open'); }
|
|
232
|
+
set open(value) { this.toggleAttribute('open', Boolean(value)); }
|
|
233
|
+
get heading() { return this.getAttribute('heading') ?? ''; }
|
|
234
|
+
set heading(value) { this.setAttribute('heading', String(value)); }
|
|
235
|
+
get placement() {
|
|
236
|
+
const value = this.getAttribute('placement');
|
|
237
|
+
return value === 'top' || value === 'bottom' || value === 'left' ? value : 'right';
|
|
238
|
+
}
|
|
239
|
+
set placement(value) {
|
|
240
|
+
this.setAttribute('placement', value === 'top' || value === 'bottom' || value === 'left' ? value : 'right');
|
|
241
|
+
}
|
|
242
|
+
/** The mask defaults to true; use mask="false" or set the property to false to disable it. */
|
|
243
|
+
get mask() { return this.getAttribute('mask') !== 'false'; }
|
|
244
|
+
set mask(value) { this.setAttribute('mask', String(Boolean(value))); }
|
|
245
|
+
get destroyOnHidden() { return this.hasAttribute('destroy-on-hidden'); }
|
|
246
|
+
set destroyOnHidden(value) { this.toggleAttribute('destroy-on-hidden', Boolean(value)); }
|
|
247
|
+
show() {
|
|
248
|
+
if (this.open)
|
|
249
|
+
return;
|
|
250
|
+
this._closeReason = 'programmatic';
|
|
251
|
+
this.open = true;
|
|
252
|
+
}
|
|
253
|
+
close(reason = 'programmatic') {
|
|
254
|
+
if (!this.open)
|
|
255
|
+
return;
|
|
256
|
+
this._closeReason = reason;
|
|
257
|
+
this.open = false;
|
|
258
|
+
}
|
|
259
|
+
_syncHeading() {
|
|
260
|
+
this._title.textContent = this.heading || 'Drawer';
|
|
261
|
+
}
|
|
262
|
+
_syncPlacement() {
|
|
263
|
+
const value = this.getAttribute('placement');
|
|
264
|
+
if (value !== null && value !== 'top' && value !== 'right' && value !== 'bottom' && value !== 'left') {
|
|
265
|
+
this.setAttribute('placement', 'right');
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
_syncFooter() {
|
|
269
|
+
this._footer.hidden = this._footerSlot.assignedElements().length === 0;
|
|
270
|
+
}
|
|
271
|
+
_syncPanelSemantics() {
|
|
272
|
+
if (this.open && this.mask)
|
|
273
|
+
this._panel.setAttribute('aria-modal', 'true');
|
|
274
|
+
else
|
|
275
|
+
this._panel.removeAttribute('aria-modal');
|
|
276
|
+
}
|
|
277
|
+
_syncOpen() {
|
|
278
|
+
if (this.open) {
|
|
279
|
+
this._cancelContentDestroy();
|
|
280
|
+
this._restoreContent();
|
|
281
|
+
this._returnFocus ??= document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
282
|
+
this._panel.setAttribute('aria-hidden', 'false');
|
|
283
|
+
this._syncPanelSemantics();
|
|
284
|
+
this._attachDocumentListener();
|
|
285
|
+
this._wasOpen = true;
|
|
286
|
+
queueMicrotask(() => {
|
|
287
|
+
if (this.open && this.isConnected)
|
|
288
|
+
this._closeButton.focus();
|
|
289
|
+
});
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
this._panel.setAttribute('aria-hidden', 'true');
|
|
293
|
+
this._syncPanelSemantics();
|
|
294
|
+
this._detachDocumentListener();
|
|
295
|
+
this._scheduleContentDestroy(this._wasOpen ? CONTENT_DESTROY_DELAY : 0);
|
|
296
|
+
if (!this._wasOpen)
|
|
297
|
+
return;
|
|
298
|
+
this._wasOpen = false;
|
|
299
|
+
const reason = this._closeReason;
|
|
300
|
+
this._closeReason = 'programmatic';
|
|
301
|
+
this.dispatchEvent(new CustomEvent('drawer-close', {
|
|
302
|
+
detail: { reason },
|
|
303
|
+
bubbles: true,
|
|
304
|
+
composed: true,
|
|
305
|
+
}));
|
|
306
|
+
this._returnFocus?.focus();
|
|
307
|
+
this._returnFocus = null;
|
|
308
|
+
}
|
|
309
|
+
_attachDocumentListener() {
|
|
310
|
+
if (this._documentListenerAbort)
|
|
311
|
+
return;
|
|
312
|
+
this._documentListenerAbort = new AbortController();
|
|
313
|
+
document.addEventListener('keydown', this._onDocumentKeyDown, {
|
|
314
|
+
capture: true,
|
|
315
|
+
signal: this._documentListenerAbort.signal,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
_detachDocumentListener() {
|
|
319
|
+
this._documentListenerAbort?.abort();
|
|
320
|
+
this._documentListenerAbort = null;
|
|
321
|
+
}
|
|
322
|
+
_onDocumentKeyDown = (event) => {
|
|
323
|
+
if (!this.open)
|
|
324
|
+
return;
|
|
325
|
+
if (event.key === 'Escape') {
|
|
326
|
+
event.preventDefault();
|
|
327
|
+
this.close('escape');
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (event.key !== 'Tab' || !this.mask)
|
|
331
|
+
return;
|
|
332
|
+
const focusable = [this._closeButton, ...this.querySelectorAll(FOCUSABLE_SELECTOR)]
|
|
333
|
+
.filter(element => !element.hidden && element.getAttribute('aria-hidden') !== 'true');
|
|
334
|
+
if (focusable.length === 0) {
|
|
335
|
+
event.preventDefault();
|
|
336
|
+
this._panel.focus();
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
const active = this.shadowRoot?.activeElement ?? document.activeElement;
|
|
340
|
+
const index = focusable.indexOf(active);
|
|
341
|
+
if (event.shiftKey && index <= 0) {
|
|
342
|
+
event.preventDefault();
|
|
343
|
+
focusable[focusable.length - 1]?.focus();
|
|
344
|
+
}
|
|
345
|
+
else if (!event.shiftKey && (index < 0 || index === focusable.length - 1)) {
|
|
346
|
+
event.preventDefault();
|
|
347
|
+
focusable[0]?.focus();
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
_scheduleContentDestroy(delay) {
|
|
351
|
+
this._cancelContentDestroy();
|
|
352
|
+
if (!this.destroyOnHidden || this.open)
|
|
353
|
+
return;
|
|
354
|
+
this._destroyTimer = window.setTimeout(() => {
|
|
355
|
+
this._destroyTimer = null;
|
|
356
|
+
if (!this.open && this.destroyOnHidden)
|
|
357
|
+
this._detachedContent.append(...Array.from(this.childNodes));
|
|
358
|
+
}, delay);
|
|
359
|
+
}
|
|
360
|
+
_cancelContentDestroy() {
|
|
361
|
+
if (this._destroyTimer === null)
|
|
362
|
+
return;
|
|
363
|
+
window.clearTimeout(this._destroyTimer);
|
|
364
|
+
this._destroyTimer = null;
|
|
365
|
+
}
|
|
366
|
+
_restoreContent() {
|
|
367
|
+
if (!this._detachedContent.hasChildNodes())
|
|
368
|
+
return;
|
|
369
|
+
this.insertBefore(this._detachedContent, this.firstChild);
|
|
370
|
+
this._syncFooter();
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
export function defineDrawerComponents() {
|
|
374
|
+
if (!customElements.get('hy-drawer'))
|
|
375
|
+
customElements.define('hy-drawer', HYDrawer);
|
|
376
|
+
}
|
|
377
|
+
//# sourceMappingURL=drawer.js.map
|
package/dist/dropdown.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface HYDropdownItem {
|
|
2
2
|
label?: string;
|
|
3
3
|
value?: string;
|
|
4
4
|
disabled?: boolean;
|
|
5
5
|
separator?: boolean;
|
|
6
6
|
}
|
|
7
|
-
export interface
|
|
7
|
+
export interface HYDropdownSelectDetail {
|
|
8
8
|
value: string;
|
|
9
|
-
item:
|
|
9
|
+
item: HYDropdownItem;
|
|
10
10
|
}
|
|
11
|
-
export type
|
|
12
|
-
export declare class
|
|
11
|
+
export type HYDropdownPlacement = 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end';
|
|
12
|
+
export declare class HYDropdown extends HTMLElement {
|
|
13
13
|
private readonly _root;
|
|
14
14
|
private readonly _style;
|
|
15
15
|
private readonly _triggerSlot;
|
|
@@ -21,14 +21,14 @@ export declare class GEDropdown extends HTMLElement {
|
|
|
21
21
|
connectedCallback(): void;
|
|
22
22
|
disconnectedCallback(): void;
|
|
23
23
|
attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void;
|
|
24
|
-
get items():
|
|
25
|
-
set items(value:
|
|
24
|
+
get items(): HYDropdownItem[];
|
|
25
|
+
set items(value: HYDropdownItem[]);
|
|
26
26
|
get open(): boolean;
|
|
27
27
|
set open(value: boolean);
|
|
28
28
|
get disabled(): boolean;
|
|
29
29
|
set disabled(value: boolean);
|
|
30
|
-
get placement():
|
|
31
|
-
set placement(value:
|
|
30
|
+
get placement(): HYDropdownPlacement;
|
|
31
|
+
set placement(value: HYDropdownPlacement);
|
|
32
32
|
show(): void;
|
|
33
33
|
close(): void;
|
|
34
34
|
toggle(): void;
|
package/dist/dropdown.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GE_MENU_ITEM_STYLES, createMenuItemButton, createMenuSeparator } from './menu-shared.js';
|
|
2
|
-
export class
|
|
2
|
+
export class HYDropdown extends HTMLElement {
|
|
3
3
|
_root;
|
|
4
4
|
_style = document.createElement('style');
|
|
5
5
|
_triggerSlot = document.createElement('slot');
|
|
@@ -17,7 +17,7 @@ export class GEDropdown extends HTMLElement {
|
|
|
17
17
|
display: inline-block;
|
|
18
18
|
width: max-content;
|
|
19
19
|
min-width: 0;
|
|
20
|
-
color: var(--
|
|
20
|
+
color: var(--hy-text-color, #d8e2f2);
|
|
21
21
|
font: 12px system-ui, sans-serif;
|
|
22
22
|
}
|
|
23
23
|
:host([disabled]) {
|
|
@@ -33,11 +33,11 @@ export class GEDropdown extends HTMLElement {
|
|
|
33
33
|
overflow: auto;
|
|
34
34
|
display: none;
|
|
35
35
|
padding: 4px;
|
|
36
|
-
border: 1px solid var(--
|
|
36
|
+
border: 1px solid var(--hy-border-color, #303746);
|
|
37
37
|
border-radius: 4px;
|
|
38
|
-
color: var(--
|
|
39
|
-
background: var(--
|
|
40
|
-
box-shadow: 0 10px 26px var(--
|
|
38
|
+
color: var(--hy-text-color, #d8e2f2);
|
|
39
|
+
background: var(--hy-menu-bg-color, var(--hy-surface-elevated-color, #1b2230));
|
|
40
|
+
box-shadow: 0 10px 26px var(--hy-menu-shadow-color, rgba(0, 0, 0, 0.36));
|
|
41
41
|
}
|
|
42
42
|
:host([open]) .menu {
|
|
43
43
|
display: block;
|
|
@@ -137,7 +137,7 @@ ${GE_MENU_ITEM_STYLES}
|
|
|
137
137
|
: [];
|
|
138
138
|
}
|
|
139
139
|
catch (error) {
|
|
140
|
-
console.warn('Invalid
|
|
140
|
+
console.warn('Invalid hy-dropdown items attribute.', error);
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
_render() {
|
|
@@ -221,8 +221,8 @@ function getVisualViewportRect() {
|
|
|
221
221
|
: { left: 0, top: 0, width: window.innerWidth, height: window.innerHeight };
|
|
222
222
|
}
|
|
223
223
|
export function defineDropdownComponents() {
|
|
224
|
-
if (!customElements.get('
|
|
225
|
-
customElements.define('
|
|
224
|
+
if (!customElements.get('hy-dropdown')) {
|
|
225
|
+
customElements.define('hy-dropdown', HYDropdown);
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
228
|
//# sourceMappingURL=dropdown.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface HYHistoryEntry {
|
|
2
|
+
readonly id: number;
|
|
3
|
+
readonly label: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class HYHistoryControls extends HTMLElement {
|
|
6
|
+
private readonly _undo;
|
|
7
|
+
private readonly _redo;
|
|
8
|
+
private _canUndo;
|
|
9
|
+
private _canRedo;
|
|
10
|
+
private _undoLabel;
|
|
11
|
+
private _redoLabel;
|
|
12
|
+
private _busy;
|
|
13
|
+
private _entries;
|
|
14
|
+
private _connected;
|
|
15
|
+
private readonly _requestUndo;
|
|
16
|
+
private readonly _requestRedo;
|
|
17
|
+
static get observedAttributes(): string[];
|
|
18
|
+
constructor();
|
|
19
|
+
connectedCallback(): void;
|
|
20
|
+
disconnectedCallback(): void;
|
|
21
|
+
attributeChangedCallback(): void;
|
|
22
|
+
get canUndo(): boolean;
|
|
23
|
+
set canUndo(value: boolean);
|
|
24
|
+
get canRedo(): boolean;
|
|
25
|
+
set canRedo(value: boolean);
|
|
26
|
+
get undoLabel(): string;
|
|
27
|
+
set undoLabel(value: string);
|
|
28
|
+
get redoLabel(): string;
|
|
29
|
+
set redoLabel(value: string);
|
|
30
|
+
get busy(): boolean;
|
|
31
|
+
set busy(value: boolean);
|
|
32
|
+
get entries(): readonly HYHistoryEntry[];
|
|
33
|
+
set entries(value: readonly HYHistoryEntry[]);
|
|
34
|
+
private _syncAttributes;
|
|
35
|
+
private _render;
|
|
36
|
+
private _request;
|
|
37
|
+
private _reflectBoolean;
|
|
38
|
+
private _reflectString;
|
|
39
|
+
}
|
|
40
|
+
export declare function defineHistoryControlsComponents(): void;
|