@haiyue/ui 0.1.0 → 0.1.2

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 (69) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/LICENSE +1 -1
  3. package/README.md +226 -2
  4. package/dist/border-beam.d.ts +26 -0
  5. package/dist/border-beam.js +174 -0
  6. package/dist/button.d.ts +10 -0
  7. package/dist/button.js +85 -0
  8. package/dist/checkbox.d.ts +2 -2
  9. package/dist/checkbox.js +11 -11
  10. package/dist/context-menu.d.ts +6 -6
  11. package/dist/context-menu.js +11 -9
  12. package/dist/dialog.d.ts +5 -5
  13. package/dist/dialog.js +18 -18
  14. package/dist/drawer.d.ts +49 -0
  15. package/dist/drawer.js +377 -0
  16. package/dist/dropdown.d.ts +9 -9
  17. package/dist/dropdown.js +9 -9
  18. package/dist/expandable.d.ts +32 -0
  19. package/dist/expandable.js +136 -0
  20. package/dist/history-controls.d.ts +40 -0
  21. package/dist/history-controls.js +123 -0
  22. package/dist/index.d.ts +36 -31
  23. package/dist/index.js +35 -85
  24. package/dist/input.d.ts +5 -5
  25. package/dist/input.js +13 -13
  26. package/dist/menu-shared.d.ts +4 -4
  27. package/dist/menu-shared.js +4 -4
  28. package/dist/notification.d.ts +55 -0
  29. package/dist/notification.js +357 -0
  30. package/dist/radio.d.ts +2 -2
  31. package/dist/radio.js +12 -12
  32. package/dist/range.d.ts +74 -0
  33. package/dist/range.js +393 -0
  34. package/dist/select.d.ts +6 -6
  35. package/dist/select.js +20 -20
  36. package/dist/split.d.ts +6 -6
  37. package/dist/split.js +14 -14
  38. package/dist/tabs.d.ts +10 -6
  39. package/dist/tabs.js +94 -30
  40. package/dist/tooltip.d.ts +4 -4
  41. package/dist/tooltip.js +9 -9
  42. package/dist/tree-model.d.ts +15 -7
  43. package/dist/tree-model.js +93 -80
  44. package/dist/tree-node.d.ts +3 -3
  45. package/dist/tree-node.js +3 -3
  46. package/dist/tree-types.d.ts +14 -14
  47. package/dist/tree.d.ts +9 -7
  48. package/dist/tree.js +68 -66
  49. package/dist/virtual-list.d.ts +61 -0
  50. package/dist/virtual-list.js +324 -0
  51. package/package.json +100 -7
  52. package/themes/haiyue-dark.css +46 -0
  53. package/themes/haiyue-light.css +46 -0
  54. package/src/checkbox.ts +0 -215
  55. package/src/context-menu.ts +0 -248
  56. package/src/dialog.ts +0 -195
  57. package/src/dropdown.ts +0 -249
  58. package/src/index.ts +0 -192
  59. package/src/input.ts +0 -150
  60. package/src/menu-shared.ts +0 -65
  61. package/src/radio.ts +0 -216
  62. package/src/select.ts +0 -271
  63. package/src/split.ts +0 -306
  64. package/src/tabs.ts +0 -182
  65. package/src/tooltip.ts +0 -321
  66. package/src/tree-model.ts +0 -305
  67. package/src/tree-node.ts +0 -67
  68. package/src/tree-types.ts +0 -47
  69. package/src/tree.ts +0 -1002
@@ -1,5 +1,5 @@
1
1
  import { GE_MENU_ITEM_STYLES, createMenuItemButton, createMenuSeparator } from './menu-shared.js';
2
- export class GEContextMenu extends HTMLElement {
2
+ export class HYContextMenu extends HTMLElement {
3
3
  _root;
4
4
  _style = document.createElement('style');
5
5
  _menu = document.createElement('div');
@@ -18,7 +18,7 @@ export class GEContextMenu extends HTMLElement {
18
18
  z-index: 10000;
19
19
  display: none;
20
20
  min-width: 132px;
21
- color: var(--ge-text-color, #d8e2f2);
21
+ color: var(--hy-text-color, #d8e2f2);
22
22
  font: 12px system-ui, sans-serif;
23
23
  }
24
24
  :host([open]) {
@@ -28,10 +28,10 @@ export class GEContextMenu extends HTMLElement {
28
28
  box-sizing: border-box;
29
29
  min-width: 132px;
30
30
  padding: 4px;
31
- border: 1px solid var(--ge-border-color, #303746);
31
+ border: 1px solid var(--hy-border-color, #303746);
32
32
  border-radius: 4px;
33
- background: var(--ge-menu-bg-color, var(--ge-surface-elevated-color, #1b2230));
34
- box-shadow: 0 10px 26px var(--ge-menu-shadow-color, rgba(0, 0, 0, 0.36));
33
+ background: var(--hy-menu-bg-color, var(--hy-surface-elevated-color, #1b2230));
34
+ box-shadow: 0 10px 26px var(--hy-menu-shadow-color, rgba(0, 0, 0, 0.36));
35
35
  }
36
36
  ${GE_MENU_ITEM_STYLES}
37
37
  `;
@@ -107,7 +107,7 @@ ${GE_MENU_ITEM_STYLES}
107
107
  this._items = Array.isArray(parsed) ? parsed : [];
108
108
  }
109
109
  catch (error) {
110
- console.warn('Invalid ge-context-menu items attribute.', error);
110
+ console.warn('Invalid hy-context-menu items attribute.', error);
111
111
  }
112
112
  }
113
113
  _render() {
@@ -188,7 +188,9 @@ ${GE_MENU_ITEM_STYLES}
188
188
  _nextEnabledIndex(direction) {
189
189
  if (!this._items.length)
190
190
  return -1;
191
- const start = this._activeIndex >= 0 ? this._activeIndex : direction > 0 ? -1 : this._items.length;
191
+ let start = this._activeIndex;
192
+ if (start < 0)
193
+ start = direction > 0 ? -1 : this._items.length;
192
194
  for (let step = 1; step <= this._items.length; step++) {
193
195
  const index = (start + direction * step + this._items.length) % this._items.length;
194
196
  if (this._isEnabledItem(index))
@@ -218,8 +220,8 @@ function getVisualViewportRect() {
218
220
  : { left: 0, top: 0, width: window.innerWidth, height: window.innerHeight };
219
221
  }
220
222
  export function defineContextMenuComponents() {
221
- if (!customElements.get('ge-context-menu')) {
222
- customElements.define('ge-context-menu', GEContextMenu);
223
+ if (!customElements.get('hy-context-menu')) {
224
+ customElements.define('hy-context-menu', HYContextMenu);
223
225
  }
224
226
  }
225
227
  //# sourceMappingURL=context-menu.js.map
package/dist/dialog.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- export type GEDialogCloseReason = 'action' | 'backdrop' | 'escape' | 'programmatic';
2
- export interface GEDialogCloseDetail {
3
- readonly reason: GEDialogCloseReason | string;
1
+ export type HYDialogCloseReason = 'action' | 'backdrop' | 'escape' | 'programmatic';
2
+ export interface HYDialogCloseDetail {
3
+ readonly reason: HYDialogCloseReason | string;
4
4
  }
5
5
  /** Accessible modal surface with slotted body/footer content and reflected open state. */
6
- export declare class GEDialog extends HTMLElement {
6
+ export declare class HYDialog extends HTMLElement {
7
7
  private readonly _dialog;
8
8
  private readonly _title;
9
9
  private readonly _closeButton;
@@ -20,7 +20,7 @@ export declare class GEDialog extends HTMLElement {
20
20
  get heading(): string;
21
21
  set heading(value: string);
22
22
  showModal(): void;
23
- close(reason?: GEDialogCloseDetail['reason']): void;
23
+ close(reason?: HYDialogCloseDetail['reason']): void;
24
24
  private _syncHeading;
25
25
  private _syncOpen;
26
26
  private _onCancel;
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 GEDialog extends HTMLElement {
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(--ge-text-color, #e6edf7);
17
+ color: var(--hy-text-color, #e6edf7);
18
18
  font: 13px system-ui, sans-serif;
19
19
  }
20
20
  dialog {
21
- width: min(var(--ge-dialog-width, 460px), calc(100vw - 32px));
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(--ge-border-color, #303746);
27
- border-radius: var(--ge-dialog-radius, 8px);
26
+ border: 1px solid var(--hy-border-color, #303746);
27
+ border-radius: var(--hy-dialog-radius, 8px);
28
28
  color: inherit;
29
- background: var(--ge-dialog-bg-color, var(--ge-surface-elevated-color, #171e2a));
30
- box-shadow: 0 22px 70px var(--ge-dialog-shadow-color, rgba(0, 0, 0, 0.52));
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(--ge-dialog-backdrop-color, rgba(3, 7, 12, 0.66));
34
- backdrop-filter: blur(var(--ge-dialog-backdrop-blur, 2px));
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(--ge-border-color, #303746);
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(--ge-secondary-text-color, #8b99ad);
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(--ge-hover-bg-color, #242d3b); }
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(--ge-dialog-body-padding, 16px);
70
- color: var(--ge-dialog-body-color, var(--ge-secondary-text-color, #a8b4c5));
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(--ge-border-color, #303746);
80
- background: var(--ge-dialog-footer-bg-color, rgba(9, 13, 19, 0.22));
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('ge-dialog'))
181
- customElements.define('ge-dialog', GEDialog);
180
+ if (!customElements.get('hy-dialog'))
181
+ customElements.define('hy-dialog', HYDialog);
182
182
  }
183
183
  //# sourceMappingURL=dialog.js.map
@@ -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
@@ -1,15 +1,15 @@
1
- export interface GEDropdownItem {
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 GEDropdownSelectDetail {
7
+ export interface HYDropdownSelectDetail {
8
8
  value: string;
9
- item: GEDropdownItem;
9
+ item: HYDropdownItem;
10
10
  }
11
- export type GEDropdownPlacement = 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end';
12
- export declare class GEDropdown extends HTMLElement {
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(): GEDropdownItem[];
25
- set items(value: GEDropdownItem[]);
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(): GEDropdownPlacement;
31
- set placement(value: GEDropdownPlacement);
30
+ get placement(): HYDropdownPlacement;
31
+ set placement(value: HYDropdownPlacement);
32
32
  show(): void;
33
33
  close(): void;
34
34
  toggle(): void;