@hoci/core 0.8.0 → 0.9.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/index.js ADDED
@@ -0,0 +1,910 @@
1
+ import { n as __reExport, t as __exportAll } from "./chunk-DzK395Rf.js";
2
+ import { classPropType, defineHookComponent, defineHookEmits, defineHookProps, elementRef, getFirstChilld, isWindow, labelPropType, throttleByRaf, toArray, toReactive, useElement, useSharedConfig, valuePropType } from "@hoci/shared";
3
+ import { isDefined, onClickOutside, syncRef, tryOnScopeDispose, useElementBounding, useElementVisibility, useEventListener, useVModel } from "@vueuse/core";
4
+ import { cls, createUnitFormat, px } from "tslx";
5
+ import { computed, inject, nextTick, provide, reactive, ref, renderSlot, shallowRef, triggerRef, watch, watchPostEffect } from "vue";
6
+ import { Virtualizer, elementScroll, observeElementOffset, observeElementRect } from "@tanstack/virtual-core";
7
+
8
+ export * from "@hoci/shared"
9
+
10
+ //#region src/affix/index.ts
11
+ const affixProps = defineHookProps({
12
+ fixedClass: {
13
+ type: String,
14
+ default: ""
15
+ },
16
+ offset: {
17
+ type: Number,
18
+ default: 0
19
+ },
20
+ position: {
21
+ type: String,
22
+ default: "top"
23
+ },
24
+ target: { type: [
25
+ String,
26
+ Object,
27
+ Function
28
+ ] },
29
+ zIndex: {
30
+ type: Number,
31
+ default: 998
32
+ }
33
+ });
34
+ const affixEmits = defineHookEmits(["scroll", "change"]);
35
+ const AFFIX_TARGET_KEY = Symbol("AFFIX_TARGET_KEY");
36
+ function getTargetRect(target) {
37
+ return isWindow(target) ? {
38
+ top: 0,
39
+ bottom: window.innerHeight
40
+ } : target.getBoundingClientRect();
41
+ }
42
+ const useAffix = defineHookComponent({
43
+ props: affixProps,
44
+ setup(props, { emit }) {
45
+ const wrapperRef = elementRef();
46
+ const wrapperRect = toReactive(useElementBounding(wrapperRef));
47
+ const parentRef = inject(AFFIX_TARGET_KEY, void 0);
48
+ const targetRef = useElement(props.target, parentRef);
49
+ const isFixed = ref(false);
50
+ const placeholderStyle = ref({});
51
+ const fixedStyle = ref({});
52
+ const className = computed(() => {
53
+ return isFixed.value ? props.fixedClass : "";
54
+ });
55
+ const wrapperVisible = useElementVisibility(wrapperRef);
56
+ const containerRef = computed(() => {
57
+ if (!wrapperVisible.value) return null;
58
+ return targetRef.value ?? window;
59
+ });
60
+ const updatePosition = throttleByRaf(async () => {
61
+ if (!wrapperRef.value || !containerRef.value) return;
62
+ if (wrapperRect.width * wrapperRect.height === 0) return;
63
+ const newPlaceholderStyles = {
64
+ width: px(wrapperRect.width),
65
+ height: px(wrapperRect.height)
66
+ };
67
+ const targetRect = getTargetRect(containerRef.value);
68
+ let newIsFixed = false;
69
+ let newFixedStyles = {};
70
+ const offset = props.offset;
71
+ if (props.position === "top") {
72
+ newIsFixed = wrapperRect.top - targetRect.top < offset && offset >= 0;
73
+ newFixedStyles = newIsFixed ? {
74
+ position: "fixed",
75
+ zIndex: props.zIndex,
76
+ top: px(targetRect.top + offset)
77
+ } : {};
78
+ } else {
79
+ newIsFixed = targetRect.bottom - wrapperRect.bottom < offset;
80
+ newFixedStyles = newIsFixed ? {
81
+ position: "fixed",
82
+ bottom: px(window.innerHeight - targetRect.bottom + offset)
83
+ } : {};
84
+ }
85
+ if (newIsFixed !== isFixed.value) {
86
+ isFixed.value = newIsFixed;
87
+ emit("change", newIsFixed);
88
+ }
89
+ placeholderStyle.value = newPlaceholderStyles;
90
+ fixedStyle.value = {
91
+ ...newFixedStyles,
92
+ ...newIsFixed ? newPlaceholderStyles : {}
93
+ };
94
+ });
95
+ useEventListener(containerRef, "scroll", () => {
96
+ emit("scroll");
97
+ updatePosition();
98
+ });
99
+ useEventListener(containerRef, "resize", updatePosition);
100
+ watchPostEffect(updatePosition);
101
+ return {
102
+ className,
103
+ wrapperRef,
104
+ containerRef,
105
+ isFixed,
106
+ placeholderStyle,
107
+ fixedStyle,
108
+ updatePosition
109
+ };
110
+ }
111
+ });
112
+ function provideAffixTarget(target) {
113
+ provide(AFFIX_TARGET_KEY, target);
114
+ }
115
+
116
+ //#endregion
117
+ //#region src/config-provider/index.ts
118
+ const configProviderProps = defineHookProps({
119
+ icon: { type: Object },
120
+ activateEvent: { type: String }
121
+ });
122
+
123
+ //#endregion
124
+ //#region src/file-upload/index.ts
125
+ const fileUploadProps = defineHookProps({
126
+ modelValue: {
127
+ type: [File, Array],
128
+ default: () => []
129
+ },
130
+ multiple: {
131
+ type: Boolean,
132
+ default: false
133
+ }
134
+ });
135
+ const fileUploadEmits = defineHookEmits(["update:modelValue", "change"]);
136
+ const useFileUpload = defineHookComponent({
137
+ props: fileUploadProps,
138
+ emits: fileUploadEmits,
139
+ setup(props, { emit }) {
140
+ const fileInputRef = elementRef();
141
+ const files = ref([]);
142
+ watch(() => toArray(props.modelValue), (value) => {
143
+ files.value = value;
144
+ }, {
145
+ immediate: true,
146
+ deep: true
147
+ });
148
+ const openFileInput = () => {
149
+ fileInputRef.value?.click();
150
+ };
151
+ const toModelValue = (files) => {
152
+ if (props.multiple) return files;
153
+ if (files.length) return files[files.length - 1];
154
+ return null;
155
+ };
156
+ useEventListener(fileInputRef, "change", (event) => {
157
+ const input = event.target;
158
+ const newFiles = Array.from(input.files ?? []);
159
+ if (newFiles.length) if (props.multiple) files.value.push(...newFiles);
160
+ else files.value = newFiles.slice(newFiles.length - 1);
161
+ input.value = "";
162
+ const value = toModelValue(files.value);
163
+ emit("update:modelValue", value);
164
+ emit("change", value);
165
+ });
166
+ return {
167
+ fileInputRef,
168
+ files,
169
+ openFileInput
170
+ };
171
+ }
172
+ });
173
+
174
+ //#endregion
175
+ //#region src/icon/index.ts
176
+ const iconProps = defineHookProps({
177
+ src: {
178
+ type: String,
179
+ required: true
180
+ },
181
+ size: { type: [Number, String] },
182
+ width: { type: [Number, String] },
183
+ height: { type: [Number, String] },
184
+ color: {
185
+ type: String,
186
+ default: "currentColor"
187
+ },
188
+ mask: {
189
+ type: [Boolean, String],
190
+ default: () => "auto"
191
+ }
192
+ });
193
+ const isSvg = (src) => src.endsWith(".svg") || src.startsWith("data:image/svg+xml");
194
+ const useIcon = defineHookComponent({
195
+ props: iconProps,
196
+ setup(props, context) {
197
+ const sharedConfig = useSharedConfig("icon");
198
+ const sizeStyle = computed(() => {
199
+ const s = props.size ?? sharedConfig.size;
200
+ const unit = createUnitFormat(sharedConfig.sizeUnit ?? "px");
201
+ const size = s ? unit(s) : void 0;
202
+ const w = props.width ?? size;
203
+ const h = props.height ?? size;
204
+ return {
205
+ width: w ? unit(w) : void 0,
206
+ height: h ? unit(h) : void 0
207
+ };
208
+ });
209
+ const dynamicStyle = computed(() => {
210
+ if (!(props.mask === "auto" ? isSvg(props.src) : props.mask)) return {
211
+ "background-image": "var(--icon-url)",
212
+ "background-size": "100% 100%"
213
+ };
214
+ return {
215
+ "mask": "var(--icon-url) no-repeat",
216
+ "mask-size": "100% 100%",
217
+ "-webkit-mask": "var(--icon-url) no-repeat",
218
+ "-webkit-mask-size": "100% 100%",
219
+ "background-color": props.color
220
+ };
221
+ });
222
+ const staticStyle = computed(() => {
223
+ return { "--icon-url": `url("${props.src}")` };
224
+ });
225
+ return { style: computed(() => {
226
+ return {
227
+ ...staticStyle.value,
228
+ ...dynamicStyle.value,
229
+ ...sizeStyle.value,
230
+ ...context.attrs.style ?? {}
231
+ };
232
+ }) };
233
+ }
234
+ });
235
+
236
+ //#endregion
237
+ //#region src/selection/index.ts
238
+ const selectionProps = defineHookProps({
239
+ modelValue: {
240
+ type: valuePropType,
241
+ default: () => null
242
+ },
243
+ activeClass: {
244
+ type: classPropType,
245
+ default: "active"
246
+ },
247
+ itemClass: {
248
+ type: classPropType,
249
+ default: ""
250
+ },
251
+ disabledClass: {
252
+ type: classPropType,
253
+ default: "disabled"
254
+ },
255
+ unactiveClass: {
256
+ type: classPropType,
257
+ default: ""
258
+ },
259
+ label: { type: labelPropType },
260
+ multiple: {
261
+ type: [
262
+ Boolean,
263
+ Number,
264
+ Array
265
+ ],
266
+ default: () => false
267
+ },
268
+ clearable: { type: Boolean },
269
+ defaultValue: {
270
+ type: valuePropType,
271
+ default: () => null
272
+ },
273
+ activateEvent: { type: String }
274
+ });
275
+ const selectionEmits = defineHookEmits([
276
+ "update:modelValue",
277
+ "change",
278
+ "load",
279
+ "unload",
280
+ "reject"
281
+ ]);
282
+ const HiSelectionContextSymbol = Symbol("[hi-selection]context");
283
+ function useSelectionContext() {
284
+ return inject(HiSelectionContextSymbol, {
285
+ isActive: () => false,
286
+ activate: () => {},
287
+ changeActive: () => {},
288
+ reject: () => {},
289
+ activeClass: "active",
290
+ unactiveClass: "unactive",
291
+ disabledClass: "disabled",
292
+ itemClass: "",
293
+ activateEvent: useSharedConfig().activateEvent,
294
+ label: null,
295
+ multiple: false,
296
+ limit: [0, Number.POSITIVE_INFINITY]
297
+ });
298
+ }
299
+ const useSelectionList = defineHookComponent({
300
+ props: selectionProps,
301
+ emits: selectionEmits,
302
+ setup(props, { emit, slots }) {
303
+ const options = reactive([]);
304
+ function toArray(value) {
305
+ if (!isDefined(value)) return [];
306
+ if (props.multiple && Array.isArray(value)) return value.filter((v) => v != null || v !== void 0);
307
+ return [value];
308
+ }
309
+ const actives = reactive([...toArray(props.modelValue ?? props.defaultValue)]);
310
+ const currentValue = computed({
311
+ get() {
312
+ return props.multiple ? actives : actives[0];
313
+ },
314
+ set(val) {
315
+ actives.splice(0, actives.length, ...toArray(val));
316
+ }
317
+ });
318
+ syncRef(currentValue, computed({
319
+ get() {
320
+ return props.modelValue ?? props.defaultValue;
321
+ },
322
+ set(val) {
323
+ emit("update:modelValue", val);
324
+ }
325
+ }), {
326
+ immediate: true,
327
+ deep: true
328
+ });
329
+ const emitChange = () => emit("change", currentValue.value);
330
+ function isActive(value) {
331
+ return actives.includes(value);
332
+ }
333
+ const multipleActive = computed(() => !!props.multiple);
334
+ /**
335
+ * [min,max]
336
+ */
337
+ const multipleLimit = computed(() => {
338
+ if (Array.isArray(props.multiple)) {
339
+ if (props.multiple[1] === void 0) return [props.multiple[0], Number.POSITIVE_INFINITY];
340
+ return props.multiple;
341
+ }
342
+ return [0, Number.POSITIVE_INFINITY];
343
+ });
344
+ function activate(value) {
345
+ const [min, max] = multipleLimit.value;
346
+ if (isActive(value)) {
347
+ if (multipleActive.value && actives.length > min || props.clearable) {
348
+ actives.splice(actives.indexOf(value), 1);
349
+ emitChange();
350
+ }
351
+ } else if (props.multiple) {
352
+ if (actives.length < max) {
353
+ actives.push(value);
354
+ emitChange();
355
+ }
356
+ } else {
357
+ actives.splice(0, actives.length, value);
358
+ emitChange();
359
+ }
360
+ }
361
+ function reject(value) {
362
+ emit("reject", value);
363
+ }
364
+ const init = (option) => {
365
+ function remove() {
366
+ const index = options.findIndex((e) => e.id === option.id);
367
+ if (index > -1) {
368
+ options.splice(index, 1);
369
+ emit("unload", option);
370
+ }
371
+ }
372
+ for (let i = 0; i < options.length; i++) if (options[i].value === option.value) {
373
+ options.splice(i, 1);
374
+ i--;
375
+ }
376
+ options.push(option);
377
+ emit("load", option);
378
+ return remove;
379
+ };
380
+ const sharedConfig = useSharedConfig();
381
+ provide(HiSelectionContextSymbol, toReactive({
382
+ activeClass: computed(() => cls(props.activeClass)),
383
+ unactiveClass: computed(() => cls(props.unactiveClass)),
384
+ disabledClass: computed(() => cls(props.disabledClass)),
385
+ itemClass: computed(() => cls(props.itemClass)),
386
+ label: computed(() => props.label),
387
+ multiple: multipleActive,
388
+ limit: multipleLimit,
389
+ clearable: computed(() => props.clearable),
390
+ defaultValue: computed(() => props.defaultValue),
391
+ activateEvent: computed(() => props.activateEvent ?? sharedConfig.activateEvent),
392
+ active: currentValue,
393
+ activate,
394
+ changeActive: activate,
395
+ isActive,
396
+ reject,
397
+ init
398
+ }));
399
+ const renderItem = () => {
400
+ const children = options.filter((e) => actives.includes(e.value)).map((e) => e.render());
401
+ return props.multiple ? children : getFirstChilld(children);
402
+ };
403
+ const slotData = {
404
+ isActive,
405
+ changeActive: activate,
406
+ renderItem
407
+ };
408
+ const render = () => {
409
+ return renderSlot(slots, "default", slotData);
410
+ };
411
+ return {
412
+ options,
413
+ actives,
414
+ isActive,
415
+ changeActive: activate,
416
+ renderItem,
417
+ render
418
+ };
419
+ }
420
+ });
421
+
422
+ //#endregion
423
+ //#region src/item/index.ts
424
+ const itemProps = defineHookProps({
425
+ value: {
426
+ type: valuePropType,
427
+ default() {
428
+ return Math.random().toString(16).slice(2);
429
+ }
430
+ },
431
+ label: { type: [Function, String] },
432
+ keepAlive: {
433
+ type: Boolean,
434
+ default: () => true
435
+ },
436
+ activateEvent: { type: String },
437
+ disabled: {
438
+ type: Boolean,
439
+ default: false
440
+ }
441
+ });
442
+ const itemEmits = defineHookEmits(["reject"]);
443
+ const useSelectionItem = defineHookComponent({
444
+ props: itemProps,
445
+ emits: itemEmits,
446
+ setup(props, { slots, emit }) {
447
+ const context = useSelectionContext();
448
+ const activate = () => {
449
+ if (props.disabled) {
450
+ emit("reject", props.value);
451
+ context.reject(props.value);
452
+ return;
453
+ }
454
+ context.activate(props.value);
455
+ };
456
+ const label = computed(() => {
457
+ let label = props.label ?? context.label;
458
+ if (label && typeof label === "function") label = label(props.value);
459
+ return Array.isArray(label) ? label : [label];
460
+ });
461
+ function render() {
462
+ return slots.default?.({
463
+ active: context.isActive(props.value),
464
+ activate
465
+ }) ?? label.value.filter(Boolean);
466
+ }
467
+ let remove = () => {};
468
+ const init = context.init;
469
+ if (init) {
470
+ watch(() => props.value, (value) => {
471
+ remove();
472
+ remove = init({
473
+ id: Math.random().toString(16).slice(2),
474
+ label: typeof props.label === "string" ? props.label : void 0,
475
+ value,
476
+ render
477
+ });
478
+ }, { immediate: true });
479
+ tryOnScopeDispose(remove);
480
+ }
481
+ const isActive = computed(() => context.isActive(props.value));
482
+ const isDisabled = computed(() => props.disabled);
483
+ return {
484
+ activate,
485
+ render,
486
+ isActive,
487
+ isDisabled,
488
+ className: computed(() => {
489
+ const array = [context.itemClass];
490
+ if (!isDisabled.value) array.push(context.isActive(props.value) ? context.activeClass : context.unactiveClass);
491
+ else array.push(context.disabledClass);
492
+ return cls(array);
493
+ }),
494
+ activateEvent: computed(() => props.activateEvent ?? context.activateEvent),
495
+ label
496
+ };
497
+ }
498
+ });
499
+
500
+ //#endregion
501
+ //#region src/popover/index.ts
502
+ const popoverProps = defineHookProps({
503
+ popupClass: { type: String },
504
+ placement: {
505
+ type: String,
506
+ default: () => "auto"
507
+ },
508
+ triggerEvent: {
509
+ type: String,
510
+ default: () => "hover"
511
+ },
512
+ offset: {
513
+ type: Number,
514
+ default: () => 8
515
+ },
516
+ lazy: {
517
+ type: Boolean,
518
+ default: () => false
519
+ },
520
+ visible: {
521
+ type: Boolean,
522
+ default: () => false
523
+ },
524
+ disabled: {
525
+ type: Boolean,
526
+ default: () => false
527
+ },
528
+ teleport: {
529
+ type: [
530
+ String,
531
+ Object,
532
+ Boolean
533
+ ],
534
+ default: () => true
535
+ }
536
+ });
537
+ const popoverEmits = defineHookEmits(["update:visible", "change"]);
538
+ const usePopover = defineHookComponent({
539
+ props: popoverProps,
540
+ emits: popoverEmits,
541
+ setup(props, context) {
542
+ const visible = useVModel(props, "visible", context.emit, { passive: true });
543
+ const triggerRef = elementRef();
544
+ const popupRef = elementRef();
545
+ const validate = (event) => {
546
+ const events = Array.isArray(event) ? event : [event];
547
+ return !props.disabled && events.includes(props.triggerEvent);
548
+ };
549
+ let timer;
550
+ const toggle = (_value) => {
551
+ const value = _value ?? !visible.value;
552
+ visible.value = value;
553
+ context.emit("change", value);
554
+ };
555
+ function onMouseover() {
556
+ if (!validate("hover")) return;
557
+ timer = setTimeout(() => {
558
+ toggle(true);
559
+ }, props.lazy ? 800 : 100);
560
+ }
561
+ function onMouseout() {
562
+ if (!validate("hover")) return;
563
+ clearTimeout(timer);
564
+ toggle(false);
565
+ }
566
+ const onClick = (e) => {
567
+ if (!validate("click")) return;
568
+ e.preventDefault();
569
+ e.stopPropagation();
570
+ toggle();
571
+ };
572
+ onClickOutside(triggerRef, () => {
573
+ if (!validate([
574
+ "click",
575
+ "contextmenu",
576
+ "touch",
577
+ "dblclick",
578
+ "mousedown"
579
+ ])) return;
580
+ toggle(false);
581
+ }, { ignore: [popupRef] });
582
+ const onContextmenu = (e) => {
583
+ if (!validate("contextmenu")) return;
584
+ e.preventDefault();
585
+ e.stopPropagation();
586
+ toggle();
587
+ };
588
+ const onFocusin = () => {
589
+ if (!validate("focus")) return;
590
+ toggle(true);
591
+ };
592
+ const onFocusout = () => {
593
+ if (!validate("focus")) return;
594
+ toggle(false);
595
+ };
596
+ const onTouchend = () => {
597
+ if (!validate("touch")) return;
598
+ toggle(true);
599
+ };
600
+ const onDblclick = () => {
601
+ if (!validate("dblclick")) return;
602
+ toggle(true);
603
+ };
604
+ const onMousedown = () => {
605
+ if (!validate("mousedown")) return;
606
+ toggle(true);
607
+ };
608
+ const onMouseup = () => {
609
+ if (!validate("mousedown")) return;
610
+ toggle(false);
611
+ };
612
+ const events = {
613
+ onMouseover,
614
+ onMouseout,
615
+ onMousedown,
616
+ onMouseup,
617
+ onContextmenu,
618
+ onClick,
619
+ onDblclick,
620
+ onFocusin,
621
+ onFocusout,
622
+ onTouchend
623
+ };
624
+ const dropdownPosition = reactive({
625
+ x: 0,
626
+ y: 0
627
+ });
628
+ const popupClass = computed(() => {
629
+ return props.popupClass;
630
+ });
631
+ function resize() {
632
+ const trigger = triggerRef.value;
633
+ const popup = popupRef.value;
634
+ if (!!trigger && !!popup && visible.value) {
635
+ const { width, height, left, top } = trigger.getBoundingClientRect();
636
+ const { clientWidth: pWidth, clientHeight: pHeight } = popup;
637
+ let x = 0;
638
+ let y = 0;
639
+ const offset = props.offset;
640
+ switch (props.placement) {
641
+ case "auto":
642
+ case "bottom":
643
+ x = left - (pWidth - width) / 2;
644
+ y = top + height + offset;
645
+ break;
646
+ case "bottom-left":
647
+ x = left;
648
+ y = top + height + offset;
649
+ break;
650
+ case "bottom-right":
651
+ x = left + width - pWidth;
652
+ y = top + height + offset;
653
+ break;
654
+ case "top":
655
+ x = left - (pWidth - width) / 2;
656
+ y = top - pHeight - offset;
657
+ break;
658
+ case "top-left":
659
+ x = left;
660
+ y = top - pHeight - offset;
661
+ break;
662
+ case "top-right":
663
+ x = left + width - pWidth;
664
+ y = top - pHeight - offset;
665
+ break;
666
+ case "left":
667
+ x = left - pWidth - offset;
668
+ y = top - (pHeight - height) / 2;
669
+ break;
670
+ case "left-top":
671
+ x = left - pWidth - offset;
672
+ y = top;
673
+ break;
674
+ case "left-bottom":
675
+ x = left - pWidth - offset;
676
+ y = top + height - pHeight;
677
+ break;
678
+ case "right":
679
+ x = left + width + offset;
680
+ y = top - (pHeight - height) / 2;
681
+ break;
682
+ case "right-top":
683
+ x = left + width + offset;
684
+ y = top;
685
+ break;
686
+ case "right-bottom":
687
+ x = left + width + offset;
688
+ y = top + height - pHeight;
689
+ break;
690
+ }
691
+ dropdownPosition.x = x;
692
+ dropdownPosition.y = y;
693
+ }
694
+ }
695
+ watch(visible, () => {
696
+ nextTick(resize);
697
+ });
698
+ return {
699
+ events,
700
+ dropdownPosition,
701
+ triggerRef,
702
+ popupRef,
703
+ popupClass,
704
+ popupStyle: computed(() => {
705
+ return {
706
+ left: px(dropdownPosition.x),
707
+ top: px(dropdownPosition.y),
708
+ visibility: visible.value ? "visible" : "hidden",
709
+ position: "fixed"
710
+ };
711
+ })
712
+ };
713
+ }
714
+ });
715
+
716
+ //#endregion
717
+ //#region src/switch/index.ts
718
+ const switchProps = defineHookProps({
719
+ modelValue: {
720
+ type: Boolean,
721
+ default: () => false
722
+ },
723
+ class: { type: classPropType },
724
+ activeClass: { type: classPropType },
725
+ unactiveClass: { type: classPropType },
726
+ activateEvent: { type: String },
727
+ disabled: {
728
+ type: Boolean,
729
+ default: () => false
730
+ },
731
+ disabledClass: { type: classPropType }
732
+ });
733
+ const switchEmits = defineHookEmits([
734
+ "update:modelValue",
735
+ "change",
736
+ "reject"
737
+ ]);
738
+ const useSwitch = defineHookComponent({
739
+ props: switchProps,
740
+ emits: switchEmits,
741
+ setup(props, context) {
742
+ const modelValue = useVModel(props, "modelValue", context.emit, {
743
+ passive: true,
744
+ defaultValue: false
745
+ });
746
+ const toggle = function(value) {
747
+ if (props.disabled) {
748
+ context.emit("reject", value);
749
+ return;
750
+ }
751
+ const oldValue = modelValue.value;
752
+ const newValue = typeof value === "boolean" ? value : !oldValue;
753
+ if (newValue !== oldValue) {
754
+ modelValue.value = newValue;
755
+ context.emit("change", newValue);
756
+ }
757
+ };
758
+ const isDisabled = computed(() => props.disabled);
759
+ const className = computed(() => {
760
+ return cls([
761
+ props.class,
762
+ modelValue.value ? props.activeClass : props.unactiveClass,
763
+ isDisabled.value ? props.disabledClass : ""
764
+ ]);
765
+ });
766
+ const sharedConfig = useSharedConfig();
767
+ return {
768
+ toggle,
769
+ modelValue,
770
+ className,
771
+ isDisabled,
772
+ activateEvent: computed(() => props.activateEvent ?? sharedConfig.activateEvent)
773
+ };
774
+ }
775
+ });
776
+
777
+ //#endregion
778
+ //#region src/virtual-list/index.ts
779
+ const virtualListProps = defineHookProps({
780
+ options: {
781
+ type: Object,
782
+ default: () => ({})
783
+ },
784
+ count: {
785
+ type: Number,
786
+ default: () => 0
787
+ },
788
+ estimateSize: {
789
+ type: [Function, Number],
790
+ default: () => 50
791
+ },
792
+ horizontal: {
793
+ type: Boolean,
794
+ default: () => false
795
+ }
796
+ });
797
+ const virtualListEmits = defineHookEmits({
798
+ scrollEnd: () => true,
799
+ scrollStart: () => true,
800
+ scroll: (_) => true
801
+ });
802
+ const useVirtualList = defineHookComponent({
803
+ props: virtualListProps,
804
+ emits: virtualListEmits,
805
+ setup(props, context) {
806
+ const { emit } = context;
807
+ const scrollElementRef = elementRef();
808
+ const propsEstimateSize = props.estimateSize;
809
+ const estimateSize = typeof propsEstimateSize === "function" ? propsEstimateSize : () => propsEstimateSize;
810
+ const options = computed(() => {
811
+ return {
812
+ ...props.options || {},
813
+ count: props.count,
814
+ estimateSize,
815
+ horizontal: props.horizontal,
816
+ getScrollElement: () => scrollElementRef.value,
817
+ observeElementRect,
818
+ observeElementOffset,
819
+ scrollToFn: elementScroll
820
+ };
821
+ });
822
+ const virtualizer = new Virtualizer(options.value);
823
+ const state = shallowRef(virtualizer);
824
+ const virtualItems = computed(() => state.value.getVirtualItems());
825
+ const virtualIndexes = computed(() => state.value.getVirtualIndexes());
826
+ const totalSize = computed(() => state.value.getTotalSize());
827
+ watch(virtualIndexes, (indexes) => {
828
+ if (indexes.length === 0) return;
829
+ if (indexes[indexes.length - 1] === props.count - 1) emit("scrollEnd");
830
+ else if (indexes[0] === 0) emit("scrollStart");
831
+ emit("scroll", indexes);
832
+ }, { immediate: true });
833
+ watch(options, (opts) => {
834
+ virtualizer.setOptions({
835
+ ...opts,
836
+ onChange: (instance, sync) => {
837
+ opts.onChange?.(instance, sync);
838
+ triggerRef(state);
839
+ }
840
+ });
841
+ virtualizer._willUpdate();
842
+ triggerRef(state);
843
+ }, { immediate: true });
844
+ watch(scrollElementRef, (el) => {
845
+ if (el) {
846
+ virtualizer._willUpdate();
847
+ triggerRef(state);
848
+ }
849
+ }, { immediate: true });
850
+ tryOnScopeDispose(virtualizer._didMount());
851
+ const measureElement = (el) => {
852
+ virtualizer.measureElement(el);
853
+ };
854
+ const scrollToIndex = (index, options = { behavior: "smooth" }) => {
855
+ virtualizer.scrollToIndex(index, options);
856
+ };
857
+ const scrollToStart = (options = { behavior: "smooth" }) => {
858
+ scrollToIndex(0, options);
859
+ };
860
+ const scrollToEnd = (options = { behavior: "smooth" }) => {
861
+ scrollToIndex(props.count - 1, options);
862
+ };
863
+ return {
864
+ virtualizer,
865
+ virtualItems,
866
+ virtualIndexes,
867
+ totalSize,
868
+ scrollElementRef,
869
+ measureElement,
870
+ scrollToIndex,
871
+ scrollToStart,
872
+ scrollToEnd
873
+ };
874
+ }
875
+ });
876
+
877
+ //#endregion
878
+ //#region index.ts
879
+ var core_exports = /* @__PURE__ */ __exportAll({
880
+ AFFIX_TARGET_KEY: () => AFFIX_TARGET_KEY,
881
+ affixEmits: () => affixEmits,
882
+ affixProps: () => affixProps,
883
+ configProviderProps: () => configProviderProps,
884
+ fileUploadEmits: () => fileUploadEmits,
885
+ fileUploadProps: () => fileUploadProps,
886
+ iconProps: () => iconProps,
887
+ itemEmits: () => itemEmits,
888
+ itemProps: () => itemProps,
889
+ popoverEmits: () => popoverEmits,
890
+ popoverProps: () => popoverProps,
891
+ provideAffixTarget: () => provideAffixTarget,
892
+ selectionEmits: () => selectionEmits,
893
+ selectionProps: () => selectionProps,
894
+ switchEmits: () => switchEmits,
895
+ switchProps: () => switchProps,
896
+ useAffix: () => useAffix,
897
+ useFileUpload: () => useFileUpload,
898
+ useIcon: () => useIcon,
899
+ usePopover: () => usePopover,
900
+ useSelectionContext: () => useSelectionContext,
901
+ useSelectionItem: () => useSelectionItem,
902
+ useSelectionList: () => useSelectionList,
903
+ useSwitch: () => useSwitch,
904
+ useVirtualList: () => useVirtualList,
905
+ virtualListEmits: () => virtualListEmits,
906
+ virtualListProps: () => virtualListProps
907
+ });
908
+
909
+ //#endregion
910
+ export { AFFIX_TARGET_KEY, affixEmits, affixProps, configProviderProps, fileUploadEmits, fileUploadProps, iconProps, itemEmits, itemProps, popoverEmits, popoverProps, provideAffixTarget, selectionEmits, selectionProps, switchEmits, switchProps, useAffix, useFileUpload, useIcon, usePopover, useSelectionContext, useSelectionItem, useSelectionList, useSwitch, useVirtualList, virtualListEmits, virtualListProps };