import { Mixin, Subscription } from "@rails/actioncable";
import Dayjs from "dayjs";
import { utc as utcPlugin } from 'dayjs/plugin/utc';
import { tz as tzPlugin } from 'dayjs/plugin/timezone';
import { duration as durationPlugin } from 'dayjs/plugin/duration';
import { isDayjs as isDayjsPlugin } from 'dayjs';
import { updateLocale as updateLocalePlugin } from 'dayjs/plugin/updateLocale';
import React from "react";
import { StringSchema } from "yup";
export function resetAuthTokens(): void;
/**
 *
 * The withEventTargetValue function is a curried function that accepts a
 *
 * function as its first parameter and an event object as its second parameter. It
 *
 * executes the given function with the event.target.value as an argument, making
 *
 * it easier to extract and work with the value of form inputs or other elements
 *
 * that trigger events.
 *
 * @example 
 *
 * const onChange = val => console.log(`Value = ${val}`);
 * 
 * <input onChange={withEventTargetValue(onChange)} />;
 * 
 * // For example, in this case when user types "1" in the input field, "Value = 1" will be printed in the console.
 * @endexample
*/
export function withEventTargetValue(func: (value: string) => void, event: React.ChangeEvent): void;
/**
 *
 * The withEventTargetValue function is a curried function that accepts a
 *
 * function as its first parameter and an event object as its second parameter. It
 *
 * executes the given function with the event.target.value as an argument, making
 *
 * it easier to extract and work with the value of form inputs or other elements
 *
 * that trigger events.
 *
 * @example 
 *
 * const onChange = val => console.log(`Value = ${val}`);
 * 
 * <input onChange={withEventTargetValue(onChange)} />;
 * 
 * // For example, in this case when user types "1" in the input field, "Value = 1" will be printed in the console.
 * @endexample
*/
export function withEventTargetValue(func: (value: string) => void): React.ChangeEventHandler;
/**
 *
 * The getSubdomain function retrieves the subdomain of the current URL and
 *
 * returns it as a string. A subdomain is a prefix that appears before the main
 *
 * domain name in a URL.
 *
 * @example 
 *
 * // Let the current url be "https://spinkart.example.com".
 * getSubdomain();
 * 
 * // output: spinkart
 * @endexample
*/
export function getSubdomain(): string;
/**
 *
 * The simulateApiCall function simulates an API call and returns a response
 *
 * object with a specified delay. This function is useful during frontend
 *
 * development when you need to mock API calls before the backend is fully
 *
 * implemented.
 *
 * @example 
 *
 * simulateApiCall(hardCodedResponseData, hardCodedErrorResponse);
 * @endexample
*/
export function simulateApiCall<T>(result: T, error?: any, errorProbability?: number, delayMs?: number): Promise<T>;
/**
 *
 * The copyToClipboard function copies the given string to the clipboard and
 *
 * displays a success message, typically a toaster notification, to indicate that
 *
 * the operation was successful.
 *
 * @example 
 *
 * copyToClipboard("https://spinkart.example.com", {
 *   showToastr: true,
 *   message: "URL copied successfully!",
 * });
 * 
 * // If the URL is copied to the clipboard, a toaster message will be shown with the message "URL copied successfully!"
 * @endexample
*/
export function copyToClipboard(text: string, configs?: {
  showToastr?: boolean;
  message?: string;
}): void;
type buildUrlOptions = {
  toSnakeCase?: boolean;
};
/**
 *
 * The buildUrl function builds a URL by inflating a route-like template string
 *
 * (e.g., /products/:productId/variants/:id) using the provided parameters. It
 *
 * allows you to create URLs dynamically based on a template and replace
 *
 * placeholders with actual values. Any additional properties in the parameters
 *
 * will be transformed to snake case and attached as query parameters to the URL.
 *
 * @example 
 *
 * buildUrl("/products/:id", { id: "123" }); // output "/products/123"
 * buildUrl("/products", { search: "abc" }); // output "/products?search=abc"
 * buildUrl("/products/:productId/variants/:variantId/attributes", {
 *   productId: "123",
 *   variantId: "456",
 *   search: "abc",
 *   page: 1,
 *   per_page: 10,
 * }); // output "/products/123/variants/456/attributes?page=1&per_page=10&search=abc"
 * buildUrl("/products", { searchTerm: "abc" }); // output "/products?search_term=abc"
 * buildUrl("/products", { searchTerm: "abc" }, { toSnakeCase: false }); // output "/products?searchTerm=abc"
 * @endexample
*/
export function buildUrl(route: string, params: object, options?: buildUrlOptions): string;
type DateTimeType = string | number | Dayjs.Dayjs | Date | null | undefined;
export const timeFormat: {
  fromNow: (time: DateTimeType) => string;
  time: (time: DateTimeType) => string;
  timeWithSeconds: (time: DateTimeType) => string;
  date: (time: DateTimeType) => string;
  dateWeek: (time: DateTimeType) => string;
  dateWeekDayExtended: (time: DateTimeType) => string;
  dateWeekWithoutYear: (time: DateTimeType) => string;
  dateWeekWithoutYearDayExtended: (time: DateTimeType) => string;
  dateTime: (time: DateTimeType) => string;
  dateTimeWithSeconds: (time: DateTimeType) => string;
  dateWeekTime: (time: DateTimeType) => string;
  dateWeekTimeDayExtended: (time: DateTimeType) => string;
  extended: (time: DateTimeType) => string;
  default: (time: DateTimeType) => string;
  defaultWithTime: (time: DateTimeType) => string;
};
/**
 *
 * The dateFormat and timeFormat functions are aliases of each other, and they
 *
 * are used for formatting dates and times in various ways. These functions provide
 *
 * a convenient way to format date and time values according to specific patterns
 *
 * and display them in a human-readable format.
 *
 * @example 
 *
 * const sourceDate = "2020-01-01T00:00:00.000Z"; // can be anything that dayjs can parse
 * 
 * dateFormat.fromNow(date); // "3 years ago"
 * timeFormat.fromNow(date); // "3 years ago"
 * 
 * dateFormat.time(date); // "12:00 AM"
 * timeFormat.time(date); // "12:00 AM"
 * 
 * dateFormat.timeWithSeconds(date); // "12:00:00 AM"
 * timeFormat.timeWithSeconds(date); // "12:00:00 AM"
 * 
 * dateFormat.date(date); // "Jan 1, 2020"
 * timeFormat.date(date); // "Jan 1, 2020"
 * 
 * dateFormat.dateWeek(date); // "Jan 1, 2020 Wed"
 * timeFormat.dateWeek(date); // "Jan 1, 2020 Wed"
 * 
 * dateFormat.dateWeekDayExtended(date); // "Jan 1, 2020 Wednesday"
 * timeFormat.dateWeekDayExtended(date); // "Jan 1, 2020 Wednesday"
 * 
 * dateFormat.dateWeekWithoutYear(date); // "Jan 1, Wed"
 * timeFormat.dateWeekWithoutYear(date); // "Jan 1, Wed"
 * 
 * dateFormat.dateWeekWithoutYearDayExtended(date); // "Jan 1, Wednesday"
 * timeFormat.dateWeekWithoutYearDayExtended(date); // "Jan 1, Wednesday"
 * 
 * dateFormat.dateTime(date); // "Jan 1, 2020 12:00 AM"
 * timeFormat.dateTime(date); // "Jan 1, 2020 12:00 AM"
 * 
 * dateFormat.dateTimeWithSeconds(date); // "Jan 1, 2020 12:00:00 AM"
 * timeFormat.dateTimeWithSeconds(date); // "Jan 1, 2020 12:00:00 AM"
 * 
 * dateFormat.dateWeekTime(date); // "Jan 1, 2020 Wed 12:00 AM"
 * timeFormat.dateWeekTime(date); // "Jan 1, 2020 Wed 12:00 AM"
 * 
 * dateFormat.dateWeekTimeDayExtended(date); // "Jan 1, 2020 Wednesday 12:00 AM"
 * timeFormat.dateWeekTimeDayExtended(date); // "Jan 1, 2020 Wednesday 12:00 AM"
 * 
 * dateFormat.extended(date); // "Wednesday January 1, 2020 12:00 AM (3 years ago)"
 * timeFormat.extended(date); // "Wednesday January 1, 2020 12:00 AM (3 years ago)"
 * 
 * dateFormat.default(date); // This will return date in user date format in globalProps
 * timeFormat.default(date); // This will return date in user date format in globalProps
 * 
 * dateFormat.defaultWithTime(date); // This will return date time in user date format in globalProps
 * timeFormat.defaultWithTime(date); // This will return date time in user date format in globalProps
 * @endexample
 * All neeto-applications should be using any one of these styles (according to the
 *
 * space available) to display date and time unless if the case is too specific to
 *
 * the project.
 *
*/
export const dateFormat: typeof timeFormat;
export interface DayjsStatic {
  (arg?: string | number | Date | Dayjs): Dayjs;
  utc: typeof utcPlugin;
  tz: typeof tzPlugin;
  duration: typeof durationPlugin;
  isDayjs: typeof isDayjsPlugin;
  updateLocale: typeof updateLocalePlugin;
  locale: (preset?: string | {
    name: string;
    [key: string]: any;
  }) => string;
}
/**
 *
 * The dayjs wrapper provides an extended version of the dayjs library with additional support for various features such as custom date parsing, localized formatting, and time zone management.
 *
 * The wrapper automatically sets the default time zone based on the globalProps.user.timeZone if it is defined. Ensure that globalProps and the user.timeZone are correctly initialized in your application.
 *
 * @example 
 *
 * // import dayjs from "@bigninary/neeto-commons-frontend/utils";
 * import { dayjs } from "@bigninary/neeto-commons-frontend/utils";
 * 
 * 
 * // Get the current date and time
 * dayjs().format("dddd, MMMM D, YYYY h:mm A"); // "Wednesday, January 1, 2020 12:00 AM" (current date and time based on the user's time zone)
 * @endexample
*/
export const dayjs: DayjsStatic;
/**
 *
 * The toLocale function converts a given number to a locale-specific string
 *
 * representation, formatting it with commas as thousands separators and respecting
 *
 * the appropriate decimal separator for the locale. It automatically detects the
 *
 * appropriate locale using globalProps and falls back to the user's browser
 *
 * locale if necessary.
 *
 * @example 
 *
 * toLocale(1000000); // "1,000,000" when locale is "en-US"
 * toLocale(1000000); // "10,00,000" when locale is "en-IN"
 * toLocale(1000000.987, { maximumFractionDigits: 2 }); // "1,000,000.99"
 * toLocale(1000000.987, {
 *   currencyDisplay: "narrowSymbol",
 *   style: "currency",
 *   currency: "INR",
 * }); // "₹1,000,000.99"
 * @endexample
*/
export function toLocale(number: string | number, options?: Intl.NumberFormatOptions): string;
export type qsOptionsType = {
  comma?: boolean | undefined;
  delimiter?: string | RegExp | undefined;
  depth?: number | false | undefined;
  decoder?: ((str: string, defaultDecoder: any, charset: string, type: "key" | "value") => any) | undefined;
  arrayLimit?: number | undefined;
  parseArrays?: boolean | undefined;
  allowDots?: boolean | undefined;
  plainObjects?: boolean | undefined;
  allowPrototypes?: boolean | undefined;
  parameterLimit?: number | undefined;
  strictNullHandling?: boolean | undefined;
  ignoreQueryPrefix?: boolean | undefined;
  charset?: "utf-8" | "iso-8859-1" | undefined;
  charsetSentinel?: boolean | undefined;
  interpretNumericEntities?: boolean | undefined;
  toCamelCase?: boolean | undefined;
};
export type QueryParamsType = {
  [key: string]: any;
};
/**
 *
 * The getQueryParams function retrieves all the query parameters from the
 *
 * current URL and returns them as an object. Query parameters are typically found
 *
 * in the URL following a "?" character and are used to pass data to a web page or
 *
 * API.
 *
 * This function will return an object containing all the query parameters in camel
 *
 * case. It will return an empty object if no query parameters are present.
 *
 * You can set toCamelCase to false if you don't want to apply any transformation to the keys.
 *
 * to false.
 *
 * More details on working:
 *
 * https://www.loom.com/share/4f369cff56e845428d5ef7451759469c
 *
 * @example 
 *
 * // Let the current url be "https://example.com?search=something&sort_by=date&order_by=desc".
 * getQueryParams();
 * // output: { search: "something", sort_by: "date", order_by: "desc" }
 * 
 * const { search, sortBy, orderBy } = getQueryParams();
 * 
 * const { search, sort_by, order_by } = getQueryParams({ toCamelCase: false });
 * @endexample
*/
export function getQueryParams(options?: qsOptionsType): QueryParamsType;
/**
 *
 * The joinHyphenCase function joins an array of strings using hyphens as the
 *
 * delimiter and returns the resulting string.
 *
 * Any number of string arguments.
 *
 * @example 
 *
 * joinHyphenCase("hello", "world"); // output: "hello-world"
 * @endexample
*/
export function joinHyphenCase(...args: string[]): string;
/**
 *
 * The hyphenize function converts strings that contain underscores, spaces, and
 *
 * camelCase strings into hyphenized strings
 *
 * @example 
 *
 * hyphenize("hello_world", ""); // output: "hello-world"
 * @endexample
*/
export function hyphenize(value: string, fallbackString?: string): string;
/**
 *
 * The debounce function is used to create a debounced function that delays the
 *
 * execution of a given function until a specified wait time, in milliseconds, has
 *
 * elapsed since the last time it was invoked.
 *
 * @example 
 *
 * const searchForProducts = debounce(async key => {
 *   // this function will be triggered once after user stops typing for 300ms
 *   const products = await productsApi.fetch(key);
 *   // do something with the products
 * }, 300);
 * <input onChange={e => searchForProducts(e.target.value)} />;
 * @endexample
*/
export function debounce<F extends Function>(func: F, delay?: number): F;
/**
 *
 * The hasPermission function checks whether the current user has a specific
 *
 * permission. It returns true if the user has the specified permission and
 *
 * false if they do not. Permissions are typically used to control access to
 *
 * various features or actions within an application. The permissions corresponding
 *
 * to a particular user is taken from the globalProps.
 *
 * @example 
 *
 * hasPermission("user.view_settings");
 * @endexample
*/
export function hasPermission(permission: string): boolean;
/**
 *
 * The hasAnyPermission function checks whether the current user has any of the
 *
 * specified permissions. It returns true if the user has at least one of the
 *
 * permissions and false if the user has none of them. The permissions
 *
 * corresponding to a particular user is taken from the globalProps.
 *
 * permissions: Any number of permission strings.
 *
 * @example 
 *
 * hasAnyPermission("user.view_settings", "user.edit_settings");
 * @endexample
*/
export function hasAnyPermission(...permissions: string[]): boolean;
/**
 *
 * The hasAllPermissions function checks whether the current user has all of the
 *
 * specified permissions. It returns true if the user has all the permissions and
 *
 * false otherwise. The permissions corresponding to a particular user is taken
 *
 * from the globalProps.
 *
 * permissions: Any number of permission strings.
 *
 * @example 
 *
 * hasAllPermissions("user.view_settings", "user.edit_settings");
 * @endexample
*/
export function hasAllPermissions(...permissions: string[]): boolean;
type ChannelNameWithParams = {
  channel: string;
  [key: string]: any;
};
/**
 *
 * The createSubscription function is used to create a subscription in a web
 *
 * application where a consumer subscribes to a Rails
 *
 * Action Cable
 *
 * channel. This function facilitates the creation of subscriptions on the client
 *
 * side to listen for updates and events broadcasted on a specific channel.
 *
 * @example 
 *
 * const subscription = createSubscription(
 *   {
 *     channel: "testChannel",
 *     deployment_id: "deploymentId",
 *   },
 *   { received: value => handleValue(value) }
 * );
 * @endexample
*/
export function createSubscription(channelName: string | ChannelNameWithParams, callbacks: Mixin): Subscription;
/**
 *
 * The getFromLocalStorage function retrieves a JSON-parsed value from the
 *
 * browser's localStorage for the specified key. If the stored value is not valid
 *
 * JSON or if the key does not exist in localStorage, the function returns
 *
 * null.
 *
 * @example 
 *
 * localStorage.setItem("key", JSON.stringify({ a: 1 }));
 * getFromLocalStorage("key"); //returns { a: 1 }
 * @endexample
*/
export function getFromLocalStorage<T extends object>(key: string): T | null;
/**
 *
 * The setToLocalStorage function takes a key and a value as its parameters
 *
 * and save the stringified representation of the value under the specified key
 *
 * within local storage.
 *
 * @example 
 *
 * setToLocalStorage("token", "1234-5678-9101-1213");
 * @endexample
*/
export function setToLocalStorage(key: string, value: any): void;
/**
 *
 * The removeFromLocalStorage function takes a key as its parameter, and will
 *
 * remove that key from the given Storage object if it exists.
 *
 * @example 
 *
 * removeFromLocalStorage("token");
 * @endexample
*/
export function removeFromLocalStorage(key: string): void;
type CurrencyFormatterFunction = (amount: number | string, currency: string, options?: Intl.NumberFormatOptions) => string;
/**
 *
 * currencyFormat is a utility which provides functions which formats a given
 *
 * number in currency formats based on the current user locale. Current user locale
 *
 * is based on dayjs.locale().
 *
 * withAmount accepts two arguments:
 *
 * All other functions accept three arguments:
 *
 * @example 
 *
 * import { currencyFormat } from "neetocommons/utils";
 * 
 * currencyFormat.withAmount(1000); // In `en` locale, returns "1,000.00"
 * currencyFormat.withAmount(125, { maximumFractionDigits: 1 }); // In `en` locale, returns "125.0"
 * 
 * currencyFormat.withSymbol(1000, "USD"); // In `en` locale, returns "$1,000.00"
 * currencyFormat.withSymbol(125, "USD", { maximumFractionDigits: 1 }); // In `en` locale, returns "$125.0"
 * 
 * currencyFormat.withCode(1000, "USD"); // In `en` locale, returns "1,000.00 USD"
 * currencyFormat.withCode(125, "USD", { maximumFractionDigits: 1 }); // In `en` locale, returns "125.0 USD"
 * 
 * currencyFormat.withSymbolAndCode(1000, "INR"); // In `en` locale, returns "₹1,000.00 INR"
 * currencyFormat.withSymbolAndCode(125, "INR", {
 *   maximumFractionDigits: 1,
 * }); // In `en` locale, returns "₹125.0 INR"
 * 
 * // `fr`
 * currencyFormat.withSymbolAndCode(1000, "EUR"); // In `fr` locale, returns "1 000 € EUR"
 * currencyFormat.withSymbolAndCode(125, "INR", {
 *   maximumFractionDigits: 1,
 * }); // In `fr` locale, returns "125,00 ₹ INR""
 * @endexample
*/
export const currencyFormat: {
  withAmount: (amount: number | string, options?: Intl.NumberFormatOptions) => string;
  withSymbol: CurrencyFormatterFunction;
  withCode: CurrencyFormatterFunction;
  withSymbolAndCode: CurrencyFormatterFunction;
};
/**
 *
 * The showThumbsUpToastr function displays a toastr notification with a thumbs-up icon,
 *
 * indicating a successful operation.
 *
 * @example 
 *
 * showThumbsUpToastr();
 * @endexample
*/
export function showThumbsUpToastr(): void;
/**
 *
 * Ensure a given string is a valid slug, containing only lowercase letters,
 *
 * numbers, and hyphens.
 *
 * @example 
 *
 * slugValidator("Slug").isValid("valid-slug"); // output true
 * slugValidator("Slug").isValid("invalid slug"); // output false
 * 
 * const schema = yup.object().shape({
 *   slug: slugValidator("Slug"),
 * });
 * @endexample
*/
export function slugValidator(label: string): StringSchema;
/**
 *
 * The captureAnalyticsEvent is a utility function which facilitates logging user
 *
 * events to Mixpanel.
 *
 * @example 
 *
 * import { captureAnalyticsEvent } from "@bigbinary/neeto-commons-frontend/utils";
 * // ...
 * 
 * captureAnalyticsEvent("event_name", { subdomain: "spinkart" });
 * 
 * // The second argument is optional, containing additional data to log as part of the event.
 * @endexample
*/
export function captureAnalyticsEvent(name: string, properties?: {
  [key: string]: any;
}): void;
/**
 *
 * The captureAnalyticsPageView is a utility function which facilitates logging user page views to Mixpanel.
 *
 * @example 
 *
 * import { captureAnalyticsPageView } from "@bigbinary/neeto-commons-frontend/utils";
 * // ...
 * 
 * captureAnalyticsPageView("page_name", { additional: "information" });
 * 
 * // The second argument is optional, containing additional data to log as part of the page.
 * @endexample
*/
export function captureAnalyticsPageView(page: string, properties?: {
  [key: string]: string;
}): void;
/**
 *
 * The buildNestedAttributesPayload function is a utility designed to
 *
 * create payloads for Rails' Active Record Nested Attributes. This function
 *
 * simplifies the process of handling nested forms by generating the correct
 *
 * payload structure, which includes the necessary attributes for creating and
 *
 * destroying nested records.
 *
 * @example 
 *
 * import { buildNestedAttributesPayload } from "@bigbinary/neeto-commons-frontend/utils";
 * 
 * // Example initial and modified values
 * const initialValues = {
 *   emails: [
 *     { id: 1, email: "test1@example.com" },
 *     { id: 2, email: "test2@example.com" },
 *   ],
 * };
 * 
 * const modifiedValues = {
 *   emails: [{ value: "test2@example.com" }, { value: "test3@example.com" }],
 * };
 * 
 * const payload = buildNestedAttributesPayload({
 *   initialValues,
 *   modifiedValues,
 *   nestedKeyToModify: "emails",
 *   nestedAttributeKeyInPayload: "email",
 *   nestedAttributesForArrayKey: "whitelistedEmailsAttributes",
 * });
 * 
 * console.log(payload);
 * // Output:
 * // {
 * //   whitelistedEmailsAttributes: [
 * //     { email: "test3@example.com" },
 * //     { id: 1, email: "test1@example.com", _destroy: true }
 * //   ]
 * // }
 * @endexample
*/
export function buildNestedAttributesPayload(modifiedValues: {
  [key: string]: any;
}, initialValues: {
  [key: string]: any;
}, nestedKeyToModify: string, nestedAttributeKeyInPayload: string, nestedAttributesForArrayKey: string): {
  [key: string]: any;
};
/**
 *
 * The loadGoogleFonts is a utility function which facilitates loading multiple Google Fonts dynamically by injecting link elements into the document head.
 *
 * @example 
 *
 * import { useEffect } from "react";
 * 
 * import { loadGoogleFonts } from "@bigbinary/neeto-commons-frontend/utils";
 * 
 * useEffect(() => {
 *   const fontFamilies = ['Roboto', 'Open Sans', 'Lato'];
 *   loadGoogleFonts(fontFamilies);
 * }, []);
 * @endexample
*/
export function loadGoogleFonts(fontFamilies: string[]): void;

// Device Information Types
export interface DeviceInformationOptions {
  appType?: string;
}
export interface DeviceInfo {
  type: string;
  os: string;
  osVersion: string;
  screen: {
    width: number;
    height: number;
    pixelRatio: number;
    colorDepth: number;
  };
  viewport: {
    width: number;
    height: number;
  };
  memoryGB: number | null;
}
export interface BrowserInfo {
  name: string;
  version: string;
  userAgent: string;
  javaScriptEnabled: boolean;
  cookiesEnabled: boolean;
  websockets: boolean;
  webgl: boolean;
  doNotTrack: string | null;
  mimeTypes: string[];
  network: {
    effectiveType: string;
    downlink: number;
    rtt: number;
    saveData: boolean;
  } | null;
}
export interface PermissionsInfo {
  microphone: string;
  camera: string;
  geolocation: string;
  notifications: string;
  media: {
    hasMic: boolean | null;
    hasCamera: boolean | null;
  };
}
export interface MetaInfo {
  time: {
    zone: string;
    offset: string;
  };
  referrer: string;
  appType: string;
}
export interface DeviceInformationResult {
  device: DeviceInfo;
  browser: BrowserInfo;
  permissions: PermissionsInfo;
  meta: MetaInfo;
}
/**
 *
 * The deviceInformation function collects comprehensive device and browser
 *
 * information including device specifications, browser details, permissions, and
 *
 * network information. This function is useful for analytics, debugging, feature
 *
 * detection, and providing device-specific experiences.
 *
 * A Promise that resolves to an object containing:
 *
 * @example 
 *
 * const deviceInfo = await deviceInformation();
 * 
 * console.log(deviceInfo.device.type); // "desktop", "mobile", or "tablet"
 * console.log(deviceInfo.browser.name); // "Chrome", "Firefox", "Safari", etc.
 * console.log(deviceInfo.permissions.microphone); // "granted", "denied", "prompt", or "unsupported"
 * @endexample
 * @example 
 *
 * {
 *   device: {
 *     type: "desktop",
 *     os: "macOS",
 *     osVersion: "13.0",
 *     screen: {
 *       width: 1920,
 *       height: 1080,
 *       pixelRatio: 2,
 *       colorDepth: 24
 *     },
 *     viewport: {
 *       width: 1440,
 *       height: 900
 *     },
 *     memoryGB: 16
 *   },
 *   browser: {
 *     name: "Chrome",
 *     version: "119.0.0.0",
 *     userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...",
 *     javaScriptEnabled: true,
 *     cookiesEnabled: true,
 *     websockets: true,
 *     webgl: true,
 *     doNotTrack: null,
 *     mimeTypes: ["text/html", "text/plain", ...],
 *     network: {
 *       effectiveType: "4g",
 *       downlink: 10,
 *       rtt: 50,
 *       saveData: false
 *     }
 *   },
 *   permissions: {
 *     microphone: "prompt",
 *     camera: "denied",
 *     geolocation: "granted",
 *     notifications: "unsupported",
 *     media: {
 *       hasMic: true,
 *       hasCamera: true
 *     }
 *   },
 *   meta: {
 *     timezone: "America/New_York",
 *     referrer: "https://example.com"
 *   },
 *   serverDerived: {
 *     country: "US",
 *     region: "California",
 *     city: "San Francisco"
 *   }
 * }
 * @endexample
*/
export function deviceInformation(options?: DeviceInformationOptions): Promise<DeviceInformationResult>;
export function getAppType(): "extension" | "desktop" | "mobile" | "web";