vira 31.9.5 → 31.10.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/elements/index.d.ts +1 -0
- package/dist/elements/index.js +1 -0
- package/dist/elements/vira-drawer.element.d.ts +23 -0
- package/dist/elements/vira-drawer.element.js +295 -0
- package/dist/elements/vira-select.element.d.ts +2 -2
- package/dist/elements/vira-select.element.js +31 -12
- package/dist/elements/vira-tag.element.js +9 -9
- package/dist/util/vira-select-option.d.ts +16 -0
- package/dist/util/vira-select-option.js +8 -1
- package/package.json +1 -1
package/dist/elements/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from './vira-card.element.js';
|
|
|
8
8
|
export * from './vira-checkbox.element.js';
|
|
9
9
|
export * from './vira-collapsible-card.element.js';
|
|
10
10
|
export * from './vira-collapsible-wrapper.element.js';
|
|
11
|
+
export * from './vira-drawer.element.js';
|
|
11
12
|
export * from './vira-dropdown.element.js';
|
|
12
13
|
export * from './vira-error.element.js';
|
|
13
14
|
export * from './vira-form.element.js';
|
package/dist/elements/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export * from './vira-card.element.js';
|
|
|
8
8
|
export * from './vira-checkbox.element.js';
|
|
9
9
|
export * from './vira-collapsible-card.element.js';
|
|
10
10
|
export * from './vira-collapsible-wrapper.element.js';
|
|
11
|
+
export * from './vira-drawer.element.js';
|
|
11
12
|
export * from './vira-dropdown.element.js';
|
|
12
13
|
export * from './vira-error.element.js';
|
|
13
14
|
export * from './vira-form.element.js';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type PartialWithUndefined } from '@augment-vir/common';
|
|
2
|
+
/**
|
|
3
|
+
* A drawer element that slides up from the bottom of the page using the built-in `dialog` element.
|
|
4
|
+
*
|
|
5
|
+
* @category Elements
|
|
6
|
+
*/
|
|
7
|
+
export declare const ViraDrawer: import("element-vir").DeclarativeElementDefinition<"vira-drawer", {
|
|
8
|
+
open: boolean;
|
|
9
|
+
} & PartialWithUndefined<{
|
|
10
|
+
/** If this isn't set, make sure to use the drawer title slot to fill it in. */
|
|
11
|
+
drawerTitle: string;
|
|
12
|
+
}>, {
|
|
13
|
+
dialogElement: HTMLDialogElement | undefined;
|
|
14
|
+
contentElement: HTMLDivElement | undefined;
|
|
15
|
+
previousOpenValue: undefined | boolean;
|
|
16
|
+
/** Cleans up all listeners that have been attached. */
|
|
17
|
+
cleanupListeners: undefined | (() => void);
|
|
18
|
+
isDragging: boolean;
|
|
19
|
+
dragStartY: number;
|
|
20
|
+
dragCurrentY: number;
|
|
21
|
+
}, {
|
|
22
|
+
drawerClose: import("element-vir").DefineEvent<void>;
|
|
23
|
+
}, "vira-drawer-dragging", "vira-drawer-backdrop-filter" | "vira-drawer-max-height", readonly ["drawerTitle"], readonly []>;
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { assertWrap } from '@augment-vir/assert';
|
|
2
|
+
import { colorCss } from '@electrovir/color';
|
|
3
|
+
import { css, defineElementEvent, html, listen, nothing, onDomCreated } from 'element-vir';
|
|
4
|
+
import { themeDefaultKey } from 'theme-vir';
|
|
5
|
+
import { listenToGlobal } from 'typed-event-target';
|
|
6
|
+
import { X24Icon } from '../icons/icon-svgs/24/x-24.icon.js';
|
|
7
|
+
import { viraAnimationDurations } from '../styles/durations.js';
|
|
8
|
+
import { viraFormCssVars } from '../styles/form-styles.js';
|
|
9
|
+
import { noNativeFormStyles, noNativeSpacing } from '../styles/native-styles.js';
|
|
10
|
+
import { viraShadows } from '../styles/shadows.js';
|
|
11
|
+
import { noUserSelect } from '../styles/user-select.js';
|
|
12
|
+
import { viraTheme } from '../styles/vira-color-theme.js';
|
|
13
|
+
import { defineViraElement } from '../util/define-vira-element.js';
|
|
14
|
+
import { ViraIcon } from './vira-icon.element.js';
|
|
15
|
+
const globalEventsToCloseDrawerOn = [
|
|
16
|
+
'pagehide',
|
|
17
|
+
'pageshow',
|
|
18
|
+
'popstate',
|
|
19
|
+
];
|
|
20
|
+
/** Minimum downward drag distance (in pixels) required to close the drawer. */
|
|
21
|
+
const dragCloseThreshold = 30;
|
|
22
|
+
/**
|
|
23
|
+
* A drawer element that slides up from the bottom of the page using the built-in `dialog` element.
|
|
24
|
+
*
|
|
25
|
+
* @category Elements
|
|
26
|
+
*/
|
|
27
|
+
export const ViraDrawer = defineViraElement()({
|
|
28
|
+
tagName: 'vira-drawer',
|
|
29
|
+
events: {
|
|
30
|
+
drawerClose: defineElementEvent(),
|
|
31
|
+
},
|
|
32
|
+
state() {
|
|
33
|
+
return {
|
|
34
|
+
dialogElement: undefined,
|
|
35
|
+
contentElement: undefined,
|
|
36
|
+
previousOpenValue: undefined,
|
|
37
|
+
/** Cleans up all listeners that have been attached. */
|
|
38
|
+
cleanupListeners: undefined,
|
|
39
|
+
isDragging: false,
|
|
40
|
+
dragStartY: 0,
|
|
41
|
+
dragCurrentY: 0,
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
cleanup({ state }) {
|
|
45
|
+
state.cleanupListeners?.();
|
|
46
|
+
},
|
|
47
|
+
hostClasses: {
|
|
48
|
+
'vira-drawer-dragging': ({ state }) => state.isDragging,
|
|
49
|
+
},
|
|
50
|
+
slotNames: ['drawerTitle'],
|
|
51
|
+
cssVars: {
|
|
52
|
+
'vira-drawer-backdrop-filter': 'blur(3px)',
|
|
53
|
+
'vira-drawer-max-height': '80dvh',
|
|
54
|
+
},
|
|
55
|
+
styles: ({ cssVars, hostClasses }) => css `
|
|
56
|
+
:host {
|
|
57
|
+
display: contents;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
${hostClasses['vira-drawer-dragging'].selector} {
|
|
61
|
+
${noUserSelect};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
h1 {
|
|
65
|
+
${noNativeSpacing};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
dialog {
|
|
69
|
+
${colorCss(viraTheme.colors[themeDefaultKey])}
|
|
70
|
+
border: none;
|
|
71
|
+
padding: 0;
|
|
72
|
+
overflow: hidden;
|
|
73
|
+
position: fixed;
|
|
74
|
+
inset: auto 0 0 0;
|
|
75
|
+
margin: 0;
|
|
76
|
+
width: 100%;
|
|
77
|
+
max-width: 100%;
|
|
78
|
+
max-height: ${cssVars['vira-drawer-max-height'].value};
|
|
79
|
+
border-radius: 16px 16px 0 0;
|
|
80
|
+
${viraShadows.modal}
|
|
81
|
+
transition: transform ${viraAnimationDurations['vira-pretty-animation-duration']
|
|
82
|
+
.value} ease;
|
|
83
|
+
|
|
84
|
+
&[open] {
|
|
85
|
+
display: flex;
|
|
86
|
+
flex-direction: column;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
&::backdrop {
|
|
90
|
+
background: ${viraFormCssVars['vira-form-modal-backdrop-color'].value};
|
|
91
|
+
backdrop-filter: ${cssVars['vira-drawer-backdrop-filter'].value};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
& .drawer-content-wrapper {
|
|
95
|
+
overflow: hidden;
|
|
96
|
+
display: flex;
|
|
97
|
+
flex-direction: column;
|
|
98
|
+
|
|
99
|
+
& .drag-handle-wrapper {
|
|
100
|
+
display: flex;
|
|
101
|
+
justify-content: center;
|
|
102
|
+
padding: 8px 0 0;
|
|
103
|
+
cursor: grab;
|
|
104
|
+
touch-action: none;
|
|
105
|
+
|
|
106
|
+
&:active {
|
|
107
|
+
cursor: grabbing;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
& .drag-handle {
|
|
111
|
+
width: 36px;
|
|
112
|
+
height: 4px;
|
|
113
|
+
border-radius: 2px;
|
|
114
|
+
background-color: ${viraFormCssVars['vira-form-secondary-body-foreground']
|
|
115
|
+
.value};
|
|
116
|
+
opacity: 0.5;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
& .header {
|
|
121
|
+
padding: 8px 24px 16px;
|
|
122
|
+
display: flex;
|
|
123
|
+
gap: 16px;
|
|
124
|
+
align-items: flex-start;
|
|
125
|
+
|
|
126
|
+
& .header-text-wrapper {
|
|
127
|
+
display: flex;
|
|
128
|
+
flex-direction: column;
|
|
129
|
+
gap: 4px;
|
|
130
|
+
align-self: center;
|
|
131
|
+
flex-grow: 1;
|
|
132
|
+
|
|
133
|
+
& h1 {
|
|
134
|
+
font-size: 20px;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
& button.close {
|
|
139
|
+
${noNativeFormStyles};
|
|
140
|
+
cursor: pointer;
|
|
141
|
+
padding: 4px;
|
|
142
|
+
border-radius: ${viraFormCssVars['vira-form-radius'].value};
|
|
143
|
+
|
|
144
|
+
&:hover {
|
|
145
|
+
background-color: ${viraFormCssVars['vira-form-selection-hover-color']
|
|
146
|
+
.value};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
& ${ViraIcon} {
|
|
150
|
+
display: flex;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
& .body {
|
|
156
|
+
padding: 0 24px 24px;
|
|
157
|
+
overflow: auto;
|
|
158
|
+
overscroll-behavior: contain;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
`,
|
|
163
|
+
render({ inputs, state, updateState, events, dispatch, slotNames }) {
|
|
164
|
+
if (state.dialogElement && inputs.open !== state.dialogElement.open) {
|
|
165
|
+
if (inputs.open) {
|
|
166
|
+
state.dialogElement.showModal();
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
state.dialogElement.close();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (state.previousOpenValue !== inputs.open) {
|
|
173
|
+
state.cleanupListeners?.();
|
|
174
|
+
updateState({
|
|
175
|
+
previousOpenValue: inputs.open,
|
|
176
|
+
});
|
|
177
|
+
if (inputs.open) {
|
|
178
|
+
const removers = globalEventsToCloseDrawerOn.map((eventName) => listenToGlobal(eventName, () => {
|
|
179
|
+
dispatch(new events.drawerClose());
|
|
180
|
+
}));
|
|
181
|
+
updateState({
|
|
182
|
+
cleanupListeners: () => {
|
|
183
|
+
removers.forEach((remover) => remover());
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function close() {
|
|
189
|
+
if (inputs.open) {
|
|
190
|
+
state.cleanupListeners?.();
|
|
191
|
+
dispatch(new events.drawerClose());
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (state.dialogElement) {
|
|
195
|
+
if (state.isDragging) {
|
|
196
|
+
const dragOffset = Math.max(0, state.dragCurrentY - state.dragStartY);
|
|
197
|
+
state.dialogElement.style.transform = `translateY(${String(dragOffset)}px)`;
|
|
198
|
+
state.dialogElement.style.transition = 'none';
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
state.dialogElement.style.transform = '';
|
|
202
|
+
state.dialogElement.style.transition = '';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return html `
|
|
206
|
+
<dialog
|
|
207
|
+
${onDomCreated((element) => {
|
|
208
|
+
updateState({
|
|
209
|
+
dialogElement: assertWrap.instanceOf(element, HTMLDialogElement),
|
|
210
|
+
});
|
|
211
|
+
})}
|
|
212
|
+
${listen('close', () => {
|
|
213
|
+
close();
|
|
214
|
+
})}
|
|
215
|
+
${listen('mousedown', (event) => {
|
|
216
|
+
if (state.contentElement &&
|
|
217
|
+
!event.composedPath().includes(state.contentElement)) {
|
|
218
|
+
close();
|
|
219
|
+
}
|
|
220
|
+
})}
|
|
221
|
+
>
|
|
222
|
+
<div
|
|
223
|
+
class="drawer-content-wrapper"
|
|
224
|
+
${onDomCreated((element) => {
|
|
225
|
+
updateState({
|
|
226
|
+
contentElement: assertWrap.instanceOf(element, HTMLDivElement),
|
|
227
|
+
});
|
|
228
|
+
})}
|
|
229
|
+
>
|
|
230
|
+
<div
|
|
231
|
+
class="drag-handle-wrapper"
|
|
232
|
+
${listen('dblclick', () => {
|
|
233
|
+
close();
|
|
234
|
+
})}
|
|
235
|
+
${listen('pointerdown', (event) => {
|
|
236
|
+
updateState({
|
|
237
|
+
isDragging: true,
|
|
238
|
+
dragStartY: event.clientY,
|
|
239
|
+
dragCurrentY: event.clientY,
|
|
240
|
+
});
|
|
241
|
+
function handlePointerMove(moveEvent) {
|
|
242
|
+
updateState({
|
|
243
|
+
dragCurrentY: moveEvent.clientY,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function handlePointerUp(upEvent) {
|
|
247
|
+
const dragDistance = upEvent.clientY - state.dragStartY;
|
|
248
|
+
updateState({
|
|
249
|
+
isDragging: false,
|
|
250
|
+
dragStartY: 0,
|
|
251
|
+
dragCurrentY: 0,
|
|
252
|
+
});
|
|
253
|
+
if (dragDistance > dragCloseThreshold) {
|
|
254
|
+
close();
|
|
255
|
+
}
|
|
256
|
+
listenerRemovers.forEach((remover) => remover());
|
|
257
|
+
}
|
|
258
|
+
const listenerRemovers = [
|
|
259
|
+
listenToGlobal('pointermove', handlePointerMove),
|
|
260
|
+
listenToGlobal('pointerup', handlePointerUp),
|
|
261
|
+
];
|
|
262
|
+
})}
|
|
263
|
+
>
|
|
264
|
+
<div class="drag-handle"></div>
|
|
265
|
+
</div>
|
|
266
|
+
<div class="header">
|
|
267
|
+
<div class="header-text-wrapper">
|
|
268
|
+
<h1>
|
|
269
|
+
<slot name=${slotNames.drawerTitle}>${inputs.drawerTitle}</slot>
|
|
270
|
+
</h1>
|
|
271
|
+
</div>
|
|
272
|
+
<button
|
|
273
|
+
class="close"
|
|
274
|
+
aria-label="Close"
|
|
275
|
+
${listen('click', () => {
|
|
276
|
+
state.dialogElement?.close();
|
|
277
|
+
})}
|
|
278
|
+
>
|
|
279
|
+
<${ViraIcon.assign({
|
|
280
|
+
icon: X24Icon,
|
|
281
|
+
})}></${ViraIcon}>
|
|
282
|
+
</button>
|
|
283
|
+
</div>
|
|
284
|
+
${inputs.open
|
|
285
|
+
? html `
|
|
286
|
+
<div class="body">
|
|
287
|
+
<slot></slot>
|
|
288
|
+
</div>
|
|
289
|
+
`
|
|
290
|
+
: nothing}
|
|
291
|
+
</div>
|
|
292
|
+
</dialog>
|
|
293
|
+
`;
|
|
294
|
+
},
|
|
295
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type PartialWithUndefined } from '@augment-vir/common';
|
|
2
2
|
import { type AttributeValues } from 'element-vir';
|
|
3
3
|
import { type ViraIconSvg } from '../icons/index.js';
|
|
4
|
-
import { type ViraSelectOption } from '../util/vira-select-option.js';
|
|
4
|
+
import { type ViraSelectOption, type ViraSelectOptionGroup } from '../util/vira-select-option.js';
|
|
5
5
|
/**
|
|
6
6
|
* Similar to {@link ViraDropdown} but is, instead, simply a wrapper for `<select>` and nothing more.
|
|
7
7
|
*
|
|
@@ -10,7 +10,7 @@ import { type ViraSelectOption } from '../util/vira-select-option.js';
|
|
|
10
10
|
* @see https://electrovir.github.io/vira/book/elements/vira-select
|
|
11
11
|
*/
|
|
12
12
|
export declare const ViraSelect: import("element-vir").DeclarativeElementDefinition<"vira-select", {
|
|
13
|
-
options: ReadonlyArray<Readonly<ViraSelectOption>>;
|
|
13
|
+
options: ReadonlyArray<Readonly<ViraSelectOption> | Readonly<ViraSelectOptionGroup>>;
|
|
14
14
|
/** The currently selected option value. */
|
|
15
15
|
value: undefined | string;
|
|
16
16
|
} & PartialWithUndefined<{
|
|
@@ -10,7 +10,20 @@ import { viraFormCssVars } from '../styles/form-styles.js';
|
|
|
10
10
|
import { viraAnimationDurations } from '../styles/index.js';
|
|
11
11
|
import { noNativeFormStyles } from '../styles/native-styles.js';
|
|
12
12
|
import { defineViraElement } from '../util/define-vira-element.js';
|
|
13
|
+
import { isViraSelectOptionGroup, } from '../util/vira-select-option.js';
|
|
13
14
|
import { ViraIcon } from './vira-icon.element.js';
|
|
15
|
+
function renderSelectOption(option, value) {
|
|
16
|
+
return html `
|
|
17
|
+
<option
|
|
18
|
+
?selected=${option.value === value}
|
|
19
|
+
aria-label=${option.label}
|
|
20
|
+
?disabled=${option.disabled}
|
|
21
|
+
value=${option.value}
|
|
22
|
+
>
|
|
23
|
+
${option.label}
|
|
24
|
+
</option>
|
|
25
|
+
`;
|
|
26
|
+
}
|
|
14
27
|
/**
|
|
15
28
|
* Similar to {@link ViraDropdown} but is, instead, simply a wrapper for `<select>` and nothing more.
|
|
16
29
|
*
|
|
@@ -262,24 +275,30 @@ export const ViraSelect = defineViraElement()({
|
|
|
262
275
|
const selectElement = extractEventTarget(event, HTMLSelectElement);
|
|
263
276
|
const newValue = selectElement.value;
|
|
264
277
|
if (selectElement.value !== value) {
|
|
265
|
-
selectElement.selectedIndex = inputs.options
|
|
278
|
+
selectElement.selectedIndex = inputs.options
|
|
279
|
+
.flatMap((entry) => {
|
|
280
|
+
return isViraSelectOptionGroup(entry)
|
|
281
|
+
? [...entry.options]
|
|
282
|
+
: [entry];
|
|
283
|
+
})
|
|
284
|
+
.findIndex((option) => option.value === value);
|
|
266
285
|
}
|
|
267
286
|
dispatch(new events.valueChange(newValue));
|
|
268
287
|
})}
|
|
269
288
|
${attributes(inputs.attributePassthrough?.select)}
|
|
270
289
|
>
|
|
271
290
|
${placeholderOptionTemplate}
|
|
272
|
-
${inputs.options.map((
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
291
|
+
${inputs.options.map((entry) => {
|
|
292
|
+
if (isViraSelectOptionGroup(entry)) {
|
|
293
|
+
return html `
|
|
294
|
+
<optgroup label=${entry.groupName}>
|
|
295
|
+
${entry.options.map((option) => {
|
|
296
|
+
return renderSelectOption(option, value);
|
|
297
|
+
})}
|
|
298
|
+
</optgroup>
|
|
299
|
+
`;
|
|
300
|
+
}
|
|
301
|
+
return renderSelectOption(entry, value);
|
|
283
302
|
})}
|
|
284
303
|
</select>
|
|
285
304
|
<!--
|
|
@@ -79,19 +79,19 @@ const tagColorVariantColors = {
|
|
|
79
79
|
[ViraColorVariant.Plain]: {
|
|
80
80
|
[ViraEmphasis.Standard]: {
|
|
81
81
|
idle: {
|
|
82
|
-
backgroundColor: viraTheme.
|
|
83
|
-
textColor: viraTheme.
|
|
84
|
-
borderColor: viraTheme.
|
|
82
|
+
backgroundColor: viraTheme.colors[themeDefaultKey].foreground,
|
|
83
|
+
textColor: viraTheme.colors[themeDefaultKey].background,
|
|
84
|
+
borderColor: viraTheme.colors[themeDefaultKey].foreground,
|
|
85
85
|
},
|
|
86
86
|
hover: {
|
|
87
|
-
backgroundColor: viraTheme.colors['vira-grey-behind-bg-
|
|
88
|
-
textColor: viraTheme.colors['vira-grey-behind-bg-
|
|
89
|
-
borderColor: viraTheme.colors['vira-grey-behind-bg-
|
|
87
|
+
backgroundColor: viraTheme.colors['vira-grey-behind-bg-body'].background,
|
|
88
|
+
textColor: viraTheme.colors['vira-grey-behind-bg-body'].foreground,
|
|
89
|
+
borderColor: viraTheme.colors['vira-grey-behind-bg-body'].background,
|
|
90
90
|
},
|
|
91
91
|
active: {
|
|
92
|
-
backgroundColor: viraTheme.
|
|
93
|
-
textColor: viraTheme.
|
|
94
|
-
borderColor: viraTheme.
|
|
92
|
+
backgroundColor: viraTheme.colors[themeDefaultKey].foreground,
|
|
93
|
+
textColor: viraTheme.colors[themeDefaultKey].background,
|
|
94
|
+
borderColor: viraTheme.colors[themeDefaultKey].foreground,
|
|
95
95
|
},
|
|
96
96
|
},
|
|
97
97
|
[ViraEmphasis.Subtle]: {
|
|
@@ -13,3 +13,19 @@ export type ViraSelectOption = {
|
|
|
13
13
|
} & PartialWithUndefined<{
|
|
14
14
|
disabled: boolean;
|
|
15
15
|
}>;
|
|
16
|
+
/**
|
|
17
|
+
* A group of options for `ViraSelect`, rendered as an `<optgroup>`.
|
|
18
|
+
*
|
|
19
|
+
* @category Dropdown
|
|
20
|
+
* @category Elements
|
|
21
|
+
*/
|
|
22
|
+
export type ViraSelectOptionGroup = {
|
|
23
|
+
groupName: string;
|
|
24
|
+
options: ReadonlyArray<Readonly<ViraSelectOption>>;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Type guard to determine if a `ViraSelect` options entry is a group.
|
|
28
|
+
*
|
|
29
|
+
* @category Internal
|
|
30
|
+
*/
|
|
31
|
+
export declare function isViraSelectOptionGroup(entry: Readonly<ViraSelectOption> | Readonly<ViraSelectOptionGroup>): entry is Readonly<ViraSelectOptionGroup>;
|