@zayne-labs/ui-react 0.7.0 → 0.7.2
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/esm/common/await/index.js +1 -1
- package/dist/esm/common/await/index.js.map +1 -1
- package/dist/esm/common/show/index.d.ts +1 -1
- package/dist/esm/common/show/index.js +1 -1
- package/dist/esm/common/show/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/esm/common/focus-scope/index.d.ts +0 -32
- package/dist/esm/common/focus-scope/index.js +0 -232
- package/dist/esm/common/focus-scope/index.js.map +0 -1
|
@@ -16,7 +16,7 @@ function AwaitInner(props) {
|
|
|
16
16
|
const { asChild, children, promise, render } = props;
|
|
17
17
|
const result = use(promise);
|
|
18
18
|
const Component = asChild ? Slot : Fragment;
|
|
19
|
-
const componentProps = asChild && { promise };
|
|
19
|
+
const componentProps = asChild && { promise, result };
|
|
20
20
|
let resolvedChildren;
|
|
21
21
|
switch (true) {
|
|
22
22
|
case typeof children === "function": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/common/await/await.tsx"],"names":["ReactFragment"],"mappings":";;;;;;AAkBO,SAAS,MAAc,KAA2B,EAAA;AACxD,EAAA,MAAM,EAAE,aAAe,EAAA,QAAA,EAAU,iBAAiB,uBAAyB,EAAA,GAAG,aAAgB,GAAA,KAAA;AAE9F,EAAA,MAAM,iBACL,GAAA,cAAA,KAAmB,eAAmB,IAAA,cAAA,KAAmB,0BACtD,aACA,GAAAA,QAAA;AAEJ,EAAA,MAAM,YACL,GAAA,cAAA,KAAmB,eAAmB,IAAA,cAAA,KAAmB,0BACtD,QACA,GAAAA,QAAA;AAEJ,EAAA,MAAM,qBAAqB,OAAQ,CAAA,aAAa,CAAK,IAAA,EAAE,UAAU,aAAc,EAAA;AAE/E,EAAA,MAAM,aAAgB,GAAA,OAAA,CAAQ,QAAQ,CAAA,IAAK,EAAE,QAAS,EAAA;AAEtD,EAAA,uBACE,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAmB,GAAG,kBAAA,EAAA,kBACrB,KAAA,CAAA,aAAA,CAAA,YAAA,EAAA,EAAc,GAAG,aAAA,EAAA,kBAChB,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAY,GAAG,WAAA,EAAa,CAC9B,CACD,CAAA;AAEF;AAOA,SAAS,WAAmB,KAAgC,EAAA;AAC3D,EAAA,MAAM,EAAE,OAAA,EAAS,QAAU,EAAA,OAAA,EAAS,QAAW,GAAA,KAAA;AAE/C,EAAM,MAAA,MAAA,GAAS,IAAI,OAAO,CAAA;AAE1B,EAAM,MAAA,SAAA,GAAY,UAAU,IAAO,GAAAA,QAAA;AAEnC,
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/common/await/await.tsx"],"names":["ReactFragment"],"mappings":";;;;;;AAkBO,SAAS,MAAc,KAA2B,EAAA;AACxD,EAAA,MAAM,EAAE,aAAe,EAAA,QAAA,EAAU,iBAAiB,uBAAyB,EAAA,GAAG,aAAgB,GAAA,KAAA;AAE9F,EAAA,MAAM,iBACL,GAAA,cAAA,KAAmB,eAAmB,IAAA,cAAA,KAAmB,0BACtD,aACA,GAAAA,QAAA;AAEJ,EAAA,MAAM,YACL,GAAA,cAAA,KAAmB,eAAmB,IAAA,cAAA,KAAmB,0BACtD,QACA,GAAAA,QAAA;AAEJ,EAAA,MAAM,qBAAqB,OAAQ,CAAA,aAAa,CAAK,IAAA,EAAE,UAAU,aAAc,EAAA;AAE/E,EAAA,MAAM,aAAgB,GAAA,OAAA,CAAQ,QAAQ,CAAA,IAAK,EAAE,QAAS,EAAA;AAEtD,EAAA,uBACE,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAmB,GAAG,kBAAA,EAAA,kBACrB,KAAA,CAAA,aAAA,CAAA,YAAA,EAAA,EAAc,GAAG,aAAA,EAAA,kBAChB,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAY,GAAG,WAAA,EAAa,CAC9B,CACD,CAAA;AAEF;AAOA,SAAS,WAAmB,KAAgC,EAAA;AAC3D,EAAA,MAAM,EAAE,OAAA,EAAS,QAAU,EAAA,OAAA,EAAS,QAAW,GAAA,KAAA;AAE/C,EAAM,MAAA,MAAA,GAAS,IAAI,OAAO,CAAA;AAE1B,EAAM,MAAA,SAAA,GAAY,UAAU,IAAO,GAAAA,QAAA;AAEnC,EAAA,MAAM,cAAiB,GAAA,OAAA,IAAW,EAAE,OAAA,EAAS,MAAO,EAAA;AAEpD,EAAI,IAAA,gBAAA;AAEJ,EAAA,QAAQ,IAAM;AAAA,IACb,KAAK,OAAO,QAAA,KAAa,UAAY,EAAA;AACpC,MAAA,gBAAA,GAAmB,SAAS,MAAM,CAAA;AAClC,MAAA;AAAA;AACD,IACA,KAAK,OAAO,MAAA,KAAW,UAAY,EAAA;AAClC,MAAA,gBAAA,GAAmB,OAAO,MAAM,CAAA;AAChC,MAAA;AAAA;AACD,IACA,SAAS;AACR,MAAA,gBAAA,GAAmB,QAAY,IAAA,MAAA;AAC/B,MAAA;AAAA;AACD;AAGD,EAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,SAAA,EAAA,EAAW,GAAG,cAAA,EAAA,EAAiB,gBAAiB,CAAA;AACzD","file":"index.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport type { DiscriminatedRenderProps } from \"@zayne-labs/toolkit-react/utils\";\nimport { Fragment as ReactFragment, Suspense, use } from \"react\";\nimport { ErrorBoundary } from \"../error-boundary\";\nimport { Slot } from \"../slot\";\nimport type { SuspenseWithBoundaryProps } from \"../suspense-with-boundary\";\n\ntype RenderPropFn<TValue> = (result: TValue) => React.ReactNode;\n\ntype AwaitProps<TValue> = AwaitInnerProps<TValue>\n\t& Pick<SuspenseWithBoundaryProps, \"errorFallback\" | \"fallback\"> & {\n\t\tasChild?: boolean;\n\t\twrapperVariant?: \"none\" | \"only-boundary\" | \"only-suspense\" | \"suspense-and-boundary\";\n\t};\n\nexport function Await<TValue>(props: AwaitProps<TValue>) {\n\tconst { errorFallback, fallback, wrapperVariant = \"suspense-and-boundary\", ...restOfProps } = props;\n\n\tconst WithErrorBoundary =\n\t\twrapperVariant === \"only-boundary\" || wrapperVariant === \"suspense-and-boundary\"\n\t\t\t? ErrorBoundary\n\t\t\t: ReactFragment;\n\n\tconst WithSuspense =\n\t\twrapperVariant === \"only-suspense\" || wrapperVariant === \"suspense-and-boundary\"\n\t\t\t? Suspense\n\t\t\t: ReactFragment;\n\n\tconst errorBoundaryProps = Boolean(errorFallback) && { fallback: errorFallback };\n\n\tconst suspenseProps = Boolean(fallback) && { fallback };\n\n\treturn (\n\t\t<WithErrorBoundary {...errorBoundaryProps}>\n\t\t\t<WithSuspense {...suspenseProps}>\n\t\t\t\t<AwaitInner {...restOfProps} />\n\t\t\t</WithSuspense>\n\t\t</WithErrorBoundary>\n\t);\n}\n\nexport type AwaitInnerProps<TValue> = DiscriminatedRenderProps<React.ReactNode | RenderPropFn<TValue>> & {\n\tasChild?: boolean;\n\tpromise: Promise<TValue>;\n};\n\nfunction AwaitInner<TValue>(props: AwaitInnerProps<TValue>) {\n\tconst { asChild, children, promise, render } = props;\n\n\tconst result = use(promise);\n\n\tconst Component = asChild ? Slot : ReactFragment;\n\n\tconst componentProps = asChild && { promise, result };\n\n\tlet resolvedChildren: React.ReactNode;\n\n\tswitch (true) {\n\t\tcase typeof children === \"function\": {\n\t\t\tresolvedChildren = children(result);\n\t\t\tbreak;\n\t\t}\n\t\tcase typeof render === \"function\": {\n\t\t\tresolvedChildren = render(result);\n\t\t\tbreak;\n\t\t}\n\t\tdefault: {\n\t\t\tresolvedChildren = children ?? render;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn <Component {...componentProps}>{resolvedChildren}</Component>;\n}\n"]}
|
|
@@ -20,7 +20,7 @@ declare namespace ShowFallback {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
declare namespace showParts {
|
|
23
|
-
export { ShowContent as Content, ShowFallback as Fallback, ShowFallback as
|
|
23
|
+
export { ShowContent as Content, ShowFallback as Fallback, ShowFallback as Otherwise, ShowRoot as Root };
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export { showParts as Show, ShowContent, ShowFallback, ShowRoot };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/common/show/show.tsx","../../../../src/components/common/show/show-parts.ts"],"names":[],"mappings":";;;;;AAaO,SAAS,QAAgB,CAAA,EAAE,QAAU,EAAA,QAAA,EAAU,MAA0B,EAAA;AAC/E,EAAA,IAAA,CAAK,QAAQ,IAAQ,IAAA,IAAA,KAAS,UAAU,CAAC,UAAA,CAAW,QAAQ,CAAG,EAAA;AAC9D,IAAM,MAAA,YAAA,GAAe,aAAc,CAAA,QAAA,EAAU,YAAc,EAAA;AAAA,MAC1D,YAAc,EAAA,mEAAA;AAAA,MACd,wBAA0B,EAAA;AAAA,KAC1B,CAAA;AAED,IAAA,IAAI,gBAAgB,QAAU,EAAA;AAC7B,MAAA,MAAM,IAAI,cAAe,CAAA;AAAA;AAAA,EAEzB,CAAA,CAAA;AAAA;AAGD,IAAA,OAAO,YAAgB,IAAA,QAAA;AAAA;AAGxB,EAAI,IAAA,IAAA,IAAQ,IAAQ,IAAA,IAAA,KAAS,KAAO,EAAA;AACnC,IAAO,OAAA,QAAA;AAAA;AAGR,EAAA,MAAM,mBAAmB,UAAW,CAAA,QAAQ,CAAI,GAAA,QAAA,CAAS,IAAI,CAAI,GAAA,QAAA;AAEjE,EAAM,MAAA,WAAA,GAAc,aAAc,CAAA,gBAAA,EAAkB,WAAa,EAAA;AAAA,IAChE,YAAc,EAAA,8CAAA;AAAA,IACd,wBAA0B,EAAA;AAAA,GAC1B,CAAA;AAED,EAAA,MAAM,kBAAkB,kBAAmB,CAAA,gBAAA,EAAkB,CAAC,YAAA,EAAc,WAAW,CAAC,CAAA;AAExF,EAAA,OAAO,WAAe,IAAA,eAAA;AACvB;AAEO,SAAS,WAAA,CAAY,EAAE,QAAA,EAA2C,EAAA;AACxE,EAAO,OAAA,QAAA;AACR;AACA,WAAY,CAAA,UAAA,GAAa,OAAO,SAAS,CAAA;AAElC,SAAS,YAAA,CAAa,EAAE,QAAA,EAA2C,EAAA;AACzE,EAAO,OAAA,QAAA;AACR;AACA,YAAa,CAAA,UAAA,GAAa,OAAO,eAAe,CAAA;;;ACrDhD,IAAA,kBAAA,GAAA;AAAA,QAAA,CAAA,kBAAA,EAAA;AAAA,EAAA,OAAA,EAAA,MAAA,WAAA;AAAA,EAAA,QAAA,EAAA,MAAA,YAAA;AAAA,EAAA,SAAA,EAAA,MAAA,YAAA;AAAA,EAAA,IAAA,EAAA,MAAA;AAAA,CAAA,CAAA","file":"index.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { getRegularChildren, getSingleSlot } from \"@zayne-labs/toolkit-react/utils\";\nimport { AssertionError, isFunction } from \"@zayne-labs/toolkit-type-helpers\";\n\ntype ShowProps<TWhen> = {\n\tchildren: React.ReactNode | ((whenValue: TWhen) => React.ReactNode);\n\tfallback?: React.ReactNode;\n\twhen: false | TWhen | null | undefined;\n};\n\nexport function ShowRoot<TWhen>({ children, fallback, when }: ShowProps<TWhen>) {\n\tif ((when == null || when === false) && !isFunction(children)) {\n\t\tconst fallBackSlot = getSingleSlot(children, ShowFallback, {\n\t\t\terrorMessage: \"Only one <Show.Fallback> or <Show.OtherWise> component is allowed\",\n\t\t\tthrowOnMultipleSlotMatch: true,\n\t\t});\n\n\t\tif (fallBackSlot && fallback) {\n\t\t\tthrow new AssertionError(`\n\t\t\tThe fallback prop and <Show.Fallback>/<Show.OtherWise> cannot be used at the same time.\n\t\t`);\n\t\t}\n\n\t\treturn fallBackSlot ?? fallback;\n\t}\n\n\tif (when == null || when === false) {\n\t\treturn fallback;\n\t}\n\n\tconst resolvedChildren = isFunction(children) ? children(when) : children;\n\n\tconst contentSlot = getSingleSlot(resolvedChildren, ShowContent, {\n\t\terrorMessage: \"Only one <Show.Content> component is allowed\",\n\t\tthrowOnMultipleSlotMatch: true,\n\t});\n\n\tconst regularChildren = getRegularChildren(resolvedChildren, [ShowFallback, ShowContent]);\n\n\treturn contentSlot ?? regularChildren;\n}\n\nexport function ShowContent({ children }: { children: React.ReactNode }) {\n\treturn children;\n}\nShowContent.slotSymbol = Symbol(\"content\");\n\nexport function ShowFallback({ children }: { children: React.ReactNode }) {\n\treturn children;\n}\nShowFallback.slotSymbol = Symbol(\"show-fallback\");\n","export {\n\tShowContent as Content,\n\tShowFallback as Fallback,\n\tShowFallback as
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/common/show/show.tsx","../../../../src/components/common/show/show-parts.ts"],"names":[],"mappings":";;;;;AAaO,SAAS,QAAgB,CAAA,EAAE,QAAU,EAAA,QAAA,EAAU,MAA0B,EAAA;AAC/E,EAAA,IAAA,CAAK,QAAQ,IAAQ,IAAA,IAAA,KAAS,UAAU,CAAC,UAAA,CAAW,QAAQ,CAAG,EAAA;AAC9D,IAAM,MAAA,YAAA,GAAe,aAAc,CAAA,QAAA,EAAU,YAAc,EAAA;AAAA,MAC1D,YAAc,EAAA,mEAAA;AAAA,MACd,wBAA0B,EAAA;AAAA,KAC1B,CAAA;AAED,IAAA,IAAI,gBAAgB,QAAU,EAAA;AAC7B,MAAA,MAAM,IAAI,cAAe,CAAA;AAAA;AAAA,EAEzB,CAAA,CAAA;AAAA;AAGD,IAAA,OAAO,YAAgB,IAAA,QAAA;AAAA;AAGxB,EAAI,IAAA,IAAA,IAAQ,IAAQ,IAAA,IAAA,KAAS,KAAO,EAAA;AACnC,IAAO,OAAA,QAAA;AAAA;AAGR,EAAA,MAAM,mBAAmB,UAAW,CAAA,QAAQ,CAAI,GAAA,QAAA,CAAS,IAAI,CAAI,GAAA,QAAA;AAEjE,EAAM,MAAA,WAAA,GAAc,aAAc,CAAA,gBAAA,EAAkB,WAAa,EAAA;AAAA,IAChE,YAAc,EAAA,8CAAA;AAAA,IACd,wBAA0B,EAAA;AAAA,GAC1B,CAAA;AAED,EAAA,MAAM,kBAAkB,kBAAmB,CAAA,gBAAA,EAAkB,CAAC,YAAA,EAAc,WAAW,CAAC,CAAA;AAExF,EAAA,OAAO,WAAe,IAAA,eAAA;AACvB;AAEO,SAAS,WAAA,CAAY,EAAE,QAAA,EAA2C,EAAA;AACxE,EAAO,OAAA,QAAA;AACR;AACA,WAAY,CAAA,UAAA,GAAa,OAAO,SAAS,CAAA;AAElC,SAAS,YAAA,CAAa,EAAE,QAAA,EAA2C,EAAA;AACzE,EAAO,OAAA,QAAA;AACR;AACA,YAAa,CAAA,UAAA,GAAa,OAAO,eAAe,CAAA;;;ACrDhD,IAAA,kBAAA,GAAA;AAAA,QAAA,CAAA,kBAAA,EAAA;AAAA,EAAA,OAAA,EAAA,MAAA,WAAA;AAAA,EAAA,QAAA,EAAA,MAAA,YAAA;AAAA,EAAA,SAAA,EAAA,MAAA,YAAA;AAAA,EAAA,IAAA,EAAA,MAAA;AAAA,CAAA,CAAA","file":"index.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { getRegularChildren, getSingleSlot } from \"@zayne-labs/toolkit-react/utils\";\nimport { AssertionError, isFunction } from \"@zayne-labs/toolkit-type-helpers\";\n\ntype ShowProps<TWhen> = {\n\tchildren: React.ReactNode | ((whenValue: TWhen) => React.ReactNode);\n\tfallback?: React.ReactNode;\n\twhen: false | TWhen | null | undefined;\n};\n\nexport function ShowRoot<TWhen>({ children, fallback, when }: ShowProps<TWhen>) {\n\tif ((when == null || when === false) && !isFunction(children)) {\n\t\tconst fallBackSlot = getSingleSlot(children, ShowFallback, {\n\t\t\terrorMessage: \"Only one <Show.Fallback> or <Show.OtherWise> component is allowed\",\n\t\t\tthrowOnMultipleSlotMatch: true,\n\t\t});\n\n\t\tif (fallBackSlot && fallback) {\n\t\t\tthrow new AssertionError(`\n\t\t\tThe fallback prop and <Show.Fallback>/<Show.OtherWise> cannot be used at the same time.\n\t\t`);\n\t\t}\n\n\t\treturn fallBackSlot ?? fallback;\n\t}\n\n\tif (when == null || when === false) {\n\t\treturn fallback;\n\t}\n\n\tconst resolvedChildren = isFunction(children) ? children(when) : children;\n\n\tconst contentSlot = getSingleSlot(resolvedChildren, ShowContent, {\n\t\terrorMessage: \"Only one <Show.Content> component is allowed\",\n\t\tthrowOnMultipleSlotMatch: true,\n\t});\n\n\tconst regularChildren = getRegularChildren(resolvedChildren, [ShowFallback, ShowContent]);\n\n\treturn contentSlot ?? regularChildren;\n}\n\nexport function ShowContent({ children }: { children: React.ReactNode }) {\n\treturn children;\n}\nShowContent.slotSymbol = Symbol(\"content\");\n\nexport function ShowFallback({ children }: { children: React.ReactNode }) {\n\treturn children;\n}\nShowFallback.slotSymbol = Symbol(\"show-fallback\");\n","export {\n\tShowContent as Content,\n\tShowFallback as Fallback,\n\tShowFallback as Otherwise,\n\tShowRoot as Root,\n} from \"./show\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import * as react from 'react';
|
|
2
|
-
import { InferProps } from '@zayne-labs/toolkit-react/utils';
|
|
3
|
-
|
|
4
|
-
type FocusScopeElement = react.ComponentRef<"div">;
|
|
5
|
-
type FocusScopeProps = Omit<InferProps<"div">, "ref"> & {
|
|
6
|
-
/**
|
|
7
|
-
* When `true`, tabbing from last item will focus first tabbable
|
|
8
|
-
* and shift+tab from first item will focus last tababble.
|
|
9
|
-
* @defaultValue false
|
|
10
|
-
*/
|
|
11
|
-
loop?: boolean;
|
|
12
|
-
/**
|
|
13
|
-
* Event handler called when auto-focusing on mount.
|
|
14
|
-
* Can be prevented.
|
|
15
|
-
*/
|
|
16
|
-
onMountAutoFocus?: (event: Event) => void;
|
|
17
|
-
/**
|
|
18
|
-
* Event handler called when auto-focusing on unmount.
|
|
19
|
-
* Can be prevented.
|
|
20
|
-
*/
|
|
21
|
-
onUnmountAutoFocus?: (event: Event) => void;
|
|
22
|
-
ref?: react.Ref<FocusScopeElement>;
|
|
23
|
-
/**
|
|
24
|
-
* When `true`, focus cannot escape the focus scope via keyboard,
|
|
25
|
-
* pointer, or a programmatic focus.
|
|
26
|
-
* @defaultValue false
|
|
27
|
-
*/
|
|
28
|
-
trapped?: boolean;
|
|
29
|
-
};
|
|
30
|
-
declare function FocusScope(props: FocusScopeProps): react.JSX.Element;
|
|
31
|
-
|
|
32
|
-
export { FocusScope };
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import '../../chunk-PZ5AY32C.js';
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { useState, useRef, useEffect } from 'react';
|
|
4
|
-
import { useCallbackRef } from '@zayne-labs/toolkit-react';
|
|
5
|
-
import { composeRefs } from '@zayne-labs/toolkit-react/utils';
|
|
6
|
-
|
|
7
|
-
// src/components/common/focus-scope/utils.ts
|
|
8
|
-
var focusFirst = (candidates, options = {}) => {
|
|
9
|
-
const { select = false } = options;
|
|
10
|
-
const previouslyFocusedElement = document.activeElement;
|
|
11
|
-
for (const candidate of candidates) {
|
|
12
|
-
focusElement(candidate, { select });
|
|
13
|
-
if (document.activeElement !== previouslyFocusedElement) return;
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
var getTabbableEdges = (container) => {
|
|
17
|
-
const candidates = getTabbableCandidates(container);
|
|
18
|
-
const first = findVisible(candidates, container);
|
|
19
|
-
const last = findVisible(candidates.reverse(), container);
|
|
20
|
-
return [first, last];
|
|
21
|
-
};
|
|
22
|
-
var getTabbableCandidates = (container) => {
|
|
23
|
-
const nodes = [];
|
|
24
|
-
const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
|
|
25
|
-
acceptNode: (node) => {
|
|
26
|
-
const isHiddenInput = node.tagName === "INPUT" && node.type === "hidden";
|
|
27
|
-
if (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP;
|
|
28
|
-
return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
while (walker.nextNode()) {
|
|
32
|
-
nodes.push(walker.currentNode);
|
|
33
|
-
}
|
|
34
|
-
return nodes;
|
|
35
|
-
};
|
|
36
|
-
var findVisible = (elements, container) => {
|
|
37
|
-
if (elements.length === 0) return null;
|
|
38
|
-
let visibleElement = null;
|
|
39
|
-
for (const element of elements) {
|
|
40
|
-
if (!isHidden(element, { upTo: container })) {
|
|
41
|
-
visibleElement = element;
|
|
42
|
-
break;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return visibleElement;
|
|
46
|
-
};
|
|
47
|
-
var isHidden = (initialNode, options) => {
|
|
48
|
-
const { upTo } = options;
|
|
49
|
-
if (!initialNode || getComputedStyle(initialNode).visibility === "hidden") {
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
let currentNode = initialNode;
|
|
53
|
-
while (currentNode) {
|
|
54
|
-
if (upTo !== void 0 && currentNode === upTo) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
if (getComputedStyle(currentNode).display === "none") {
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
currentNode = currentNode.parentElement;
|
|
61
|
-
}
|
|
62
|
-
return false;
|
|
63
|
-
};
|
|
64
|
-
var isSelectableInput = (element) => {
|
|
65
|
-
return element instanceof HTMLInputElement && "select" in element;
|
|
66
|
-
};
|
|
67
|
-
var focusElement = (element, options = {}) => {
|
|
68
|
-
const { select = false } = options;
|
|
69
|
-
if (element && typeof element.focus === "function") {
|
|
70
|
-
const previouslyFocusedElement = document.activeElement;
|
|
71
|
-
element.focus({ preventScroll: true });
|
|
72
|
-
if (element !== previouslyFocusedElement && isSelectableInput(element) && select) {
|
|
73
|
-
element.select();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
var createFocusScopesStack = () => {
|
|
78
|
-
let stack = [];
|
|
79
|
-
const api = {
|
|
80
|
-
add(focusScope) {
|
|
81
|
-
const activeFocusScope = stack[0];
|
|
82
|
-
if (focusScope !== activeFocusScope) {
|
|
83
|
-
activeFocusScope?.pause();
|
|
84
|
-
}
|
|
85
|
-
stack = arrayRemove(stack, focusScope);
|
|
86
|
-
stack.unshift(focusScope);
|
|
87
|
-
},
|
|
88
|
-
remove(focusScope) {
|
|
89
|
-
stack = arrayRemove(stack, focusScope);
|
|
90
|
-
stack[0]?.resume();
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
return api;
|
|
94
|
-
};
|
|
95
|
-
var focusScopesStack = createFocusScopesStack();
|
|
96
|
-
var arrayRemove = (array, item) => {
|
|
97
|
-
const updatedArray = [...array];
|
|
98
|
-
const index = updatedArray.indexOf(item);
|
|
99
|
-
if (index !== -1) {
|
|
100
|
-
updatedArray.splice(index, 1);
|
|
101
|
-
}
|
|
102
|
-
return updatedArray;
|
|
103
|
-
};
|
|
104
|
-
var removeLinks = (items) => {
|
|
105
|
-
return items.filter((item) => item.tagName !== "A");
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
// src/components/common/focus-scope/focus-scope.tsx
|
|
109
|
-
var AUTOFOCUS_ON_MOUNT = "focusScope.autoFocusOnMount";
|
|
110
|
-
var AUTOFOCUS_ON_UNMOUNT = "focusScope.autoFocusOnUnmount";
|
|
111
|
-
var EVENT_OPTIONS = { bubbles: false, cancelable: true };
|
|
112
|
-
function FocusScope(props) {
|
|
113
|
-
const {
|
|
114
|
-
loop = false,
|
|
115
|
-
onMountAutoFocus,
|
|
116
|
-
onUnmountAutoFocus,
|
|
117
|
-
ref: forwardedRef,
|
|
118
|
-
trapped = false,
|
|
119
|
-
...scopeProps
|
|
120
|
-
} = props;
|
|
121
|
-
const [container, setContainer] = useState(null);
|
|
122
|
-
const savedOnMountAutoFocus = useCallbackRef(onMountAutoFocus);
|
|
123
|
-
const savedOnUnmountAutoFocus = useCallbackRef(onUnmountAutoFocus);
|
|
124
|
-
const lastFocusedElementRef = useRef(null);
|
|
125
|
-
const composedRefs = composeRefs([forwardedRef, (node) => setContainer(node)]);
|
|
126
|
-
const focusScope = useRef({
|
|
127
|
-
pause() {
|
|
128
|
-
this.paused = true;
|
|
129
|
-
},
|
|
130
|
-
paused: false,
|
|
131
|
-
resume() {
|
|
132
|
-
this.paused = false;
|
|
133
|
-
}
|
|
134
|
-
}).current;
|
|
135
|
-
useEffect(() => {
|
|
136
|
-
if (!trapped) return;
|
|
137
|
-
const handleFocusIn = function(event) {
|
|
138
|
-
if (focusScope.paused || !container) return;
|
|
139
|
-
const target = event.target;
|
|
140
|
-
if (container.contains(target)) {
|
|
141
|
-
lastFocusedElementRef.current = target;
|
|
142
|
-
} else {
|
|
143
|
-
focusElement(lastFocusedElementRef.current, { select: true });
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
const handleFocusOut = function(event) {
|
|
147
|
-
if (focusScope.paused || !container) return;
|
|
148
|
-
const relatedTarget = event.relatedTarget;
|
|
149
|
-
if (relatedTarget === null) return;
|
|
150
|
-
if (!container.contains(relatedTarget)) {
|
|
151
|
-
focusElement(lastFocusedElementRef.current, { select: true });
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
const handleMutations = function(mutations) {
|
|
155
|
-
const focusedElement = document.activeElement;
|
|
156
|
-
if (focusedElement !== document.body) return;
|
|
157
|
-
for (const mutation of mutations) {
|
|
158
|
-
if (mutation.removedNodes.length > 0) focusElement(container);
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
document.addEventListener("focusin", handleFocusIn);
|
|
162
|
-
document.addEventListener("focusout", handleFocusOut);
|
|
163
|
-
const mutationObserver = new MutationObserver(handleMutations);
|
|
164
|
-
if (container) {
|
|
165
|
-
mutationObserver.observe(container, { childList: true, subtree: true });
|
|
166
|
-
}
|
|
167
|
-
return () => {
|
|
168
|
-
document.removeEventListener("focusin", handleFocusIn);
|
|
169
|
-
document.removeEventListener("focusout", handleFocusOut);
|
|
170
|
-
mutationObserver.disconnect();
|
|
171
|
-
};
|
|
172
|
-
}, [trapped, container, focusScope.paused]);
|
|
173
|
-
useEffect(() => {
|
|
174
|
-
if (!container) return;
|
|
175
|
-
focusScopesStack.add(focusScope);
|
|
176
|
-
const previouslyFocusedElement = document.activeElement;
|
|
177
|
-
const hasFocusedCandidate = container.contains(previouslyFocusedElement);
|
|
178
|
-
if (!hasFocusedCandidate) {
|
|
179
|
-
const mountEvent = new CustomEvent(AUTOFOCUS_ON_MOUNT, EVENT_OPTIONS);
|
|
180
|
-
container.addEventListener(AUTOFOCUS_ON_MOUNT, savedOnMountAutoFocus);
|
|
181
|
-
container.dispatchEvent(mountEvent);
|
|
182
|
-
if (!mountEvent.defaultPrevented) {
|
|
183
|
-
focusFirst(removeLinks(getTabbableCandidates(container)), { select: true });
|
|
184
|
-
document.activeElement === previouslyFocusedElement && focusElement(container);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return () => {
|
|
188
|
-
container.removeEventListener(AUTOFOCUS_ON_MOUNT, savedOnMountAutoFocus);
|
|
189
|
-
setTimeout(() => {
|
|
190
|
-
const unmountEvent = new CustomEvent(AUTOFOCUS_ON_UNMOUNT, EVENT_OPTIONS);
|
|
191
|
-
container.addEventListener(AUTOFOCUS_ON_UNMOUNT, savedOnUnmountAutoFocus);
|
|
192
|
-
container.dispatchEvent(unmountEvent);
|
|
193
|
-
if (!unmountEvent.defaultPrevented) {
|
|
194
|
-
focusElement(document.body, { select: true });
|
|
195
|
-
}
|
|
196
|
-
container.removeEventListener(AUTOFOCUS_ON_UNMOUNT, savedOnUnmountAutoFocus);
|
|
197
|
-
focusScopesStack.remove(focusScope);
|
|
198
|
-
}, 0);
|
|
199
|
-
};
|
|
200
|
-
}, [container, savedOnMountAutoFocus, savedOnUnmountAutoFocus, focusScope]);
|
|
201
|
-
const handleKeyDown = (event) => {
|
|
202
|
-
if (!loop && !trapped) return;
|
|
203
|
-
if (focusScope.paused) return;
|
|
204
|
-
const isTabKey = event.key === "Tab" && !event.altKey && !event.ctrlKey && !event.metaKey;
|
|
205
|
-
const focusedElement = document.activeElement;
|
|
206
|
-
if (!(isTabKey && focusedElement)) return;
|
|
207
|
-
const container2 = event.currentTarget;
|
|
208
|
-
const [first, last] = getTabbableEdges(container2);
|
|
209
|
-
const hasTabbableElementsInside = first && last;
|
|
210
|
-
if (!hasTabbableElementsInside && focusedElement === container2) {
|
|
211
|
-
event.preventDefault();
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
if (!event.shiftKey && focusedElement === last) {
|
|
215
|
-
event.preventDefault();
|
|
216
|
-
if (loop && first) {
|
|
217
|
-
focusElement(first, { select: true });
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
if (event.shiftKey && focusedElement === first) {
|
|
221
|
-
event.preventDefault();
|
|
222
|
-
if (loop && last) {
|
|
223
|
-
focusElement(last, { select: true });
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
return /* @__PURE__ */ React.createElement("div", { tabIndex: -1, ...scopeProps, onKeyDown: handleKeyDown, ref: composedRefs });
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
export { FocusScope };
|
|
231
|
-
//# sourceMappingURL=index.js.map
|
|
232
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/common/focus-scope/utils.ts","../../../../src/components/common/focus-scope/focus-scope.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export const focusFirst = (candidates: HTMLElement[], options: { select?: boolean } = {}) => {\n\tconst { select = false } = options;\n\n\tconst previouslyFocusedElement = document.activeElement;\n\n\tfor (const candidate of candidates) {\n\t\tfocusElement(candidate, { select });\n\t\tif (document.activeElement !== previouslyFocusedElement) return;\n\t}\n};\n\nexport const getTabbableEdges = (container: HTMLElement) => {\n\tconst candidates = getTabbableCandidates(container);\n\tconst first = findVisible(candidates, container);\n\tconst last = findVisible(candidates.reverse(), container);\n\treturn [first, last];\n};\n\nexport const getTabbableCandidates = (container: HTMLElement): HTMLElement[] => {\n\tconst nodes: HTMLElement[] = [];\n\n\tconst walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {\n\t\tacceptNode: (node: HTMLInputElement) => {\n\t\t\tconst isHiddenInput = node.tagName === \"INPUT\" && node.type === \"hidden\";\n\n\t\t\tif (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP;\n\n\t\t\treturn node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n\t\t},\n\t});\n\n\twhile (walker.nextNode()) {\n\t\tnodes.push(walker.currentNode as HTMLElement);\n\t}\n\n\treturn nodes;\n};\n\nconst findVisible = (elements: HTMLElement[], container: HTMLElement): HTMLElement | null => {\n\tif (elements.length === 0) return null;\n\tlet visibleElement: HTMLElement | null = null;\n\n\tfor (const element of elements) {\n\t\tif (!isHidden(element, { upTo: container })) {\n\t\t\tvisibleElement = element;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn visibleElement;\n};\n\nconst isHidden = (\n\tinitialNode: HTMLElement | null,\n\toptions: { upTo: HTMLElement | undefined }\n): boolean => {\n\tconst { upTo } = options;\n\n\tif (!initialNode || getComputedStyle(initialNode).visibility === \"hidden\") {\n\t\treturn true;\n\t}\n\n\tlet currentNode: HTMLElement | null = initialNode;\n\n\twhile (currentNode) {\n\t\tif (upTo !== void 0 && currentNode === upTo) {\n\t\t\treturn false;\n\t\t}\n\t\tif (getComputedStyle(currentNode).display === \"none\") {\n\t\t\treturn true;\n\t\t}\n\t\tcurrentNode = currentNode.parentElement;\n\t}\n\n\treturn false;\n};\n\nconst isSelectableInput = (element: HTMLElement): element is HTMLInputElement => {\n\treturn element instanceof HTMLInputElement && \"select\" in element;\n};\n\nexport const focusElement = (element: HTMLElement | null, options: { select?: boolean } = {}) => {\n\tconst { select = false } = options;\n\n\tif (element && typeof element.focus === \"function\") {\n\t\tconst previouslyFocusedElement = document.activeElement;\n\t\telement.focus({ preventScroll: true });\n\n\t\tif (element !== previouslyFocusedElement && isSelectableInput(element) && select) {\n\t\t\telement.select();\n\t\t}\n\t}\n};\n\nconst createFocusScopesStack = () => {\n\tlet stack: Array<{ pause: () => void; paused: boolean; resume: () => void }> = [];\n\n\tconst api = {\n\t\tadd(focusScope: { pause: () => void; paused: boolean; resume: () => void }) {\n\t\t\tconst activeFocusScope = stack[0];\n\t\t\tif (focusScope !== activeFocusScope) {\n\t\t\t\tactiveFocusScope?.pause();\n\t\t\t}\n\t\t\tstack = arrayRemove(stack, focusScope);\n\t\t\tstack.unshift(focusScope);\n\t\t},\n\t\tremove(focusScope: { pause: () => void; paused: boolean; resume: () => void }) {\n\t\t\tstack = arrayRemove(stack, focusScope);\n\t\t\tstack[0]?.resume();\n\t\t},\n\t};\n\n\treturn api;\n};\n\nexport const focusScopesStack = createFocusScopesStack();\n\nconst arrayRemove = <T>(array: T[], item: T): T[] => {\n\tconst updatedArray = [...array];\n\tconst index = updatedArray.indexOf(item);\n\tif (index !== -1) {\n\t\tupdatedArray.splice(index, 1);\n\t}\n\treturn updatedArray;\n};\n\nexport const removeLinks = (items: HTMLElement[]): HTMLElement[] => {\n\treturn items.filter((item) => item.tagName !== \"A\");\n};\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { useCallbackRef } from \"@zayne-labs/toolkit-react\";\nimport { type InferProps, composeRefs } from \"@zayne-labs/toolkit-react/utils\";\nimport { useEffect, useRef, useState } from \"react\";\nimport {\n\tfocusElement,\n\tfocusFirst,\n\tfocusScopesStack,\n\tgetTabbableCandidates,\n\tgetTabbableEdges,\n\tremoveLinks,\n} from \"./utils\";\n\n/* -------------------------------------------------------------------------------------------------\n * FocusScope\n * Copied and modified from @radix-ui/react-focus-scope\n * @see https://github.com/radix-ui/primitives/tree/main/packages/react/focus-scope\n * ----------------------------------------------------------------------------------------------- */\n\ntype FocusScopeElement = React.ComponentRef<\"div\">;\n\ntype FocusScopeProps = Omit<InferProps<\"div\">, \"ref\"> & {\n\t/**\n\t * When `true`, tabbing from last item will focus first tabbable\n\t * and shift+tab from first item will focus last tababble.\n\t * @defaultValue false\n\t */\n\tloop?: boolean;\n\t/**\n\t * Event handler called when auto-focusing on mount.\n\t * Can be prevented.\n\t */\n\tonMountAutoFocus?: (event: Event) => void;\n\t/**\n\t * Event handler called when auto-focusing on unmount.\n\t * Can be prevented.\n\t */\n\tonUnmountAutoFocus?: (event: Event) => void;\n\n\tref?: React.Ref<FocusScopeElement>;\n\n\t/**\n\t * When `true`, focus cannot escape the focus scope via keyboard,\n\t * pointer, or a programmatic focus.\n\t * @defaultValue false\n\t */\n\ttrapped?: boolean;\n};\n\nconst AUTOFOCUS_ON_MOUNT = \"focusScope.autoFocusOnMount\";\nconst AUTOFOCUS_ON_UNMOUNT = \"focusScope.autoFocusOnUnmount\";\nconst EVENT_OPTIONS = { bubbles: false, cancelable: true };\n\nfunction FocusScope(props: FocusScopeProps) {\n\tconst {\n\t\tloop = false,\n\t\tonMountAutoFocus,\n\t\tonUnmountAutoFocus,\n\t\tref: forwardedRef,\n\t\ttrapped = false,\n\t\t...scopeProps\n\t} = props;\n\tconst [container, setContainer] = useState<HTMLElement | null>(null);\n\n\tconst savedOnMountAutoFocus = useCallbackRef(onMountAutoFocus);\n\n\tconst savedOnUnmountAutoFocus = useCallbackRef(onUnmountAutoFocus);\n\n\tconst lastFocusedElementRef = useRef<HTMLElement | null>(null);\n\tconst composedRefs = composeRefs([forwardedRef, (node) => setContainer(node)]);\n\n\tconst focusScope = useRef({\n\t\tpause() {\n\t\t\tthis.paused = true;\n\t\t},\n\t\tpaused: false,\n\t\tresume() {\n\t\t\tthis.paused = false;\n\t\t},\n\t}).current;\n\n\tuseEffect(() => {\n\t\tif (!trapped) return;\n\n\t\tconst handleFocusIn = function (event: FocusEvent) {\n\t\t\tif (focusScope.paused || !container) return;\n\t\t\tconst target = event.target as HTMLElement;\n\t\t\tif (container.contains(target)) {\n\t\t\t\tlastFocusedElementRef.current = target;\n\t\t\t} else {\n\t\t\t\tfocusElement(lastFocusedElementRef.current, { select: true });\n\t\t\t}\n\t\t};\n\n\t\tconst handleFocusOut = function (event: FocusEvent) {\n\t\t\tif (focusScope.paused || !container) return;\n\t\t\tconst relatedTarget = event.relatedTarget as HTMLElement | null;\n\t\t\tif (relatedTarget === null) return;\n\t\t\tif (!container.contains(relatedTarget)) {\n\t\t\t\tfocusElement(lastFocusedElementRef.current, { select: true });\n\t\t\t}\n\t\t};\n\n\t\tconst handleMutations = function (mutations: MutationRecord[]) {\n\t\t\tconst focusedElement = document.activeElement;\n\t\t\tif (focusedElement !== document.body) return;\n\t\t\tfor (const mutation of mutations) {\n\t\t\t\tif (mutation.removedNodes.length > 0) focusElement(container);\n\t\t\t}\n\t\t};\n\n\t\tdocument.addEventListener(\"focusin\", handleFocusIn);\n\t\tdocument.addEventListener(\"focusout\", handleFocusOut);\n\t\tconst mutationObserver = new MutationObserver(handleMutations);\n\n\t\tif (container) {\n\t\t\tmutationObserver.observe(container, { childList: true, subtree: true });\n\t\t}\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"focusin\", handleFocusIn);\n\t\t\tdocument.removeEventListener(\"focusout\", handleFocusOut);\n\t\t\tmutationObserver.disconnect();\n\t\t};\n\t}, [trapped, container, focusScope.paused]);\n\n\tuseEffect(() => {\n\t\tif (!container) return;\n\n\t\tfocusScopesStack.add(focusScope);\n\n\t\tconst previouslyFocusedElement = document.activeElement;\n\t\tconst hasFocusedCandidate = container.contains(previouslyFocusedElement);\n\n\t\tif (!hasFocusedCandidate) {\n\t\t\tconst mountEvent = new CustomEvent(AUTOFOCUS_ON_MOUNT, EVENT_OPTIONS);\n\t\t\tcontainer.addEventListener(AUTOFOCUS_ON_MOUNT, savedOnMountAutoFocus);\n\t\t\tcontainer.dispatchEvent(mountEvent);\n\n\t\t\tif (!mountEvent.defaultPrevented) {\n\t\t\t\tfocusFirst(removeLinks(getTabbableCandidates(container)), { select: true });\n\t\t\t\tdocument.activeElement === previouslyFocusedElement && focusElement(container);\n\t\t\t}\n\t\t}\n\n\t\treturn () => {\n\t\t\tcontainer.removeEventListener(AUTOFOCUS_ON_MOUNT, savedOnMountAutoFocus);\n\n\t\t\t// eslint-disable-next-line react-web-api/no-leaked-timeout -- Allow\n\t\t\tsetTimeout(() => {\n\t\t\t\tconst unmountEvent = new CustomEvent(AUTOFOCUS_ON_UNMOUNT, EVENT_OPTIONS);\n\t\t\t\t// eslint-disable-next-line react-web-api/no-leaked-event-listener -- Allow\n\t\t\t\tcontainer.addEventListener(AUTOFOCUS_ON_UNMOUNT, savedOnUnmountAutoFocus);\n\t\t\t\tcontainer.dispatchEvent(unmountEvent);\n\t\t\t\tif (!unmountEvent.defaultPrevented) {\n\t\t\t\t\tfocusElement(document.body, { select: true });\n\t\t\t\t}\n\t\t\t\tcontainer.removeEventListener(AUTOFOCUS_ON_UNMOUNT, savedOnUnmountAutoFocus);\n\t\t\t\tfocusScopesStack.remove(focusScope);\n\t\t\t}, 0);\n\t\t};\n\t}, [container, savedOnMountAutoFocus, savedOnUnmountAutoFocus, focusScope]);\n\n\tconst handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n\t\tif (!loop && !trapped) return;\n\t\tif (focusScope.paused) return;\n\n\t\tconst isTabKey = event.key === \"Tab\" && !event.altKey && !event.ctrlKey && !event.metaKey;\n\t\tconst focusedElement = document.activeElement;\n\n\t\tif (!(isTabKey && focusedElement)) return;\n\n\t\tconst container2 = event.currentTarget;\n\t\tconst [first, last] = getTabbableEdges(container2);\n\t\tconst hasTabbableElementsInside = first && last;\n\n\t\tif (!hasTabbableElementsInside && focusedElement === container2) {\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tif (!event.shiftKey && focusedElement === last) {\n\t\t\tevent.preventDefault();\n\t\t\tif (loop && first) {\n\t\t\t\tfocusElement(first, { select: true });\n\t\t\t}\n\t\t}\n\n\t\tif (event.shiftKey && focusedElement === first) {\n\t\t\tevent.preventDefault();\n\t\t\tif (loop && last) {\n\t\t\t\tfocusElement(last, { select: true });\n\t\t\t}\n\t\t}\n\t};\n\n\treturn <div tabIndex={-1} {...scopeProps} onKeyDown={handleKeyDown} ref={composedRefs} />;\n}\n\nexport { FocusScope };\n"]}
|