@destyler/combobox 0.0.1-beta.20

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.
@@ -0,0 +1,1152 @@
1
+ 'use strict';
2
+
3
+ const vue = require('vue');
4
+ const primitive = require('@destyler/primitive');
5
+ const composition = require('@destyler/composition');
6
+ const popper = require('@destyler/popper');
7
+ const shared = require('@destyler/shared');
8
+ const isEqual = require('fast-deep-equal');
9
+ const collection = require('@destyler/collection');
10
+ const component = require('@destyler/visually-hidden/dist/component');
11
+ const dismissableLayer = require('@destyler/dismissable-layer');
12
+ const directives = require('@destyler/directives');
13
+ const presence = require('@destyler/presence');
14
+ const teleport = require('@destyler/teleport');
15
+
16
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
17
+
18
+ const isEqual__default = /*#__PURE__*/_interopDefaultCompat(isEqual);
19
+
20
+ const destylerComboboxAnchorProps = {
21
+ as: {
22
+ type: [String, Object],
23
+ required: false,
24
+ default: "div"
25
+ },
26
+ asChild: {
27
+ type: Boolean,
28
+ required: false,
29
+ default: false
30
+ }
31
+ };
32
+ const DestylerComboboxAnchor = vue.defineComponent({
33
+ name: "DestylerComboboxAnchor",
34
+ props: destylerComboboxAnchorProps,
35
+ setup() {
36
+ const { forwardRef } = composition.useForwardExpose();
37
+ return {
38
+ forwardRef
39
+ };
40
+ },
41
+ render() {
42
+ return vue.h(popper.DestylerPopperAnchor, {
43
+ asChild: true
44
+ }, {
45
+ default: () => {
46
+ return vue.h(primitive.DestylerPrimitive, vue.mergeProps(this.$attrs, {
47
+ ref: (el) => this.forwardRef(el),
48
+ as: this.$props.as,
49
+ asChild: this.$props.asChild
50
+ }), {
51
+ default: () => this.$slots.default?.()
52
+ });
53
+ }
54
+ });
55
+ }
56
+ });
57
+
58
+ const destylerComboboxRootProps = {
59
+ as: {
60
+ type: [String, Object],
61
+ required: false,
62
+ default: "div"
63
+ },
64
+ asChild: {
65
+ type: Boolean,
66
+ required: false,
67
+ default: false
68
+ },
69
+ modelValue: {
70
+ type: [String, Number, Boolean, Object],
71
+ required: false
72
+ },
73
+ defaultValue: {
74
+ type: [String, Number, Boolean, Object],
75
+ required: false
76
+ },
77
+ open: {
78
+ type: Boolean,
79
+ required: false,
80
+ default: void 0
81
+ },
82
+ defaultOpen: {
83
+ type: Boolean,
84
+ required: false
85
+ },
86
+ searchTerm: {
87
+ type: String,
88
+ required: false
89
+ },
90
+ multiple: {
91
+ type: Boolean,
92
+ required: false
93
+ },
94
+ disabled: {
95
+ type: Boolean,
96
+ required: false
97
+ },
98
+ name: {
99
+ type: String,
100
+ required: false
101
+ },
102
+ dir: {
103
+ type: String,
104
+ required: false
105
+ },
106
+ filterFunction: {
107
+ type: Function,
108
+ required: false
109
+ },
110
+ displayValue: {
111
+ type: Function,
112
+ required: false
113
+ }
114
+ };
115
+ const [injectComboboxRootContext, provideComboboxRootContext] = shared.createContext("DestylerComboboxRoot");
116
+ const DestylerComboboxRoot = vue.defineComponent({
117
+ name: "DestylerComboboxRoot",
118
+ props: destylerComboboxRootProps,
119
+ emits: ["update:modelValue", "update:open", "update:searchTerm"],
120
+ setup(props, { emit }) {
121
+ const { multiple, disabled, dir: propDir } = vue.toRefs(props);
122
+ const dir = composition.useDirection(propDir);
123
+ const searchTerm = composition.useVModel(props, "searchTerm", emit, {
124
+ defaultValue: "",
125
+ passive: props.searchTerm === void 0
126
+ });
127
+ const modelValue = composition.useVModel(props, "modelValue", emit, {
128
+ defaultValue: props.defaultValue ?? multiple.value ? [] : void 0,
129
+ passive: props.modelValue === void 0,
130
+ deep: true
131
+ });
132
+ const open = composition.useVModel(props, "open", emit, {
133
+ defaultValue: props.defaultOpen,
134
+ passive: props.open === void 0
135
+ });
136
+ const selectedValue = vue.ref();
137
+ const isUserInputted = vue.ref(false);
138
+ const inputElement = vue.ref();
139
+ const contentElement = vue.ref();
140
+ const { forwardRef, currentElement: parentElement } = composition.useForwardExpose();
141
+ const { getItems, reactiveItems, itemMapSize } = collection.createCollection("data-destyler-combobox-item");
142
+ async function onOpenChange(val) {
143
+ open.value = val;
144
+ await vue.nextTick();
145
+ if (val) {
146
+ if (modelValue.value) {
147
+ if (Array.isArray(modelValue.value) && multiple.value)
148
+ selectedValue.value = getItems().find((i) => i.ref?.dataset?.state === "checked")?.value;
149
+ else
150
+ selectedValue.value = modelValue.value;
151
+ }
152
+ inputElement.value?.focus();
153
+ scrollSelectedValueIntoView();
154
+ } else {
155
+ isUserInputted.value = false;
156
+ resetSearchTerm();
157
+ }
158
+ }
159
+ function onValueChange(val) {
160
+ if (Array.isArray(modelValue.value) && multiple.value) {
161
+ const index = modelValue.value.findIndex((i) => isEqual__default(i, val));
162
+ index === -1 ? modelValue.value.push(val) : modelValue.value.splice(index, 1);
163
+ } else {
164
+ modelValue.value = val;
165
+ onOpenChange(false);
166
+ }
167
+ }
168
+ const options = shared.computedWithControl(() => itemMapSize.value, () => {
169
+ return getItems().map((i) => i.value);
170
+ });
171
+ const filteredOptions = vue.computed(() => {
172
+ if (isUserInputted.value) {
173
+ if (props.filterFunction)
174
+ return props.filterFunction(options.value, searchTerm.value);
175
+ else if (typeof options.value[0] === "string")
176
+ return options.value.filter((i) => i.toLowerCase().includes(searchTerm.value?.toLowerCase()));
177
+ }
178
+ return options.value;
179
+ });
180
+ function resetSearchTerm() {
181
+ if (!multiple.value && modelValue.value) {
182
+ if (props.displayValue)
183
+ searchTerm.value = props.displayValue(modelValue.value);
184
+ else if (typeof modelValue.value !== "object")
185
+ searchTerm.value = modelValue.value.toString();
186
+ else
187
+ searchTerm.value = "";
188
+ } else {
189
+ searchTerm.value = "";
190
+ }
191
+ }
192
+ const activeIndex = vue.computed(() => filteredOptions.value.findIndex((i) => isEqual__default(i, selectedValue.value)));
193
+ const selectedElement = vue.computed(() => {
194
+ return reactiveItems.value.find((i) => i.value === selectedValue.value)?.ref;
195
+ });
196
+ vue.watch(modelValue, async () => {
197
+ await vue.nextTick();
198
+ resetSearchTerm();
199
+ }, { immediate: true });
200
+ vue.watch(() => filteredOptions.value.length, async (length) => {
201
+ await vue.nextTick();
202
+ await vue.nextTick();
203
+ if (length && activeIndex.value === -1)
204
+ selectedValue.value = filteredOptions.value[0];
205
+ });
206
+ const isFormControl = composition.useFormControl(parentElement);
207
+ function scrollSelectedValueIntoView() {
208
+ if (selectedElement.value instanceof Element)
209
+ selectedElement.value.scrollIntoView({ block: "nearest" });
210
+ }
211
+ provideComboboxRootContext({
212
+ searchTerm,
213
+ modelValue,
214
+ onValueChange,
215
+ isUserInputted,
216
+ multiple,
217
+ disabled,
218
+ open,
219
+ onOpenChange,
220
+ filteredOptions,
221
+ contentId: composition.useId(),
222
+ inputElement,
223
+ onInputElementChange: (val) => inputElement.value = val,
224
+ onInputNavigation: async (val) => {
225
+ const index = activeIndex.value;
226
+ if (index === 0 && val === "up" || index === filteredOptions.value.length - 1 && val === "down")
227
+ return;
228
+ if (index === -1 && filteredOptions.value.length || val === "home")
229
+ selectedValue.value = filteredOptions.value[0];
230
+ else if (val === "end")
231
+ selectedValue.value = filteredOptions.value[filteredOptions.value.length - 1];
232
+ else
233
+ selectedValue.value = filteredOptions.value[val === "up" ? index - 1 : index + 1];
234
+ scrollSelectedValueIntoView();
235
+ },
236
+ onInputEnter: async () => {
237
+ if (filteredOptions.value.length && selectedValue.value && selectedElement.value instanceof Element)
238
+ selectedElement.value?.click();
239
+ },
240
+ selectedValue,
241
+ onSelectedValueChange: (val) => selectedValue.value = val,
242
+ parentElement,
243
+ contentElement,
244
+ onContentElementChange: (val) => contentElement.value = val
245
+ });
246
+ return {
247
+ forwardRef,
248
+ isFormControl,
249
+ open,
250
+ modelValue,
251
+ dir
252
+ };
253
+ },
254
+ render() {
255
+ return vue.h(popper.DestylerPopperRoot, {}, {
256
+ default: () => {
257
+ return vue.h(primitive.DestylerPrimitive, vue.mergeProps(this.$attrs, {
258
+ ref: (el) => this.forwardRef(el),
259
+ style: {
260
+ pointerEvents: this.open ? "auto" : void 0
261
+ },
262
+ as: this.$props.as,
263
+ asChild: this.$props.asChild,
264
+ dir: this.dir
265
+ }), {
266
+ default: () => {
267
+ return [
268
+ this.$slots.default?.({ open: this.open, modelValue: this.modelValue }),
269
+ this.isFormControl && this.$props.name ? vue.h(component.DestylerVisuallyhiddenInput, {
270
+ name: this.$props.name,
271
+ value: this.modelValue
272
+ }) : null
273
+ ];
274
+ }
275
+ });
276
+ }
277
+ });
278
+ }
279
+ });
280
+
281
+ const destylerComboboxContentImplProps = {
282
+ as: {
283
+ type: [String, Object],
284
+ required: false,
285
+ default: "div"
286
+ },
287
+ asChild: {
288
+ type: Boolean,
289
+ required: false,
290
+ default: false
291
+ },
292
+ side: {
293
+ type: String,
294
+ required: false,
295
+ default: "bottom"
296
+ },
297
+ sideOffset: {
298
+ type: Number,
299
+ required: false,
300
+ default: 0
301
+ },
302
+ align: {
303
+ type: String,
304
+ required: false,
305
+ default: "center"
306
+ },
307
+ alignOffset: {
308
+ type: Number,
309
+ required: false,
310
+ default: 0
311
+ },
312
+ avoidCollisions: {
313
+ type: Boolean,
314
+ required: false,
315
+ default: true
316
+ },
317
+ collisionBoundary: {
318
+ type: [Object, Array, null],
319
+ required: false,
320
+ default: () => []
321
+ },
322
+ collisionPadding: {
323
+ type: [Number, Object],
324
+ required: false,
325
+ default: 0
326
+ },
327
+ arrowPadding: {
328
+ type: Number,
329
+ required: false,
330
+ default: 0
331
+ },
332
+ sticky: {
333
+ type: String,
334
+ required: false,
335
+ default: "partial"
336
+ },
337
+ hideWhenDetached: {
338
+ type: Boolean,
339
+ required: false,
340
+ default: false
341
+ },
342
+ updatePositionStrategy: {
343
+ type: String,
344
+ required: false,
345
+ default: "optimized"
346
+ },
347
+ onPlaced: {
348
+ type: Function,
349
+ required: false
350
+ },
351
+ prioritizePosition: {
352
+ type: Boolean,
353
+ required: false,
354
+ default: false
355
+ },
356
+ disableOutsidePointerEvents: {
357
+ type: Boolean,
358
+ required: false,
359
+ default: false
360
+ },
361
+ isDismissable: {
362
+ type: Boolean,
363
+ required: false,
364
+ default: true
365
+ },
366
+ position: {
367
+ type: String,
368
+ required: false,
369
+ default: "inline"
370
+ },
371
+ bodyLock: {
372
+ type: Boolean,
373
+ required: false
374
+ },
375
+ dismissable: {
376
+ type: Boolean,
377
+ required: false,
378
+ default: true
379
+ }
380
+ };
381
+ const [injectComboboxContentContext, provideComboboxContentContext] = shared.createContext("DestylerComboboxContent");
382
+ const DestylerComboboxContentImpl = vue.defineComponent({
383
+ name: "DestylerComboboxContentImpl",
384
+ props: destylerComboboxContentImplProps,
385
+ emits: ["escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "dismiss"],
386
+ setup(props) {
387
+ const { position } = vue.toRefs(props);
388
+ const rootContext = injectComboboxRootContext();
389
+ composition.useBodyScrollLock(props.bodyLock);
390
+ const { forwardRef, currentElement } = composition.useForwardExpose();
391
+ composition.useHideOthers(currentElement);
392
+ const pickedProps = vue.computed(() => {
393
+ if (props.position === "popper")
394
+ return props;
395
+ else
396
+ return {};
397
+ });
398
+ const forwardedProps = composition.useForwardProps(pickedProps.value);
399
+ function handleLeave() {
400
+ rootContext.onSelectedValueChange("");
401
+ }
402
+ vue.onMounted(() => {
403
+ rootContext.onContentElementChange(currentElement.value);
404
+ });
405
+ const popperStyle = {
406
+ "boxSizing": "border-box",
407
+ "--destyler_combobox_content_transform_origin": "var(--destyler_popper_transform_origin)",
408
+ "--destyler_combobox_content_available_width": "var(--destyler_popper_available_width)",
409
+ "--destyler_combobox_content_available_height": "var(--destyler_popper_available_height)",
410
+ "--destyler_combobox_trigger_width": "var(--destyler_popper_anchor_width)",
411
+ "--destyler_combobox_trigger_height": "var(--destyler_popper_anchor_height)"
412
+ };
413
+ provideComboboxContentContext({ position });
414
+ return {
415
+ rootContext,
416
+ popperStyle,
417
+ forwardedProps,
418
+ forwardRef,
419
+ handleLeave
420
+ };
421
+ },
422
+ render() {
423
+ return vue.h(collection.DestylerCollectionSlot, null, {
424
+ default: () => {
425
+ return [
426
+ this.$props.dismissable ? vue.h(dismissableLayer.DestylerDismissableLayer, vue.mergeProps(this.$attrs, this.forwardedProps, {
427
+ asChild: true,
428
+ disableOutsidePointerEvents: this.$props.disableOutsidePointerEvents,
429
+ onDismiss: () => {
430
+ this.rootContext.onOpenChange(false);
431
+ },
432
+ onFocusOutside: (event) => {
433
+ if (this.rootContext.parentElement.value?.contains(event.target))
434
+ event.preventDefault();
435
+ this.$emit("focusOutside", event);
436
+ },
437
+ onInteractOutside: (event) => {
438
+ this.$emit("interactOutside", event);
439
+ },
440
+ onEscapeKeyDown: (event) => {
441
+ this.$emit("escapeKeyDown", event);
442
+ },
443
+ onPointerDownOutside: (event) => {
444
+ if (this.rootContext.parentElement.value?.contains(event.target))
445
+ event.preventDefault();
446
+ this.$emit("pointerDownOutside", event);
447
+ }
448
+ }), {
449
+ default: () => {
450
+ return vue.withDirectives(vue.h(this.$props.position === "popper" ? popper.DestylerPopperContent : primitive.DestylerPrimitive, {
451
+ "ref": (el) => this.forwardRef(el),
452
+ "role": "listbox",
453
+ "data-state": this.rootContext.open.value ? "open" : "closed",
454
+ "style": {
455
+ display: "flex",
456
+ flexDirection: "column",
457
+ outline: "none",
458
+ ...this.$props.position === "popper" ? this.popperStyle : {}
459
+ },
460
+ "onPointerleave": () => {
461
+ this.handleLeave();
462
+ }
463
+ }, {
464
+ default: () => this.$slots.default?.()
465
+ }), [
466
+ [directives.BindOnceDirective, { id: this.rootContext.contentId }]
467
+ ]);
468
+ }
469
+ }) : vue.withDirectives(vue.h(this.$props.position === "popper" ? popper.DestylerPopperContent : primitive.DestylerPrimitive, {
470
+ "ref": (el) => this.forwardRef(el),
471
+ "role": "listbox",
472
+ "data-state": this.rootContext.open.value ? "open" : "closed",
473
+ "style": {
474
+ display: "flex",
475
+ flexDirection: "column",
476
+ outline: "none",
477
+ ...this.$props.position === "popper" ? this.popperStyle : {}
478
+ },
479
+ "onPointerleave": () => {
480
+ this.handleLeave();
481
+ }
482
+ }, {
483
+ default: () => this.$slots.default?.()
484
+ }), [
485
+ [directives.BindOnceDirective, { id: this.rootContext.contentId }]
486
+ ])
487
+ ];
488
+ }
489
+ });
490
+ }
491
+ });
492
+
493
+ const destylerComboboxArrowProps = {
494
+ asChild: {
495
+ type: Boolean,
496
+ required: false,
497
+ default: false
498
+ },
499
+ width: {
500
+ type: Number,
501
+ required: false,
502
+ default: 10
503
+ },
504
+ height: {
505
+ type: Number,
506
+ required: false,
507
+ default: 5
508
+ },
509
+ as: {
510
+ type: [String, Object],
511
+ required: false,
512
+ default: "svg"
513
+ }
514
+ };
515
+ const DestylerComboboxArrow = vue.defineComponent({
516
+ name: "DestylerComboboxArrow",
517
+ props: destylerComboboxArrowProps,
518
+ setup() {
519
+ composition.useForwardExpose();
520
+ const rootContext = injectComboboxRootContext();
521
+ const contentContext = injectComboboxContentContext();
522
+ return {
523
+ rootContext,
524
+ contentContext
525
+ };
526
+ },
527
+ render() {
528
+ if (this.rootContext.open.value && this.contentContext.position.value === "popper") {
529
+ return vue.h(popper.DestylerPopperArrow, this.$props, {
530
+ default: () => this.$slots.default?.()
531
+ });
532
+ }
533
+ }
534
+ });
535
+
536
+ const destylerComboboxCancelProps = {
537
+ as: {
538
+ type: [String, Object],
539
+ required: false,
540
+ default: "button"
541
+ },
542
+ asChild: {
543
+ type: Boolean,
544
+ required: false,
545
+ default: false
546
+ }
547
+ };
548
+ const DestylerComboboxCancel = vue.defineComponent({
549
+ name: "DestylerComboboxCancel",
550
+ props: destylerComboboxCancelProps,
551
+ setup() {
552
+ composition.useForwardExpose();
553
+ const rootContext = injectComboboxRootContext();
554
+ function handleClick() {
555
+ rootContext.searchTerm.value = "";
556
+ rootContext.inputElement.value?.focus();
557
+ }
558
+ return {
559
+ rootContext,
560
+ handleClick
561
+ };
562
+ },
563
+ render() {
564
+ return vue.h(primitive.DestylerPrimitive, vue.mergeProps(this.$props, {
565
+ type: this.$props.as === "button" ? "button" : void 0,
566
+ tabindex: "-1",
567
+ onClick: () => {
568
+ this.handleClick();
569
+ }
570
+ }), {
571
+ default: () => this.$slots.default?.()
572
+ });
573
+ }
574
+ });
575
+
576
+ const destylerComboboxContentProps = {
577
+ ...destylerComboboxContentImplProps,
578
+ forceMount: {
579
+ type: Boolean,
580
+ required: false
581
+ }
582
+ };
583
+ const DestylerComboboxContent = vue.defineComponent({
584
+ name: "DestylerComboboxContent",
585
+ props: destylerComboboxContentProps,
586
+ emits: ["escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "dismiss"],
587
+ setup(props, { emit }) {
588
+ const forwarded = composition.useForwardPropsEmits(props, emit);
589
+ const { forwardRef } = composition.useForwardExpose();
590
+ const rootContext = injectComboboxRootContext();
591
+ return {
592
+ forwardRef,
593
+ forwarded,
594
+ rootContext
595
+ };
596
+ },
597
+ render() {
598
+ return vue.h(presence.DestylerPresence, {
599
+ present: this.$props.forceMount || this.rootContext.open.value
600
+ }, {
601
+ default: () => {
602
+ return vue.h(DestylerComboboxContentImpl, vue.mergeProps(this.$attrs, this.forwarded, {
603
+ ref: (el) => this.forwardRef(el)
604
+ }), {
605
+ default: () => this.$slots.default?.()
606
+ });
607
+ }
608
+ });
609
+ }
610
+ });
611
+
612
+ const destylerComboboxEmptyProps = {
613
+ as: {
614
+ type: [String, Object],
615
+ required: false,
616
+ default: "button"
617
+ },
618
+ asChild: {
619
+ type: Boolean,
620
+ required: false,
621
+ default: false
622
+ }
623
+ };
624
+ const DestylerComboboxEmpty = vue.defineComponent({
625
+ name: "DestylerComboboxEmpty",
626
+ props: destylerComboboxEmptyProps,
627
+ setup() {
628
+ composition.useForwardExpose();
629
+ const rootContext = injectComboboxRootContext();
630
+ const isEmpty = vue.computed(() => rootContext.filteredOptions.value.length === 0);
631
+ return {
632
+ rootContext,
633
+ isEmpty
634
+ };
635
+ },
636
+ render() {
637
+ if (this.isEmpty) {
638
+ return vue.h(primitive.DestylerPrimitive, this.$props, {
639
+ default: () => this.$slots.default ? this.$slots.default?.() : "No options"
640
+ });
641
+ }
642
+ }
643
+ });
644
+
645
+ const destylerComboboxGroupProps = {
646
+ as: {
647
+ type: [String, Object],
648
+ required: false,
649
+ default: "div"
650
+ },
651
+ asChild: {
652
+ type: Boolean,
653
+ required: false,
654
+ default: false
655
+ }
656
+ };
657
+ const [injectComboboxGroupContext, provideComboboxGroupContext] = shared.createContext("DestylerComboboxGroup");
658
+ const DestylerComboboxGroup = vue.defineComponent({
659
+ name: "DestylerComboboxGroup",
660
+ props: destylerComboboxGroupProps,
661
+ setup() {
662
+ const { currentRef, currentElement } = composition.useForwardExpose();
663
+ const id = composition.useId();
664
+ const rootContext = injectComboboxRootContext();
665
+ const hasOptions = vue.ref(false);
666
+ function checkCollectionItem() {
667
+ if (!currentElement.value)
668
+ return;
669
+ const collectionItem = currentElement.value.querySelectorAll("[data-destyler-combobox-item]:not([data-hidden])");
670
+ hasOptions.value = !!collectionItem.length;
671
+ }
672
+ composition.useMutationObserver(currentElement, () => {
673
+ checkCollectionItem();
674
+ }, { childList: true });
675
+ vue.watch(() => rootContext.searchTerm.value, () => {
676
+ vue.nextTick(() => {
677
+ checkCollectionItem();
678
+ });
679
+ }, { immediate: true });
680
+ provideComboboxGroupContext({
681
+ id
682
+ });
683
+ return {
684
+ currentRef,
685
+ hasOptions,
686
+ id
687
+ };
688
+ },
689
+ render() {
690
+ return vue.h(primitive.DestylerPrimitive, vue.mergeProps(this.$props, {
691
+ "ref": "currentRef",
692
+ "role": "group",
693
+ "aria-labelledby": this.id,
694
+ ...this.hasOptions ? {} : { style: { display: "none" } }
695
+ }), {
696
+ default: () => this.$slots.default?.()
697
+ });
698
+ }
699
+ });
700
+
701
+ const destylerComboboxInputProps = {
702
+ as: {
703
+ type: [String, Object],
704
+ required: false,
705
+ default: "input"
706
+ },
707
+ asChild: {
708
+ type: Boolean,
709
+ required: false,
710
+ default: false
711
+ },
712
+ type: {
713
+ type: String,
714
+ required: false,
715
+ default: "text"
716
+ },
717
+ disabled: {
718
+ type: Boolean,
719
+ required: false
720
+ },
721
+ autoFocus: {
722
+ type: Boolean,
723
+ required: false
724
+ }
725
+ };
726
+ const DestylerComboboxInput = vue.defineComponent({
727
+ name: "DestylerComboboxInput",
728
+ props: destylerComboboxInputProps,
729
+ setup(props) {
730
+ const rootContext = injectComboboxRootContext();
731
+ const { forwardRef, currentElement } = composition.useForwardExpose();
732
+ vue.onMounted(() => {
733
+ const inputEl = currentElement.value.nodeName === "INPUT" ? currentElement.value : currentElement.value.querySelector("input");
734
+ if (!inputEl)
735
+ return;
736
+ rootContext.onInputElementChange(inputEl);
737
+ setTimeout(() => {
738
+ if (props.autoFocus)
739
+ inputEl?.focus();
740
+ }, 1);
741
+ });
742
+ const disabled = vue.computed(() => props.disabled || rootContext.disabled.value || false);
743
+ function handleKeyDown(ev) {
744
+ if (!rootContext.open.value)
745
+ rootContext.onOpenChange(true);
746
+ else
747
+ rootContext.onInputNavigation(ev.key === "ArrowUp" ? "up" : "down");
748
+ }
749
+ function handleHomeEnd(ev) {
750
+ if (!rootContext.open.value)
751
+ return;
752
+ rootContext.onInputNavigation(ev.key === "Home" ? "home" : "end");
753
+ }
754
+ function handleInput(event) {
755
+ rootContext.searchTerm.value = event.target?.value;
756
+ if (!rootContext.open.value)
757
+ rootContext.onOpenChange(true);
758
+ rootContext.isUserInputted.value = true;
759
+ }
760
+ return {
761
+ disabled,
762
+ rootContext,
763
+ forwardRef,
764
+ handleInput,
765
+ handleKeyDown,
766
+ handleHomeEnd
767
+ };
768
+ },
769
+ render() {
770
+ return vue.h(primitive.DestylerPrimitive, {
771
+ "ref": (el) => this.forwardRef(el),
772
+ "as": this.$props.as,
773
+ "asChild": this.$props.asChild,
774
+ "type": this.$props.type,
775
+ "disabled": this.disabled,
776
+ "value": this.rootContext.searchTerm.value,
777
+ "aria-expanded": this.rootContext.open.value,
778
+ "aria-controls": this.rootContext.contentId,
779
+ "aria-disabled": this.disabled ?? void 0,
780
+ "aria-autocomplete": "list",
781
+ "role": "combobox",
782
+ "autocomplete": "false",
783
+ "onInput": (event) => {
784
+ this.handleInput(event);
785
+ },
786
+ "onKeydown": vue.withKeys((event) => {
787
+ switch (event.key) {
788
+ case "ArrowUp":
789
+ case "ArrowDown":
790
+ event.preventDefault();
791
+ this.handleKeyDown(event);
792
+ break;
793
+ case "Home":
794
+ case "End":
795
+ event.preventDefault();
796
+ this.handleHomeEnd(event);
797
+ break;
798
+ case "Enter":
799
+ this.rootContext.onInputEnter();
800
+ break;
801
+ }
802
+ }, ["down", "up", "enter", "home", "end"])
803
+ }, {
804
+ default: () => this.$slots.default?.()
805
+ });
806
+ }
807
+ });
808
+
809
+ const COMBOBOX_SELECT = "combobox.select";
810
+ const destylerComboboxItemProps = {
811
+ as: {
812
+ type: [String, Object],
813
+ required: false,
814
+ default: "div"
815
+ },
816
+ asChild: {
817
+ type: Boolean,
818
+ required: false,
819
+ default: false
820
+ },
821
+ value: {
822
+ type: [String, Number, Boolean, Object],
823
+ required: true
824
+ },
825
+ disabled: {
826
+ type: Boolean,
827
+ required: false
828
+ }
829
+ };
830
+ const [injectComboboxItemContext, provideComboboxItemContext] = shared.createContext("DestylerComboboxItem");
831
+ const DestylerComboboxItem = vue.defineComponent({
832
+ name: "DestylerComboboxItem",
833
+ props: destylerComboboxItemProps,
834
+ emits: ["select"],
835
+ setup(props, { emit }) {
836
+ const { disabled } = vue.toRefs(props);
837
+ const rootContext = injectComboboxRootContext();
838
+ injectComboboxGroupContext({ id: "", options: vue.ref([]) });
839
+ const { forwardRef } = composition.useForwardExpose();
840
+ const isSelected = vue.computed(
841
+ () => rootContext.multiple.value && Array.isArray(rootContext.modelValue.value) ? rootContext.modelValue.value?.includes(props.value) : isEqual__default(rootContext.modelValue?.value, props.value)
842
+ );
843
+ const isFocused = vue.computed(() => isEqual__default(rootContext.selectedValue.value, props.value));
844
+ const textId = composition.useId();
845
+ const isInOption = vue.computed(() => rootContext.isUserInputted.value ? rootContext.searchTerm.value === "" || !!rootContext.filteredOptions.value.find((i) => isEqual__default(i, props.value)) : true);
846
+ async function handleSelect(ev) {
847
+ emit("select", ev);
848
+ if (ev?.defaultPrevented)
849
+ return;
850
+ if (!disabled.value && ev)
851
+ rootContext.onValueChange(props.value);
852
+ }
853
+ function handleSelectCustomEvent(ev) {
854
+ if (!ev)
855
+ return;
856
+ const eventDetail = { originalEvent: ev, value: props.value };
857
+ shared.handleAndDispatchCustomEvent(COMBOBOX_SELECT, handleSelect, eventDetail);
858
+ }
859
+ async function handlePointerMove(event) {
860
+ await vue.nextTick();
861
+ if (event.defaultPrevented)
862
+ return;
863
+ rootContext.onSelectedValueChange(props.value);
864
+ }
865
+ if (props.value === "") {
866
+ throw new Error(
867
+ "A <DestylerSelectItem /> must have a value prop that is not an empty string. This is because the Select value can be set to an empty string to clear the selection and show the placeholder."
868
+ );
869
+ }
870
+ provideComboboxItemContext({
871
+ isSelected
872
+ });
873
+ return {
874
+ forwardRef,
875
+ textId,
876
+ isFocused,
877
+ isSelected,
878
+ isInOption,
879
+ handleSelectCustomEvent,
880
+ handlePointerMove
881
+ };
882
+ },
883
+ render() {
884
+ return vue.h(collection.DestylerCollectionItem, null, {
885
+ default: () => {
886
+ return vue.h(primitive.DestylerPrimitive, {
887
+ "ref": (el) => this.forwardRef(el),
888
+ "role": "option",
889
+ "tabindex": "-1",
890
+ "aria-labelledby": this.textId,
891
+ "data-highlighted": this.isFocused ? "" : void 0,
892
+ "aria-selected": this.isSelected,
893
+ "data-state": this.isSelected ? "checked" : "unchecked",
894
+ "aria-disabled": this.$props.disabled || void 0,
895
+ "data-disabled": this.$props.disabled ? "" : void 0,
896
+ "as": this.$props.as,
897
+ "asChild": this.$props.asChild,
898
+ "data-hidden": !this.isInOption ? true : void 0,
899
+ "onClick": (event) => {
900
+ this.handleSelectCustomEvent(event);
901
+ },
902
+ "onPointermove": (event) => {
903
+ this.handlePointerMove(event);
904
+ },
905
+ ...this.isInOption ? {} : { style: { display: "none" } }
906
+ }, {
907
+ default: () => this.$slots.default ? this.$slots.default?.() : this.$props.value
908
+ });
909
+ }
910
+ });
911
+ }
912
+ });
913
+
914
+ const destylerComboboxItemIndicatorProps = {
915
+ as: {
916
+ type: [String, Object],
917
+ required: false,
918
+ default: "span"
919
+ },
920
+ asChild: {
921
+ type: Boolean,
922
+ required: false,
923
+ default: false
924
+ }
925
+ };
926
+ const DestylerComboboxItemIndicator = vue.defineComponent({
927
+ name: "DestylerComboboxItemIndicator",
928
+ props: destylerComboboxItemIndicatorProps,
929
+ setup() {
930
+ composition.useForwardExpose();
931
+ const itemContext = injectComboboxItemContext();
932
+ return {
933
+ itemContext
934
+ };
935
+ },
936
+ render() {
937
+ if (this.itemContext.isSelected.value) {
938
+ return vue.h(primitive.DestylerPrimitive, vue.mergeProps(this.$props, {
939
+ "aria-hidden": ""
940
+ }), {
941
+ default: () => this.$slots.default?.()
942
+ });
943
+ }
944
+ }
945
+ });
946
+
947
+ const destylerComboboxLabelProps = {
948
+ as: {
949
+ type: [String, Object],
950
+ required: false,
951
+ default: "div"
952
+ },
953
+ asChild: {
954
+ type: Boolean,
955
+ required: false,
956
+ default: false
957
+ },
958
+ for: {
959
+ type: String,
960
+ required: false
961
+ }
962
+ };
963
+ const DestylerComboboxLabel = vue.defineComponent({
964
+ name: "DestylerComboboxLabel",
965
+ props: destylerComboboxLabelProps,
966
+ setup() {
967
+ composition.useForwardExpose();
968
+ const groupContext = injectComboboxGroupContext({ id: "" });
969
+ return {
970
+ groupContext
971
+ };
972
+ },
973
+ render() {
974
+ return vue.withDirectives(vue.h(primitive.DestylerPrimitive, this.$props, {
975
+ default: () => this.$slots.default?.()
976
+ }), [
977
+ [directives.BindOnceDirective, { id: this.groupContext.id }]
978
+ ]);
979
+ }
980
+ });
981
+
982
+ const destylerComboboxPortalProps = {
983
+ to: {
984
+ type: [String, Object],
985
+ required: false,
986
+ default: "body"
987
+ },
988
+ disabled: {
989
+ type: Boolean,
990
+ required: false,
991
+ default: false
992
+ },
993
+ forceMount: {
994
+ type: Boolean,
995
+ required: false,
996
+ default: false
997
+ }
998
+ };
999
+ const DestylerComboboxPortal = vue.defineComponent({
1000
+ name: "DestylerComboboxPortal",
1001
+ props: destylerComboboxPortalProps,
1002
+ render() {
1003
+ return vue.h(teleport.DestylerTeleport, this.$props, {
1004
+ default: () => this.$slots.default?.()
1005
+ });
1006
+ }
1007
+ });
1008
+
1009
+ const destylerComboboxSeparatorProps = {
1010
+ as: {
1011
+ type: [String, Object],
1012
+ required: false,
1013
+ default: "div"
1014
+ },
1015
+ asChild: {
1016
+ type: Boolean,
1017
+ required: false,
1018
+ default: false
1019
+ }
1020
+ };
1021
+ const DestylerComboboxSeparator = vue.defineComponent({
1022
+ name: "DestylerComboboxSeparator",
1023
+ props: destylerComboboxSeparatorProps,
1024
+ setup() {
1025
+ composition.useForwardExpose();
1026
+ },
1027
+ render() {
1028
+ return vue.h(primitive.DestylerPrimitive, vue.mergeProps(this.$props, {
1029
+ "aria-hidden": ""
1030
+ }));
1031
+ }
1032
+ });
1033
+
1034
+ const destylerComboboxTriggerProps = {
1035
+ as: {
1036
+ type: [String, Object],
1037
+ required: false,
1038
+ default: "button"
1039
+ },
1040
+ asChild: {
1041
+ type: Boolean,
1042
+ required: false,
1043
+ default: false
1044
+ },
1045
+ disabled: {
1046
+ type: Boolean,
1047
+ required: false
1048
+ }
1049
+ };
1050
+ const DestylerComboboxTrigger = vue.defineComponent({
1051
+ name: "DestylerComboboxTrigger",
1052
+ props: destylerComboboxTriggerProps,
1053
+ setup(props) {
1054
+ composition.useForwardExpose();
1055
+ const rootContext = injectComboboxRootContext();
1056
+ const disabled = vue.computed(() => props.disabled || rootContext.disabled.value || false);
1057
+ return {
1058
+ rootContext,
1059
+ disabled
1060
+ };
1061
+ },
1062
+ render() {
1063
+ return vue.h(primitive.DestylerPrimitive, vue.mergeProps(this.$props, {
1064
+ "type": this.$props.as === "button" ? "button" : void 0,
1065
+ "tabindex": "-1",
1066
+ "aria-label": "Show popup",
1067
+ "aria-haspopup": "listbox",
1068
+ "aria-expanded": this.rootContext.open.value,
1069
+ "aria-controls": this.rootContext.contentId,
1070
+ "data-state": this.rootContext.open.value ? "open" : "closed",
1071
+ "disabled": this.disabled,
1072
+ "data-disabled": this.disabled ? "" : void 0,
1073
+ "aria-disabled": this.disabled ?? void 0,
1074
+ "onClick": () => {
1075
+ this.rootContext.onOpenChange(!this.rootContext.open.value);
1076
+ }
1077
+ }), {
1078
+ default: () => this.$slots.default?.()
1079
+ });
1080
+ }
1081
+ });
1082
+
1083
+ const destylerComboboxViewportProps = {
1084
+ as: {
1085
+ type: [String, Object],
1086
+ required: false,
1087
+ default: "div"
1088
+ },
1089
+ asChild: {
1090
+ type: Boolean,
1091
+ required: false,
1092
+ default: false
1093
+ }
1094
+ };
1095
+ const DestylerComboboxViewport = vue.defineComponent({
1096
+ name: "DestylerComboboxViewport",
1097
+ props: destylerComboboxViewportProps,
1098
+ setup() {
1099
+ const { forwardRef } = composition.useForwardExpose();
1100
+ return {
1101
+ forwardRef
1102
+ };
1103
+ },
1104
+ render() {
1105
+ return [
1106
+ vue.h(primitive.DestylerPrimitive, {
1107
+ "ref": (el) => this.forwardRef(el),
1108
+ "data-destyler-combobox-viewport": "",
1109
+ "role": "presentation",
1110
+ "style": {
1111
+ position: "relative",
1112
+ flex: 1,
1113
+ overflow: "auto"
1114
+ }
1115
+ }, {
1116
+ default: () => this.$slots.default?.()
1117
+ }),
1118
+ vue.h(primitive.DestylerPrimitive, {
1119
+ as: "style"
1120
+ }, {
1121
+ default: () => `
1122
+ /* Hide scrollbars cross-browser and enable momentum scroll for touch devices */
1123
+ [data-destyler-combobox-viewport] {
1124
+ scrollbar-width:none;
1125
+ -ms-overflow-style: none;
1126
+ -webkit-overflow-scrolling: touch;
1127
+ }
1128
+ [data-destyler-combobox-viewport]::-webkit-scrollbar {
1129
+ display: none;
1130
+ }
1131
+ `
1132
+ })
1133
+ ];
1134
+ }
1135
+ });
1136
+
1137
+ exports.DestylerComboboxAnchor = DestylerComboboxAnchor;
1138
+ exports.DestylerComboboxArrow = DestylerComboboxArrow;
1139
+ exports.DestylerComboboxCancel = DestylerComboboxCancel;
1140
+ exports.DestylerComboboxContent = DestylerComboboxContent;
1141
+ exports.DestylerComboboxContentImpl = DestylerComboboxContentImpl;
1142
+ exports.DestylerComboboxEmpty = DestylerComboboxEmpty;
1143
+ exports.DestylerComboboxGroup = DestylerComboboxGroup;
1144
+ exports.DestylerComboboxInput = DestylerComboboxInput;
1145
+ exports.DestylerComboboxItem = DestylerComboboxItem;
1146
+ exports.DestylerComboboxItemIndicator = DestylerComboboxItemIndicator;
1147
+ exports.DestylerComboboxLabel = DestylerComboboxLabel;
1148
+ exports.DestylerComboboxPortal = DestylerComboboxPortal;
1149
+ exports.DestylerComboboxRoot = DestylerComboboxRoot;
1150
+ exports.DestylerComboboxSeparator = DestylerComboboxSeparator;
1151
+ exports.DestylerComboboxTrigger = DestylerComboboxTrigger;
1152
+ exports.DestylerComboboxViewport = DestylerComboboxViewport;