import { default as React, Ref, RefObject } from 'react'; import { AnimationFileName, LoggedInUser, Logo, User, ZeniDate } from '@zeniai/client-epic-state'; import { Colors } from '../designSystem/zeniConstants'; /** * Common Helpers */ export declare const usePrevious: (value: any) => undefined; export declare const useFocus: () => [React.MutableRefObject, (isBlur?: boolean) => void]; export declare function mergeRefs(...refs: Ref[]): Ref; export declare const capitaliseWords: (text: string) => string; export declare const useDeviceDetect: () => { isMobileOrTabletScreen: boolean; }; export declare const useIPadDeviceDetect: () => { isIPadScreen: boolean; }; export declare const useIPhoneDeviceDetect: () => { isIPhoneScreen: boolean; }; export declare const useAndroidDeviceDetect: () => { isAndroidScreen: boolean; }; export declare function useLockBodyScroll(): void; export declare const useOnScreen: (ref: RefObject) => boolean; /** * Hook for playing audio with conditional loading. * Audio is only loaded when `enabled` is true, improving page load performance. * Uses useRef to allow dynamic creation when enabled changes from false to true. * * @param audioUrl - URL of the audio file to play * @param enabled - If false, audio will not be loaded or played (default: true for backward compatibility) */ export declare const useMusic: (audioUrl: string, enabled?: boolean) => [boolean, (start: boolean) => void]; export declare const formHasDirtyFields: (dirtyFields: any) => boolean; export declare const capitalizeFirstLetter: (string: string) => string; export declare const capitalizeFirstLetterString: (string: string) => string; export declare const isZeniAIUser: (users: User[], userId: string | undefined) => boolean; export declare const getFullName: (user: User, includeMiddleName?: boolean, includeEmail?: boolean) => string; export declare const getLoggedInUserName: (user: LoggedInUser | undefined) => string; export declare const JPEG_IMAGE_BASE_64 = "data:image/jpeg;base64,"; export declare const PNG_IMAGE_BASE_64 = "data:image/png;base64,"; export declare const PDF_BASE_64 = "data:application/pdf;base64,"; /** * Builds an `` data URI for institution logos (Plaid PNG base64, CDN url). * Defaults to PNG when base64 is present — Plaid institution logos are PNG. */ export declare const toInstitutionLogoDataUri: (logo: Logo | undefined) => string | undefined; export declare const SUCCESS_SOUND_SOURCE = "https://storage.googleapis.com/zeni-apis.appspot.com/data/upload_complete_notification.mp3"; export declare const base64FileSize: (base64String: string) => string; export declare const formatFileSize: (bytes: number, decimals?: number) => string; export declare function isDateMoreThanHoursAgo(hours: number, dateToCheck: Date): boolean; export declare const isDateOfNDay: (date: ZeniDate, day: number) => boolean; export declare const isDateOnOrBetweenRange: (startDate: ZeniDate, endDate: ZeniDate, date: ZeniDate) => boolean; export declare const getColorForALabel: (props: Readonly<{ label: string; index?: number; }>) => Colors; /** * Function to wait for react props - predicates. * @param {function() : Promise. | function() : Boolean} predicate * - A function that returns a bool * @param {Number} [timeout] - Optional maximum waiting time in ms after rejected */ export declare const waitFor: (predicate: () => boolean, timeout?: number) => Promise; export declare const toAbsoluteUrl: (url: string) => string | undefined; export declare const mapIndexToString: (index: number) => string; export declare const fetchAnimationFile: (animationFileName: AnimationFileName) => Promise; export declare const fetchAnimationData: (endPointUrl: string | undefined, animationFileName: AnimationFileName) => Promise; export declare const toMonthStr: (month: number) => string; export declare const toKebabCase: (str: string) => string; export declare const generateDataTestId: (label: string, secondaryLabel?: string) => string; export declare const scrollContainerToTargetAdjusted: (element: HTMLDivElement | null, container: HTMLDivElement | null) => void; export declare const scrollToTop: () => void; export declare function escapeRegExp(keyword: string): string; export declare const formatToSentenceCase: (text: string) => string; export declare const convertMinutesToDays: (minutes: number) => number; export declare const convertMinutesToWeeks: (minutes: number) => number; /** * "Jul 29, 2026" from an ISO timestamp, or null when there is nothing to show. * * Returns null rather than a placeholder string so the caller decides the copy — a * skill that has never been updated reads differently from one whose timestamp we * failed to parse, and both are worse than an em-dash chosen here. */ export declare const formatIsoDateShort: (iso: string | null) => string | null; export declare const formatMonthYear: (monthStr: string) => string; type YearMonthPeriod = string & { readonly __brand: "YearMonthPeriod"; }; export declare const toYearMonthPeriodOrThrow: (period: string) => YearMonthPeriod; export declare const isCurrentMonthPeriod: (period: YearMonthPeriod) => boolean; export declare const roundAmountIfNeeded: (amount: number) => number; export declare const flowFromUrl: () => string; export declare const isEqualProps: >(prevProps: T, newProps: T, listOfProps: ReadonlyArray) => boolean; export declare const normalizeString: (str: string | undefined) => string; export declare const isDeepLinkUrn: (href: string) => boolean; /** * Flattens deep links to their label for copy/download output. * * A URN is meaningless outside the app — pasted into an email it is noise, and a * link the renderer deliberately dropped would otherwise still be copied as link * syntax, asserting a link the reader never saw. * * Handles both markdown link forms, because they fail differently. An inline link * copies the URN inside the parens. A REFERENCE link renders as a perfectly clean * anchor — the reader sees only "Acme" — while its definition line carries the raw * URN to the bottom of the copied text, so the screen and the clipboard disagree. * That divergence is the whole reason this function exists, and it is worse in an * Excel export, where the URN lands in a cell a finance user sends onward. * * Accepts a non-string because callers pass API payload fields. * * KNOWN LIMITS — verified by execution, not assumed. Each of these renders as a * working anchor on screen but survives this function, so the raw URN reaches the * clipboard or an Excel cell: * - a CommonMark autolink, `` (also shows the URN as the link text) * - a label spanning two lines * - a `>` inside the destination * - an escaped bracket in the label, `[Acme\] Inc](zeni://…)` * - a nested bracket in the label, `[See [Report]](zeni://…)` * And one case where screen and clipboard disagree textually rather than leaking: * `See [Acme [x](zeni://…)` renders `See [Acme x` but copies `See Acme [x`. * * An earlier version of this comment claimed such labels are never produced and * that the function fails closed rather than corrupting a label. Both claims were * wrong; the cases above were demonstrated against the real renderer. * * These persist because a regex cannot see markdown structure. The correct fix is * an mdast pass over `link`/`linkReference`/`definition` nodes, which would handle * every form and skip code by construction — but it needs `mdast-util-from-markdown` * and `unist-util-visit` as direct dependencies of this library, which is a team * decision rather than a drive-by one. Tracked for follow-up. */ export declare const stripDeepLinkMarkup: (text: unknown) => string; export declare const base64ToBytes: (base64: string) => Uint8Array; export {};