@sit-onyx/headless 0.4.0-dev-20251110091137 → 0.4.0-dev-20251111095201

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.
@@ -9,7 +9,7 @@ export type UseOutsideClickOptions<TCheckOnTab extends boolean | undefined = und
9
9
  /**
10
10
  * Callback when an outside click occurred.
11
11
  */
12
- onOutsideClick: (event: TCheckOnTab extends true ? MouseEvent | KeyboardEvent : MouseEvent) => void;
12
+ onOutsideClick: (event: TCheckOnTab extends true ? MouseEvent | KeyboardEvent | FocusEvent : MouseEvent) => void;
13
13
  /**
14
14
  * Whether the outside focus should also be checked when pressing the Tab key.
15
15
  */
@@ -99,4 +99,5 @@ export declare const createListbox: <TValue extends ListboxValue, TMultiple exte
99
99
  isFocused: Ref<boolean, boolean>;
100
100
  }, {
101
101
  getOptionId: (value: TValue) => string;
102
+ getOptionValueById: (id: string) => TValue | undefined;
102
103
  }>;
package/dist/index.js CHANGED
@@ -392,12 +392,42 @@ const useOutsideClick = ({
392
392
  };
393
393
  useGlobalEventListener({ type: "mousedown", listener: clickListener, disabled });
394
394
  if (checkOnTab) {
395
- const keydownListener = async (event) => {
395
+ const keydownListener = (event) => {
396
396
  if (event.key !== "Tab") return;
397
- await new Promise((resolve) => setTimeout(resolve));
398
397
  if (isOutsideClick(document.activeElement)) {
399
398
  onOutsideClick(event);
400
399
  }
400
+ const controller = new AbortController();
401
+ const { signal } = controller;
402
+ const onFocusIn = (event2) => {
403
+ const target = event2.target;
404
+ if (isOutsideClick(target)) {
405
+ onOutsideClick(event2);
406
+ }
407
+ controller.abort();
408
+ };
409
+ const onWindowBlur = (event2) => {
410
+ if (isOutsideClick(document.activeElement)) {
411
+ onOutsideClick(event2);
412
+ }
413
+ controller.abort();
414
+ };
415
+ const onKeyUp = (e) => {
416
+ if (e.key === "Tab") controller.abort();
417
+ };
418
+ document.addEventListener("focusin", onFocusIn, {
419
+ once: true,
420
+ capture: true,
421
+ // Capture phase to handle before component focus handlers
422
+ signal
423
+ });
424
+ window.addEventListener("blur", onWindowBlur, { once: true, signal });
425
+ document.addEventListener("keyup", onKeyUp, {
426
+ once: true,
427
+ capture: true,
428
+ // Capture phase to prevent conflicts with prevented keydown
429
+ signal
430
+ });
401
431
  };
402
432
  useGlobalEventListener({ type: "keydown", listener: keydownListener, disabled });
403
433
  }
@@ -434,6 +464,10 @@ const createListbox = createBuilder(
434
464
  }
435
465
  return descendantKeyIdMap.get(value);
436
466
  };
467
+ const getOptionValueById = (id) => {
468
+ const entries = Array.from(descendantKeyIdMap.entries());
469
+ return entries.find(([_value, key]) => key === id)?.[0];
470
+ };
437
471
  const isFocused = ref(false);
438
472
  watchEffect(async () => {
439
473
  if (!isExpanded.value || options.activeOption.value == void 0 || !isFocused.value && !options.controlled) {
@@ -527,7 +561,8 @@ const createListbox = createBuilder(
527
561
  isFocused
528
562
  },
529
563
  internals: {
530
- getOptionId
564
+ getOptionId,
565
+ getOptionValueById
531
566
  }
532
567
  };
533
568
  }
@@ -646,7 +681,7 @@ const createComboBox = createBuilder(
646
681
  });
647
682
  const {
648
683
  elements: { option, group, listbox },
649
- internals: { getOptionId }
684
+ internals: { getOptionId, getOptionValueById }
650
685
  } = createListbox({
651
686
  label: listLabel,
652
687
  description: listDescription,
@@ -697,7 +732,8 @@ const createComboBox = createBuilder(
697
732
  tabindex: "-1",
698
733
  onClick: () => onToggle?.()
699
734
  }))
700
- }
735
+ },
736
+ internals: { getOptionId, getOptionValueById }
701
737
  };
702
738
  }
703
739
  );
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sit-onyx/headless",
3
3
  "description": "Headless composables for Vue",
4
- "version": "0.4.0-dev-20251110091137",
4
+ "version": "0.4.0-dev-20251111095201",
5
5
  "type": "module",
6
6
  "author": "Schwarz IT KG",
7
7
  "license": "Apache-2.0",