@pega/cosmos-react-core 3.0.8 → 3.0.10

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.
@@ -1 +1 @@
1
- {"version":3,"file":"useFocusWithin.d.ts","sourceRoot":"","sources":["../../src/hooks/useFocusWithin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,SAAS,EAAuB,MAAM,OAAO,CAAC;AAI5E;;;;GAIG;AACH,QAAA,MAAM,cAAc,8GAEU,OAAO,wBAAwB,IAAI,kBAC9D,OA8EF,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"useFocusWithin.d.ts","sourceRoot":"","sources":["../../src/hooks/useFocusWithin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,SAAS,EAAuB,MAAM,OAAO,CAAC;AAI5E;;;;GAIG;AACH,QAAA,MAAM,cAAc,8GAEU,OAAO,wBAAwB,IAAI,kBAC9D,OA4FF,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -8,13 +8,16 @@ import { normalizeElements } from '../utils';
8
8
  const useFocusWithin = (els, onFocusChange) => {
9
9
  const [hasFocus, setFocus] = useState(false);
10
10
  const focusedElRef = useRef(null);
11
- const blurTimerRef = useRef();
12
- const elsRef = useRef(els);
13
- elsRef.current = els;
11
+ const handlerAbortControllerRef = useRef();
12
+ useEffect(() => {
13
+ return () => {
14
+ handlerAbortControllerRef.current?.abort();
15
+ };
16
+ }, []);
14
17
  const onBlur = useCallback(({ relatedTarget }) => {
15
18
  if (!hasFocus)
16
19
  return;
17
- const elements = normalizeElements(elsRef.current);
20
+ const elements = normalizeElements(els);
18
21
  if (relatedTarget instanceof Node) {
19
22
  // changing focus to another relevant child doesn't count
20
23
  const focusedEl = elements.find(el => el?.contains(relatedTarget));
@@ -24,19 +27,36 @@ const useFocusWithin = (els, onFocusChange) => {
24
27
  return;
25
28
  }
26
29
  }
27
- clearTimeout(blurTimerRef.current);
28
- blurTimerRef.current = setTimeout(() => {
30
+ // Code below is similar to the useOuterEvent hook, but single-shot only and need to be attached
31
+ // after blur event only. Due to various order of events between browsers and OSes, we need to
32
+ // postpone calling 'onBlur' callback until next element gets focus or on outer click to check
33
+ // if the relevant element contains the target element, which means the focus is retained.
34
+ const handlerAbortController = new AbortController();
35
+ const handler = (e) => {
29
36
  if (!elements.some(el => {
30
- return el?.contains(document.activeElement);
37
+ return el?.contains(e.target);
31
38
  })) {
32
39
  setFocus(false);
33
40
  onFocusChange?.(false, focusedElRef.current);
34
41
  focusedElRef.current = null;
35
42
  }
43
+ handlerAbortController.abort();
44
+ };
45
+ // For keyboard and SR navigation - wait for 'focusin'.
46
+ document.addEventListener('focusin', handler, {
47
+ once: true,
48
+ signal: handlerAbortController.signal
36
49
  });
37
- }, [hasFocus, onFocusChange]);
50
+ // For mouse and touch navigation - wait for 'mouseup'.
51
+ // The chosen event need to occur before 'click' to allow the given callback code finish before
52
+ // 'click' handlers.
53
+ document.addEventListener('mouseup', handler, {
54
+ once: true,
55
+ signal: handlerAbortController.signal
56
+ });
57
+ handlerAbortControllerRef.current = handlerAbortController;
58
+ }, [hasFocus, onFocusChange, els]);
38
59
  const onFocus = useCallback(({ currentTarget }) => {
39
- clearTimeout(blurTimerRef.current);
40
60
  if (!hasFocus) {
41
61
  setFocus(true);
42
62
  const targetEl = currentTarget;
@@ -57,10 +77,6 @@ const useFocusWithin = (els, onFocusChange) => {
57
77
  });
58
78
  };
59
79
  }, [els, onFocus, onBlur]);
60
- // Clear timeout when component un-mounts.
61
- useEffect(() => () => {
62
- clearTimeout(blurTimerRef.current);
63
- }, []);
64
80
  return hasFocus;
65
81
  };
66
82
  export default useFocusWithin;
@@ -1 +1 @@
1
- {"version":3,"file":"useFocusWithin.js","sourceRoot":"","sources":["../../src/hooks/useFocusWithin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAa,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C;;;;GAIG;AACH,MAAM,cAAc,GAAG,CACrB,GAAuC,EACvC,aAA+D,EACtD,EAAE;IACX,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,MAAM,CAAW,IAAI,CAAC,CAAC;IAC5C,MAAM,YAAY,GAAG,MAAM,EAAU,CAAC;IAEtC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC;IAErB,MAAM,MAAM,GAAG,WAAW,CACxB,CAAC,EAAE,aAAa,EAAc,EAAE,EAAE;QAChC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEnD,IAAI,aAAa,YAAY,IAAI,EAAE;YACjC,yDAAyD;YACzD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;YACnE,IAAI,SAAS,EAAE;gBACb,6CAA6C;gBAC7C,YAAY,CAAC,OAAO,GAAG,SAAS,CAAC;gBACjC,OAAO;aACR;SACF;QAED,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACnC,YAAY,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YACrC,IACE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;gBAClB,OAAO,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;YAC9C,CAAC,CAAC,EACF;gBACA,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAChB,aAAa,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;gBAC7C,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC;aAC7B;QACH,CAAC,CAAC,CAAC;IACL,CAAC,EACD,CAAC,QAAQ,EAAE,aAAa,CAAC,CAC1B,CAAC;IAEF,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,EAAE,aAAa,EAAc,EAAE,EAAE;QAChC,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAEnC,IAAI,CAAC,QAAQ,EAAE;YACb,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,MAAM,QAAQ,GAAG,aAAkB,CAAC;YACpC,aAAa,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAChC,YAAY,CAAC,OAAO,GAAG,QAAQ,CAAC;SACjC;IACH,CAAC,EACD,CAAC,QAAQ,EAAE,aAAa,CAAC,CAC1B,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAExC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;YACpB,EAAE,EAAE,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACzC,EAAE,EAAE,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;gBACpB,EAAE,EAAE,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBAC5C,EAAE,EAAE,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC9C,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAE3B,0CAA0C;IAC1C,SAAS,CACP,GAAG,EAAE,CAAC,GAAG,EAAE;QACT,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC,EACD,EAAE,CACH,CAAC;IAEF,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["import { useState, useEffect, RefObject, useCallback, useRef } from 'react';\n\nimport { normalizeElements } from '../utils';\n\n/** Hook for properly handling focus state of children components.\n * @example const hasFocus = useFocusWithin([containerRef, ...], (isFocused, element) => { doSomething; });\n * @param onFocusChange Callback function that is invoked with the current focus state and the current element when any child elements takes focus or all of them lose focus.\n * @returns * hasFocus:: A boolean indicating if the ref element has focus or not.\n */\nconst useFocusWithin = <T extends HTMLElement = HTMLElement>(\n els: (T | null | RefObject<T | null>)[],\n onFocusChange?: (isFocused: boolean, element: T | null) => void\n): boolean => {\n const [hasFocus, setFocus] = useState(false);\n const focusedElRef = useRef<T | null>(null);\n const blurTimerRef = useRef<number>();\n\n const elsRef = useRef(els);\n elsRef.current = els;\n\n const onBlur = useCallback(\n ({ relatedTarget }: FocusEvent) => {\n if (!hasFocus) return;\n\n const elements = normalizeElements(elsRef.current);\n\n if (relatedTarget instanceof Node) {\n // changing focus to another relevant child doesn't count\n const focusedEl = elements.find(el => el?.contains(relatedTarget));\n if (focusedEl) {\n // ... just update the currently focused item\n focusedElRef.current = focusedEl;\n return;\n }\n }\n\n clearTimeout(blurTimerRef.current);\n blurTimerRef.current = setTimeout(() => {\n if (\n !elements.some(el => {\n return el?.contains(document.activeElement);\n })\n ) {\n setFocus(false);\n onFocusChange?.(false, focusedElRef.current);\n focusedElRef.current = null;\n }\n });\n },\n [hasFocus, onFocusChange]\n );\n\n const onFocus = useCallback(\n ({ currentTarget }: FocusEvent) => {\n clearTimeout(blurTimerRef.current);\n\n if (!hasFocus) {\n setFocus(true);\n const targetEl = currentTarget as T;\n onFocusChange?.(true, targetEl);\n focusedElRef.current = targetEl;\n }\n },\n [hasFocus, onFocusChange]\n );\n\n useEffect(() => {\n const elements = normalizeElements(els);\n\n elements.forEach(el => {\n el?.addEventListener('focusin', onFocus);\n el?.addEventListener('focusout', onBlur);\n });\n return () => {\n elements.forEach(el => {\n el?.removeEventListener('focusin', onFocus);\n el?.removeEventListener('focusout', onBlur);\n });\n };\n }, [els, onFocus, onBlur]);\n\n // Clear timeout when component un-mounts.\n useEffect(\n () => () => {\n clearTimeout(blurTimerRef.current);\n },\n []\n );\n\n return hasFocus;\n};\n\nexport default useFocusWithin;\n"]}
1
+ {"version":3,"file":"useFocusWithin.js","sourceRoot":"","sources":["../../src/hooks/useFocusWithin.ts"],"names":[],"mappings":"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","sourcesContent":["import { useState, useEffect, RefObject, useCallback, useRef } from 'react';\n\nimport { normalizeElements } from '../utils';\n\n/** Hook for properly handling focus state of children components.\n * @example const hasFocus = useFocusWithin([containerRef, ...], (isFocused, element) => { doSomething; });\n * @param onFocusChange Callback function that is invoked with the current focus state and the current element when any child elements takes focus or all of them lose focus.\n * @returns * hasFocus:: A boolean indicating if the ref element has focus or not.\n */\nconst useFocusWithin = <T extends HTMLElement = HTMLElement>(\n els: (T | null | RefObject<T | null>)[],\n onFocusChange?: (isFocused: boolean, element: T | null) => void\n): boolean => {\n const [hasFocus, setFocus] = useState(false);\n const focusedElRef = useRef<T | null>(null);\n\n const handlerAbortControllerRef = useRef<AbortController>();\n useEffect(() => {\n return () => {\n handlerAbortControllerRef.current?.abort();\n };\n }, []);\n\n const onBlur = useCallback(\n ({ relatedTarget }: FocusEvent) => {\n if (!hasFocus) return;\n\n const elements = normalizeElements(els);\n\n if (relatedTarget instanceof Node) {\n // changing focus to another relevant child doesn't count\n const focusedEl = elements.find(el => el?.contains(relatedTarget));\n if (focusedEl) {\n // ... just update the currently focused item\n focusedElRef.current = focusedEl;\n return;\n }\n }\n\n // Code below is similar to the useOuterEvent hook, but single-shot only and need to be attached\n // after blur event only. Due to various order of events between browsers and OSes, we need to\n // postpone calling 'onBlur' callback until next element gets focus or on outer click to check\n // if the relevant element contains the target element, which means the focus is retained.\n const handlerAbortController = new AbortController();\n const handler = (e: FocusEvent | MouseEvent) => {\n if (\n !elements.some(el => {\n return el?.contains(e.target as Node);\n })\n ) {\n setFocus(false);\n onFocusChange?.(false, focusedElRef.current);\n focusedElRef.current = null;\n }\n handlerAbortController.abort();\n };\n\n // For keyboard and SR navigation - wait for 'focusin'.\n document.addEventListener('focusin', handler, {\n once: true,\n signal: handlerAbortController.signal\n });\n\n // For mouse and touch navigation - wait for 'mouseup'.\n // The chosen event need to occur before 'click' to allow the given callback code finish before\n // 'click' handlers.\n document.addEventListener('mouseup', handler, {\n once: true,\n signal: handlerAbortController.signal\n });\n\n handlerAbortControllerRef.current = handlerAbortController;\n },\n [hasFocus, onFocusChange, els]\n );\n\n const onFocus = useCallback(\n ({ currentTarget }: FocusEvent) => {\n if (!hasFocus) {\n setFocus(true);\n const targetEl = currentTarget as T;\n onFocusChange?.(true, targetEl);\n focusedElRef.current = targetEl;\n }\n },\n [hasFocus, onFocusChange]\n );\n\n useEffect(() => {\n const elements = normalizeElements(els);\n\n elements.forEach(el => {\n el?.addEventListener('focusin', onFocus);\n el?.addEventListener('focusout', onBlur);\n });\n return () => {\n elements.forEach(el => {\n el?.removeEventListener('focusin', onFocus);\n el?.removeEventListener('focusout', onBlur);\n });\n };\n }, [els, onFocus, onBlur]);\n\n return hasFocus;\n};\n\nexport default useFocusWithin;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pega/cosmos-react-core",
3
- "version": "3.0.8",
3
+ "version": "3.0.10",
4
4
  "description": "Cosmos is a visual design system and UI component collection. Its goal is to empower application developers in their pursuit to create engaging and rewarding user experiences.",
5
5
  "author": "Pegasystems",
6
6
  "license": "SEE LICENSE IN LICENSE",