Skip to content
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"build:docs": "PARCEL_WORKER_BACKEND=process DOCS_ENV=staging parcel build 'packages/@react-{spectrum,aria,stately}/*/docs/*.mdx' 'packages/dev/docs/pages/**/*.mdx' --no-scope-hoist",
"test": "yarn jest",
"test:ssr": "yarn jest --config jest.ssr.config.js",
"ci-test": "yarn jest --maxWorkers=2",
"ci-test": "yarn jest --maxWorkers=2 && yarn test:ssr --maxWorkers=2",
"lint": "yarn check-types && eslint packages --ext .js,.ts,.tsx && node scripts/lint-packages.js",
"jest": "node scripts/jest.js",
"copyrights": "babel-node --presets @babel/env ./scripts/addHeaders.js",
Expand Down
3 changes: 2 additions & 1 deletion packages/@react-aria/focus/src/FocusScope.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
*/

import {focusSafely} from './focusSafely';
import React, {ReactNode, RefObject, useContext, useEffect, useLayoutEffect, useRef} from 'react';
import React, {ReactNode, RefObject, useContext, useEffect, useRef} from 'react';
import {useLayoutEffect} from '@react-aria/utils';

// import {FocusScope, useFocusScope} from 'react-events/focus-scope';
// export {FocusScope};
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-aria/overlays/src/useOverlayPosition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export function useOverlayPosition(props: AriaPositionProps): PositionAria {
placement = 'bottom' as Placement,
containerPadding = 12,
shouldFlip = true,
boundaryElement = document.body,
boundaryElement = typeof document !== 'undefined' ? document.body : null,
offset = 0,
crossOffset = 0,
shouldUpdatePosition = true,
Expand Down Expand Up @@ -95,7 +95,7 @@ export function useOverlayPosition(props: AriaPositionProps): PositionAria {
];

let updatePosition = useCallback(() => {
if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !scrollRef.current) {
if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !scrollRef.current || !boundaryElement) {
return;
}

Expand Down
3 changes: 2 additions & 1 deletion packages/@react-aria/radio/src/useRadio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import {AriaRadioProps} from '@react-types/radio';
import {filterDOMProps, mergeProps} from '@react-aria/utils';
import {InputHTMLAttributes, RefObject} from 'react';
import {radioGroupNames} from './utils';
import {RadioGroupState} from '@react-stately/radio';
import {useFocusable} from '@react-aria/focus';
import {usePress} from '@react-aria/interactions';
Expand Down Expand Up @@ -82,7 +83,7 @@ export function useRadio(props: RadioAriaProps, state: RadioGroupState, ref: Ref
inputProps: mergeProps(domProps, {
...interactions,
type: 'radio',
name: state.name,
name: radioGroupNames.get(state),
tabIndex,
disabled: isDisabled,
readOnly: isReadOnly,
Expand Down
7 changes: 6 additions & 1 deletion packages/@react-aria/radio/src/useRadioGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
*/

import {AriaRadioGroupProps} from '@react-types/radio';
import {filterDOMProps, mergeProps} from '@react-aria/utils';
import {filterDOMProps, mergeProps, useId} from '@react-aria/utils';
import {getFocusableTreeWalker} from '@react-aria/focus';
import {HTMLAttributes} from 'react';
import {radioGroupNames} from './utils';
import {RadioGroupState} from '@react-stately/radio';
import {useFocusWithin} from '@react-aria/interactions';
import {useLabel} from '@react-aria/label';
Expand All @@ -34,6 +35,7 @@ interface RadioGroupAria {
*/
export function useRadioGroup(props: AriaRadioGroupProps, state: RadioGroupState): RadioGroupAria {
let {
name,
validationState,
isReadOnly,
isRequired,
Expand Down Expand Up @@ -111,6 +113,9 @@ export function useRadioGroup(props: AriaRadioGroupProps, state: RadioGroupState
}
};

let groupName = useId(name);
radioGroupNames.set(state, groupName);

return {
radioGroupProps: mergeProps(domProps, {
// https://www.w3.org/TR/wai-aria-1.2/#radiogroup
Expand Down
15 changes: 15 additions & 0 deletions packages/@react-aria/radio/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

import {RadioGroupState} from '@react-stately/radio';

export const radioGroupNames = new WeakMap<RadioGroupState, string>();
22 changes: 21 additions & 1 deletion packages/@react-aria/ssr/src/SSRProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* governing permissions and limitations under the License.
*/

import React, {ReactNode, useContext, useMemo} from 'react';
import React, {ReactNode, useContext, useLayoutEffect, useMemo, useState} from 'react';

// To support SSR, the auto incrementing id counter is stored in a context. This allows
// it to be reset on every request to ensure the client and server are consistent.
Expand Down Expand Up @@ -77,3 +77,23 @@ export function useSSRSafeId(defaultId?: string): string {

return useMemo(() => defaultId || `react-aria-${ctx.prefix}-${++ctx.current}`, [defaultId]);
}

/** @private */
export function useIsSSR(): boolean {
let cur = useContext(SSRContext);
let isInSSRContext = cur !== defaultContext;
let [isSSR, setIsSSR] = useState(isInSSRContext);

// If on the client, and the component was initially server rendered,
// then schedule a layout effect to update the component after hydration.
if (typeof window !== 'undefined' && isInSSRContext) {
// This if statement technically breaks the rules of hooks, but is safe
// because the condition never changes after mounting.
// eslint-disable-next-line react-hooks/rules-of-hooks
useLayoutEffect(() => {
setIsSSR(false);
}, []);
}

return isSSR;
}
1 change: 1 addition & 0 deletions packages/@react-aria/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ export * from './useUpdateEffect';
export * from './focusWithoutScrolling';
export * from './filterDOMProps';
export * from './runAfterTransition';
export * from './useLayoutEffect';
3 changes: 2 additions & 1 deletion packages/@react-aria/utils/src/useId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
* governing permissions and limitations under the License.
*/

import {useLayoutEffect, useState} from 'react';
import {useLayoutEffect} from './useLayoutEffect';
import {useSSRSafeId} from '@react-aria/ssr';
import {useState} from 'react';

let map: Map<string, (v: string) => void> = new Map();

Expand Down
20 changes: 20 additions & 0 deletions packages/@react-aria/utils/src/useLayoutEffect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

import React from 'react';

// During SSR, React emits a warning when calling useLayoutEffect.
// Since neither useLayoutEffect nor useEffect run on the server,
// we can suppress this by replace it with a noop on the server.
export const useLayoutEffect = typeof window !== 'undefined'
? React.useLayoutEffect
: () => {};
2 changes: 1 addition & 1 deletion packages/@react-aria/virtualizer/src/ScrollView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import React, {
RefObject,
useCallback,
useEffect,
useLayoutEffect,
useRef,
useState
} from 'react';
import {Rect, Size} from '@react-stately/virtualizer';
import {useLayoutEffect} from '@react-aria/utils';
import {useLocale} from '@react-aria/i18n';

interface ScrollViewProps extends HTMLAttributes<HTMLElement> {
Expand Down
3 changes: 2 additions & 1 deletion packages/@react-aria/virtualizer/src/useVirtualizerItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
* governing permissions and limitations under the License.
*/

import {RefObject, useCallback, useLayoutEffect} from 'react';
import {RefObject, useCallback} from 'react';
import {ReusableView, Size} from '@react-stately/virtualizer';
import {useLayoutEffect} from '@react-aria/utils';

interface VirtualizerItemOptions<T extends object, V, W> {
reusableView: ReusableView<T, V>,
Expand Down
3 changes: 2 additions & 1 deletion packages/@react-spectrum/breadcrumbs/src/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import {classNames, useDOMRef, useResizeObserver, useStyleProps} from '@react-sp
import {DOMRef} from '@react-types/shared';
import FolderBreadcrumb from '@spectrum-icons/ui/FolderBreadcrumb';
import {Menu, MenuTrigger} from '@react-spectrum/menu';
import React, {Key, ReactElement, useCallback, useLayoutEffect, useRef, useState} from 'react';
import React, {Key, ReactElement, useCallback, useRef, useState} from 'react';
import {SpectrumBreadcrumbsProps} from '@react-types/breadcrumbs';
import styles from '@adobe/spectrum-css-temp/components/breadcrumb/vars.css';
import {useBreadcrumbs} from '@react-aria/breadcrumbs';
import {useLayoutEffect} from '@react-aria/utils';
import {useProviderProps} from '@react-spectrum/provider';

const MIN_VISIBLE_ITEMS = 1;
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-spectrum/buttongroup/src/ButtonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

import {classNames, SlotProvider, useDOMRef, useSlotProps, useStyleProps} from '@react-spectrum/utils';
import {DOMRef} from '@react-types/shared';
import {filterDOMProps} from '@react-aria/utils';
import React, {useCallback, useEffect, useLayoutEffect, useState} from 'react';
import {filterDOMProps, useLayoutEffect} from '@react-aria/utils';
import React, {useCallback, useEffect, useState} from 'react';
import {SpectrumButtonGroupProps} from '@react-types/buttongroup';
import styles from '@adobe/spectrum-css-temp/components/buttongroup/vars.css';
import {useProvider, useProviderProps} from '@react-spectrum/provider';
Expand Down
1 change: 1 addition & 0 deletions packages/@react-spectrum/combobox/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@react-aria/focus": "^3.1.0",
"@react-aria/i18n": "^3.1.0",
"@react-aria/overlays": "^3.1.0",
"@react-aria/utils": "3.2.0",
"@react-spectrum/button": "^3.1.0",
"@react-spectrum/label": "^3.1.0",
"@react-spectrum/listbox": "^3.1.0",
Expand Down
3 changes: 2 additions & 1 deletion packages/@react-spectrum/combobox/src/ComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ import labelStyles from '@adobe/spectrum-css-temp/components/fieldlabel/vars.css
import {ListBoxBase, useListBoxLayout} from '@react-spectrum/listbox';
import {Placement} from '@react-types/overlays';
import {Popover, Tray} from '@react-spectrum/overlays';
import React, {ReactElement, RefObject, useLayoutEffect, useRef, useState} from 'react';
import React, {ReactElement, RefObject, useRef, useState} from 'react';
import {SpectrumComboBoxProps} from '@react-types/combobox';
import styles from '@adobe/spectrum-css-temp/components/inputgroup/vars.css';
import {TextFieldBase} from '@react-spectrum/textfield';
import {TextFieldRef} from '@react-types/textfield';
import {useCollator} from '@react-aria/i18n';
import {useComboBox} from '@react-aria/combobox';
import {useComboBoxState} from '@react-stately/combobox';
import {useLayoutEffect} from '@react-aria/utils';
import {useProvider, useProviderProps} from '@react-spectrum/provider';

function ComboBox<T extends object>(props: SpectrumComboBoxProps<T>, ref: RefObject<TextFieldRef>) {
Expand Down
1 change: 1 addition & 0 deletions packages/@react-spectrum/layout/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
},
"dependencies": {
"@babel/runtime": "^7.6.2",
"@react-aria/ssr": "3.0.0-alpha.1",
"@react-aria/utils": "^3.2.0",
"@react-spectrum/utils": "^3.2.0",
"@react-types/layout": "^3.1.0",
Expand Down
8 changes: 5 additions & 3 deletions packages/@react-spectrum/layout/src/Flex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {DOMRef} from '@react-types/shared';
import {filterDOMProps} from '@react-aria/utils';
import {FlexProps} from '@react-types/layout';
import React, {forwardRef} from 'react';
import styles from './flex.css';
import styles from './flex-gap.css';
import {useIsSSR} from '@react-aria/ssr';

const flexStyleProps: StyleHandlers = {
direction: ['flexDirection', passthroughStyle],
Expand All @@ -33,14 +34,15 @@ function Flex(props: FlexProps, ref: DOMRef<HTMLDivElement>) {
let {styleProps} = useStyleProps(otherProps);
let {styleProps: flexStyle} = useStyleProps(otherProps, flexStyleProps);
let domRef = useDOMRef(ref);
let isSSR = useIsSSR();

// If a gap property is specified, and there is no native support, use a shim.
// If a gap property is specified, and there is no native support or we're in SSR, use a shim.
// Two divs are required for this: the outer one contains most style properties, and the inner
// one is the flex container. Each item inside the flex container gets a margin around it based
// on the gap, and the flex container has a negative margin to counteract this. The outer container
// is necessary to allow nesting of flex containers with gaps, so that the inner CSS variable doesn't
// override the outer one.
if ((props.gap || props.rowGap || props.columnGap) && !isFlexGapSupported()) {
if ((props.gap || props.rowGap || props.columnGap) && (isSSR || !isFlexGapSupported())) {
let style = {
...flexStyle.style,
'--column-gap': props.columnGap != null ? dimensionValue(props.columnGap) : undefined,
Expand Down
15 changes: 10 additions & 5 deletions packages/@react-spectrum/listbox/test/ListBox.ssr.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ describe('ListBox SSR', function () {
it('should render without errors', async function () {
await testSSR(__filename, `
import {ListBox, Item} from '../';
<ListBox>
<Item>Left</Item>
<Item>Middle</Item>
<Item>Right</Item>
</ListBox>
import {Provider} from '@react-spectrum/provider';
import {theme} from '@react-spectrum/theme-default';

<Provider theme={theme}>
<ListBox aria-label="Listbox">
<Item>Left</Item>
<Item>Middle</Item>
<Item>Right</Item>
</ListBox>
</Provider>
`);
});
});
4 changes: 2 additions & 2 deletions packages/@react-spectrum/overlays/src/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@

import {classNames, useDOMRef, useStyleProps} from '@react-spectrum/utils';
import {DOMRef} from '@react-types/shared';
import {mergeProps} from '@react-aria/utils';
import {mergeProps, useLayoutEffect} from '@react-aria/utils';
import {Overlay} from './Overlay';
import overrideStyles from './overlays.css';
import {PlacementAxis, PopoverProps} from '@react-types/overlays';
import React, {forwardRef, HTMLAttributes, ReactNode, RefObject, useLayoutEffect, useRef, useState} from 'react';
import React, {forwardRef, HTMLAttributes, ReactNode, RefObject, useRef, useState} from 'react';
import styles from '@adobe/spectrum-css-temp/components/popover/vars.css';
import {useModal, useOverlay} from '@react-aria/overlays';

Expand Down
4 changes: 2 additions & 2 deletions packages/@react-spectrum/picker/src/Picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ import intlMessages from '../intl/*.json';
import {Label} from '@react-spectrum/label';
import labelStyles from '@adobe/spectrum-css-temp/components/fieldlabel/vars.css';
import {ListBoxBase, useListBoxLayout} from '@react-spectrum/listbox';
import {mergeProps} from '@react-aria/utils';
import {mergeProps, useLayoutEffect} from '@react-aria/utils';
import {Placement} from '@react-types/overlays';
import {Popover, Tray} from '@react-spectrum/overlays';
import {PressResponder, useHover} from '@react-aria/interactions';
import {ProgressCircle} from '@react-spectrum/progress';
import React, {ReactElement, useLayoutEffect, useRef, useState} from 'react';
import React, {ReactElement, useRef, useState} from 'react';
import {SpectrumPickerProps} from '@react-types/select';
import styles from '@adobe/spectrum-css-temp/components/dropdown/vars.css';
import {Text} from '@react-spectrum/text';
Expand Down
15 changes: 10 additions & 5 deletions packages/@react-spectrum/picker/test/Picker.ssr.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ describe('Picker SSR', function () {
it('should render without errors', async function () {
await testSSR(__filename, `
import {Picker, Item} from '../';
<Picker>
<Item>One</Item>
<Item>Two</Item>
<Item>Three</Item>
</Picker>
import {Provider} from '@react-spectrum/provider';
import {theme} from '@react-spectrum/theme-default';

<Provider theme={theme}>
<Picker label="Picker">
<Item>One</Item>
<Item>Two</Item>
<Item>Three</Item>
</Picker>
</Provider>
`);
});
});
4 changes: 2 additions & 2 deletions packages/@react-spectrum/tabs/src/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
import {classNames, useStyleProps} from '@react-spectrum/utils';
import {DOMProps, Node, Orientation, StyleProps} from '@react-types/shared';
import {FocusRing} from '@react-aria/focus';
import {mergeProps} from '@react-aria/utils';
import React, {useEffect, useLayoutEffect, useRef, useState} from 'react';
import {mergeProps, useLayoutEffect} from '@react-aria/utils';
import React, {useEffect, useRef, useState} from 'react';
import {SingleSelectListState, useSingleSelectListState} from '@react-stately/list';
import {SpectrumTabsProps} from '@react-types/tabs';
import styles from '@adobe/spectrum-css-temp/components/tabs/vars.css';
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-spectrum/textfield/src/TextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
* governing permissions and limitations under the License.
*/

import {chain} from '@react-aria/utils';
import React, {RefObject, useCallback, useLayoutEffect, useRef} from 'react';
import {chain, useLayoutEffect} from '@react-aria/utils';
import React, {RefObject, useCallback, useRef} from 'react';
import {SpectrumTextFieldProps, TextFieldRef} from '@react-types/textfield';
import {TextFieldBase} from './TextFieldBase';
import {useControlledState} from '@react-stately/utils';
Expand Down
1 change: 1 addition & 0 deletions packages/@react-spectrum/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"dependencies": {
"@babel/runtime": "^7.6.2",
"@react-aria/i18n": "^3.1.0",
"@react-aria/ssr": "3.0.0-alpha.1",
"@react-aria/utils": "^3.2.0",
"@react-types/shared": "^3.2.0",
"clsx": "^1.1.1"
Expand Down
3 changes: 2 additions & 1 deletion packages/@react-spectrum/utils/src/useHasChild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
* governing permissions and limitations under the License.
*/

import {RefObject, useLayoutEffect, useState} from 'react';
import {RefObject, useState} from 'react';
import {useLayoutEffect} from '@react-aria/utils';

export function useHasChild(query: string, ref: RefObject<HTMLElement>) {
let [hasChild, setHasChild] = useState(true);
Expand Down
Loading