- The last thing you want in your kitchen is a{' '}
-
- fire
- {' '}
- even though there is{' '}
-
- water
- {' '}
- nearby. The last thing you want in your kitchen is a{' '}
-
- fire
- {' '}
- even though there is{' '}
-
- water
- {' '}
- nearby. The last thing you want in your kitchen is a{' '}
-
- fire
- {' '}
- even though there is{' '}
-
- water
- {' '}
- nearby.
-
- );
- }
-}
diff --git a/src/components/icon/examples/icon-b.tsx b/src/components/icon/examples/icon-b.tsx
new file mode 100644
index 00000000..d92139d4
--- /dev/null
+++ b/src/components/icon/examples/icon-b.tsx
@@ -0,0 +1,37 @@
+/*
+Icons rendered inline with multi-line text.
+*/
+import React, { ReactElement } from 'react';
+import Icon from '../icon';
+
+export default function Example(): ReactElement {
+ return (
+
+ The last thing you want in your kitchen is a{' '}
+
+ fire
+ {' '}
+ even though there is{' '}
+
+ water
+ {' '}
+ nearby. The last thing you want in your kitchen is a{' '}
+
+ fire
+ {' '}
+ even though there is{' '}
+
+ water
+ {' '}
+ nearby. The last thing you want in your kitchen is a{' '}
+
+ fire
+ {' '}
+ even though there is{' '}
+
+ water
+ {' '}
+ nearby.
+
+ );
+}
diff --git a/src/components/icon/icon.js b/src/components/icon/icon.tsx
similarity index 60%
rename from src/components/icon/icon.js
rename to src/components/icon/icon.tsx
index 36a998f6..12270935 100644
--- a/src/components/icon/icon.js
+++ b/src/components/icon/icon.tsx
@@ -1,7 +1,16 @@
-import React from 'react';
+import React, { ReactElement, CSSProperties, useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import getWindow from '../utils/get-window';
-import shallowEqualObjects from '../utils/shallow-equal-objects';
+import * as AccessibleIcon from '@radix-ui/react-accessible-icon';
+
+interface Props {
+ name: string;
+ inline?: boolean;
+ passthroughProps?: {
+ style?: CSSProperties
+ };
+ size?: number;
+}
/**
* Display an Assembly icon.
@@ -12,66 +21,52 @@ import shallowEqualObjects from '../utils/shallow-equal-objects';
* - Provides an `inline` mode that automatically sizes icons to match their
* surrounding text.
*/
-export default class Icon extends React.Component {
- componentDidMount() {
- this.setHeight();
- }
-
- shouldComponentUpdate(nextProps) {
- return !shallowEqualObjects(this.props, nextProps, ['passthroughProps']);
- }
+export default function Icon({
+ name,
+ inline = false,
+ passthroughProps = {},
+ size = 18
+}: Props): ReactElement {
+ const el = useRef(null);
- componentDidUpdate() {
- this.setHeight();
- }
-
- setHeight() {
- if (this.props.inline && this.iconElement) {
- const lineHeight = getWindow().getComputedStyle(this.iconElement)[
+ useEffect(() => {
+ if (inline && el.current) {
+ const lineHeight = getWindow().getComputedStyle(el.current)[
'line-height'
];
- this.iconElement.style.height = lineHeight;
+ el.current.style.height = lineHeight;
}
- }
-
- setIconElement = (element) => {
- this.iconElement = element;
- };
+ }, [inline, size]);
- render() {
- const { props } = this;
-
- let iconClasses = 'events-none icon';
- if (props.inline) {
- iconClasses += ' inline-block align-t';
- }
+ let iconClasses = 'events-none icon';
+ if (inline) {
+ iconClasses += ' inline-block align-t';
+ }
- const svgStyle = props.passthroughProps.style || {};
- if (!svgStyle.width && props.size) {
- svgStyle.width = props.size;
- }
- if (!svgStyle.height && props.size) {
- svgStyle.height = props.size;
- }
+ const svgStyle = passthroughProps.style || {};
+ if (!svgStyle.width && size) {
+ svgStyle.width = size;
+ }
+ if (!svgStyle.height && size) {
+ svgStyle.height = size;
+ }
- const iconContent = (
+ return (
+
- );
-
- return iconContent;
- }
+
+ );
}
Icon.propTypes = {
@@ -110,9 +105,3 @@ Icon.propTypes = {
*/
passthroughProps: PropTypes.object
};
-
-Icon.defaultProps = {
- inline: false,
- passthroughProps: {},
- size: 18
-};
diff --git a/src/components/minimum-duration-loader/__tests__/minimum-duration-loader.test.js b/src/components/minimum-duration-loader/__tests__/minimum-duration-loader.test.js
index e333b9fc..a96439a1 100644
--- a/src/components/minimum-duration-loader/__tests__/minimum-duration-loader.test.js
+++ b/src/components/minimum-duration-loader/__tests__/minimum-duration-loader.test.js
@@ -28,7 +28,7 @@ describe('MinimumDurationLoader', () => {
wrapper.update();
expect(wrapper.find('[data-test-loader]').length).toEqual(1);
expect(wrapper.find('[data-test-content]').length).toEqual(0);
- jest.runTimersToTime(1000);
+ jest.advanceTimersByTime(1000);
wrapper.update();
expect(wrapper.find('[data-test-loader]').length).toEqual(0);
expect(wrapper.find('[data-test-content]').length).toEqual(1);
@@ -40,7 +40,7 @@ describe('MinimumDurationLoader', () => {
wrapper.setProps({ isLoaded: true });
expect(wrapper.html()).toEqual(loaderHtml);
- jest.runTimersToTime(1000);
+ jest.advanceTimersByTime(1000);
wrapper.update();
expect(wrapper.html()).toEqual(contentHtml);
wrapper.setProps({ isLoaded: false });
@@ -49,7 +49,7 @@ describe('MinimumDurationLoader', () => {
wrapper.setProps({ isLoaded: true });
wrapper.update();
expect(wrapper.html()).toEqual(loaderHtml);
- jest.runTimersToTime(1000);
+ jest.advanceTimersByTime(1000);
wrapper.update();
expect(wrapper.html()).toEqual(contentHtml);
});
@@ -94,12 +94,12 @@ describe('MinimumDurationLoader', () => {
// Loader should exist
expect(wrapper.find('[data-test-loader]').length).toEqual(1);
expect(wrapper.find('[data-test-content]').length).toEqual(0);
- jest.runTimersToTime(1000);
+ jest.advanceTimersByTime(1000);
wrapper.update();
// Loader should still exist because we exceeded the minimum duration
expect(wrapper.find('[data-test-loader]').length).toEqual(1);
expect(wrapper.find('[data-test-content]').length).toEqual(0);
- jest.runTimersToTime(4000);
+ jest.advanceTimersByTime(4000);
wrapper.update();
// We've exceeded the minimum duration, so the loader should not exist
expect(wrapper.find('[data-test-loader]').length).toEqual(0);
diff --git a/src/components/modal/__tests__/__snapshots__/modal.test.js.snap b/src/components/modal/__tests__/__snapshots__/modal.test.js.snap
index 5b138469..503a99f4 100644
--- a/src/components/modal/__tests__/__snapshots__/modal.test.js.snap
+++ b/src/components/modal/__tests__/__snapshots__/modal.test.js.snap
@@ -49,10 +49,7 @@ exports[`Modal No fixed width, display only renders 1`] = `
type="button"
>
@@ -122,10 +119,7 @@ exports[`Modal all options renders 1`] = `
type="button"
>
@@ -209,10 +203,7 @@ exports[`Modal basic default renders 1`] = `
type="button"
>
@@ -283,10 +274,7 @@ exports[`Modal basic small renders 1`] = `
type="button"
>
diff --git a/src/components/tab-list/__tests__/__snapshots__/tab-list.test.js.snap b/src/components/tab-list/__tests__/__snapshots__/tab-list.test.js.snap
index 654625ad..7d5157f6 100644
--- a/src/components/tab-list/__tests__/__snapshots__/tab-list.test.js.snap
+++ b/src/components/tab-list/__tests__/__snapshots__/tab-list.test.js.snap
@@ -17,10 +17,7 @@ exports[`TabList a label contains a node renders 1`] = `
type="button"
>
diff --git a/src/components/utils/__tests__/maybe-add-period.test.js b/src/components/utils/__tests__/maybe-add-period.test.ts
similarity index 100%
rename from src/components/utils/__tests__/maybe-add-period.test.js
rename to src/components/utils/__tests__/maybe-add-period.test.ts
diff --git a/src/components/utils/__tests__/omit.test.js b/src/components/utils/__tests__/omit.test.ts
similarity index 100%
rename from src/components/utils/__tests__/omit.test.js
rename to src/components/utils/__tests__/omit.test.ts
diff --git a/src/components/utils/__tests__/shallow-equal-objects.test.js b/src/components/utils/__tests__/shallow-equal-objects.test.ts
similarity index 86%
rename from src/components/utils/__tests__/shallow-equal-objects.test.js
rename to src/components/utils/__tests__/shallow-equal-objects.test.ts
index 6dd5150a..d5bfa590 100644
--- a/src/components/utils/__tests__/shallow-equal-objects.test.js
+++ b/src/components/utils/__tests__/shallow-equal-objects.test.ts
@@ -7,8 +7,8 @@ test('returns true', () => {
expect(
shallowEqualObjects({ a: 'true', b: 232 }, { a: 'true', b: 232 })
).toBe(true);
- const fn = () => {};
- expect(shallowEqualObjects({ a: fn, b: 232 }, { a: fn, b: 232 })).toBe(true);
+ const mockedFn = jest.fn();
+ expect(shallowEqualObjects({ a: mockedFn, b: 232 }, { a: mockedFn, b: 232 })).toBe(true);
expect(
shallowEqualObjects(
{ a: true, b: { c: false } },
@@ -23,7 +23,7 @@ test('returns false', () => {
expect(shallowEqualObjects({ a: true }, { a: false })).toBe(false);
expect(shallowEqualObjects({ a: 'a' }, { a: 'b' })).toBe(false);
expect(
- shallowEqualObjects({ a: () => {}, b: 232 }, { a: () => {}, b: 232 })
+ shallowEqualObjects({ a: jest.fn(), b: 232 }, { a: jest.fn(), b: 232 })
).toBe(false);
expect(
shallowEqualObjects(
diff --git a/src/components/utils/__tests__/styles.test.js b/src/components/utils/__tests__/styles.test.ts
similarity index 100%
rename from src/components/utils/__tests__/styles.test.js
rename to src/components/utils/__tests__/styles.test.ts
diff --git a/src/components/utils/capitalize.js b/src/components/utils/capitalize.ts
similarity index 100%
rename from src/components/utils/capitalize.js
rename to src/components/utils/capitalize.ts
diff --git a/src/components/utils/get-window.js b/src/components/utils/get-window.ts
similarity index 100%
rename from src/components/utils/get-window.js
rename to src/components/utils/get-window.ts
diff --git a/src/components/utils/maybe-add-period.js b/src/components/utils/maybe-add-period.ts
similarity index 78%
rename from src/components/utils/maybe-add-period.js
rename to src/components/utils/maybe-add-period.ts
index bf80c1c2..99bf22de 100644
--- a/src/components/utils/maybe-add-period.js
+++ b/src/components/utils/maybe-add-period.ts
@@ -1,4 +1,4 @@
-export default function maybeAddPeriod(text) {
+export default function maybeAddPeriod(text: string): string {
if (!text) return text;
const trimmedText = text.trim();
const lastChar = trimmedText[trimmedText.length - 1];
diff --git a/src/components/utils/omit.js b/src/components/utils/omit.js
deleted file mode 100644
index 5a916c5d..00000000
--- a/src/components/utils/omit.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function omit(source = {}, omittedProperties = []) {
- return Object.keys(source).reduce((result, key) => {
- if (omittedProperties.indexOf(key) === -1) {
- result[key] = source[key];
- }
- return result;
- }, {});
-}
diff --git a/src/components/utils/omit.ts b/src/components/utils/omit.ts
new file mode 100644
index 00000000..185504b2
--- /dev/null
+++ b/src/components/utils/omit.ts
@@ -0,0 +1,14 @@
+type PrimitiveDataTypes = string | boolean | number;
+type PropertyValues = PrimitiveDataTypes | { [key: string]: PrimitiveDataTypes };
+
+export default function omit(
+ source: ({ [key: string]: PropertyValues }) = {},
+ omittedProperties: Array = []
+): ({ [key: string]: PropertyValues }) {
+ return Object.keys(source).reduce((result, key) => {
+ if (omittedProperties.indexOf(key) === -1) {
+ result[key] = source[key];
+ }
+ return result;
+ }, {});
+}
diff --git a/src/components/utils/shallow-equal-objects.js b/src/components/utils/shallow-equal-objects.ts
similarity index 82%
rename from src/components/utils/shallow-equal-objects.js
rename to src/components/utils/shallow-equal-objects.ts
index ae505fef..1ff29f5e 100644
--- a/src/components/utils/shallow-equal-objects.js
+++ b/src/components/utils/shallow-equal-objects.ts
@@ -1,7 +1,8 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
export default function shallowEqualObjects(
- objA,
- objB,
- allowedObjectKeys = []
+ objA: { [key: string]: any },
+ objB: { [key: string]: any },
+ allowedObjectKeys: Array = []
) {
const aKeys = Object.keys(objA);
const bKeys = Object.keys(objB);
diff --git a/src/components/utils/styles.js b/src/components/utils/styles.ts
similarity index 76%
rename from src/components/utils/styles.js
rename to src/components/utils/styles.ts
index ed149a79..9895e4cd 100644
--- a/src/components/utils/styles.js
+++ b/src/components/utils/styles.ts
@@ -1,4 +1,8 @@
-const styles = {
+interface Constants {
+ [key: string]: string;
+}
+
+const styles: Constants = {
h1: 'txt-h1-mm txt-h2 txt-fancy mb6',
h2: 'txt-h2-mm txt-h3 txt-fancy mb6',
h3: 'txt-h3-mm txt-h4 txt-fancy mb6',
@@ -26,27 +30,27 @@ let _styles = styles;
/**
* Replace existing constant object with a new constant object. Use
* with no argument to reset constant object to it's default.
- * @param s {object} an object that conforms to { [id]: string }.
+ * @param constants {object} an object that conforms to { [id]: string }.
*/
-function setStyles(constants = styles) {
+function setStyles(constants: Constants = styles) {
_styles = { ...constants };
}
/**
* Merge a new constant object with existing constants.
- * @param s {object} an object that conforms to { [id]: string }.
+ * @param constants {object} an object that conforms to { [id]: string }.
*/
-function mergeStyles(constants) {
+function mergeStyles(constants: Constants) {
_styles = { ..._styles, ...constants };
}
/**
* Get the classlist for a style constant.
* @param constant {string} a string corresponding to a constant that resolves to a class list.
- * @param exclude {array} a list of classes to exclude from the style constant.
+ * @param exclude {string | array} a list of classes to exclude from the style constant.
* @return {string} a space-separated list of classes.
*/
-function getStyle(constant, exclude) {
+function getStyle(constant: string, exclude?: string | Array): string {
if (!_styles[constant]) {
throw Error(`${constant} is not a valid constant.`);
}
@@ -55,7 +59,7 @@ function getStyle(constant, exclude) {
if (exclude && exclude.length > 0) {
classList = classList
.split(' ')
- .filter((c) => {
+ .filter((c: string) => {
return exclude.indexOf(c) === -1;
})
.join(' ');
diff --git a/src/docs/app.js b/src/docs/app.tsx
similarity index 76%
rename from src/docs/app.js
rename to src/docs/app.tsx
index d36d29ea..54abb297 100644
--- a/src/docs/app.js
+++ b/src/docs/app.tsx
@@ -1,11 +1,12 @@
-import React from 'react';
+import React, { ReactElement } from 'react';
import components from './data/components'; // eslint-disable-line
import ComponentSection from './components/component-section';
import Sidebar from './components/sidebar';
import Colors from './components/colors';
import Assets from './components/assets';
+import { Entry, Section } from './typings';
-function AppSection({ name, entries, intro }) {
+function AppSection({ name, entries, intro }: Section): ReactElement {
const id = name.replace(/ /g, '-').toLowerCase();
return (
- These assets are exclusively available in Mapbox's build of
- Assembly. When using these assets, especially the logo, be attentive
- to the{' '}
-
- Mapbox brand guidelines
-
- .
-
+ These assets are exclusively available in Mapbox's build of
+ Assembly. When using these assets, especially the logo, be attentive
+ to the{' '}
+
+ Mapbox brand guidelines
+
+ .
+