@atlaskit/heading 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @atlaskit/heading
2
2
 
3
+ ## 1.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#68604](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/68604) [`fdf7f6635426`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/fdf7f6635426) - Modified mapping of `variant` to the HTML element that gets rendered. Previously `xlarge` would render a `h2`, `large` would render a `h3` etc... Now `xlarge` renders a `h1` and so on...
8
+
3
9
  ## 1.5.1
4
10
 
5
11
  ### Patch Changes
@@ -0,0 +1,82 @@
1
+ import core, {
2
+ API,
3
+ ASTPath,
4
+ FileInfo,
5
+ ImportDeclaration,
6
+ Options,
7
+ } from 'jscodeshift';
8
+
9
+ export default function transformer(
10
+ fileInfo: FileInfo,
11
+ { jscodeshift: j }: API,
12
+ options: Options,
13
+ ) {
14
+ const base = j(fileInfo.source);
15
+ const headingSpecifier = getDefaultSpecifier(j, base, '@atlaskit/heading');
16
+ if (!headingSpecifier) {
17
+ return;
18
+ }
19
+
20
+ replaceLevelWithVariant(j, base, headingSpecifier);
21
+
22
+ return base.toSource();
23
+ }
24
+
25
+ const levelToVariantMap = {
26
+ h900: 'xxlarge',
27
+ h800: 'xlarge',
28
+ h700: 'large',
29
+ h600: 'medium',
30
+ h500: 'small',
31
+ h400: 'xsmall',
32
+ h300: 'xxsmall',
33
+ // We may want to auto-transform h100s and h200s in the future
34
+ // h200: 'xxsmall',
35
+ // h100: 'xxsmall',
36
+ };
37
+
38
+ function replaceLevelWithVariant(
39
+ j: core.JSCodeshift,
40
+ source: ReturnType<typeof j>,
41
+ specifier: string,
42
+ ) {
43
+ source.findJSXElements(specifier).forEach(element => {
44
+ j(element)
45
+ .find(j.JSXAttribute, { name: { type: 'JSXIdentifier', name: 'level' } })
46
+ .forEach(attr => {
47
+ const attrValue = j(attr).nodes()[0].value;
48
+ if (attrValue.type === 'StringLiteral') {
49
+ const replacementValue =
50
+ levelToVariantMap[
51
+ attrValue.value as keyof typeof levelToVariantMap
52
+ ];
53
+ if (replacementValue) {
54
+ j(attr).replaceWith(
55
+ j.jsxAttribute(
56
+ j.jsxIdentifier('variant'),
57
+ j.stringLiteral(replacementValue),
58
+ ),
59
+ );
60
+ }
61
+ }
62
+ });
63
+ });
64
+ }
65
+
66
+ function getDefaultSpecifier(
67
+ j: core.JSCodeshift,
68
+ source: any,
69
+ specifier: string,
70
+ ) {
71
+ const specifiers = source
72
+ .find(j.ImportDeclaration)
73
+ .filter(
74
+ (path: ASTPath<ImportDeclaration>) =>
75
+ path.node.source.value === specifier,
76
+ )
77
+ .find(j.ImportDefaultSpecifier);
78
+ if (!specifiers.length) {
79
+ return null;
80
+ }
81
+ return specifiers.nodes()[0]!.local!.name;
82
+ }
@@ -0,0 +1,46 @@
1
+ import { API, FileInfo, Options } from 'jscodeshift';
2
+
3
+ import noop from '@atlaskit/ds-lib/noop';
4
+
5
+ const applyTransform = require('jscodeshift/dist/testUtils').applyTransform;
6
+
7
+ type Transformer = (file: FileInfo, jscodeshift: API, options: Options) => void;
8
+
9
+ type TestArgs = {
10
+ it: string;
11
+ original: string;
12
+ expected: string;
13
+ transformer: Transformer;
14
+ mode?: 'only' | 'skip' | 'standard';
15
+ before?: () => void;
16
+ after?: () => void;
17
+ };
18
+
19
+ export function check({
20
+ it: name,
21
+ original,
22
+ expected,
23
+ transformer,
24
+ before = noop,
25
+ after = noop,
26
+ mode = 'standard',
27
+ }: TestArgs) {
28
+ const run = mode === 'only' ? it.only : mode === 'skip' ? it.skip : it;
29
+ run(name, () => {
30
+ before();
31
+ try {
32
+ const output: string = applyTransform(
33
+ { default: transformer, parser: 'tsx' },
34
+ {},
35
+ { source: original },
36
+ );
37
+ expect(output).toBe(expected.trim());
38
+ } catch (e) {
39
+ // a failed assertion will throw
40
+ after();
41
+ throw e;
42
+ }
43
+ // will only be hit if we don't throw
44
+ after();
45
+ });
46
+ }
@@ -0,0 +1,80 @@
1
+ jest.autoMockOff();
2
+
3
+ import transformer from '../1.6.0-level-to-variant';
4
+
5
+ import { check } from './_framework';
6
+
7
+ check({
8
+ transformer,
9
+ it: 'should replace level with variant only on Heading component',
10
+ original: `
11
+ import Heading from '@atlaskit/heading';
12
+
13
+ function App() {
14
+ return <>
15
+ <Heading level="h700" as="h3">hello</Heading>
16
+ <SomethingElse level="h700">still here</SomethingElse>
17
+ </>;
18
+ }
19
+ `,
20
+ expected: `
21
+ import Heading from '@atlaskit/heading';
22
+
23
+ function App() {
24
+ return <>
25
+ <Heading variant="large" as="h3">hello</Heading>
26
+ <SomethingElse level="h700">still here</SomethingElse>
27
+ </>;
28
+ }
29
+ `,
30
+ });
31
+
32
+ check({
33
+ transformer,
34
+ it: 'should do nothing if level is h200 or h100',
35
+ original: `
36
+ import Heading from '@atlaskit/heading';
37
+
38
+ function App() {
39
+ return <>
40
+ <Heading level="h300">hello</Heading>
41
+ <Heading level="h200">hello</Heading>
42
+ <Heading level="h100">hello</Heading>
43
+ </>;
44
+ }
45
+ `,
46
+ expected: `
47
+ import Heading from '@atlaskit/heading';
48
+
49
+ function App() {
50
+ return <>
51
+ <Heading variant="xxsmall">hello</Heading>
52
+ <Heading level="h200">hello</Heading>
53
+ <Heading level="h100">hello</Heading>
54
+ </>;
55
+ }
56
+ `,
57
+ });
58
+
59
+ check({
60
+ transformer,
61
+ it: 'should do nothing if variant already exists',
62
+ original: `
63
+ import Heading from '@atlaskit/heading';
64
+
65
+ function App() {
66
+ return <>
67
+ <Heading variant="large">hello</Heading>
68
+ </>;
69
+ }
70
+ `,
71
+ expected: `
72
+ import Heading from '@atlaskit/heading';
73
+
74
+ function App() {
75
+ return <>
76
+ <Heading variant="large">hello</Heading>
77
+ </>;
78
+ }
79
+ `,
80
+ });
@@ -11,14 +11,14 @@ var _headingContext = require("./heading-context");
11
11
  /** @jsx jsx */
12
12
 
13
13
  // https://atlassian.design/foundations/typography
14
- var levelMap = {
14
+ var variantTagMap = {
15
15
  xxlarge: 'h1',
16
- xlarge: 'h2',
17
- large: 'h3',
18
- medium: 'h4',
19
- small: 'h5',
20
- xsmall: 'h6',
21
- xxsmall: 'div'
16
+ xlarge: 'h1',
17
+ large: 'h2',
18
+ medium: 'h3',
19
+ small: 'h4',
20
+ xsmall: 'h5',
21
+ xxsmall: 'h6'
22
22
  };
23
23
  var headingResetStyles = (0, _react.css)({
24
24
  color: "var(--ds-text, #172B4D)",
@@ -33,16 +33,12 @@ var inverseStyles = (0, _react.css)({
33
33
  /**
34
34
  * __Heading__
35
35
  *
36
- * A heading is a typography component used to display text in different sizes and formats.
36
+ * Heading is a typography component used to display text in defined sizes and styles.
37
37
  *
38
38
  * @example
39
39
  *
40
40
  * ```jsx
41
- * import Heading from '@atlaskit/heading';
42
- *
43
- * const HeadingXXL = () => (
44
- * <Heading level="xxlarge">XXL</Heading>
45
- * );
41
+ * <Heading variant="xxlarge">Page title</Heading>
46
42
  * ```
47
43
  */
48
44
  var Heading = function Heading(_ref) {
@@ -56,13 +52,16 @@ var Heading = function Heading(_ref) {
56
52
  if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production' && as && typeof as !== 'string') {
57
53
  throw new Error('`as` prop should be a string.');
58
54
  }
59
- var _useHeading = (0, _headingContext.useHeading)(levelMap[variant]),
55
+
56
+ // Technically variant can be undefined here due to how the types work.
57
+ // Once removing the level prop this assertion can be removed since variant will be a required prop.
58
+ var _useHeading = (0, _headingContext.useHeading)(variantTagMap[variant]),
60
59
  _useHeading2 = (0, _slicedToArray2.default)(_useHeading, 2),
61
60
  hLevel = _useHeading2[0],
62
61
  inferredElement = _useHeading2[1];
63
- var Markup = as || inferredElement;
64
- var needsAriaRole = Markup === 'div' && hLevel;
65
- return (0, _react.jsx)(Markup, {
62
+ var Component = as || inferredElement;
63
+ var needsAriaRole = Component === 'div' && hLevel;
64
+ return (0, _react.jsx)(Component, {
66
65
  id: id,
67
66
  "data-testid": testId,
68
67
  role: needsAriaRole ? 'heading' : undefined,
@@ -2,14 +2,14 @@
2
2
  import { css, jsx } from '@emotion/react';
3
3
  import { useHeading } from './heading-context';
4
4
  // https://atlassian.design/foundations/typography
5
- const levelMap = {
5
+ const variantTagMap = {
6
6
  xxlarge: 'h1',
7
- xlarge: 'h2',
8
- large: 'h3',
9
- medium: 'h4',
10
- small: 'h5',
11
- xsmall: 'h6',
12
- xxsmall: 'div'
7
+ xlarge: 'h1',
8
+ large: 'h2',
9
+ medium: 'h3',
10
+ small: 'h4',
11
+ xsmall: 'h5',
12
+ xxsmall: 'h6'
13
13
  };
14
14
  const headingResetStyles = css({
15
15
  color: "var(--ds-text, #172B4D)",
@@ -24,16 +24,12 @@ const inverseStyles = css({
24
24
  /**
25
25
  * __Heading__
26
26
  *
27
- * A heading is a typography component used to display text in different sizes and formats.
27
+ * Heading is a typography component used to display text in defined sizes and styles.
28
28
  *
29
29
  * @example
30
30
  *
31
31
  * ```jsx
32
- * import Heading from '@atlaskit/heading';
33
- *
34
- * const HeadingXXL = () => (
35
- * <Heading level="xxlarge">XXL</Heading>
36
- * );
32
+ * <Heading variant="xxlarge">Page title</Heading>
37
33
  * ```
38
34
  */
39
35
  const Heading = ({
@@ -47,10 +43,13 @@ const Heading = ({
47
43
  if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production' && as && typeof as !== 'string') {
48
44
  throw new Error('`as` prop should be a string.');
49
45
  }
50
- const [hLevel, inferredElement] = useHeading(levelMap[variant]);
51
- const Markup = as || inferredElement;
52
- const needsAriaRole = Markup === 'div' && hLevel;
53
- return jsx(Markup, {
46
+
47
+ // Technically variant can be undefined here due to how the types work.
48
+ // Once removing the level prop this assertion can be removed since variant will be a required prop.
49
+ const [hLevel, inferredElement] = useHeading(variantTagMap[variant]);
50
+ const Component = as || inferredElement;
51
+ const needsAriaRole = Component === 'div' && hLevel;
52
+ return jsx(Component, {
54
53
  id: id,
55
54
  "data-testid": testId,
56
55
  role: needsAriaRole ? 'heading' : undefined,
@@ -3,14 +3,14 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  import { css, jsx } from '@emotion/react';
4
4
  import { useHeading } from './heading-context';
5
5
  // https://atlassian.design/foundations/typography
6
- var levelMap = {
6
+ var variantTagMap = {
7
7
  xxlarge: 'h1',
8
- xlarge: 'h2',
9
- large: 'h3',
10
- medium: 'h4',
11
- small: 'h5',
12
- xsmall: 'h6',
13
- xxsmall: 'div'
8
+ xlarge: 'h1',
9
+ large: 'h2',
10
+ medium: 'h3',
11
+ small: 'h4',
12
+ xsmall: 'h5',
13
+ xxsmall: 'h6'
14
14
  };
15
15
  var headingResetStyles = css({
16
16
  color: "var(--ds-text, #172B4D)",
@@ -25,16 +25,12 @@ var inverseStyles = css({
25
25
  /**
26
26
  * __Heading__
27
27
  *
28
- * A heading is a typography component used to display text in different sizes and formats.
28
+ * Heading is a typography component used to display text in defined sizes and styles.
29
29
  *
30
30
  * @example
31
31
  *
32
32
  * ```jsx
33
- * import Heading from '@atlaskit/heading';
34
- *
35
- * const HeadingXXL = () => (
36
- * <Heading level="xxlarge">XXL</Heading>
37
- * );
33
+ * <Heading variant="xxlarge">Page title</Heading>
38
34
  * ```
39
35
  */
40
36
  var Heading = function Heading(_ref) {
@@ -48,13 +44,16 @@ var Heading = function Heading(_ref) {
48
44
  if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production' && as && typeof as !== 'string') {
49
45
  throw new Error('`as` prop should be a string.');
50
46
  }
51
- var _useHeading = useHeading(levelMap[variant]),
47
+
48
+ // Technically variant can be undefined here due to how the types work.
49
+ // Once removing the level prop this assertion can be removed since variant will be a required prop.
50
+ var _useHeading = useHeading(variantTagMap[variant]),
52
51
  _useHeading2 = _slicedToArray(_useHeading, 2),
53
52
  hLevel = _useHeading2[0],
54
53
  inferredElement = _useHeading2[1];
55
- var Markup = as || inferredElement;
56
- var needsAriaRole = Markup === 'div' && hLevel;
57
- return jsx(Markup, {
54
+ var Component = as || inferredElement;
55
+ var needsAriaRole = Component === 'div' && hLevel;
56
+ return jsx(Component, {
58
57
  id: id,
59
58
  "data-testid": testId,
60
59
  role: needsAriaRole ? 'heading' : undefined,
@@ -4,16 +4,12 @@ import type { HeadingProps } from './types';
4
4
  /**
5
5
  * __Heading__
6
6
  *
7
- * A heading is a typography component used to display text in different sizes and formats.
7
+ * Heading is a typography component used to display text in defined sizes and styles.
8
8
  *
9
9
  * @example
10
10
  *
11
11
  * ```jsx
12
- * import Heading from '@atlaskit/heading';
13
- *
14
- * const HeadingXXL = () => (
15
- * <Heading level="xxlarge">XXL</Heading>
16
- * );
12
+ * <Heading variant="xxlarge">Page title</Heading>
17
13
  * ```
18
14
  */
19
15
  declare const Heading: ({ children, variant, id, testId, as, color, }: HeadingProps) => jsx.JSX.Element;
@@ -4,16 +4,12 @@ import type { HeadingProps } from './types';
4
4
  /**
5
5
  * __Heading__
6
6
  *
7
- * A heading is a typography component used to display text in different sizes and formats.
7
+ * Heading is a typography component used to display text in defined sizes and styles.
8
8
  *
9
9
  * @example
10
10
  *
11
11
  * ```jsx
12
- * import Heading from '@atlaskit/heading';
13
- *
14
- * const HeadingXXL = () => (
15
- * <Heading level="xxlarge">XXL</Heading>
16
- * );
12
+ * <Heading variant="xxlarge">Page title</Heading>
17
13
  * ```
18
14
  */
19
15
  declare const Heading: ({ children, variant, id, testId, as, color, }: HeadingProps) => jsx.JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/heading",
3
- "version": "1.5.1",
3
+ "version": "1.6.0",
4
4
  "description": "A heading is a typography component used to display text in different sizes and formats.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -47,6 +47,7 @@
47
47
  "@atlassian/atlassian-frontend-prettier-config-1.0.0": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.0",
48
48
  "@atlassian/codegen": "^0.1.0",
49
49
  "@testing-library/react": "^12.1.5",
50
+ "jscodeshift": "^0.13.0",
50
51
  "prettier": "^2.8.0",
51
52
  "react-dom": "^16.8.0",
52
53
  "ts-node": "^10.9.1",