@sekiui/elements 0.0.88 → 0.1.0
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/dist/cdn/p-CQQRfw1L.js +18 -0
- package/dist/cdn/seki-date-picker.js +71 -36
- package/dist/cdn/seki-drawer.js +76 -32
- package/dist/cdn/seki-hover-card.js +58 -3
- package/dist/cdn/seki-select-content.js +21 -13
- package/dist/cdn/seki-select-group.js +3 -4
- package/dist/cdn/seki-select-option.js +33 -15
- package/dist/cdn/seki-select-trigger.js +6 -4
- package/dist/cdn/seki-sheet.js +71 -30
- package/dist/cdn/seki-tooltip.js +47 -2
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/option-id-wIa73qWK.js +20 -0
- package/dist/cjs/seki-date-picker.cjs.entry.js +64 -32
- package/dist/cjs/seki-drawer.cjs.entry.js +67 -27
- package/dist/cjs/seki-hover-card.cjs.entry.js +52 -2
- package/dist/cjs/seki-select-content.cjs.entry.js +20 -11
- package/dist/cjs/seki-select-group.cjs.entry.js +2 -2
- package/dist/cjs/seki-select-option.cjs.entry.js +32 -13
- package/dist/cjs/seki-select-trigger.cjs.entry.js +5 -2
- package/dist/cjs/seki-sheet.cjs.entry.js +62 -25
- package/dist/cjs/seki-tooltip.cjs.entry.js +43 -2
- package/dist/cjs/sekiui.cjs.js +1 -1
- package/dist/collection/components/date-picker/seki-date-picker.js +124 -36
- package/dist/collection/components/drawer/seki-drawer.js +132 -31
- package/dist/collection/components/hover-card/seki-hover-card.js +138 -2
- package/dist/collection/components/select-content/seki-select-content.css +8 -0
- package/dist/collection/components/select-content/seki-select-content.js +20 -11
- package/dist/collection/components/select-group/seki-select-group.js +2 -2
- package/dist/collection/components/select-option/seki-select-option.js +32 -13
- package/dist/collection/components/select-trigger/seki-select-trigger.js +5 -2
- package/dist/collection/components/sheet/seki-sheet.js +127 -29
- package/dist/collection/components/tooltip/seki-tooltip.js +92 -2
- package/dist/collection/utils/select/index.js +1 -0
- package/dist/collection/utils/select/option-id.js +16 -0
- package/dist/components/p-CQQRfw1L.js +18 -0
- package/dist/components/seki-date-picker.js +71 -36
- package/dist/components/seki-drawer.js +76 -32
- package/dist/components/seki-hover-card.js +58 -3
- package/dist/components/seki-select-content.js +21 -13
- package/dist/components/seki-select-group.js +3 -4
- package/dist/components/seki-select-option.js +33 -15
- package/dist/components/seki-select-trigger.js +6 -4
- package/dist/components/seki-sheet.js +71 -30
- package/dist/components/seki-tooltip.js +47 -2
- package/dist/esm/loader.js +1 -1
- package/dist/esm/option-id-CQQRfw1L.js +18 -0
- package/dist/esm/seki-date-picker.entry.js +64 -32
- package/dist/esm/seki-drawer.entry.js +67 -27
- package/dist/esm/seki-hover-card.entry.js +52 -2
- package/dist/esm/seki-select-content.entry.js +20 -11
- package/dist/esm/seki-select-group.entry.js +2 -2
- package/dist/esm/seki-select-option.entry.js +32 -13
- package/dist/esm/seki-select-trigger.entry.js +5 -2
- package/dist/esm/seki-sheet.entry.js +62 -25
- package/dist/esm/seki-tooltip.entry.js +43 -2
- package/dist/esm/sekiui.js +1 -1
- package/dist/sekiui/p-05b33a61.entry.js +1 -0
- package/dist/sekiui/p-1cd6b3e6.entry.js +1 -0
- package/dist/sekiui/p-3de5878b.entry.js +1 -0
- package/dist/sekiui/p-649dbdf0.entry.js +1 -0
- package/dist/sekiui/p-CQQRfw1L.js +1 -0
- package/dist/sekiui/p-a2ae6d1b.entry.js +1 -0
- package/dist/sekiui/p-b82c2267.entry.js +1 -0
- package/dist/sekiui/p-c0f21b6a.entry.js +1 -0
- package/dist/sekiui/p-c3ef507f.entry.js +1 -0
- package/dist/sekiui/p-fe3e661d.entry.js +1 -0
- package/dist/sekiui/sekiui.esm.js +1 -1
- package/dist/types/components/date-picker/seki-date-picker.d.ts +21 -5
- package/dist/types/components/drawer/seki-drawer.d.ts +22 -6
- package/dist/types/components/hover-card/seki-hover-card.d.ts +21 -0
- package/dist/types/components/select-content/seki-select-content.d.ts +8 -5
- package/dist/types/components/select-option/seki-select-option.d.ts +6 -4
- package/dist/types/components/sheet/seki-sheet.d.ts +22 -6
- package/dist/types/components/tooltip/seki-tooltip.d.ts +13 -0
- package/dist/types/components.d.ts +132 -9
- package/dist/types/utils/select/index.d.ts +1 -0
- package/dist/types/utils/select/option-id.d.ts +14 -0
- package/package.json +1 -1
- package/dist/sekiui/p-1866201e.entry.js +0 -1
- package/dist/sekiui/p-2e18933c.entry.js +0 -1
- package/dist/sekiui/p-779764c0.entry.js +0 -1
- package/dist/sekiui/p-786c153b.entry.js +0 -1
- package/dist/sekiui/p-87bcbb66.entry.js +0 -1
- package/dist/sekiui/p-9abfa3a5.entry.js +0 -1
- package/dist/sekiui/p-ac7bd611.entry.js +0 -1
- package/dist/sekiui/p-c62c4ad7.entry.js +0 -1
- package/dist/sekiui/p-e45e6992.entry.js +0 -1
|
@@ -19,51 +19,75 @@ import { syncTheme } from "../../utils/theme-sync";
|
|
|
19
19
|
*/
|
|
20
20
|
export class SekiDrawer {
|
|
21
21
|
constructor() {
|
|
22
|
+
/**
|
|
23
|
+
* Controlled open state. Also readable/writable as the `open` attribute, so
|
|
24
|
+
* `<seki-drawer open>` renders open with no script involved.
|
|
25
|
+
*/
|
|
26
|
+
this.open = false;
|
|
27
|
+
/**
|
|
28
|
+
* Initial open state for uncontrolled usage
|
|
29
|
+
*/
|
|
30
|
+
this.defaultOpen = false;
|
|
22
31
|
/**
|
|
23
32
|
* Internal state for drawer open/closed
|
|
24
33
|
*/
|
|
25
|
-
this.
|
|
34
|
+
this._isOpen = false;
|
|
26
35
|
/**
|
|
27
36
|
* Current snap point (0-1)
|
|
28
37
|
*/
|
|
29
38
|
this.currentSnapPoint = 1;
|
|
30
39
|
}
|
|
40
|
+
componentWillLoad() {
|
|
41
|
+
this._isOpen = this.open || this.defaultOpen;
|
|
42
|
+
this.open = this._isOpen;
|
|
43
|
+
this.currentSnapPoint = this._isOpen ? 1 : 0;
|
|
44
|
+
}
|
|
45
|
+
componentDidLoad() {
|
|
46
|
+
this.updateContext();
|
|
47
|
+
}
|
|
48
|
+
handleOpenPropChange(newValue) {
|
|
49
|
+
// An outside assignment (`drawer.open = true`) has to win after first render;
|
|
50
|
+
// `open` is only read once in componentWillLoad otherwise.
|
|
51
|
+
if (newValue === this._isOpen)
|
|
52
|
+
return;
|
|
53
|
+
if (newValue) {
|
|
54
|
+
this.openDrawer();
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.closeDrawer();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
31
60
|
/**
|
|
32
61
|
* Opens the drawer
|
|
33
62
|
*/
|
|
34
|
-
async
|
|
35
|
-
this.
|
|
63
|
+
async openDrawer() {
|
|
64
|
+
this._isOpen = true;
|
|
65
|
+
this.open = true;
|
|
36
66
|
this.currentSnapPoint = 1;
|
|
37
67
|
this.updateContext();
|
|
38
68
|
this.drawerOpen.emit();
|
|
69
|
+
this.sekiOpenChange.emit(true);
|
|
39
70
|
}
|
|
40
71
|
/**
|
|
41
72
|
* Closes the drawer
|
|
42
73
|
*/
|
|
43
|
-
async
|
|
44
|
-
this.
|
|
74
|
+
async closeDrawer() {
|
|
75
|
+
this._isOpen = false;
|
|
76
|
+
this.open = false;
|
|
45
77
|
this.currentSnapPoint = 0;
|
|
46
78
|
this.updateContext();
|
|
47
79
|
this.drawerClose.emit();
|
|
48
|
-
|
|
49
|
-
updateContext() {
|
|
50
|
-
// seki-drawer-content has no other way to know this drawer's open state —
|
|
51
|
-
// it reads this off the host element via closest('seki-drawer').
|
|
52
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
53
|
-
this.el._drawerContext = { isOpen: this.isOpen };
|
|
54
|
-
}
|
|
55
|
-
componentDidLoad() {
|
|
56
|
-
this.updateContext();
|
|
80
|
+
this.sekiOpenChange.emit(false);
|
|
57
81
|
}
|
|
58
82
|
/**
|
|
59
83
|
* Toggles the drawer
|
|
60
84
|
*/
|
|
61
|
-
async
|
|
62
|
-
if (this.
|
|
63
|
-
await this.
|
|
85
|
+
async toggleDrawer() {
|
|
86
|
+
if (this._isOpen) {
|
|
87
|
+
await this.closeDrawer();
|
|
64
88
|
}
|
|
65
89
|
else {
|
|
66
|
-
await this.
|
|
90
|
+
await this.openDrawer();
|
|
67
91
|
}
|
|
68
92
|
}
|
|
69
93
|
/**
|
|
@@ -71,37 +95,49 @@ export class SekiDrawer {
|
|
|
71
95
|
*/
|
|
72
96
|
async snapTo(point) {
|
|
73
97
|
if (point <= 0) {
|
|
74
|
-
await this.
|
|
98
|
+
await this.closeDrawer();
|
|
75
99
|
}
|
|
76
100
|
else {
|
|
77
101
|
this.currentSnapPoint = point;
|
|
78
|
-
|
|
102
|
+
const wasOpen = this._isOpen;
|
|
103
|
+
this._isOpen = true;
|
|
104
|
+
this.open = true;
|
|
79
105
|
this.updateContext();
|
|
106
|
+
if (!wasOpen) {
|
|
107
|
+
this.drawerOpen.emit();
|
|
108
|
+
this.sekiOpenChange.emit(true);
|
|
109
|
+
}
|
|
80
110
|
this.drawerSnap.emit({ point });
|
|
81
111
|
}
|
|
82
112
|
}
|
|
113
|
+
updateContext() {
|
|
114
|
+
// seki-drawer-content has no other way to know this drawer's open state —
|
|
115
|
+
// it reads this off the host element via closest('seki-drawer').
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
117
|
+
this.el._drawerContext = { isOpen: this._isOpen };
|
|
118
|
+
}
|
|
83
119
|
handleTriggerClick() {
|
|
84
|
-
this.
|
|
120
|
+
this.toggleDrawer();
|
|
85
121
|
}
|
|
86
122
|
handleRequestClose() {
|
|
87
|
-
this.
|
|
123
|
+
this.closeDrawer();
|
|
88
124
|
}
|
|
89
125
|
handleRequestSnap(event) {
|
|
90
126
|
this.snapTo(event.detail.point);
|
|
91
127
|
}
|
|
92
128
|
handleKeydown(ev) {
|
|
93
|
-
if (this.
|
|
94
|
-
this.
|
|
129
|
+
if (this._isOpen && ev.key === 'Escape') {
|
|
130
|
+
this.closeDrawer();
|
|
95
131
|
}
|
|
96
132
|
}
|
|
97
133
|
connectedCallback() {
|
|
98
134
|
syncTheme(this.el);
|
|
99
135
|
}
|
|
100
136
|
render() {
|
|
101
|
-
return (h("div", { key: '
|
|
137
|
+
return (h("div", { key: '824d218c42cd41a0a79bef604e940f6c95a64470', class: {
|
|
102
138
|
'seki-drawer': true,
|
|
103
|
-
'seki-drawer--open': this.
|
|
104
|
-
}, "data-snap-point": this.currentSnapPoint, part: "drawer" }, h("slot", { key: '
|
|
139
|
+
'seki-drawer--open': this._isOpen,
|
|
140
|
+
}, "data-snap-point": this.currentSnapPoint, part: "drawer" }, h("slot", { key: '26982c14006c01915390898306d79fa665e30463' }), this._isOpen && (h("div", { key: 'a0f90520c0deaa5c320bbc027ca5b6a4edc4d9ff', class: "seki-drawer-overlay", part: "overlay", onClick: () => this.closeDrawer() }))));
|
|
105
141
|
}
|
|
106
142
|
static get is() { return "seki-drawer"; }
|
|
107
143
|
static get encapsulation() { return "shadow"; }
|
|
@@ -115,9 +151,53 @@ export class SekiDrawer {
|
|
|
115
151
|
"$": ["seki-drawer.css"]
|
|
116
152
|
};
|
|
117
153
|
}
|
|
154
|
+
static get properties() {
|
|
155
|
+
return {
|
|
156
|
+
"open": {
|
|
157
|
+
"type": "boolean",
|
|
158
|
+
"mutable": true,
|
|
159
|
+
"complexType": {
|
|
160
|
+
"original": "boolean",
|
|
161
|
+
"resolved": "boolean",
|
|
162
|
+
"references": {}
|
|
163
|
+
},
|
|
164
|
+
"required": false,
|
|
165
|
+
"optional": false,
|
|
166
|
+
"docs": {
|
|
167
|
+
"tags": [],
|
|
168
|
+
"text": "Controlled open state. Also readable/writable as the `open` attribute, so\n`<seki-drawer open>` renders open with no script involved."
|
|
169
|
+
},
|
|
170
|
+
"getter": false,
|
|
171
|
+
"setter": false,
|
|
172
|
+
"reflect": true,
|
|
173
|
+
"attribute": "open",
|
|
174
|
+
"defaultValue": "false"
|
|
175
|
+
},
|
|
176
|
+
"defaultOpen": {
|
|
177
|
+
"type": "boolean",
|
|
178
|
+
"mutable": false,
|
|
179
|
+
"complexType": {
|
|
180
|
+
"original": "boolean",
|
|
181
|
+
"resolved": "boolean",
|
|
182
|
+
"references": {}
|
|
183
|
+
},
|
|
184
|
+
"required": false,
|
|
185
|
+
"optional": false,
|
|
186
|
+
"docs": {
|
|
187
|
+
"tags": [],
|
|
188
|
+
"text": "Initial open state for uncontrolled usage"
|
|
189
|
+
},
|
|
190
|
+
"getter": false,
|
|
191
|
+
"setter": false,
|
|
192
|
+
"reflect": false,
|
|
193
|
+
"attribute": "default-open",
|
|
194
|
+
"defaultValue": "false"
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
118
198
|
static get states() {
|
|
119
199
|
return {
|
|
120
|
-
"
|
|
200
|
+
"_isOpen": {},
|
|
121
201
|
"currentSnapPoint": {}
|
|
122
202
|
};
|
|
123
203
|
}
|
|
@@ -167,11 +247,26 @@ export class SekiDrawer {
|
|
|
167
247
|
"resolved": "{ point: number; }",
|
|
168
248
|
"references": {}
|
|
169
249
|
}
|
|
250
|
+
}, {
|
|
251
|
+
"method": "sekiOpenChange",
|
|
252
|
+
"name": "sekiOpenChange",
|
|
253
|
+
"bubbles": true,
|
|
254
|
+
"cancelable": true,
|
|
255
|
+
"composed": true,
|
|
256
|
+
"docs": {
|
|
257
|
+
"tags": [],
|
|
258
|
+
"text": "Emitted whenever the open state changes. Matches the dialog/popover/collapsible\nevent shape so a consumer can listen to one event name across every overlay."
|
|
259
|
+
},
|
|
260
|
+
"complexType": {
|
|
261
|
+
"original": "boolean",
|
|
262
|
+
"resolved": "boolean",
|
|
263
|
+
"references": {}
|
|
264
|
+
}
|
|
170
265
|
}];
|
|
171
266
|
}
|
|
172
267
|
static get methods() {
|
|
173
268
|
return {
|
|
174
|
-
"
|
|
269
|
+
"openDrawer": {
|
|
175
270
|
"complexType": {
|
|
176
271
|
"signature": "() => Promise<void>",
|
|
177
272
|
"parameters": [],
|
|
@@ -188,7 +283,7 @@ export class SekiDrawer {
|
|
|
188
283
|
"tags": []
|
|
189
284
|
}
|
|
190
285
|
},
|
|
191
|
-
"
|
|
286
|
+
"closeDrawer": {
|
|
192
287
|
"complexType": {
|
|
193
288
|
"signature": "() => Promise<void>",
|
|
194
289
|
"parameters": [],
|
|
@@ -205,7 +300,7 @@ export class SekiDrawer {
|
|
|
205
300
|
"tags": []
|
|
206
301
|
}
|
|
207
302
|
},
|
|
208
|
-
"
|
|
303
|
+
"toggleDrawer": {
|
|
209
304
|
"complexType": {
|
|
210
305
|
"signature": "() => Promise<void>",
|
|
211
306
|
"parameters": [],
|
|
@@ -246,6 +341,12 @@ export class SekiDrawer {
|
|
|
246
341
|
};
|
|
247
342
|
}
|
|
248
343
|
static get elementRef() { return "el"; }
|
|
344
|
+
static get watchers() {
|
|
345
|
+
return [{
|
|
346
|
+
"propName": "open",
|
|
347
|
+
"methodName": "handleOpenPropChange"
|
|
348
|
+
}];
|
|
349
|
+
}
|
|
249
350
|
static get listeners() {
|
|
250
351
|
return [{
|
|
251
352
|
"name": "triggerClick",
|
|
@@ -54,6 +54,17 @@ export class SekiHoverCard {
|
|
|
54
54
|
* @default false
|
|
55
55
|
*/
|
|
56
56
|
this.disabled = false;
|
|
57
|
+
/**
|
|
58
|
+
* Controlled open state. Reflects to the `open` attribute, so
|
|
59
|
+
* `<seki-hover-card open>` renders open with no script involved.
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
this.open = false;
|
|
63
|
+
/**
|
|
64
|
+
* Initial open state for uncontrolled usage
|
|
65
|
+
* @default false
|
|
66
|
+
*/
|
|
67
|
+
this.defaultOpen = false;
|
|
57
68
|
/**
|
|
58
69
|
* Internal open state
|
|
59
70
|
*/
|
|
@@ -114,6 +125,20 @@ export class SekiHoverCard {
|
|
|
114
125
|
}
|
|
115
126
|
};
|
|
116
127
|
}
|
|
128
|
+
componentWillLoad() {
|
|
129
|
+
// `disabled` wins over a requested initial open state.
|
|
130
|
+
this._isOpen = (this.open || this.defaultOpen) && !this.disabled;
|
|
131
|
+
this.open = this._isOpen;
|
|
132
|
+
}
|
|
133
|
+
openChanged(newValue) {
|
|
134
|
+
// An outside assignment (`card.open = true`) has to win after first render;
|
|
135
|
+
// `open` is only read once in componentWillLoad otherwise.
|
|
136
|
+
if (newValue === this._isOpen)
|
|
137
|
+
return;
|
|
138
|
+
this.cancelOpen();
|
|
139
|
+
this.cancelClose();
|
|
140
|
+
this.setOpen(newValue);
|
|
141
|
+
}
|
|
117
142
|
disabledChanged(newValue) {
|
|
118
143
|
if (newValue && this._isOpen) {
|
|
119
144
|
this.setOpen(false);
|
|
@@ -123,9 +148,17 @@ export class SekiHoverCard {
|
|
|
123
148
|
* Set the open state and emit change event
|
|
124
149
|
*/
|
|
125
150
|
setOpen(open) {
|
|
126
|
-
if (this.
|
|
151
|
+
if (open && this.disabled) {
|
|
152
|
+
// Keep the reflected prop honest when an open request is refused.
|
|
153
|
+
this.open = false;
|
|
127
154
|
return;
|
|
155
|
+
}
|
|
156
|
+
if (this._isOpen === open) {
|
|
157
|
+
this.open = open;
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
128
160
|
this._isOpen = open;
|
|
161
|
+
this.open = open;
|
|
129
162
|
this.updateContext();
|
|
130
163
|
this.sekiOpenChange.emit({ open });
|
|
131
164
|
if (open) {
|
|
@@ -135,6 +168,22 @@ export class SekiHoverCard {
|
|
|
135
168
|
this.removeScrollListener();
|
|
136
169
|
}
|
|
137
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Open the hover card immediately, skipping `openDelay`
|
|
173
|
+
*/
|
|
174
|
+
async openHoverCard() {
|
|
175
|
+
this.cancelOpen();
|
|
176
|
+
this.cancelClose();
|
|
177
|
+
this.setOpen(true);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Close the hover card immediately, skipping `closeDelay`
|
|
181
|
+
*/
|
|
182
|
+
async closeHoverCard() {
|
|
183
|
+
this.cancelOpen();
|
|
184
|
+
this.cancelClose();
|
|
185
|
+
this.setOpen(false);
|
|
186
|
+
}
|
|
138
187
|
/**
|
|
139
188
|
* Close the hover card immediately and focus the trigger
|
|
140
189
|
*/
|
|
@@ -233,7 +282,7 @@ export class SekiHoverCard {
|
|
|
233
282
|
this.removeScrollListener();
|
|
234
283
|
}
|
|
235
284
|
render() {
|
|
236
|
-
return (h(Host, { key: '
|
|
285
|
+
return (h(Host, { key: '2a5bed9d9abe8647cdbd202d97984a05c8bb9eb1', "data-state": this._isOpen ? 'open' : 'closed' }, h("div", { key: 'c3f1e0be795cea7a59c08d2a341c7a40d8754e04', class: "hover-card" }, h("slot", { key: '0021d9d0ede67170a903db785c6b334ffc5aaba7' }))));
|
|
237
286
|
}
|
|
238
287
|
static get is() { return "seki-hover-card"; }
|
|
239
288
|
static get encapsulation() { return "shadow"; }
|
|
@@ -375,6 +424,52 @@ export class SekiHoverCard {
|
|
|
375
424
|
"reflect": false,
|
|
376
425
|
"attribute": "disabled",
|
|
377
426
|
"defaultValue": "false"
|
|
427
|
+
},
|
|
428
|
+
"open": {
|
|
429
|
+
"type": "boolean",
|
|
430
|
+
"mutable": true,
|
|
431
|
+
"complexType": {
|
|
432
|
+
"original": "boolean",
|
|
433
|
+
"resolved": "boolean",
|
|
434
|
+
"references": {}
|
|
435
|
+
},
|
|
436
|
+
"required": false,
|
|
437
|
+
"optional": false,
|
|
438
|
+
"docs": {
|
|
439
|
+
"tags": [{
|
|
440
|
+
"name": "default",
|
|
441
|
+
"text": "false"
|
|
442
|
+
}],
|
|
443
|
+
"text": "Controlled open state. Reflects to the `open` attribute, so\n`<seki-hover-card open>` renders open with no script involved."
|
|
444
|
+
},
|
|
445
|
+
"getter": false,
|
|
446
|
+
"setter": false,
|
|
447
|
+
"reflect": true,
|
|
448
|
+
"attribute": "open",
|
|
449
|
+
"defaultValue": "false"
|
|
450
|
+
},
|
|
451
|
+
"defaultOpen": {
|
|
452
|
+
"type": "boolean",
|
|
453
|
+
"mutable": false,
|
|
454
|
+
"complexType": {
|
|
455
|
+
"original": "boolean",
|
|
456
|
+
"resolved": "boolean",
|
|
457
|
+
"references": {}
|
|
458
|
+
},
|
|
459
|
+
"required": false,
|
|
460
|
+
"optional": false,
|
|
461
|
+
"docs": {
|
|
462
|
+
"tags": [{
|
|
463
|
+
"name": "default",
|
|
464
|
+
"text": "false"
|
|
465
|
+
}],
|
|
466
|
+
"text": "Initial open state for uncontrolled usage"
|
|
467
|
+
},
|
|
468
|
+
"getter": false,
|
|
469
|
+
"setter": false,
|
|
470
|
+
"reflect": false,
|
|
471
|
+
"attribute": "default-open",
|
|
472
|
+
"defaultValue": "false"
|
|
378
473
|
}
|
|
379
474
|
};
|
|
380
475
|
}
|
|
@@ -401,9 +496,50 @@ export class SekiHoverCard {
|
|
|
401
496
|
}
|
|
402
497
|
}];
|
|
403
498
|
}
|
|
499
|
+
static get methods() {
|
|
500
|
+
return {
|
|
501
|
+
"openHoverCard": {
|
|
502
|
+
"complexType": {
|
|
503
|
+
"signature": "() => Promise<void>",
|
|
504
|
+
"parameters": [],
|
|
505
|
+
"references": {
|
|
506
|
+
"Promise": {
|
|
507
|
+
"location": "global",
|
|
508
|
+
"id": "global::Promise"
|
|
509
|
+
}
|
|
510
|
+
},
|
|
511
|
+
"return": "Promise<void>"
|
|
512
|
+
},
|
|
513
|
+
"docs": {
|
|
514
|
+
"text": "Open the hover card immediately, skipping `openDelay`",
|
|
515
|
+
"tags": []
|
|
516
|
+
}
|
|
517
|
+
},
|
|
518
|
+
"closeHoverCard": {
|
|
519
|
+
"complexType": {
|
|
520
|
+
"signature": "() => Promise<void>",
|
|
521
|
+
"parameters": [],
|
|
522
|
+
"references": {
|
|
523
|
+
"Promise": {
|
|
524
|
+
"location": "global",
|
|
525
|
+
"id": "global::Promise"
|
|
526
|
+
}
|
|
527
|
+
},
|
|
528
|
+
"return": "Promise<void>"
|
|
529
|
+
},
|
|
530
|
+
"docs": {
|
|
531
|
+
"text": "Close the hover card immediately, skipping `closeDelay`",
|
|
532
|
+
"tags": []
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
}
|
|
404
537
|
static get elementRef() { return "el"; }
|
|
405
538
|
static get watchers() {
|
|
406
539
|
return [{
|
|
540
|
+
"propName": "open",
|
|
541
|
+
"methodName": "openChanged"
|
|
542
|
+
}, {
|
|
407
543
|
"propName": "disabled",
|
|
408
544
|
"methodName": "disabledChanged"
|
|
409
545
|
}];
|
|
@@ -816,6 +816,14 @@
|
|
|
816
816
|
min-width: 100%;
|
|
817
817
|
}
|
|
818
818
|
|
|
819
|
+
/* Hides the listbox (and, since it's no longer un-slotted, every option
|
|
820
|
+
inside it) while closed. See the comment on render()'s Host class in
|
|
821
|
+
seki-select-content.tsx for why this replaced a conditional `return null`.
|
|
822
|
+
Mirrors seki-combobox-content.css's identical :host(.hidden) rule. */
|
|
823
|
+
:host(.hidden) {
|
|
824
|
+
display: none;
|
|
825
|
+
}
|
|
826
|
+
|
|
819
827
|
.content-container {
|
|
820
828
|
background: var(--seki-select-content-bg);
|
|
821
829
|
border: var(--seki-select-content-border);
|
|
@@ -52,11 +52,14 @@ export class SekiSelectContent {
|
|
|
52
52
|
/**
|
|
53
53
|
* Accessible name for the listbox.
|
|
54
54
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* string
|
|
59
|
-
*
|
|
55
|
+
* As of #300, seki-select-trigger and this listbox render in the same real
|
|
56
|
+
* DOM tree scope (scoped, non-shadow mode), so an aria-labelledby pointing
|
|
57
|
+
* back at the trigger's combobox would technically resolve now. Kept as a
|
|
58
|
+
* mirrored literal string anyway — simpler and more robust than a live
|
|
59
|
+
* cross-component id reference, and it avoids coupling this component's
|
|
60
|
+
* accessible name to the trigger's specific DOM shape. An aria-labelledby
|
|
61
|
+
* on the <seki-select> host *can* still be resolved here, because the host
|
|
62
|
+
* and its label sit in the same tree (unchanged).
|
|
60
63
|
*/
|
|
61
64
|
getAccessibleName(selectContext) {
|
|
62
65
|
var _a, _b, _c;
|
|
@@ -81,16 +84,22 @@ export class SekiSelectContent {
|
|
|
81
84
|
return null;
|
|
82
85
|
}
|
|
83
86
|
const isOpen = selectContext.open;
|
|
84
|
-
// Lazy rendering - only render when open
|
|
85
|
-
if (!isOpen) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
87
|
const parent = this.el.closest('seki-select');
|
|
89
88
|
const maxHeight = (parent === null || parent === void 0 ? void 0 : parent.maxHeight) || '12.5rem';
|
|
90
|
-
|
|
89
|
+
// Always render, hiding via CSS instead of `return null` when closed (the
|
|
90
|
+
// seki-combobox-content pattern this mirrors). Under shadow DOM this used
|
|
91
|
+
// to conditionally return null and rely on the browser's own behavior of
|
|
92
|
+
// never rendering un-slotted light-DOM children — with no <slot> to
|
|
93
|
+
// assign them to, the options were simply invisible. Scoped (non-shadow)
|
|
94
|
+
// mode has no such mechanism: each seki-select-option still renders its
|
|
95
|
+
// own role="option" div regardless of whether a parent slot exists for
|
|
96
|
+
// it, so returning null here left every option fully visible — and
|
|
97
|
+
// interactable — even while "closed" (#300 e2e regression). See
|
|
98
|
+
// :host(.hidden) in seki-select-content.css.
|
|
99
|
+
return (h(Host, { class: { hidden: !isOpen } }, h("div", { class: "content-container", role: "listbox", id: selectContext.contentId, "aria-label": this.getAccessibleName(selectContext), "aria-multiselectable": selectContext.multiple ? 'true' : undefined }, h("div", { ref: (el) => (this.scrollContainerRef = el), class: "content-scroll", style: { maxHeight } }, h("slot", null)))));
|
|
91
100
|
}
|
|
92
101
|
static get is() { return "seki-select-content"; }
|
|
93
|
-
static get encapsulation() { return "
|
|
102
|
+
static get encapsulation() { return "scoped"; }
|
|
94
103
|
static get originalStyleUrls() {
|
|
95
104
|
return {
|
|
96
105
|
"$": ["seki-select-content.css"]
|
|
@@ -15,10 +15,10 @@ export class SekiSelectGroup {
|
|
|
15
15
|
syncTheme(this.el);
|
|
16
16
|
}
|
|
17
17
|
render() {
|
|
18
|
-
return (h(Host, { key: '
|
|
18
|
+
return (h(Host, { key: 'e1cb8d09575a3851c93f823623cd9331be3e96cc' }, h("div", { key: 'ddb385f0668bb61461f9e5121be9b8394218b629', class: "group", role: "group", "aria-labelledby": this.groupLabelId }, h("div", { key: 'de153ac27303e514ab3f6c85547809523b41584a', class: "group-separator", "aria-hidden": "true" }), h("div", { key: 'f8e67ce663167d38ff6432b704abec5631c5d52c', class: "group-label", id: this.groupLabelId, role: "presentation" }, h("slot", { key: '622315b7efb3aafc12b93f0b0bbf32a22292c95b', name: "label" }, this.label)), h("div", { key: 'beb13a0aeac5543fb9dcde5da98caf81d92a23e2', class: "group-options" }, h("slot", { key: '8919337fddfeb602538eaca3914a1e4bb36c65ee' })))));
|
|
19
19
|
}
|
|
20
20
|
static get is() { return "seki-select-group"; }
|
|
21
|
-
static get encapsulation() { return "
|
|
21
|
+
static get encapsulation() { return "scoped"; }
|
|
22
22
|
static get originalStyleUrls() {
|
|
23
23
|
return {
|
|
24
24
|
"$": ["seki-select-group.css"]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Host, h } from "@stencil/core";
|
|
2
|
+
import { buildOptionId } from "../../utils/select";
|
|
2
3
|
import { syncTheme } from "../../utils/theme-sync";
|
|
3
4
|
import { subscribeToContextChange } from "../../utils/context-bridge";
|
|
4
5
|
/**
|
|
@@ -15,19 +16,20 @@ export class SekiSelectOption {
|
|
|
15
16
|
this.hasRegistered = false;
|
|
16
17
|
this.contextSubscription = { parent: null, unsubscribe: () => { } };
|
|
17
18
|
/**
|
|
18
|
-
* Refresh aria-selected/data-selected/data-focused directly on the
|
|
19
|
-
* DOM whenever the parent's value/focus state changes post-mount.
|
|
20
|
-
* applied imperatively rather than through a Stencil @State bump +
|
|
19
|
+
* Refresh aria-selected/data-selected/data-focused directly on the
|
|
20
|
+
* rendered DOM whenever the parent's value/focus state changes post-mount.
|
|
21
|
+
* This is applied imperatively rather than through a Stencil @State bump +
|
|
22
|
+
* render()
|
|
21
23
|
* — a component that reads a parent's state via closest() + an
|
|
22
24
|
* addEventListener callback and relies on render() re-invoking to reflect
|
|
23
25
|
* it is a confirmed-unreliable shape in this codebase (#244). Mutating the
|
|
24
|
-
*
|
|
26
|
+
* DOM directly here side-steps that entirely.
|
|
25
27
|
*/
|
|
26
28
|
this.handleParentContextChange = () => {
|
|
27
|
-
|
|
28
|
-
const optionEl = (_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.option');
|
|
29
|
+
const optionEl = this.el.querySelector('.option');
|
|
29
30
|
if (!optionEl)
|
|
30
31
|
return;
|
|
32
|
+
optionEl.id = this.optionId;
|
|
31
33
|
const selectContext = this.getSelectContext();
|
|
32
34
|
const isSelected = (selectContext === null || selectContext === void 0 ? void 0 : selectContext.isValueSelected(this.value)) || false;
|
|
33
35
|
const isFocused = (selectContext === null || selectContext === void 0 ? void 0 : selectContext.focusedOptionValue) === this.value;
|
|
@@ -75,15 +77,21 @@ export class SekiSelectOption {
|
|
|
75
77
|
// ===========================
|
|
76
78
|
// State
|
|
77
79
|
// ===========================
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
80
|
+
// Real, page-scoped DOM id as of #300 (scoped, non-shadow rendering) —
|
|
81
|
+
// seki-select-trigger's aria-activedescendant references this directly, so
|
|
82
|
+
// it must stay collision-free across multiple <seki-select> instances on
|
|
83
|
+
// one page. Prefixed with the parent select's own randomized contentId via
|
|
84
|
+
// buildOptionId (shared with seki-select-trigger so both compute the exact
|
|
85
|
+
// same string); falls back to the literal string 'select' if no parent
|
|
86
|
+
// context is available yet (e.g. before componentDidLoad registers it).
|
|
82
87
|
get optionId() {
|
|
83
|
-
|
|
88
|
+
var _a;
|
|
89
|
+
const selectContext = this.getSelectContext();
|
|
90
|
+
return buildOptionId((_a = selectContext === null || selectContext === void 0 ? void 0 : selectContext.contentId) !== null && _a !== void 0 ? _a : 'select', this.value);
|
|
84
91
|
}
|
|
85
92
|
componentDidLoad() {
|
|
86
93
|
this.registerWithParent();
|
|
94
|
+
this.refreshOptionId();
|
|
87
95
|
this.contextSubscription = subscribeToContextChange(this.el, 'seki-select', this.handleParentContextChange);
|
|
88
96
|
}
|
|
89
97
|
connectedCallback() {
|
|
@@ -101,6 +109,17 @@ export class SekiSelectOption {
|
|
|
101
109
|
selectContext === null || selectContext === void 0 ? void 0 : selectContext.unregisterOption(this.value);
|
|
102
110
|
this.contextSubscription.unsubscribe();
|
|
103
111
|
}
|
|
112
|
+
// If render() ran before the parent's selectContext was available (see the
|
|
113
|
+
// 'select' fallback in optionId's getter above), the DOM id was baked in as
|
|
114
|
+
// a non-unique placeholder. componentDidLoad and every later context change
|
|
115
|
+
// both call this to correct it once the real contentId is known — cheap
|
|
116
|
+
// because it's just an attribute write, not a structural re-render.
|
|
117
|
+
refreshOptionId() {
|
|
118
|
+
const optionEl = this.el.querySelector('.option');
|
|
119
|
+
if (optionEl) {
|
|
120
|
+
optionEl.id = this.optionId;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
104
123
|
registerWithParent() {
|
|
105
124
|
var _a;
|
|
106
125
|
const selectContext = this.getSelectContext();
|
|
@@ -126,10 +145,10 @@ export class SekiSelectOption {
|
|
|
126
145
|
const selectContext = this.getSelectContext();
|
|
127
146
|
const isSelected = (selectContext === null || selectContext === void 0 ? void 0 : selectContext.isValueSelected(this.value)) || false;
|
|
128
147
|
const isFocused = (selectContext === null || selectContext === void 0 ? void 0 : selectContext.focusedOptionValue) === this.value;
|
|
129
|
-
return (h(Host, { key: '
|
|
148
|
+
return (h(Host, { key: '5e81a06da7048aeea965ec7a1f3be01c38610b14' }, h("div", { key: '3129f00c2f8be28153ea68d4ad3552d5fe5babf2', class: "option", role: "option", id: this.optionId, onClick: this.handleOptionClick, onFocus: this.handleOptionFocus, onKeyDown: this.handleOptionKeyDown, "aria-selected": isSelected ? 'true' : 'false', "aria-disabled": this.disabled ? 'true' : undefined, "data-selected": isSelected ? 'true' : undefined, "data-focused": isFocused ? 'true' : undefined, "data-disabled": this.disabled ? 'true' : undefined, tabindex: -1 }, h("span", { key: 'fa3daec06f3f25a8339cde8ed9e19778bec0f515', class: "option-label" }, h("slot", { key: 'd778727c4ad82c8b155c6157b2f2c13f7b20bd56' })), h("span", { key: 'a0103ece80cb3a52cf1aa0afaaab801093fa9118', class: "option-indicator", "aria-hidden": "true" }, h("slot", { key: '6d17a76a97fec448881f315bfbd41714604325f5', name: "selected-indicator" }, h("svg", { key: '1b4066f6025db32d6d0e9c4c6e3cc6ee12844631', width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { key: 'c60be1174d75bc7f6f96e87d6f90a1ba4185d43e', d: "M10 3L4.5 8.5L2 6", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" })))))));
|
|
130
149
|
}
|
|
131
150
|
static get is() { return "seki-select-option"; }
|
|
132
|
-
static get encapsulation() { return "
|
|
151
|
+
static get encapsulation() { return "scoped"; }
|
|
133
152
|
static get originalStyleUrls() {
|
|
134
153
|
return {
|
|
135
154
|
"$": ["seki-select-option.css"]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Host, h } from "@stencil/core";
|
|
2
|
+
import { buildOptionId } from "../../utils/select";
|
|
2
3
|
import { syncTheme } from "../../utils/theme-sync";
|
|
3
4
|
import { subscribeToContextChange } from "../../utils/context-bridge";
|
|
4
5
|
/**
|
|
@@ -124,12 +125,14 @@ export class SekiSelectTrigger {
|
|
|
124
125
|
}
|
|
125
126
|
const isOpen = selectContext.open;
|
|
126
127
|
const isDisabled = selectContext.disabled;
|
|
127
|
-
return (h(Host, null, h("button", { ref: (el) => (this.buttonRef = el), type: "button", class: "trigger-button", role: "combobox", "aria-expanded": isOpen ? 'true' : 'false', "aria-controls": selectContext.contentId, "aria-
|
|
128
|
+
return (h(Host, null, h("button", { ref: (el) => (this.buttonRef = el), type: "button", class: "trigger-button", role: "combobox", "aria-expanded": isOpen ? 'true' : 'false', "aria-controls": selectContext.contentId, "aria-activedescendant": selectContext.focusedOptionValue !== null
|
|
129
|
+
? buildOptionId(selectContext.contentId, selectContext.focusedOptionValue)
|
|
130
|
+
: undefined, "aria-label": selectContext.ariaLabel, "aria-labelledby": selectContext.ariaLabelledby, "aria-disabled": isDisabled ? 'true' : undefined, disabled: isDisabled, "data-disabled": isDisabled ? 'true' : undefined, "data-state": isOpen ? 'open' : 'closed' }, selectContext.multiple
|
|
128
131
|
? this.renderMultiValue(selectContext)
|
|
129
132
|
: this.renderSingleValue(selectContext), h("svg", { class: "trigger-chevron", width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true" }, h("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" })))));
|
|
130
133
|
}
|
|
131
134
|
static get is() { return "seki-select-trigger"; }
|
|
132
|
-
static get encapsulation() { return "
|
|
135
|
+
static get encapsulation() { return "scoped"; }
|
|
133
136
|
static get originalStyleUrls() {
|
|
134
137
|
return {
|
|
135
138
|
"$": ["seki-select-trigger.css"]
|