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

refactor(typescript): convert Grid, FlexGrid and children to TypeScript #13074

Merged
merged 3 commits into from
Feb 16, 2023
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2016, 2018
* Copyright IBM Corp. 2016, 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
Expand All @@ -9,20 +9,22 @@ import cx from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import { usePrefix } from '../../internal/usePrefix';
import { PolymorphicProps } from '../../types/common';
import { GridSettings, useGridSettings } from './GridContext';
import { GridComponent, GridProps } from './GridTypes';

function CSSGrid({
as: BaseComponent = 'div',
function CSSGrid<T extends React.ElementType>({
as: BaseComponent = 'div' as T,
children,
className: customClassName,
condensed = false,
fullWidth = false,
narrow = false,
...rest
}) {
}: GridProps<T>) {
const prefix = usePrefix();
const { subgrid } = useGridSettings();
let mode = 'wide';
let mode: SubgridMode = 'wide';
if (narrow) {
mode = 'narrow';
} else if (condensed) {
Expand All @@ -36,7 +38,8 @@ function CSSGrid({
as={BaseComponent}
className={customClassName}
mode={mode}
{...rest}>
{...rest}
>
{children}
</Subgrid>
</GridSettings>
Expand All @@ -50,11 +53,13 @@ function CSSGrid({
[`${prefix}--css-grid--full-width`]: fullWidth,
});

// cast as any to let TypeScript allow passing in attributes to base component
const BaseComponentAsAny: any = BaseComponent
return (
<GridSettings mode="css-grid" subgrid>
<BaseComponent className={className} {...rest}>
<BaseComponentAsAny className={className} {...rest}>
{children}
</BaseComponent>
</BaseComponentAsAny>
</GridSettings>
);
}
Expand Down Expand Up @@ -93,13 +98,36 @@ CSSGrid.propTypes = {
narrow: PropTypes.bool,
};

function Subgrid({
type SubgridMode = 'wide' | 'narrow' | 'condensed'

interface SubgridBaseProps {

/**
* Pass in content that will be rendered within the `Subgrid`
*/
children?: React.ReactNode;

/**
* Specify a custom className to be applied to the `Subgrid`
*/
className?: string;

/**
* Specify the grid mode for the subgrid
*/
mode?: SubgridMode;

}

type SubgridProps = PolymorphicProps<any, SubgridBaseProps>

const Subgrid = ({
as: BaseComponent = 'div',
className: customClassName,
children,
mode,
...rest
}) {
}: SubgridProps) => {
const prefix = usePrefix();
const className = cx(customClassName, {
[`${prefix}--subgrid`]: true,
Expand Down Expand Up @@ -133,7 +161,9 @@ Subgrid.propTypes = {
/**
* Specify the grid mode for the subgrid
*/
mode: PropTypes.oneOf(['wide', 'narrow', 'condensed']),
mode: PropTypes.oneOf(['wide', 'narrow', 'condensed'] as SubgridMode[]),
};

export { CSSGrid };
const CSSGridComponent: GridComponent = CSSGrid;

export { CSSGridComponent as CSSGrid };
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2016, 2018
* Copyright IBM Corp. 2016, 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
Expand All @@ -10,10 +10,95 @@ import cx from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import { usePrefix } from '../../internal/usePrefix';
import { PolymorphicProps } from '../../types/common';
import { useGridSettings } from './GridContext';

function Column({
as: BaseComponent = 'div',
type ColumnSpanPercent = '25%' | '50%' | '75%' | '100%';

type ColumnSpanSimple = boolean | number | ColumnSpanPercent

interface ColumnSpanObject {

span?: ColumnSpanSimple;

offset?: number;

start?: number;

end?: number;

}

export type ColumnSpan = ColumnSpanSimple | ColumnSpanObject

interface ColumnBaseProps {

/**
* Pass in content that will be rendered within the `Column`
*/
children?: React.ReactNode;

/**
* Specify a custom className to be applied to the `Column`
*/
className?: string,

/**
* Specify column span for the `lg` breakpoint (Default breakpoint up to 1312px)
* This breakpoint supports 16 columns by default.
*
* @see https://www.carbondesignsystem.com/guidelines/layout#breakpoints
*/
lg?: ColumnSpan;

/**
* Specify column span for the `max` breakpoint. This breakpoint supports 16
* columns by default.
*
* @see https://www.carbondesignsystem.com/guidelines/layout#breakpoints
*/
max?: ColumnSpan;

/**
* Specify column span for the `md` breakpoint (Default breakpoint up to 1056px)
* This breakpoint supports 8 columns by default.
*
* @see https://www.carbondesignsystem.com/guidelines/layout#breakpoints
*/
md?: ColumnSpan;

/**
* Specify column span for the `sm` breakpoint (Default breakpoint up to 672px)
* This breakpoint supports 4 columns by default.
*
* @see https://www.carbondesignsystem.com/guidelines/layout#breakpoints
*/
sm?: ColumnSpan;

/**
* Specify column span for the `xlg` breakpoint (Default breakpoint up to
* 1584px) This breakpoint supports 16 columns by default.
*
* @see https://www.carbondesignsystem.com/guidelines/layout#breakpoints
*/
xlg?: ColumnSpan;

/**
* Specify constant column span, start, or end values that will not change
* based on breakpoint
*/
span?: ColumnSpan;

}

export type ColumnProps<T extends React.ElementType> = PolymorphicProps<T, ColumnBaseProps>;

export interface ColumnComponent {
<T extends React.ElementType>(props: ColumnProps<T>, context?: any): React.ReactElement<any, any> | null;
}

function Column<T extends React.ElementType>({
as: BaseComponent = 'div' as T,
children,
className: customClassName,
sm,
Expand All @@ -22,7 +107,7 @@ function Column({
xlg,
max,
...rest
}) {
}: ColumnProps<T>) {
const { mode } = useGridSettings();
const prefix = usePrefix();

Expand Down Expand Up @@ -50,10 +135,12 @@ function Column({
[`${prefix}--col`]: columnClassName.length === 0,
});

// cast as any to let TypeScript allow passing in attributes to base component
const BaseComponentAsAny: any = BaseComponent
return (
<BaseComponent className={className} {...rest}>
<BaseComponentAsAny className={className} {...rest}>
{children}
</BaseComponent>
</BaseComponentAsAny>
);
}

Expand Down Expand Up @@ -148,7 +235,7 @@ function CSSGridColumn({
max,
span,
...rest
}) {
}: ColumnProps<any>) {
const prefix = usePrefix();
const breakpointClassName = getClassNameForBreakpoints(
[sm, md, lg, xlg, max],
Expand Down Expand Up @@ -250,8 +337,8 @@ const breakpointNames = ['sm', 'md', 'lg', 'xlg', 'max'];
* @param {Array<boolean|number|Breakpoint>} breakpoints
* @returns {string}
*/
function getClassNameForBreakpoints(breakpoints, prefix) {
const classNames = [];
function getClassNameForBreakpoints(breakpoints: (ColumnSpan | undefined)[], prefix: string): string {
const classNames: string[] = [];

for (let i = 0; i < breakpoints.length; i++) {
const breakpoint = breakpoints[i];
Expand Down Expand Up @@ -282,25 +369,27 @@ function getClassNameForBreakpoints(breakpoints, prefix) {
continue;
}

const { span, offset, start, end } = breakpoint;

if (typeof offset === 'number' && offset > 0) {
classNames.push(`${prefix}--${name}:col-start-${offset + 1}`);
}

if (typeof start === 'number') {
classNames.push(`${prefix}--${name}:col-start-${start}`);
}

if (typeof end === 'number') {
classNames.push(`${prefix}--${name}:col-end-${end}`);
}

if (typeof span === 'number') {
classNames.push(`${prefix}--${name}:col-span-${span}`);
} else if (typeof span === 'string') {
classNames.push(`${prefix}--${name}:col-span-${span.slice(0, -1)}`);
continue;
if (typeof breakpoint === 'object') {
const { span, offset, start, end } = breakpoint;

if (typeof offset === 'number' && offset > 0) {
classNames.push(`${prefix}--${name}:col-start-${offset + 1}`);
}

if (typeof start === 'number') {
classNames.push(`${prefix}--${name}:col-start-${start}`);
}

if (typeof end === 'number') {
classNames.push(`${prefix}--${name}:col-end-${end}`);
}

if (typeof span === 'number') {
classNames.push(`${prefix}--${name}:col-span-${span}`);
} else if (typeof span === 'string') {
classNames.push(`${prefix}--${name}:col-span-${span.slice(0, -1)}`);
continue;
}
}
}

Expand All @@ -312,8 +401,8 @@ function getClassNameForBreakpoints(breakpoints, prefix) {
* @param {Array<boolean|number|Breakpoint>} breakpoints
* @returns {string}
*/
function getClassNameForFlexGridBreakpoints(breakpoints, prefix) {
const classNames = [];
function getClassNameForFlexGridBreakpoints(breakpoints: (ColumnSpan | undefined)[], prefix: string): string {
const classNames: string[] = [];

for (let i = 0; i < breakpoints.length; i++) {
const breakpoint = breakpoints[i];
Expand All @@ -337,17 +426,19 @@ function getClassNameForFlexGridBreakpoints(breakpoints, prefix) {
continue;
}

const { span, offset } = breakpoint;
if (typeof span === 'number') {
classNames.push(`${prefix}--col-${name}-${span}`);
}
if (typeof breakpoint === 'object') {
const { span, offset } = breakpoint;
if (typeof span === 'number') {
classNames.push(`${prefix}--col-${name}-${span}`);
}

if (span === true) {
classNames.push(`${prefix}--col-${name}`);
}
if (span === true) {
classNames.push(`${prefix}--col-${name}`);
}

if (typeof offset === 'number') {
classNames.push(`${prefix}--offset-${name}-${offset}`);
if (typeof offset === 'number') {
classNames.push(`${prefix}--offset-${name}-${offset}`);
}
}
}

Expand All @@ -357,8 +448,8 @@ function getClassNameForFlexGridBreakpoints(breakpoints, prefix) {
/**
* Build the appropriate className for a span value
*/
function getClassNameForSpan(value, prefix) {
const classNames = [];
function getClassNameForSpan(value: ColumnSpan | undefined, prefix: string): string {
const classNames: string[] = [];

if (typeof value === 'number' || typeof value === 'string') {
classNames.push(`${prefix}--col-span-${value}`);
Expand All @@ -381,4 +472,4 @@ function getClassNameForSpan(value, prefix) {
return classNames.join('');
}

export default Column;
export default Column as ColumnComponent;
Loading