@xyo-network/react-access-gate 7.4.2 → 7.5.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.
@@ -2,7 +2,7 @@ import type { Meta } from '@storybook/react-vite';
2
2
  import { AccessCodeGateFlexbox } from './AccessCodeGateFlexbox.tsx';
3
3
  declare const _default: Meta;
4
4
  export default _default;
5
- declare const Default: import(".store/storybook-virtual-a067dd1507/package/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, AccessCodeGateFlexbox>;
6
- declare const WithAccessCodes: import(".store/storybook-virtual-a067dd1507/package/internal/csf").AnnotatedStoryFn<import("@storybook/react-vite").ReactRenderer, AccessCodeGateFlexbox>;
5
+ declare const Default: import("storybook/internal/csf").AnnotatedStoryFn<import("@storybook/react").ReactRenderer, AccessCodeGateFlexbox>;
6
+ declare const WithAccessCodes: import("storybook/internal/csf").AnnotatedStoryFn<import("@storybook/react").ReactRenderer, AccessCodeGateFlexbox>;
7
7
  export { Default, WithAccessCodes };
8
8
  //# sourceMappingURL=AccessCodeGateFlexbox.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AccessCodeGateFlexbox.stories.d.ts","sourceRoot":"","sources":["../../../src/components/AccessCodeGateFlexbox.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAW,MAAM,uBAAuB,CAAA;AAK1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;wBAO9D,IAAI;AAHT,wBAGS;AAkCT,QAAA,MAAM,OAAO,2JAAoB,CAAA;AACjC,QAAA,MAAM,eAAe,2JAAmC,CAAA;AAExD,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,CAAA"}
1
+ {"version":3,"file":"AccessCodeGateFlexbox.stories.d.ts","sourceRoot":"","sources":["../../../src/components/AccessCodeGateFlexbox.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAW,MAAM,uBAAuB,CAAA;AAK1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;wBAO9D,IAAI;AAHT,wBAGS;AAkCT,QAAA,MAAM,OAAO,oHAAoB,CAAA;AACjC,QAAA,MAAM,eAAe,oHAAmC,CAAA;AAExD,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,CAAA"}
@@ -1,79 +1,75 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
1
4
  // src/components/AccessCodeGateFlexbox.tsx
2
5
  import { FormControl } from "@mui/material";
3
6
  import { ButtonEx } from "@xylabs/react-button";
4
7
  import { FlexGrowCol, FlexGrowRow } from "@xylabs/react-flexbox";
5
- import {
6
- useCallback,
7
- useEffect,
8
- useState
9
- } from "react";
8
+ import React2, { useCallback, useEffect, useState } from "react";
10
9
 
11
10
  // src/components/CodeTextField.tsx
12
11
  import { CheckCircleOutline, ErrorOutline } from "@mui/icons-material";
13
- import {
14
- InputAdornment,
15
- styled,
16
- TextField
17
- } from "@mui/material";
18
- import { jsx, jsxs } from "react/jsx-runtime";
19
- var CodeTextField = ({
20
- codeInput,
21
- disabled,
22
- onEnter,
23
- setCodeInput,
24
- validCode,
12
+ import { InputAdornment, styled, TextField } from "@mui/material";
13
+ import React from "react";
14
+ var CodeTextField = /* @__PURE__ */ __name(({ codeInput, disabled, onEnter, setCodeInput, validCode, ...props }) => /* @__PURE__ */ React.createElement(StyledTextField, {
15
+ InputProps: {
16
+ endAdornment: /* @__PURE__ */ React.createElement(InputAdornment, {
17
+ position: "start"
18
+ }, /* @__PURE__ */ React.createElement(CheckCircleOutline, {
19
+ sx: {
20
+ display: validCode === null ? "block" : "hidden",
21
+ visibility: "hidden"
22
+ }
23
+ }), /* @__PURE__ */ React.createElement(CheckCircleOutline, {
24
+ color: "success",
25
+ fontSize: "medium",
26
+ sx: {
27
+ position: "absolute",
28
+ visibility: validCode === true ? "visible" : "hidden"
29
+ }
30
+ }), /* @__PURE__ */ React.createElement(ErrorOutline, {
31
+ color: "error",
32
+ fontSize: "medium",
33
+ sx: {
34
+ position: "absolute",
35
+ visibility: validCode === false ? "visible" : "hidden"
36
+ }
37
+ }))
38
+ },
39
+ onKeyUp: /* @__PURE__ */ __name((event) => event.key === "Enter" && !disabled ? onEnter?.() : null, "onKeyUp"),
40
+ autoFocus: true,
41
+ size: "small",
42
+ value: codeInput ?? "",
43
+ onChange: /* @__PURE__ */ __name((event) => setCodeInput?.(event.target.value), "onChange"),
25
44
  ...props
26
- }) => /* @__PURE__ */ jsx(
27
- StyledTextField,
28
- {
29
- InputProps: {
30
- endAdornment: /* @__PURE__ */ jsxs(InputAdornment, { position: "start", children: [
31
- /* @__PURE__ */ jsx(CheckCircleOutline, { sx: { display: validCode === null ? "block" : "hidden", visibility: "hidden" } }),
32
- /* @__PURE__ */ jsx(
33
- CheckCircleOutline,
34
- {
35
- color: "success",
36
- fontSize: "medium",
37
- sx: { position: "absolute", visibility: validCode === true ? "visible" : "hidden" }
38
- }
39
- ),
40
- /* @__PURE__ */ jsx(ErrorOutline, { color: "error", fontSize: "medium", sx: { position: "absolute", visibility: validCode === false ? "visible" : "hidden" } })
41
- ] })
42
- },
43
- onKeyUp: (event) => event.key === "Enter" && !disabled ? onEnter?.() : null,
44
- autoFocus: true,
45
- size: "small",
46
- value: codeInput ?? "",
47
- onChange: (event) => setCodeInput?.(event.target.value),
48
- ...props
45
+ }), "CodeTextField");
46
+ var StyledTextField = styled(TextField, {
47
+ name: "StyledTextField"
48
+ })(() => ({
49
+ "& .MuiInputBase-root": {
50
+ paddingRight: 0
49
51
  }
50
- );
51
- var StyledTextField = styled(TextField, { name: "StyledTextField" })(() => ({ "& .MuiInputBase-root": { paddingRight: 0 } }));
52
+ }));
52
53
 
53
54
  // src/components/AccessCodeGateFlexbox.tsx
54
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
55
- var AccessCodeGateFlexbox = ({
56
- children,
57
- onCodeInputChange,
58
- onAccessCodeSuccess,
59
- successRedirectDelay = 1500,
60
- userAccessCodes,
61
- validAccessCodes,
62
- validateFunction,
63
- ...props
64
- }) => {
55
+ var AccessCodeGateFlexbox = /* @__PURE__ */ __name(({ children, onCodeInputChange, onAccessCodeSuccess, successRedirectDelay = 1500, userAccessCodes, validAccessCodes, validateFunction, ...props }) => {
65
56
  const [initialized, setInitialized] = useState(false);
66
57
  const [accessGranted, setAccessGranted] = useState(false);
67
58
  const [codeInput, setCodeInput] = useState();
68
59
  const [validCode, setValidCode] = useState(null);
69
60
  const disabled = validateFunction ? !validateFunction(codeInput) : !codeInput;
70
- const validateCode = useCallback((accessCode) => accessCode ? validAccessCodes?.includes(accessCode) : false, [validAccessCodes]);
61
+ const validateCode = useCallback((accessCode) => accessCode ? validAccessCodes?.includes(accessCode) : false, [
62
+ validAccessCodes
63
+ ]);
71
64
  useEffect(() => {
72
65
  if (onCodeInputChange) {
73
66
  onCodeInputChange(codeInput);
74
67
  }
75
- }, [codeInput, onCodeInputChange]);
76
- const onEnter = () => {
68
+ }, [
69
+ codeInput,
70
+ onCodeInputChange
71
+ ]);
72
+ const onEnter = /* @__PURE__ */ __name(() => {
77
73
  onCodeInputChange?.(codeInput);
78
74
  if (codeInput) {
79
75
  const granted = validateCode(codeInput);
@@ -87,10 +83,12 @@ var AccessCodeGateFlexbox = ({
87
83
  setValidCode(false);
88
84
  }
89
85
  }
90
- };
86
+ }, "onEnter");
91
87
  useEffect(() => {
92
88
  setValidCode(null);
93
- }, [codeInput]);
89
+ }, [
90
+ codeInput
91
+ ]);
94
92
  useEffect(() => {
95
93
  if (userAccessCodes) {
96
94
  const granted = userAccessCodes.some((code) => validateCode(code));
@@ -100,42 +98,52 @@ var AccessCodeGateFlexbox = ({
100
98
  }
101
99
  }
102
100
  setInitialized(true);
103
- }, [onAccessCodeSuccess, userAccessCodes, validateCode]);
104
- return /* @__PURE__ */ jsx2(Fragment, { children: initialized ? accessGranted ? children : /* @__PURE__ */ jsx2(FlexGrowCol, { gap: 2, ...props, children: /* @__PURE__ */ jsxs2(FlexGrowRow, { gap: 2, alignItems: "start", children: [
105
- /* @__PURE__ */ jsx2(FormControl, { children: /* @__PURE__ */ jsx2(
106
- CodeTextField,
107
- {
108
- codeInput,
109
- disabled,
110
- label: "Enter Access Code",
111
- setCodeInput,
112
- validCode,
113
- onEnter
114
- }
115
- ) }),
116
- /* @__PURE__ */ jsx2(FormControl, { children: /* @__PURE__ */ jsx2(ButtonEx, { disabled, onClick: onEnter, variant: "contained", children: "Enter" }) })
117
- ] }) }) : null });
118
- };
101
+ }, [
102
+ onAccessCodeSuccess,
103
+ userAccessCodes,
104
+ validateCode
105
+ ]);
106
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, initialized ? accessGranted ? children : /* @__PURE__ */ React2.createElement(FlexGrowCol, {
107
+ gap: 2,
108
+ ...props
109
+ }, /* @__PURE__ */ React2.createElement(FlexGrowRow, {
110
+ gap: 2,
111
+ alignItems: "start"
112
+ }, /* @__PURE__ */ React2.createElement(FormControl, null, /* @__PURE__ */ React2.createElement(CodeTextField, {
113
+ codeInput,
114
+ disabled,
115
+ label: "Enter Access Code",
116
+ setCodeInput,
117
+ validCode,
118
+ onEnter
119
+ })), /* @__PURE__ */ React2.createElement(FormControl, null, /* @__PURE__ */ React2.createElement(ButtonEx, {
120
+ disabled,
121
+ onClick: onEnter,
122
+ variant: "contained"
123
+ }, "Enter")))) : null);
124
+ }, "AccessCodeGateFlexbox");
119
125
 
120
126
  // src/hooks/useAccessCodes.ts
121
127
  import { useMemo, useState as useState2 } from "react";
122
- var useAccessCodes = (localStorageKey, validCodeLength = 6) => {
128
+ var useAccessCodes = /* @__PURE__ */ __name((localStorageKey, validCodeLength = 6) => {
123
129
  const [validated, setValidated] = useState2(false);
124
130
  const [codeInput, setCodeInput] = useState2("");
125
- const onAccessCodeSuccess = () => {
131
+ const onAccessCodeSuccess = /* @__PURE__ */ __name(() => {
126
132
  if (codeInput) {
127
- localStorage.setItem(localStorageKey, JSON.stringify([codeInput]));
133
+ localStorage.setItem(localStorageKey, JSON.stringify([
134
+ codeInput
135
+ ]));
128
136
  setValidated(true);
129
137
  } else {
130
138
  setValidated(true);
131
139
  }
132
- };
133
- const validateCodeInput = (code) => {
140
+ }, "onAccessCodeSuccess");
141
+ const validateCodeInput = /* @__PURE__ */ __name((code) => {
134
142
  return code?.length === validCodeLength;
135
- };
136
- const onCodeInputChange = (code) => {
143
+ }, "validateCodeInput");
144
+ const onCodeInputChange = /* @__PURE__ */ __name((code) => {
137
145
  setCodeInput(code ?? "");
138
- };
146
+ }, "onCodeInputChange");
139
147
  const userAccessCodes = useMemo(() => {
140
148
  const storedCodes = localStorage.getItem(localStorageKey);
141
149
  if (storedCodes) {
@@ -151,7 +159,7 @@ var useAccessCodes = (localStorageKey, validCodeLength = 6) => {
151
159
  onCodeInputChange,
152
160
  validateCodeInput
153
161
  };
154
- };
162
+ }, "useAccessCodes");
155
163
  export {
156
164
  AccessCodeGateFlexbox,
157
165
  useAccessCodes
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/AccessCodeGateFlexbox.tsx","../../src/components/CodeTextField.tsx","../../src/hooks/useAccessCodes.ts"],"sourcesContent":["import { FormControl } from '@mui/material'\nimport { ButtonEx } from '@xylabs/react-button'\nimport type { FlexBoxProps } from '@xylabs/react-flexbox'\nimport { FlexGrowCol, FlexGrowRow } from '@xylabs/react-flexbox'\nimport type { PropsWithChildren } from 'react'\nimport React, {\n useCallback, useEffect, useState,\n} from 'react'\n\nimport { CodeTextField } from './CodeTextField.tsx'\n\nexport interface AccessCodeGateFlexbox extends PropsWithChildren, FlexBoxProps {\n onAccessCodeSuccess?: (code?: string) => void\n onCodeInputChange?: (codeInput?: string) => void\n successRedirectDelay?: number\n textFieldHelperText?: string\n userAccessCodes?: string[]\n validAccessCodes?: string[]\n validateFunction?: (codeInput?: string) => boolean\n}\n\nexport const AccessCodeGateFlexbox: React.FC<AccessCodeGateFlexbox> = ({\n children,\n onCodeInputChange,\n onAccessCodeSuccess,\n successRedirectDelay = 1500,\n userAccessCodes,\n validAccessCodes,\n validateFunction,\n ...props\n}) => {\n const [initialized, setInitialized] = useState(false)\n const [accessGranted, setAccessGranted] = useState(false)\n const [codeInput, setCodeInput] = useState<string>()\n const [validCode, setValidCode] = useState<boolean | null>(null)\n\n const disabled = validateFunction ? !validateFunction(codeInput) : !codeInput\n const validateCode = useCallback((accessCode: string) => (accessCode ? validAccessCodes?.includes(accessCode) : false), [validAccessCodes])\n\n // keep the parent informed of the code input\n useEffect(() => {\n if (onCodeInputChange) {\n onCodeInputChange(codeInput)\n }\n }, [codeInput, onCodeInputChange])\n\n const onEnter = () => {\n onCodeInputChange?.(codeInput)\n if (codeInput) {\n const granted = validateCode(codeInput)\n if (granted) {\n setValidCode(true)\n // delay success callback to ensure the ui shows success before next action\n setTimeout(() => {\n setAccessGranted(granted)\n onAccessCodeSuccess?.(codeInput)\n }, successRedirectDelay)\n } else {\n setValidCode(false)\n }\n }\n }\n\n useEffect(() => {\n // whenever a code changes, reset the success/failure warning\n setValidCode(null)\n }, [codeInput])\n\n useEffect(() => {\n if (userAccessCodes) {\n const granted = userAccessCodes.some(code => validateCode(code))\n setAccessGranted(granted)\n if (granted) {\n onAccessCodeSuccess?.()\n }\n }\n setInitialized(true)\n }, [onAccessCodeSuccess, userAccessCodes, validateCode])\n\n return (\n <>\n {initialized\n ? accessGranted\n ? children\n : (\n <FlexGrowCol gap={2} {...props}>\n <FlexGrowRow gap={2} alignItems=\"start\">\n <FormControl>\n <CodeTextField\n codeInput={codeInput}\n disabled={disabled}\n label=\"Enter Access Code\"\n setCodeInput={setCodeInput}\n validCode={validCode}\n onEnter={onEnter}\n />\n </FormControl>\n <FormControl>\n <ButtonEx disabled={disabled} onClick={onEnter} variant=\"contained\">\n Enter\n </ButtonEx>\n </FormControl>\n </FlexGrowRow>\n </FlexGrowCol>\n )\n\n : null}\n </>\n )\n}\n","import { CheckCircleOutline, ErrorOutline } from '@mui/icons-material'\nimport type { TextFieldProps } from '@mui/material'\nimport {\n InputAdornment, styled, TextField,\n} from '@mui/material'\nimport type {\n Dispatch, KeyboardEvent, SetStateAction,\n} from 'react'\nimport React from 'react'\n\nexport type CodeTextFieldProps = TextFieldProps & {\n codeInput?: string\n disabled?: boolean\n onEnter?: () => void\n setCodeInput?: Dispatch<SetStateAction<string | undefined>>\n validCode?: boolean | null\n}\n\nexport const CodeTextField: React.FC<CodeTextFieldProps> = ({\n codeInput, disabled, onEnter, setCodeInput, validCode, ...props\n}) => (\n <StyledTextField\n InputProps={{\n endAdornment: (\n <InputAdornment position=\"start\">\n {/* Having a display block element for all 3 states (null, false, true) means the icon coming in and out\n does not affect the overall width */}\n <CheckCircleOutline sx={{ display: validCode === null ? 'block' : 'hidden', visibility: 'hidden' }} />\n <CheckCircleOutline\n color=\"success\"\n fontSize=\"medium\"\n sx={{ position: 'absolute', visibility: validCode === true ? 'visible' : 'hidden' }}\n />\n <ErrorOutline color=\"error\" fontSize=\"medium\" sx={{ position: 'absolute', visibility: validCode === false ? 'visible' : 'hidden' }} />\n </InputAdornment>\n ),\n }}\n onKeyUp={(event: KeyboardEvent) => (event.key === 'Enter' && !disabled ? onEnter?.() : null)}\n autoFocus\n size=\"small\"\n value={codeInput ?? ''}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) => setCodeInput?.(event.target.value)}\n {...props}\n />\n)\n\nconst StyledTextField = styled(TextField, { name: 'StyledTextField' })(() => ({ '& .MuiInputBase-root': { paddingRight: 0 } }))\n","import { useMemo, useState } from 'react'\n\nexport const useAccessCodes = (localStorageKey: string, validCodeLength = 6) => {\n const [validated, setValidated] = useState(false)\n const [codeInput, setCodeInput] = useState('')\n\n const onAccessCodeSuccess = () => {\n // Save the access code to local storage\n if (codeInput) {\n localStorage.setItem(localStorageKey, JSON.stringify([codeInput]))\n setValidated(true)\n } else {\n // If the codeInput is empty, but we have success, do nothing since the successful code is already saved\n setValidated(true)\n }\n }\n const validateCodeInput = (code?: string) => {\n return code?.length === validCodeLength\n }\n const onCodeInputChange = (code?: string) => {\n setCodeInput(code ?? '')\n }\n const userAccessCodes = useMemo(() => {\n const storedCodes = localStorage.getItem(localStorageKey)\n if (storedCodes) {\n const parsedResult = JSON.parse(storedCodes ?? '')\n if (Array.isArray(parsedResult)) return parsedResult\n }\n }, [])\n\n return {\n codeInput, validated, userAccessCodes, onAccessCodeSuccess, onCodeInputChange, validateCodeInput,\n }\n}\n"],"mappings":"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","names":["jsx","jsxs","useState"]}
1
+ {"version":3,"sources":["../../src/components/AccessCodeGateFlexbox.tsx","../../src/components/CodeTextField.tsx","../../src/hooks/useAccessCodes.ts"],"sourcesContent":["import { FormControl } from '@mui/material'\nimport { ButtonEx } from '@xylabs/react-button'\nimport type { FlexBoxProps } from '@xylabs/react-flexbox'\nimport { FlexGrowCol, FlexGrowRow } from '@xylabs/react-flexbox'\nimport type { PropsWithChildren } from 'react'\nimport React, {\n useCallback, useEffect, useState,\n} from 'react'\n\nimport { CodeTextField } from './CodeTextField.tsx'\n\nexport interface AccessCodeGateFlexbox extends PropsWithChildren, FlexBoxProps {\n onAccessCodeSuccess?: (code?: string) => void\n onCodeInputChange?: (codeInput?: string) => void\n successRedirectDelay?: number\n textFieldHelperText?: string\n userAccessCodes?: string[]\n validAccessCodes?: string[]\n validateFunction?: (codeInput?: string) => boolean\n}\n\nexport const AccessCodeGateFlexbox: React.FC<AccessCodeGateFlexbox> = ({\n children,\n onCodeInputChange,\n onAccessCodeSuccess,\n successRedirectDelay = 1500,\n userAccessCodes,\n validAccessCodes,\n validateFunction,\n ...props\n}) => {\n const [initialized, setInitialized] = useState(false)\n const [accessGranted, setAccessGranted] = useState(false)\n const [codeInput, setCodeInput] = useState<string>()\n const [validCode, setValidCode] = useState<boolean | null>(null)\n\n const disabled = validateFunction ? !validateFunction(codeInput) : !codeInput\n const validateCode = useCallback((accessCode: string) => (accessCode ? validAccessCodes?.includes(accessCode) : false), [validAccessCodes])\n\n // keep the parent informed of the code input\n useEffect(() => {\n if (onCodeInputChange) {\n onCodeInputChange(codeInput)\n }\n }, [codeInput, onCodeInputChange])\n\n const onEnter = () => {\n onCodeInputChange?.(codeInput)\n if (codeInput) {\n const granted = validateCode(codeInput)\n if (granted) {\n setValidCode(true)\n // delay success callback to ensure the ui shows success before next action\n setTimeout(() => {\n setAccessGranted(granted)\n onAccessCodeSuccess?.(codeInput)\n }, successRedirectDelay)\n } else {\n setValidCode(false)\n }\n }\n }\n\n useEffect(() => {\n // whenever a code changes, reset the success/failure warning\n setValidCode(null)\n }, [codeInput])\n\n useEffect(() => {\n if (userAccessCodes) {\n const granted = userAccessCodes.some(code => validateCode(code))\n setAccessGranted(granted)\n if (granted) {\n onAccessCodeSuccess?.()\n }\n }\n setInitialized(true)\n }, [onAccessCodeSuccess, userAccessCodes, validateCode])\n\n return (\n <>\n {initialized\n ? accessGranted\n ? children\n : (\n <FlexGrowCol gap={2} {...props}>\n <FlexGrowRow gap={2} alignItems=\"start\">\n <FormControl>\n <CodeTextField\n codeInput={codeInput}\n disabled={disabled}\n label=\"Enter Access Code\"\n setCodeInput={setCodeInput}\n validCode={validCode}\n onEnter={onEnter}\n />\n </FormControl>\n <FormControl>\n <ButtonEx disabled={disabled} onClick={onEnter} variant=\"contained\">\n Enter\n </ButtonEx>\n </FormControl>\n </FlexGrowRow>\n </FlexGrowCol>\n )\n\n : null}\n </>\n )\n}\n","import { CheckCircleOutline, ErrorOutline } from '@mui/icons-material'\nimport type { TextFieldProps } from '@mui/material'\nimport {\n InputAdornment, styled, TextField,\n} from '@mui/material'\nimport type {\n Dispatch, KeyboardEvent, SetStateAction,\n} from 'react'\nimport React from 'react'\n\nexport type CodeTextFieldProps = TextFieldProps & {\n codeInput?: string\n disabled?: boolean\n onEnter?: () => void\n setCodeInput?: Dispatch<SetStateAction<string | undefined>>\n validCode?: boolean | null\n}\n\nexport const CodeTextField: React.FC<CodeTextFieldProps> = ({\n codeInput, disabled, onEnter, setCodeInput, validCode, ...props\n}) => (\n <StyledTextField\n InputProps={{\n endAdornment: (\n <InputAdornment position=\"start\">\n {/* Having a display block element for all 3 states (null, false, true) means the icon coming in and out\n does not affect the overall width */}\n <CheckCircleOutline sx={{ display: validCode === null ? 'block' : 'hidden', visibility: 'hidden' }} />\n <CheckCircleOutline\n color=\"success\"\n fontSize=\"medium\"\n sx={{ position: 'absolute', visibility: validCode === true ? 'visible' : 'hidden' }}\n />\n <ErrorOutline color=\"error\" fontSize=\"medium\" sx={{ position: 'absolute', visibility: validCode === false ? 'visible' : 'hidden' }} />\n </InputAdornment>\n ),\n }}\n onKeyUp={(event: KeyboardEvent) => (event.key === 'Enter' && !disabled ? onEnter?.() : null)}\n autoFocus\n size=\"small\"\n value={codeInput ?? ''}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) => setCodeInput?.(event.target.value)}\n {...props}\n />\n)\n\nconst StyledTextField = styled(TextField, { name: 'StyledTextField' })(() => ({ '& .MuiInputBase-root': { paddingRight: 0 } }))\n","import { useMemo, useState } from 'react'\n\nexport const useAccessCodes = (localStorageKey: string, validCodeLength = 6) => {\n const [validated, setValidated] = useState(false)\n const [codeInput, setCodeInput] = useState('')\n\n const onAccessCodeSuccess = () => {\n // Save the access code to local storage\n if (codeInput) {\n localStorage.setItem(localStorageKey, JSON.stringify([codeInput]))\n setValidated(true)\n } else {\n // If the codeInput is empty, but we have success, do nothing since the successful code is already saved\n setValidated(true)\n }\n }\n const validateCodeInput = (code?: string) => {\n return code?.length === validCodeLength\n }\n const onCodeInputChange = (code?: string) => {\n setCodeInput(code ?? '')\n }\n const userAccessCodes = useMemo(() => {\n const storedCodes = localStorage.getItem(localStorageKey)\n if (storedCodes) {\n const parsedResult = JSON.parse(storedCodes ?? '')\n if (Array.isArray(parsedResult)) return parsedResult\n }\n }, [])\n\n return {\n codeInput, validated, userAccessCodes, onAccessCodeSuccess, onCodeInputChange, validateCodeInput,\n }\n}\n"],"mappings":"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","names":["FormControl","ButtonEx","FlexGrowCol","FlexGrowRow","React","useCallback","useEffect","useState","CheckCircleOutline","ErrorOutline","InputAdornment","styled","TextField","React","CodeTextField","codeInput","disabled","onEnter","setCodeInput","validCode","props","StyledTextField","InputProps","endAdornment","InputAdornment","position","CheckCircleOutline","sx","display","visibility","color","fontSize","ErrorOutline","onKeyUp","event","key","autoFocus","size","value","onChange","target","styled","TextField","name","paddingRight","AccessCodeGateFlexbox","children","onCodeInputChange","onAccessCodeSuccess","successRedirectDelay","userAccessCodes","validAccessCodes","validateFunction","props","initialized","setInitialized","useState","accessGranted","setAccessGranted","codeInput","setCodeInput","validCode","setValidCode","disabled","validateCode","useCallback","accessCode","includes","useEffect","onEnter","granted","setTimeout","some","code","React","FlexGrowCol","gap","FlexGrowRow","alignItems","FormControl","CodeTextField","label","ButtonEx","onClick","variant","useMemo","useState","useAccessCodes","localStorageKey","validCodeLength","validated","setValidated","useState","codeInput","setCodeInput","onAccessCodeSuccess","localStorage","setItem","JSON","stringify","validateCodeInput","code","length","onCodeInputChange","userAccessCodes","useMemo","storedCodes","getItem","parsedResult","parse","Array","isArray"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xyo-network/react-access-gate",
3
- "version": "7.4.2",
3
+ "version": "7.5.0",
4
4
  "description": "Common React library for all XYO projects that use React",
5
5
  "keywords": [
6
6
  "xyo",
@@ -43,24 +43,24 @@
43
43
  "src"
44
44
  ],
45
45
  "dependencies": {
46
- "@xylabs/react-button": "~7.1.8",
47
- "@xylabs/react-flexbox": "~7.1.8"
46
+ "@xylabs/react-button": "~7.1.9",
47
+ "@xylabs/react-flexbox": "~7.1.9"
48
48
  },
49
49
  "devDependencies": {
50
- "@mui/icons-material": "~7.3.6",
51
- "@mui/material": "~7.3.6",
52
- "@storybook/react-vite": "~10.1.4",
53
- "@types/react": "^19.2.7",
54
- "@xylabs/ts-scripts-yarn3": "~7.2.8",
55
- "@xylabs/tsconfig": "~7.2.8",
56
- "@xylabs/tsconfig-dom": "~7.2.8",
57
- "@xylabs/tsconfig-react": "~7.2.8",
58
- "react": "^19.2.1",
59
- "react-dom": "^19.2.1",
60
- "react-router-dom": "^7.10.0",
61
- "storybook": "~10.1.4",
50
+ "@mui/icons-material": "~7.3.7",
51
+ "@mui/material": "~7.3.7",
52
+ "@storybook/react-vite": "~10.2.1",
53
+ "@types/react": "^19.2.10",
54
+ "@xylabs/ts-scripts-yarn3": "~7.3.2",
55
+ "@xylabs/tsconfig": "~7.3.2",
56
+ "@xylabs/tsconfig-dom": "~7.3.2",
57
+ "@xylabs/tsconfig-react": "~7.3.2",
58
+ "react": "^19.2.4",
59
+ "react-dom": "^19.2.4",
60
+ "react-router-dom": "^7.13.0",
61
+ "storybook": "~10.2.1",
62
62
  "typescript": "^5.9.3",
63
- "vite": "~7.2.6"
63
+ "vite": "~7.3.1"
64
64
  },
65
65
  "peerDependencies": {
66
66
  "@mui/icons-material": ">=6 <8",
@@ -73,4 +73,4 @@
73
73
  "access": "public"
74
74
  },
75
75
  "docs": "dist/docs.json"
76
- }
76
+ }