Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: improve browser check to resolve SSR errors #9897

Merged
merged 6 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/calcite-components/conventions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,9 +373,9 @@ This generates a `hydrate` directory which exposes `renderToString()` (for the s
Since many of the same lifecycle methods are called on the client and server you may need to differentiate any code that relies on browser APIs like so:

```ts
import { Build } from "@stencil/core";
import { isBrowser } from "../utils/browser";

if (Build.isBrowser) {
if (isBrowser()) {
// client side
} else {
// server side
Expand Down
8 changes: 4 additions & 4 deletions packages/calcite-components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4518,7 +4518,7 @@ export namespace Components {
*/
"detached": boolean;
/**
* When `displayMode` is `float-content`, specifies the maximum height of the component.
* When `displayMode` is `float-content` or `float`, specifies the maximum height of the component.
* @deprecated Use `heightScale` instead.
*/
"detachedHeightScale": Scale;
Expand Down Expand Up @@ -4547,7 +4547,7 @@ export namespace Components {
*/
"position": Extract<"start" | "end", Position>;
/**
* When `true` and `displayMode` is not `float-content`, the component's content area is resizable.
* When `true` and `displayMode` is not `float-content` or `float`, the component's content area is resizable.
*/
"resizable": boolean;
/**
Expand Down Expand Up @@ -12638,7 +12638,7 @@ declare namespace LocalJSX {
*/
"detached"?: boolean;
/**
* When `displayMode` is `float-content`, specifies the maximum height of the component.
* When `displayMode` is `float-content` or `float`, specifies the maximum height of the component.
* @deprecated Use `heightScale` instead.
*/
"detachedHeightScale"?: Scale;
Expand Down Expand Up @@ -12669,7 +12669,7 @@ declare namespace LocalJSX {
*/
"position"?: Extract<"start" | "end", Position>;
/**
* When `true` and `displayMode` is not `float-content`, the component's content area is resizable.
* When `true` and `displayMode` is not `float-content` or `float`, the component's content area is resizable.
*/
"resizable"?: boolean;
/**
Expand Down
4 changes: 2 additions & 2 deletions packages/calcite-components/src/components/action/action.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
Build,
Component,
Element,
forceUpdate,
Expand Down Expand Up @@ -38,6 +37,7 @@ import {
} from "../../utils/t9n";
import { Alignment, Appearance, Scale } from "../interfaces";
import { IconName } from "../icon/interfaces";
import { isBrowser } from "../../utils/browser";
import { ActionMessages } from "./assets/action/t9n";
import { CSS, SLOTS } from "./resources";

Expand Down Expand Up @@ -182,7 +182,7 @@ export class Action

async componentWillLoad(): Promise<void> {
setUpLoadableComponent(this);
if (Build.isBrowser) {
if (isBrowser()) {
await setUpMessages(this);
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/calcite-components/src/components/button/button.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
Build,
Component,
Element,
forceUpdate,
Expand Down Expand Up @@ -38,6 +37,7 @@ import {
import { Appearance, FlipContext, Kind, Scale, Width } from "../interfaces";
import { toAriaBoolean } from "../../utils/dom";
import { IconName } from "../icon/interfaces";
import { isBrowser } from "../../utils/browser";
import { ButtonMessages } from "./assets/button/t9n";
import { ButtonAlignment } from "./interfaces";
import { CSS } from "./resources";
Expand Down Expand Up @@ -226,7 +226,7 @@ export class Button

async componentWillLoad(): Promise<void> {
setUpLoadableComponent(this);
if (Build.isBrowser) {
if (isBrowser()) {
this.updateHasContent();
await setUpMessages(this);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/calcite-components/src/components/chip/chip.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
Build,
Component,
Element,
Event,
Expand Down Expand Up @@ -39,6 +38,7 @@ import { connectLocalized, disconnectLocalized, LocalizedComponent } from "../..
import { isActivationKey } from "../../utils/key";
import { getIconScale } from "../../utils/component";
import { IconName } from "../icon/interfaces";
import { isBrowser } from "../../utils/browser";
import { ChipMessages } from "./assets/chip/t9n";
import { CSS, SLOTS, ICONS } from "./resources";

Expand Down Expand Up @@ -230,7 +230,7 @@ export class Chip

async componentWillLoad(): Promise<void> {
setUpLoadableComponent(this);
if (Build.isBrowser) {
if (isBrowser()) {
await setUpMessages(this);
this.updateHasText();
}
Expand Down
4 changes: 2 additions & 2 deletions packages/calcite-components/src/components/combobox/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Build } from "@stencil/core";
import { nodeListToArray } from "../../utils/dom";
import { isBrowser } from "../../utils/browser";
import { ComboboxChildElement } from "./interfaces";
import { ComboboxChildSelector } from "./resources";
import { Combobox } from "./combobox";
Expand All @@ -26,7 +26,7 @@ export function hasActiveChildren(node: HTMLCalciteComboboxItemElement): boolean
}

export function getDepth(element: HTMLElement): number {
if (!Build.isBrowser) {
if (!isBrowser()) {
return 0;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
Build,
Component,
Element,
Event,
Expand Down Expand Up @@ -42,6 +41,7 @@ import {
updateMessages,
} from "../../utils/t9n";
import { HeadingLevel } from "../functional/Heading";
import { isBrowser } from "../../utils/browser";
import { DatePickerMessages } from "./assets/date-picker/t9n";
import { DATE_PICKER_FORMAT_OPTIONS, HEADING_LEVEL } from "./resources";
import { DateLocaleData, getLocaleData, getValueAsDateRange } from "./utils";
Expand Down Expand Up @@ -347,7 +347,7 @@ export class DatePicker implements LocalizedComponent, LoadableComponent, T9nCom

@Watch("effectiveLocale")
private async loadLocaleData(): Promise<void> {
if (!Build.isBrowser) {
if (!isBrowser()) {
return;
}

Expand Down
5 changes: 3 additions & 2 deletions packages/calcite-components/src/components/icon/icon.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { CalciteIconPath, CalciteMultiPathEntry } from "@esri/calcite-ui-icons";
import { Build, Component, Element, h, Host, Prop, State, VNode, Watch } from "@stencil/core";
import { Component, Element, h, Host, Prop, State, VNode, Watch } from "@stencil/core";
import { getElementDir, toAriaBoolean } from "../../utils/dom";
import { createObserver } from "../../utils/observers";
import { Scale } from "../interfaces";
import { isBrowser } from "../../utils/browser";
import { CSS } from "./resources";
import { fetchIcon, getCachedIconData, scaleToPx } from "./utils";
import { IconName } from "./interfaces";
Expand Down Expand Up @@ -137,7 +138,7 @@ export class Icon {
private async loadIconPathData(): Promise<void> {
const { icon, scale, visible } = this;

if (!Build.isBrowser || !icon || !visible) {
if (!isBrowser() || !icon || !visible) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
Build,
Component,
Element,
Event,
Expand Down Expand Up @@ -90,6 +89,7 @@ import { Status } from "../interfaces";
import { Validation } from "../functional/Validation";
import { IconName } from "../icon/interfaces";
import { syncHiddenFormInput } from "../input/common/input";
import { isBrowser } from "../../utils/browser";
import { normalizeToCurrentCentury, isTwoDigitYear } from "./utils";
import { InputDatePickerMessages } from "./assets/input-date-picker/t9n";
import { CSS } from "./resources";
Expand Down Expand Up @@ -981,7 +981,7 @@ export class InputDatePicker
};

private async loadLocaleData(): Promise<void> {
if (!Build.isBrowser) {
if (!isBrowser()) {
return;
}
numberStringFormatter.numberFormatOptions = {
Expand Down
4 changes: 2 additions & 2 deletions packages/calcite-components/src/components/list-item/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Build } from "@stencil/core";
import { isBrowser } from "../../utils/browser";

const listSelector = "calcite-list";
const listItemGroupSelector = "calcite-list-item-group";
Expand Down Expand Up @@ -38,7 +38,7 @@ export function updateListItemChildren(listItemChildren: HTMLCalciteListItemElem
}

export function getDepth(element: HTMLElement, includeGroup = false): number {
if (!Build.isBrowser) {
if (!isBrowser()) {
return 0;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
Build,
Component,
Element,
Event,
Expand Down Expand Up @@ -39,6 +38,7 @@ import { Appearance, Layout, Scale, Status, Width } from "../interfaces";
import { createObserver } from "../../utils/observers";
import { Validation } from "../functional/Validation";
import { IconName } from "../icon/interfaces";
import { isBrowser } from "../../utils/browser";
import { CSS } from "./resources";

/**
Expand Down Expand Up @@ -390,7 +390,7 @@ export class SegmentedControl
});

this.selectedItem = match;
if (Build.isBrowser && match) {
if (isBrowser() && match) {
match.focus();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
Build,
Component,
Element,
Event,
Expand Down Expand Up @@ -36,6 +35,7 @@ import {
} from "../../utils/t9n";
import { getIconScale } from "../../utils/component";
import { IconName } from "../icon/interfaces";
import { isBrowser } from "../../utils/browser";
import { TabTitleMessages } from "./assets/tab-title/t9n";
import { CSS, ICONS } from "./resources";

Expand Down Expand Up @@ -172,7 +172,7 @@ export class TabTitle implements InteractiveComponent, LocalizedComponent, T9nCo

async componentWillLoad(): Promise<void> {
await setUpMessages(this);
if (Build.isBrowser) {
if (isBrowser()) {
this.updateHasText();
}
if (this.tab && this.selected) {
Expand Down
11 changes: 10 additions & 1 deletion packages/calcite-components/src/utils/browser.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { Build } from "@stencil/core";

export const isBrowser = (): boolean =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🆒

Build.isBrowser &&
typeof navigator !== "undefined" &&
typeof window !== "undefined" &&
typeof location !== "undefined" &&
typeof document !== "undefined" &&
window.location === location &&
window.document === document;

interface NavigatorUAData {
brands: Array<{ brand: string; version: string }>;
mobile: boolean;
Expand All @@ -11,7 +20,7 @@ function getUserAgentData(): NavigatorUAData | undefined {
}

export function getUserAgentString(): string {
if (!Build.isBrowser) {
if (!isBrowser()) {
return "";
}

Expand Down
6 changes: 3 additions & 3 deletions packages/calcite-components/src/utils/floating-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ import {
Strategy,
VirtualElement,
} from "@floating-ui/dom";
import { Build } from "@stencil/core";
import { debounce, DebouncedFunc } from "lodash-es";
import { offsetParent } from "composed-offset-position";
import { Layout } from "../components/interfaces";
import { DEBOUNCE } from "./resources";
import { getElementDir } from "./dom";
import { isBrowser } from "./browser";

(function setUpFloatingUiForShadowDomPositioning(): void {
if (Build.isBrowser) {
if (isBrowser()) {
const originalGetOffsetParent = platform.getOffsetParent;
platform.getOffsetParent = (element: Element) => originalGetOffsetParent(element, offsetParent);
}
Expand Down Expand Up @@ -499,7 +499,7 @@ async function runAutoUpdate(
return;
}

const effectiveAutoUpdate = Build.isBrowser
const effectiveAutoUpdate = isBrowser()
? autoUpdate
: (_refEl: HTMLElement, _floatingEl: HTMLElement, updateCallback: () => void): (() => void) => {
updateCallback();
Expand Down
10 changes: 2 additions & 8 deletions packages/calcite-components/src/utils/globalScript.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import { initModeChangeEvent } from "./mode";
import { stampVersion } from "./config";
import { isBrowser } from "./browser";

/**
* This file is imported in Stencil's `globalScript` config option.
*
* @see {@link https://stenciljs.com/docs/config#globalscript}
*/
export default function (): void {
const isBrowser =
typeof window !== "undefined" &&
typeof location !== "undefined" &&
typeof document !== "undefined" &&
window.location === location &&
window.document === document;

if (isBrowser) {
if (isBrowser()) {
if (document.readyState === "interactive") {
initModeChangeEvent();
} else {
Expand Down
5 changes: 3 additions & 2 deletions packages/calcite-components/src/utils/loadable.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Build, forceUpdate } from "@stencil/core";
import { forceUpdate } from "@stencil/core";
import { isBrowser } from "./browser";

/**
* This helper adds support for knowing when a component has been loaded.
Expand Down Expand Up @@ -134,7 +135,7 @@ export function componentLoaded(component: LoadableComponent): Promise<void> {
export async function componentFocusable(component: LoadableComponent): Promise<void> {
await componentLoaded(component);

if (!Build.isBrowser) {
if (!isBrowser()) {
return;
}

Expand Down
4 changes: 2 additions & 2 deletions packages/calcite-components/src/utils/observers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Build } from "@stencil/core";
import { isBrowser } from "./browser";

export interface ExtendedMutationObserver extends MutationObserver {
new: () => ExtendedMutationObserver;
Expand Down Expand Up @@ -50,7 +50,7 @@ export function createObserver<T extends ObserverType>(
callback: ObserverCallbackType<T>,
options?: ObserverOptions<T>,
): ObserverInstanceType<T> | undefined {
if (!Build.isBrowser) {
if (!isBrowser()) {
return undefined;
}

Expand Down
5 changes: 3 additions & 2 deletions packages/calcite-components/src/utils/t9n.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Build, getAssetPath } from "@stencil/core";
import { getAssetPath } from "@stencil/core";
import { getSupportedLocale, LocalizedComponent } from "./locale";
import { isBrowser } from "./browser";

export type MessageBundle = Record<string, string>;

Expand Down Expand Up @@ -50,7 +51,7 @@ export async function setUpMessages(component: T9nComponent): Promise<void> {
}

async function fetchMessages(component: T9nComponent, lang: string): Promise<MessageBundle> {
if (!Build.isBrowser) {
if (!isBrowser()) {
return {};
}

Expand Down
Loading