diff --git a/app/forms/image-upload.tsx b/app/forms/image-upload.tsx index fca839ef2f..f16d67b4f4 100644 --- a/app/forms/image-upload.tsx +++ b/app/forms/image-upload.tsx @@ -44,6 +44,7 @@ import { readBlobAsBase64 } from '~/util/file' import { invariant } from '~/util/invariant' import { links } from '~/util/links' import { pb } from '~/util/path-builder' +import { isAllZeros } from '~/util/str' import { GiB, KiB } from '~/util/units' /** Format file size with two decimal points */ @@ -113,12 +114,6 @@ function Step({ children, state, label, className }: StepProps) { ) } -/** - * Does a base64 string represent underlying data that's all zeros, i.e., does - * it look like `AAAAAAAAAAAAAAAA==`? - */ -export const isAllZeros = (base64Data: string) => /^A*=*$/.test(base64Data) - const randInt = () => Math.floor(Math.random() * 100000000) function getTmpDiskName(imageName: string) { diff --git a/app/ui/lib/Modal.tsx b/app/ui/lib/Modal.tsx index 4632fcbccc..8e61d0f613 100644 --- a/app/ui/lib/Modal.tsx +++ b/app/ui/lib/Modal.tsx @@ -7,7 +7,7 @@ */ import * as Dialog from '@radix-ui/react-dialog' import { animated, useTransition } from '@react-spring/web' -import React, { createContext, forwardRef, useContext, useId } from 'react' +import React, { forwardRef, useId } from 'react' import { Close12Icon } from '@oxide/design-system/icons/react' @@ -15,10 +15,7 @@ import { classed } from '~/util/classed' import { Button } from './Button' import { DialogOverlay } from './DialogOverlay' - -const ModalContext = createContext(false) - -export const useIsInModal = () => useContext(ModalContext) +import { ModalContext } from './modal-context' export type ModalProps = { title?: string diff --git a/app/ui/lib/SideModal.tsx b/app/ui/lib/SideModal.tsx index f1404a4a4b..9f461aad97 100644 --- a/app/ui/lib/SideModal.tsx +++ b/app/ui/lib/SideModal.tsx @@ -8,20 +8,16 @@ import * as Dialog from '@radix-ui/react-dialog' import { animated, useTransition } from '@react-spring/web' import cn from 'classnames' -import React, { createContext, useContext, useRef, type ReactNode } from 'react' +import React, { useRef, type ReactNode } from 'react' import { Close12Icon, Error12Icon } from '@oxide/design-system/icons/react' import { useIsOverflow } from '~/hooks' import { Message } from '~/ui/lib/Message' -import { useIsInModal } from '~/ui/lib/Modal' import { classed } from '~/util/classed' import { DialogOverlay } from './DialogOverlay' - -const SideModalContext = createContext(false) - -export const useIsInSideModal = () => useContext(SideModalContext) +import { SideModalContext, useIsInModal, useIsInSideModal } from './modal-context' export function usePopoverZIndex() { const isInModal = useIsInModal() diff --git a/app/ui/lib/modal-context.ts b/app/ui/lib/modal-context.ts new file mode 100644 index 0000000000..54ac677632 --- /dev/null +++ b/app/ui/lib/modal-context.ts @@ -0,0 +1,15 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ + +import { createContext, useContext } from 'react' + +export const ModalContext = createContext(false) +export const useIsInModal = () => useContext(ModalContext) + +export const SideModalContext = createContext(false) +export const useIsInSideModal = () => useContext(SideModalContext) diff --git a/app/forms/all-zeros.spec.ts b/app/util/all-zeros.spec.ts similarity index 96% rename from app/forms/all-zeros.spec.ts rename to app/util/all-zeros.spec.ts index 0ffb361820..43c2915104 100644 --- a/app/forms/all-zeros.spec.ts +++ b/app/util/all-zeros.spec.ts @@ -7,7 +7,7 @@ */ import { expect, test } from 'vitest' -import { isAllZeros } from './image-upload' +import { isAllZeros } from '~/util/str' function numberToUint8Array(num: number) { const bytes = [] diff --git a/app/util/str.ts b/app/util/str.ts index 55cde1f7bb..069f8508ee 100644 --- a/app/util/str.ts +++ b/app/util/str.ts @@ -65,3 +65,9 @@ export const validateIp = (ip: string) => { const isv6 = !isv4 && IPV6_REGEX.test(ip) return { isv4, isv6, valid: isv4 || isv6 } } + +/** + * Does a base64 string represent underlying data that's all zeros, i.e., does + * it look like `AAAAAAAAAAAAAAAA==`? + */ +export const isAllZeros = (base64Data: string) => /^A*=*$/.test(base64Data)