import React from 'react'; type VersionLimits = { softLimit?: number; hardLimit?: number; }; type BrowserVersionOverrides = { Chrome?: VersionLimits; MobileChrome?: VersionLimits; Edge?: VersionLimits; Firefox?: VersionLimits; MobileFirefox?: VersionLimits; Safari?: VersionLimits; MobileSafari?: VersionLimits; Opera?: VersionLimits; SamsungInternet?: VersionLimits; Electron?: VersionLimits; WebKit?: VersionLimits; }; /** * * A wrapper that displays a callout message for partially supported browsers * * (below a soft limit) along with the site content. If the browser is an * * unsupported version (below a hard limit), it shows a full-page message to update * * the browser and does not display the site content. If the browser is in the list * * of unsupported browsers, it displays a full-page message that the browser is * * unsupported and does not display the site content. * * @example * * import BrowserSupport from "@bigbinary/neeto-molecules/BrowserSupport"; * * const App = () => ( * * {children} * *
* ) * @endexample * This placement handles browsers that load the app but cannot render it properly. * * It cannot help when the browser is too old to parse the app chunk at all — see * * the next section, which is the placement most products actually want. * * Wrapping Main in cannot help when the browser is old enough * * that the app chunk fails to parse. mount() rejects on the dynamic import and * * React never renders, so the user gets a blank page rather than an explanation. * * For that case call renderBrowserSupportGate from the pack, before mount(), * * where only the entry chunk has had to parse. It returns true when the browser * * was blocked, meaning the app must not be mounted: * * @example * * import mount from "neetocommons/react-utils/mount"; * import { renderBrowserSupportGate } from "@bigbinary/neeto-molecules/v2/BrowserSupport"; * * const initializeAndMount = async () => { * await initializeApplication(); * * if (renderBrowserSupportGate()) return; * * mount(componentMap); * }; * @endexample * It renders into [data-react-class] by default, the same element mount() * * uses; pass element to override. When it blocks it also removes * * #neeto-page-loader, the loader rendered by shared/_page_loader in * * neeto-commons-backend, which sits outside the react root and would otherwise * * keep spinning over the message; pass loaderSelector if your product renders a * * different one. overrides and unsupportedBrowsers behave as they do on the * * component, and products should not normally need either — the defaults are the * * floor the shared stack imposes, so a product that overrides them is opting out * * of the guarantee rather than configuring it. Whatever the pack imports has to * * stay parseable on the browsers being guarded against, so keep the entry chunk * * free of syntax newer than the floor you are enforcing. * * The overrides prop changes the limits for a specific browser. The usual reason * * to reach for it is to open a partial band, where a browser below softLimit but * * at or above hardLimit gets a callout and still sees the page: * * @example * * * @endexample * Here Chrome 111 to 119 and Safari 16.4 to 16.6 get the callout along with the * * page contents. Chrome below 111 and Safari below 16.4 get the full-page message * * and no content. Every version of Samsung Internet is blocked outright. * * Lowering hardLimit below the defaults is possible but rarely a good idea. The * * defaults are the point at which the generated CSS stops applying, so lowering * * them serves a visibly broken page instead of a message explaining why. * * The default minimum versions are set by Tailwind v4, which hardcodes its * * Lightning CSS targets to Safari/iOS 16.4, Chrome 111 and Firefox 128 and exposes * * no option to lower them. Below that floor the generated CSS (@property, * * oklch(), :has(), @container) is dropped by the parser without an error, so * * the app renders broken rather than degraded. The remaining engines are pinned to * * the first release built on an equivalent core. * * | Browser name | Min supported version | * * | :-------------- | :-------------------- | * * | Chrome | 111 | * * | MobileChrome | 111 | * * | Edge | 111 | * * | Firefox | 128 | * * | MobileFirefox | 128 | * * | Safari | 16.4 | * * | MobileSafari | 16.4 | * * | Opera | 98 | * * | SamsungInternet | 22 | * * | Electron | 24 | * * | WebKit | 605 | * * softLimit and hardLimit are equal by default, so a browser below the floor * * gets the full-page message rather than a callout. There is no meaningful * * "degraded but usable" band below it — the CSS either applies or it does not. Set * * an explicit overrides entry if a product wants a partial band. * * Safari freezes the WebKit build number in its user agent (605.1.15 since * * Safari 12), so the WebKit entry cannot discriminate versions. It exists only * * to keep generic WebKit clients out of the unknown-browser branch. * * The default unsupported browsers are given below. These cannot reach the floor * * at any released version, and are blocked before overrides are consulted: * * Any other browser which is not in the above lists will be considered as unknown * * and a corresponding callout will be shown. * */ declare const BrowserSupport: React.FC<{ overrides?: BrowserVersionOverrides; unsupportedBrowsers?: string[]; children?: React.ReactNode | React.ReactNode[]; }>; declare const renderBrowserSupportGate: (options?: { overrides?: BrowserVersionOverrides; unsupportedBrowsers?: string[]; element?: HTMLElement | null; loaderSelector?: string; }) => boolean; export { BrowserSupport as default, renderBrowserSupportGate };