@atlaskit/modal-dialog 12.0.2

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.
Files changed (127) hide show
  1. package/CHANGELOG.md +2111 -0
  2. package/LICENSE +13 -0
  3. package/README.md +13 -0
  4. package/__perf__/default.tsx +42 -0
  5. package/__perf__/interactions.tsx +136 -0
  6. package/__perf__/scroll.tsx +98 -0
  7. package/codemods/12.0.0-lite-mode.ts +51 -0
  8. package/codemods/__tests__/12.0.0-lite-mode.test.ts +493 -0
  9. package/codemods/__tests__/handle-prop-spread.tsx +276 -0
  10. package/codemods/__tests__/inline-WidthNames-declaration.test.ts +260 -0
  11. package/codemods/__tests__/map-actions-prop.tsx +436 -0
  12. package/codemods/__tests__/map-body-from-props.test.ts +645 -0
  13. package/codemods/__tests__/map-container-from-props.test.ts +323 -0
  14. package/codemods/__tests__/map-footer-from-props.test.ts +544 -0
  15. package/codemods/__tests__/map-header-from-props.test.ts +559 -0
  16. package/codemods/__tests__/map-heading-prop.tsx +438 -0
  17. package/codemods/__tests__/remove-appearance-prop.test.ts +79 -0
  18. package/codemods/__tests__/remove-component-override-props.test.ts +153 -0
  19. package/codemods/__tests__/remove-is-chromeless.tsx +182 -0
  20. package/codemods/__tests__/rename-appearance-type.test.ts +52 -0
  21. package/codemods/__tests__/rename-inner-component-prop-types.test.ts +82 -0
  22. package/codemods/__tests__/rename-scrollBehavior-to-shouldScrollInViewport.test.ts +237 -0
  23. package/codemods/internal/constants.tsx +41 -0
  24. package/codemods/internal/utils.tsx +223 -0
  25. package/codemods/migrations/handle-prop-spread.tsx +51 -0
  26. package/codemods/migrations/inline-WidthNames-declaration.ts +92 -0
  27. package/codemods/migrations/map-actions-prop.tsx +430 -0
  28. package/codemods/migrations/map-body-from-props.ts +147 -0
  29. package/codemods/migrations/map-container-from-props.ts +72 -0
  30. package/codemods/migrations/map-footer-from-props.ts +107 -0
  31. package/codemods/migrations/map-header-from-props.ts +101 -0
  32. package/codemods/migrations/map-heading-prop.tsx +193 -0
  33. package/codemods/migrations/remove-appearance-prop.ts +27 -0
  34. package/codemods/migrations/remove-component-override-props.ts +84 -0
  35. package/codemods/migrations/remove-is-chromeless.tsx +42 -0
  36. package/codemods/migrations/rename-appearance-type.ts +9 -0
  37. package/codemods/migrations/rename-inner-component-prop-types.ts +28 -0
  38. package/codemods/migrations/rename-scrollBehavior-to-shouldScrollInViewport.ts +82 -0
  39. package/dist/cjs/hooks.js +22 -0
  40. package/dist/cjs/index.js +63 -0
  41. package/dist/cjs/internal/components/modal-dialog.js +155 -0
  42. package/dist/cjs/internal/components/positioner.js +89 -0
  43. package/dist/cjs/internal/components/scroll-container.js +138 -0
  44. package/dist/cjs/internal/constants.js +48 -0
  45. package/dist/cjs/internal/context.js +13 -0
  46. package/dist/cjs/internal/hooks/use-modal-stack.js +110 -0
  47. package/dist/cjs/internal/hooks/use-on-motion-finish.js +24 -0
  48. package/dist/cjs/internal/hooks/use-prevent-programmatic-scroll.js +55 -0
  49. package/dist/cjs/internal/hooks/use-scroll.js +20 -0
  50. package/dist/cjs/internal/utils.js +35 -0
  51. package/dist/cjs/modal-body.js +66 -0
  52. package/dist/cjs/modal-footer.js +40 -0
  53. package/dist/cjs/modal-header.js +43 -0
  54. package/dist/cjs/modal-title.js +108 -0
  55. package/dist/cjs/modal-transition.js +21 -0
  56. package/dist/cjs/modal-wrapper.js +126 -0
  57. package/dist/cjs/types.js +5 -0
  58. package/dist/cjs/version.json +5 -0
  59. package/dist/es2019/hooks.js +11 -0
  60. package/dist/es2019/index.js +7 -0
  61. package/dist/es2019/internal/components/modal-dialog.js +120 -0
  62. package/dist/es2019/internal/components/positioner.js +78 -0
  63. package/dist/es2019/internal/components/scroll-container.js +97 -0
  64. package/dist/es2019/internal/constants.js +27 -0
  65. package/dist/es2019/internal/context.js +3 -0
  66. package/dist/es2019/internal/hooks/use-modal-stack.js +85 -0
  67. package/dist/es2019/internal/hooks/use-on-motion-finish.js +17 -0
  68. package/dist/es2019/internal/hooks/use-prevent-programmatic-scroll.js +39 -0
  69. package/dist/es2019/internal/hooks/use-scroll.js +11 -0
  70. package/dist/es2019/internal/utils.js +22 -0
  71. package/dist/es2019/modal-body.js +50 -0
  72. package/dist/es2019/modal-footer.js +30 -0
  73. package/dist/es2019/modal-header.js +30 -0
  74. package/dist/es2019/modal-title.js +94 -0
  75. package/dist/es2019/modal-transition.js +10 -0
  76. package/dist/es2019/modal-wrapper.js +88 -0
  77. package/dist/es2019/types.js +1 -0
  78. package/dist/es2019/version.json +5 -0
  79. package/dist/esm/hooks.js +11 -0
  80. package/dist/esm/index.js +7 -0
  81. package/dist/esm/internal/components/modal-dialog.js +131 -0
  82. package/dist/esm/internal/components/positioner.js +76 -0
  83. package/dist/esm/internal/components/scroll-container.js +114 -0
  84. package/dist/esm/internal/constants.js +27 -0
  85. package/dist/esm/internal/context.js +3 -0
  86. package/dist/esm/internal/hooks/use-modal-stack.js +96 -0
  87. package/dist/esm/internal/hooks/use-on-motion-finish.js +16 -0
  88. package/dist/esm/internal/hooks/use-prevent-programmatic-scroll.js +44 -0
  89. package/dist/esm/internal/hooks/use-scroll.js +11 -0
  90. package/dist/esm/internal/utils.js +22 -0
  91. package/dist/esm/modal-body.js +49 -0
  92. package/dist/esm/modal-footer.js +29 -0
  93. package/dist/esm/modal-header.js +29 -0
  94. package/dist/esm/modal-title.js +93 -0
  95. package/dist/esm/modal-transition.js +10 -0
  96. package/dist/esm/modal-wrapper.js +96 -0
  97. package/dist/esm/types.js +1 -0
  98. package/dist/esm/version.json +5 -0
  99. package/dist/types/hooks.d.ts +1 -0
  100. package/dist/types/index.d.ts +8 -0
  101. package/dist/types/internal/components/modal-dialog.d.ts +3 -0
  102. package/dist/types/internal/components/positioner.d.ts +10 -0
  103. package/dist/types/internal/components/scroll-container.d.ts +20 -0
  104. package/dist/types/internal/constants.d.ts +25 -0
  105. package/dist/types/internal/context.d.ts +20 -0
  106. package/dist/types/internal/hooks/use-modal-stack.d.ts +13 -0
  107. package/dist/types/internal/hooks/use-on-motion-finish.d.ts +4 -0
  108. package/dist/types/internal/hooks/use-prevent-programmatic-scroll.d.ts +7 -0
  109. package/dist/types/internal/hooks/use-scroll.d.ts +1 -0
  110. package/dist/types/internal/utils.d.ts +3 -0
  111. package/dist/types/modal-body.d.ts +16 -0
  112. package/dist/types/modal-footer.d.ts +16 -0
  113. package/dist/types/modal-header.d.ts +16 -0
  114. package/dist/types/modal-title.d.ts +26 -0
  115. package/dist/types/modal-transition.d.ts +3 -0
  116. package/dist/types/modal-wrapper.d.ts +5 -0
  117. package/dist/types/types.d.ts +90 -0
  118. package/extract-react-types/modal-attributes.tsx +5 -0
  119. package/hooks/package.json +7 -0
  120. package/modal-body/package.json +7 -0
  121. package/modal-dialog/package.json +7 -0
  122. package/modal-footer/package.json +7 -0
  123. package/modal-header/package.json +7 -0
  124. package/modal-title/package.json +7 -0
  125. package/modal-transition/package.json +7 -0
  126. package/package.json +113 -0
  127. package/types/package.json +7 -0
@@ -0,0 +1,147 @@
1
+ import core, { ASTPath, JSXElement } from 'jscodeshift';
2
+ import { Collection } from 'jscodeshift/src/Collection';
3
+
4
+ import {
5
+ addDynamicImport,
6
+ getDefaultSpecifier,
7
+ getDynamicImportName,
8
+ getNamedSpecifier,
9
+ getSafeImportName,
10
+ } from '@atlaskit/codemod-utils';
11
+
12
+ import {
13
+ BODY_PROP_NAME,
14
+ COMPONENTS_PROP_NAME,
15
+ MODAL_BODY_COMPONENT_FALLBACK_NAME,
16
+ MODAL_BODY_COMPONENT_NAME,
17
+ MODAL_BODY_ENDPOINT,
18
+ PACKAGE_NAME,
19
+ } from '../internal/constants';
20
+ import {
21
+ addToImport,
22
+ getComponentImportName,
23
+ getOverrideFromComponentsProp,
24
+ getOverrideFromIndividualProp,
25
+ getVariableDeclarationPathByName,
26
+ replaceChildren,
27
+ } from '../internal/utils';
28
+
29
+ export const mapBodyFromProps = (
30
+ j: core.JSCodeshift,
31
+ source: Collection<Node>,
32
+ ) => {
33
+ const defaultSpecifier = getDefaultSpecifier(j, source, PACKAGE_NAME);
34
+ const dynamicImportSpecifier = getDynamicImportName(j, source, PACKAGE_NAME);
35
+ const modalDialogComponentName = defaultSpecifier || dynamicImportSpecifier;
36
+
37
+ if (!modalDialogComponentName) {
38
+ return;
39
+ }
40
+
41
+ let shouldImportModalBody;
42
+
43
+ const modalBodySpecifier = getNamedSpecifier(
44
+ j,
45
+ source,
46
+ PACKAGE_NAME,
47
+ MODAL_BODY_COMPONENT_NAME,
48
+ );
49
+
50
+ const modalBodyComponentName =
51
+ modalBodySpecifier ||
52
+ getSafeImportName({
53
+ j,
54
+ base: source,
55
+ currentDefaultSpecifierName: null,
56
+ desiredName: MODAL_BODY_COMPONENT_NAME,
57
+ fallbackName: MODAL_BODY_COMPONENT_FALLBACK_NAME,
58
+ });
59
+
60
+ source
61
+ .findJSXElements(modalDialogComponentName)
62
+ .forEach((element: ASTPath<JSXElement>) => {
63
+ const bodyFromIndividualProp = getOverrideFromIndividualProp(
64
+ j,
65
+ element,
66
+ BODY_PROP_NAME,
67
+ );
68
+ const bodyFromComponentsProp = getOverrideFromComponentsProp(
69
+ j,
70
+ element,
71
+ COMPONENTS_PROP_NAME,
72
+ 'Body',
73
+ );
74
+
75
+ /**
76
+ * If both overrides are declared, use the body passed to the components prop
77
+ * to replicate the logic in the source code (pre-lite mode).
78
+ */
79
+ const body = bodyFromComponentsProp || bodyFromIndividualProp;
80
+
81
+ if (!body) {
82
+ const isSelfClosing = j(element)
83
+ .find(j.JSXOpeningElement)
84
+ .at(0)
85
+ .get('selfClosing').value;
86
+
87
+ /**
88
+ * We only wrap the default ModalBody around the remaining children
89
+ * if the consumer hasn't already imported/used it, and if
90
+ * their ModalDialog is not self-closing (because that means
91
+ * there's no children to be wrapped around).
92
+ */
93
+ if (isSelfClosing || modalBodySpecifier) {
94
+ return;
95
+ }
96
+
97
+ shouldImportModalBody = true;
98
+
99
+ const wrappedChildren = j.jsxElement(
100
+ j.jsxOpeningElement(j.jsxIdentifier(modalBodyComponentName)),
101
+ j.jsxClosingElement(j.jsxIdentifier(modalBodyComponentName)),
102
+ element.value.children,
103
+ );
104
+
105
+ replaceChildren(j, element, modalDialogComponentName, wrappedChildren);
106
+
107
+ return;
108
+ }
109
+
110
+ const props = j.objectExpression([
111
+ j.objectProperty(
112
+ j.identifier('children'),
113
+ j.jsxFragment(
114
+ j.jsxOpeningFragment(),
115
+ j.jsxClosingFragment(),
116
+ element.value.children,
117
+ ),
118
+ ),
119
+ ]);
120
+
121
+ replaceChildren(
122
+ j,
123
+ element,
124
+ modalDialogComponentName,
125
+ j.jsxExpressionContainer(j.callExpression(body, [props])),
126
+ );
127
+ });
128
+
129
+ if (shouldImportModalBody) {
130
+ if (defaultSpecifier) {
131
+ addToImport(j, source, [
132
+ getComponentImportName(
133
+ j,
134
+ modalBodyComponentName,
135
+ MODAL_BODY_COMPONENT_NAME,
136
+ ),
137
+ ]);
138
+ } else if (dynamicImportSpecifier) {
139
+ addDynamicImport(
140
+ j,
141
+ getVariableDeclarationPathByName(j, source, dynamicImportSpecifier),
142
+ modalBodyComponentName,
143
+ MODAL_BODY_ENDPOINT,
144
+ );
145
+ }
146
+ }
147
+ };
@@ -0,0 +1,72 @@
1
+ import core, { ASTPath, JSXElement, StringLiteral } from 'jscodeshift';
2
+ import { Collection } from 'jscodeshift/src/Collection';
3
+
4
+ import { getDefaultSpecifier } from '@atlaskit/codemod-utils';
5
+
6
+ import { COMPONENTS_PROP_NAME, PACKAGE_NAME } from '../internal/constants';
7
+ import {
8
+ getOverrideFromComponentsProp,
9
+ replaceChildren,
10
+ } from '../internal/utils';
11
+
12
+ export const mapContainerFromProps = (
13
+ j: core.JSCodeshift,
14
+ source: Collection<Node>,
15
+ ) => {
16
+ const defaultSpecifier = getDefaultSpecifier(j, source, PACKAGE_NAME);
17
+
18
+ if (!defaultSpecifier) {
19
+ return;
20
+ }
21
+
22
+ source
23
+ .findJSXElements(defaultSpecifier)
24
+ .forEach((element: ASTPath<JSXElement>) => {
25
+ const container = getOverrideFromComponentsProp(
26
+ j,
27
+ element,
28
+ COMPONENTS_PROP_NAME,
29
+ 'Container',
30
+ );
31
+
32
+ if (!container) {
33
+ return;
34
+ }
35
+
36
+ if ((container as StringLiteral).type === 'StringLiteral') {
37
+ const wrappedChildren = j.jsxElement(
38
+ j.jsxOpeningElement(
39
+ j.jsxIdentifier((container as StringLiteral).value),
40
+ ),
41
+ j.jsxClosingElement(
42
+ j.jsxIdentifier((container as StringLiteral).value),
43
+ ),
44
+ element.value.children,
45
+ );
46
+
47
+ replaceChildren(j, element, defaultSpecifier, wrappedChildren);
48
+
49
+ return;
50
+ } else {
51
+ const props = j.objectExpression([
52
+ j.objectProperty(
53
+ j.identifier('children'),
54
+ j.jsxFragment(
55
+ j.jsxOpeningFragment(),
56
+ j.jsxClosingFragment(),
57
+ element.value.children,
58
+ ),
59
+ ),
60
+ ]);
61
+
62
+ replaceChildren(
63
+ j,
64
+ element,
65
+ defaultSpecifier,
66
+ j.jsxExpressionContainer(j.callExpression(container, [props])),
67
+ );
68
+
69
+ return;
70
+ }
71
+ });
72
+ };
@@ -0,0 +1,107 @@
1
+ import core, {
2
+ ASTPath,
3
+ JSXElement,
4
+ JSXExpressionContainer,
5
+ JSXFragment,
6
+ JSXSpreadChild,
7
+ } from 'jscodeshift';
8
+ import { Collection } from 'jscodeshift/src/Collection';
9
+
10
+ import { getDefaultSpecifier } from '@atlaskit/codemod-utils';
11
+
12
+ import {
13
+ APPEARANCE_PROP_NAME,
14
+ COMPONENTS_PROP_NAME,
15
+ FOOTER_PROP_NAME,
16
+ PACKAGE_NAME,
17
+ } from '../internal/constants';
18
+ import {
19
+ getAppearanceFromProp,
20
+ getOverrideFromComponentsProp,
21
+ getOverrideFromIndividualProp,
22
+ } from '../internal/utils';
23
+
24
+ export const mapFooterFromProps = (
25
+ j: core.JSCodeshift,
26
+ source: Collection<Node>,
27
+ ) => {
28
+ const defaultSpecifier = getDefaultSpecifier(j, source, PACKAGE_NAME);
29
+
30
+ if (!defaultSpecifier) {
31
+ return;
32
+ }
33
+
34
+ source
35
+ .findJSXElements(defaultSpecifier)
36
+ .forEach((element: ASTPath<JSXElement>) => {
37
+ const footerFromIndividualProp = getOverrideFromIndividualProp(
38
+ j,
39
+ element,
40
+ FOOTER_PROP_NAME,
41
+ );
42
+ const footerFromComponentsProp = getOverrideFromComponentsProp(
43
+ j,
44
+ element,
45
+ COMPONENTS_PROP_NAME,
46
+ 'Footer',
47
+ );
48
+
49
+ /**
50
+ * If declared, use the footer passed to the components prop
51
+ * to replicate the logic in the source code (pre-lite mode).
52
+ */
53
+ const footer = footerFromComponentsProp || footerFromIndividualProp;
54
+
55
+ if (!footer) {
56
+ return;
57
+ }
58
+
59
+ const appearance = getAppearanceFromProp(j, element);
60
+ const props = appearance
61
+ ? [
62
+ j.objectExpression([
63
+ j.objectProperty(j.identifier(APPEARANCE_PROP_NAME), appearance),
64
+ ]),
65
+ ]
66
+ : [];
67
+
68
+ appendFooterAsLastChild(
69
+ j,
70
+ element,
71
+ defaultSpecifier,
72
+ j.jsxExpressionContainer(j.callExpression(footer, props)),
73
+ );
74
+ });
75
+ };
76
+
77
+ const appendFooterAsLastChild = (
78
+ j: core.JSCodeshift,
79
+ element: ASTPath<JSXElement>,
80
+ specifier: string,
81
+ footer: JSXElement | JSXExpressionContainer | JSXFragment | JSXSpreadChild,
82
+ ) => {
83
+ const children = element.node.children
84
+ ? element.node.children.concat([footer, j.jsxText('\n')])
85
+ : [footer, j.jsxText('\n')];
86
+
87
+ j(element)
88
+ .find(j.JSXOpeningElement)
89
+ .forEach((openingElement) => {
90
+ const openingElementName = openingElement.value.name;
91
+ if (
92
+ openingElementName.type === 'JSXIdentifier' &&
93
+ openingElementName.name === specifier
94
+ ) {
95
+ j(element).replaceWith(
96
+ j.jsxElement(
97
+ j.jsxOpeningElement(
98
+ j.jsxIdentifier(specifier),
99
+ openingElement.value.attributes,
100
+ ),
101
+ j.jsxClosingElement(j.jsxIdentifier(specifier)),
102
+ children,
103
+ ),
104
+ );
105
+ }
106
+ });
107
+ };
@@ -0,0 +1,101 @@
1
+ import core, { ASTPath, JSXElement } from 'jscodeshift';
2
+ import { Collection } from 'jscodeshift/src/Collection';
3
+
4
+ import { getDefaultSpecifier } from '@atlaskit/codemod-utils';
5
+
6
+ import {
7
+ APPEARANCE_PROP_NAME,
8
+ COMPONENTS_PROP_NAME,
9
+ HEADER_PROP_NAME,
10
+ PACKAGE_NAME,
11
+ } from '../internal/constants';
12
+ import {
13
+ getAppearanceFromProp,
14
+ getOverrideFromComponentsProp,
15
+ getOverrideFromIndividualProp,
16
+ } from '../internal/utils';
17
+
18
+ export const mapHeaderFromProps = (
19
+ j: core.JSCodeshift,
20
+ source: Collection<Node>,
21
+ ) => {
22
+ const defaultSpecifier = getDefaultSpecifier(j, source, PACKAGE_NAME);
23
+
24
+ if (!defaultSpecifier) {
25
+ return;
26
+ }
27
+
28
+ source
29
+ .findJSXElements(defaultSpecifier)
30
+ .forEach((element: ASTPath<JSXElement>) => {
31
+ const headerFromIndividualProp = getOverrideFromIndividualProp(
32
+ j,
33
+ element,
34
+ HEADER_PROP_NAME,
35
+ );
36
+ const headerFromComponentsProp = getOverrideFromComponentsProp(
37
+ j,
38
+ element,
39
+ COMPONENTS_PROP_NAME,
40
+ 'Header',
41
+ );
42
+
43
+ /**
44
+ * If declared, use the header passed to the components prop
45
+ * to replicate the logic in the source code (pre-lite mode).
46
+ */
47
+ const header = headerFromComponentsProp || headerFromIndividualProp;
48
+
49
+ if (!header) {
50
+ return;
51
+ }
52
+
53
+ const appearance = getAppearanceFromProp(j, element);
54
+ const props = appearance
55
+ ? [
56
+ j.objectExpression([
57
+ j.objectProperty(j.identifier(APPEARANCE_PROP_NAME), appearance),
58
+ ]),
59
+ ]
60
+ : [];
61
+
62
+ appendHeaderAsFirstChild(
63
+ j,
64
+ element,
65
+ defaultSpecifier,
66
+ j.jsxExpressionContainer(j.callExpression(header, props)),
67
+ );
68
+ });
69
+ };
70
+
71
+ const appendHeaderAsFirstChild = (
72
+ j: core.JSCodeshift,
73
+ element: ASTPath<JSXElement>,
74
+ specifier: string,
75
+ header: any,
76
+ ) => {
77
+ const children = element.node.children
78
+ ? [j.jsxText('\n'), header].concat(element.node.children)
79
+ : [j.jsxText('\n'), header];
80
+
81
+ j(element)
82
+ .find(j.JSXOpeningElement)
83
+ .forEach((openingElement) => {
84
+ const openingElementName = openingElement.value.name;
85
+ if (
86
+ openingElementName.type === 'JSXIdentifier' &&
87
+ openingElementName.name === specifier
88
+ ) {
89
+ j(element).replaceWith(
90
+ j.jsxElement(
91
+ j.jsxOpeningElement(
92
+ j.jsxIdentifier(specifier),
93
+ openingElement.value.attributes,
94
+ ),
95
+ j.jsxClosingElement(j.jsxIdentifier(specifier)),
96
+ children,
97
+ ),
98
+ );
99
+ }
100
+ });
101
+ };
@@ -0,0 +1,193 @@
1
+ import core, {
2
+ ASTPath,
3
+ Collection,
4
+ JSXAttribute,
5
+ JSXElement,
6
+ StringLiteral,
7
+ } from 'jscodeshift/src/core';
8
+
9
+ import {
10
+ addDynamicImport,
11
+ getDefaultSpecifier,
12
+ getDynamicImportName,
13
+ getJSXAttributesByName,
14
+ getSafeImportName,
15
+ } from '@atlaskit/codemod-utils';
16
+
17
+ import {
18
+ APPEARANCE_PROP_NAME,
19
+ HEADING_PROP_NAME,
20
+ IS_MULTILINE_PROP_NAME,
21
+ MODAL_HEADER_COMPONENT_FALLBACK_NAME,
22
+ MODAL_HEADER_COMPONENT_NAME,
23
+ MODAL_HEADER_ENDPOINT,
24
+ MODAL_TITLE_COMPONENT_FALLBACK_NAME,
25
+ MODAL_TITLE_COMPONENT_NAME,
26
+ MODAL_TITLE_ENDPOINT,
27
+ PACKAGE_NAME,
28
+ } from '../internal/constants';
29
+ import {
30
+ addToImport,
31
+ getAppearanceFromProp,
32
+ getComponentImportName,
33
+ getIsMultilineFromProp,
34
+ getVariableDeclarationPathByName,
35
+ } from '../internal/utils';
36
+
37
+ export const mapHeadingPropToModalTitle = (
38
+ j: core.JSCodeshift,
39
+ source: Collection<Node>,
40
+ ) => {
41
+ let doesHeadingPropExist;
42
+ const defaultSpecifierName = getDefaultSpecifier(j, source, PACKAGE_NAME);
43
+ const dynamicImportName = getDynamicImportName(j, source, PACKAGE_NAME);
44
+ const modalDialogComponentName = defaultSpecifierName || dynamicImportName;
45
+
46
+ if (!modalDialogComponentName) {
47
+ return;
48
+ }
49
+
50
+ const modalHeaderComponentName = getSafeImportName({
51
+ j,
52
+ base: source,
53
+ currentDefaultSpecifierName: null,
54
+ desiredName: MODAL_HEADER_COMPONENT_NAME,
55
+ fallbackName: MODAL_HEADER_COMPONENT_FALLBACK_NAME,
56
+ });
57
+ const modalTitleComponentName = getSafeImportName({
58
+ j,
59
+ base: source,
60
+ currentDefaultSpecifierName: null,
61
+ desiredName: MODAL_TITLE_COMPONENT_NAME,
62
+ fallbackName: MODAL_TITLE_COMPONENT_FALLBACK_NAME,
63
+ });
64
+
65
+ source
66
+ .findJSXElements(modalDialogComponentName)
67
+ .forEach((element: ASTPath<JSXElement>) => {
68
+ getJSXAttributesByName(j, element, HEADING_PROP_NAME).forEach(
69
+ (attribute: ASTPath<JSXAttribute>) => {
70
+ const headingPropValue = attribute.node.value;
71
+ doesHeadingPropExist = true;
72
+
73
+ j(attribute).remove();
74
+ element.node.openingElement.selfClosing = false;
75
+ element.node.closingElement = j.jsxClosingElement(
76
+ j.jsxIdentifier(modalDialogComponentName),
77
+ );
78
+
79
+ const headerComponent = getHeaderComponent(
80
+ j,
81
+ element,
82
+ modalHeaderComponentName,
83
+ modalTitleComponentName,
84
+ headingPropValue,
85
+ );
86
+
87
+ if (element.node.children) {
88
+ element.node.children.unshift(
89
+ j.jsxText('\n'),
90
+ headerComponent,
91
+ j.jsxText('\n'),
92
+ );
93
+ } else {
94
+ element.node.children = [
95
+ j.jsxText('\n'),
96
+ headerComponent,
97
+ j.jsxText('\n'),
98
+ ];
99
+ }
100
+ },
101
+ );
102
+ });
103
+
104
+ if (doesHeadingPropExist) {
105
+ if (defaultSpecifierName) {
106
+ addToImport(j, source, [
107
+ getComponentImportName(
108
+ j,
109
+ modalTitleComponentName,
110
+ MODAL_TITLE_COMPONENT_NAME,
111
+ ),
112
+ getComponentImportName(
113
+ j,
114
+ modalHeaderComponentName,
115
+ MODAL_HEADER_COMPONENT_NAME,
116
+ ),
117
+ ]);
118
+ } else if (dynamicImportName) {
119
+ addDynamicImport(
120
+ j,
121
+ getVariableDeclarationPathByName(j, source, dynamicImportName),
122
+ modalHeaderComponentName,
123
+ MODAL_HEADER_ENDPOINT,
124
+ );
125
+ addDynamicImport(
126
+ j,
127
+ getVariableDeclarationPathByName(j, source, dynamicImportName),
128
+ modalTitleComponentName,
129
+ MODAL_TITLE_ENDPOINT,
130
+ );
131
+ }
132
+ }
133
+ };
134
+
135
+ const getModalTitleAttributes = (
136
+ j: core.JSCodeshift,
137
+ element: ASTPath<JSXElement>,
138
+ ) => {
139
+ const appearance = getAppearanceFromProp(j, element);
140
+ const isMultiline = getIsMultilineFromProp(j, element);
141
+
142
+ const attributes = [];
143
+
144
+ if (appearance !== undefined) {
145
+ const appearanceValue =
146
+ (appearance as StringLiteral).type === 'StringLiteral'
147
+ ? appearance
148
+ : j.jsxExpressionContainer(appearance);
149
+
150
+ const appearanceAttr = j.jsxAttribute(
151
+ j.jsxIdentifier(APPEARANCE_PROP_NAME),
152
+ appearanceValue,
153
+ );
154
+
155
+ attributes.push(appearanceAttr);
156
+ }
157
+
158
+ if (isMultiline !== undefined) {
159
+ const isMultilineAttr = j.jsxAttribute(
160
+ j.jsxIdentifier(IS_MULTILINE_PROP_NAME),
161
+ isMultiline ? j.jsxExpressionContainer(isMultiline) : isMultiline,
162
+ );
163
+
164
+ attributes.push(isMultilineAttr);
165
+ }
166
+
167
+ return attributes;
168
+ };
169
+
170
+ const getHeaderComponent = (
171
+ j: core.JSCodeshift,
172
+ element: ASTPath<JSXElement>,
173
+ headerComponentName: string,
174
+ titleComponentName: string,
175
+ heading: any,
176
+ ) => {
177
+ return j.jsxElement(
178
+ j.jsxOpeningElement(j.jsxIdentifier(headerComponentName)),
179
+ j.jsxClosingElement(j.jsxIdentifier(headerComponentName)),
180
+ [
181
+ j.jsxText('\n'),
182
+ j.jsxElement(
183
+ j.jsxOpeningElement(
184
+ j.jsxIdentifier(titleComponentName),
185
+ getModalTitleAttributes(j, element),
186
+ ),
187
+ j.jsxClosingElement(j.jsxIdentifier(titleComponentName)),
188
+ [j.jsxText('\n'), heading, j.jsxText('\n')],
189
+ ),
190
+ j.jsxText('\n'),
191
+ ],
192
+ );
193
+ };