@atlaskit/eslint-plugin-design-system 13.0.3 → 13.1.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +1 -0
  3. package/dist/cjs/presets/all-flat.codegen.js +2 -1
  4. package/dist/cjs/presets/all.codegen.js +2 -1
  5. package/dist/cjs/presets/recommended-flat.codegen.js +2 -1
  6. package/dist/cjs/presets/recommended.codegen.js +2 -1
  7. package/dist/cjs/rules/consistent-css-prop-usage/index.js +15 -0
  8. package/dist/cjs/rules/index.codegen.js +3 -1
  9. package/dist/cjs/rules/use-modal-dialog-close-button/index.js +165 -0
  10. package/dist/es2019/presets/all-flat.codegen.js +2 -1
  11. package/dist/es2019/presets/all.codegen.js +2 -1
  12. package/dist/es2019/presets/recommended-flat.codegen.js +2 -1
  13. package/dist/es2019/presets/recommended.codegen.js +2 -1
  14. package/dist/es2019/rules/consistent-css-prop-usage/index.js +15 -0
  15. package/dist/es2019/rules/index.codegen.js +3 -1
  16. package/dist/es2019/rules/use-modal-dialog-close-button/index.js +145 -0
  17. package/dist/esm/presets/all-flat.codegen.js +2 -1
  18. package/dist/esm/presets/all.codegen.js +2 -1
  19. package/dist/esm/presets/recommended-flat.codegen.js +2 -1
  20. package/dist/esm/presets/recommended.codegen.js +2 -1
  21. package/dist/esm/rules/consistent-css-prop-usage/index.js +15 -0
  22. package/dist/esm/rules/index.codegen.js +3 -1
  23. package/dist/esm/rules/use-modal-dialog-close-button/index.js +161 -0
  24. package/dist/types/index.codegen.d.ts +9 -0
  25. package/dist/types/presets/all-flat.codegen.d.ts +1 -0
  26. package/dist/types/presets/all.codegen.d.ts +1 -0
  27. package/dist/types/presets/recommended-flat.codegen.d.ts +1 -0
  28. package/dist/types/presets/recommended.codegen.d.ts +1 -0
  29. package/dist/types/rules/index.codegen.d.ts +1 -0
  30. package/dist/types/rules/use-modal-dialog-close-button/index.d.ts +7 -0
  31. package/dist/types-ts4.5/index.codegen.d.ts +9 -0
  32. package/dist/types-ts4.5/presets/all-flat.codegen.d.ts +1 -0
  33. package/dist/types-ts4.5/presets/all.codegen.d.ts +1 -0
  34. package/dist/types-ts4.5/presets/recommended-flat.codegen.d.ts +1 -0
  35. package/dist/types-ts4.5/presets/recommended.codegen.d.ts +1 -0
  36. package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -0
  37. package/dist/types-ts4.5/rules/use-modal-dialog-close-button/index.d.ts +7 -0
  38. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @atlaskit/eslint-plugin-design-system
2
2
 
3
+ ## 13.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#127961](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/127961)
8
+ [`900f91f38c047`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/900f91f38c047) -
9
+ Add rule for modal dialog to ensure a close button is used.
10
+
11
+ ## 13.0.4
12
+
13
+ ### Patch Changes
14
+
15
+ - [#128626](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/128626)
16
+ [`142648610a166`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/142648610a166) -
17
+ Fixes the `consistent-css-prop-usage` rule to allow `xcss` pass-through values to the `xcss` prop.
18
+
3
19
  ## 13.0.3
4
20
 
5
21
  ### Patch Changes
package/README.md CHANGED
@@ -88,6 +88,7 @@ module.exports = {
88
88
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-latest-xcss-syntax/README.md">use-latest-xcss-syntax</a> | Enforces usage of space design tokens rather than hard-coded values in xcss. | Yes | Yes | |
89
89
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-latest-xcss-syntax-typography/README.md">use-latest-xcss-syntax-typography</a> | Prohibits use of unsafe styling properties in xcss. Please use Text/Heading primitives instead. | Yes | Yes | |
90
90
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-menu-section-title/README.md">use-menu-section-title</a> | Encourages makers to provide accessible title for Atlassian Design System Menu Section component. | Yes | | Yes |
91
+ | <a href="./packages/design-system/eslint-plugin/src/rules/use-modal-dialog-close-button/README.md">use-modal-dialog-close-button</a> | Encourages makers to use close button in Atlassian Design System's modal dialog component. | Yes | Yes | Yes |
91
92
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-onboarding-spotlight-label/README.md">use-onboarding-spotlight-label</a> | Ensures onboarding spotlight dialogs are described to assistive technology by a direct label or by another element. | Yes | | Yes |
92
93
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-popup-label/README.md">use-popup-label</a> | Encourages to provide accessible name for Atlassian Design System Popup component. | Yes | | Yes |
93
94
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-primitives/README.md">use-primitives</a> | Encourage the usage of primitives components. | | Yes | Yes |
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::7fdb05980fdb097dac9851477f1907e4>>
9
+ * @codegen <<SignedSource::f4b6800bf45a85f5c3acea28681b1cbc>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
  var _default = exports.default = {
@@ -51,6 +51,7 @@ var _default = exports.default = {
51
51
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
52
52
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
53
53
  '@atlaskit/design-system/use-menu-section-title': 'warn',
54
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
54
55
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
55
56
  '@atlaskit/design-system/use-popup-label': 'warn',
56
57
  '@atlaskit/design-system/use-primitives': 'warn',
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::75357860fd00d6fc5060362c75d5db5e>>
9
+ * @codegen <<SignedSource::d9b89cc91a0359b1083c0020c56e1e7f>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
  var _default = exports.default = {
@@ -50,6 +50,7 @@ var _default = exports.default = {
50
50
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
51
51
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
52
52
  '@atlaskit/design-system/use-menu-section-title': 'warn',
53
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
53
54
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
54
55
  '@atlaskit/design-system/use-popup-label': 'warn',
55
56
  '@atlaskit/design-system/use-primitives': 'warn',
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::4dc3e3e8d6fc34692db49347e4785d72>>
9
+ * @codegen <<SignedSource::f697bb4e7d6f53db6d4d1f522ae0ba43>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
  var _default = exports.default = {
@@ -39,6 +39,7 @@ var _default = exports.default = {
39
39
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
40
40
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
41
41
  '@atlaskit/design-system/use-menu-section-title': 'warn',
42
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
42
43
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
43
44
  '@atlaskit/design-system/use-popup-label': 'warn',
44
45
  '@atlaskit/design-system/use-tag-group-label': 'warn',
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::1f8c75cb592edbc7ccb124c7e831e475>>
9
+ * @codegen <<SignedSource::c593f40801552ec33891506bcba81689>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
  var _default = exports.default = {
@@ -38,6 +38,7 @@ var _default = exports.default = {
38
38
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
39
39
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
40
40
  '@atlaskit/design-system/use-menu-section-title': 'warn',
41
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
41
42
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
42
43
  '@atlaskit/design-system/use-popup-label': 'warn',
43
44
  '@atlaskit/design-system/use-tag-group-label': 'warn',
@@ -124,6 +124,21 @@ var JSXExpressionLinter = /*#__PURE__*/function () {
124
124
  // Identifier isn't in the module, skip!
125
125
  return;
126
126
  }
127
+
128
+ // Specifically for the `xcss` prop we allow `xcss` values that come from a function parameter.
129
+ if (this.cssAttributeName === 'xcss' && (
130
+ // Allowing `xcss` and `${string}Xcss` values
131
+ identifier.name === 'xcss' || identifier.name.endsWith('Xcss'))) {
132
+ var sourceCode = (0, _contextCompat.getSourceCode)(this.context);
133
+ var variable = (0, _findVariable.findVariable)({
134
+ identifier: identifier,
135
+ sourceCode: sourceCode
136
+ });
137
+ // Only allowing values where the parameter definition is the only definition
138
+ if ((variable === null || variable === void 0 ? void 0 : variable.defs.length) === 1 && (variable === null || variable === void 0 ? void 0 : variable.defs[0].type) === 'Parameter') {
139
+ return;
140
+ }
141
+ }
127
142
  if (identifier.parent.type !== 'VariableDeclarator') {
128
143
  // When variable is not in the file or coming from import
129
144
  this.context.report({
@@ -44,6 +44,7 @@ var _useHrefInLinkItem = _interopRequireDefault(require("./use-href-in-link-item
44
44
  var _useLatestXcssSyntax = _interopRequireDefault(require("./use-latest-xcss-syntax"));
45
45
  var _useLatestXcssSyntaxTypography = _interopRequireDefault(require("./use-latest-xcss-syntax-typography"));
46
46
  var _useMenuSectionTitle = _interopRequireDefault(require("./use-menu-section-title"));
47
+ var _useModalDialogCloseButton = _interopRequireDefault(require("./use-modal-dialog-close-button"));
47
48
  var _useOnboardingSpotlightLabel = _interopRequireDefault(require("./use-onboarding-spotlight-label"));
48
49
  var _usePopupLabel = _interopRequireDefault(require("./use-popup-label"));
49
50
  var _usePrimitives = _interopRequireDefault(require("./use-primitives"));
@@ -54,7 +55,7 @@ var _useTokensTypography = _interopRequireDefault(require("./use-tokens-typograp
54
55
  var _useVisuallyHidden = _interopRequireDefault(require("./use-visually-hidden"));
55
56
  /**
56
57
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
57
- * @codegen <<SignedSource::50c700a7a1e85949b0e5136a8c576c72>>
58
+ * @codegen <<SignedSource::4655f06909a45281bdcc9780314776c5>>
58
59
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
59
60
  */
60
61
 
@@ -98,6 +99,7 @@ var rules = exports.rules = {
98
99
  'use-latest-xcss-syntax': _useLatestXcssSyntax.default,
99
100
  'use-latest-xcss-syntax-typography': _useLatestXcssSyntaxTypography.default,
100
101
  'use-menu-section-title': _useMenuSectionTitle.default,
102
+ 'use-modal-dialog-close-button': _useModalDialogCloseButton.default,
101
103
  'use-onboarding-spotlight-label': _useOnboardingSpotlightLabel.default,
102
104
  'use-popup-label': _usePopupLabel.default,
103
105
  'use-primitives': _usePrimitives.default,
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useCloseButtonOrNewProp = exports.setHasCloseButtonPropToTrue = exports.ruleName = exports.default = exports.addHasCloseButtonProp = void 0;
7
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
8
+ var _jsxAttribute = require("../../ast-nodes/jsx-attribute");
9
+ var _jsxElement = require("../../ast-nodes/jsx-element");
10
+ var _createRule = require("../utils/create-rule");
11
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
12
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
13
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } // eslint-disable-next-line import/no-extraneous-dependencies
14
+ var PROP_NAME = 'hasCloseButton';
15
+
16
+ // Lint rule message
17
+ var message = '`hasCloseButton` should be set to `true` or the `CloseButton` component should be used to make modal dialog accessible.';
18
+
19
+ // Fix messages
20
+ var addHasCloseButtonProp = exports.addHasCloseButtonProp = 'Add `hasCloseButton` prop.';
21
+ var setHasCloseButtonPropToTrue = exports.setHasCloseButtonPropToTrue = 'Set `hasCloseButton` prop to `true`.';
22
+ var useCloseButtonOrNewProp = exports.useCloseButtonOrNewProp = 'Set `hasCloseButton` prop to `true` in `ModalHeader` or use `CloseButton` export if customization is desired.';
23
+ var ruleName = exports.ruleName = __dirname.split('/').slice(-1)[0];
24
+ var rule = (0, _createRule.createLintRule)({
25
+ meta: {
26
+ name: ruleName,
27
+ type: 'suggestion',
28
+ fixable: 'code',
29
+ hasSuggestions: true,
30
+ docs: {
31
+ description: "Encourages makers to use close button in Atlassian Design System's modal dialog component.",
32
+ recommended: true,
33
+ severity: 'warn'
34
+ },
35
+ messages: {
36
+ modalHeaderMissingHasCloseButtonProp: message,
37
+ modalHeaderHasCloseButtonPropIsFalse: message,
38
+ noCloseButtonExists: message
39
+ }
40
+ },
41
+ create: function create(context) {
42
+ // List of component's locally imported names that match
43
+ var defaultImportLocalName;
44
+ var modalHeaderLocalName;
45
+ var closeButtonLocalName;
46
+ return {
47
+ // Only run rule in files where the package is imported
48
+ ImportDeclaration: function ImportDeclaration(node) {
49
+ // Ignore non-modal imports
50
+ if (node.source.value !== '@atlaskit/modal-dialog') {
51
+ return;
52
+ }
53
+ node.specifiers.forEach(function (identifier) {
54
+ if ((0, _eslintCodemodUtils.isNodeOfType)(identifier, 'ImportDefaultSpecifier')) {
55
+ defaultImportLocalName = identifier.local.name;
56
+ } else if ((0, _eslintCodemodUtils.isNodeOfType)(identifier, 'ImportSpecifier')) {
57
+ var importName = identifier.imported.name;
58
+ var localName = identifier.local.name;
59
+ if (importName === 'ModalHeader') {
60
+ modalHeaderLocalName = localName;
61
+ } else if (importName === 'CloseButton') {
62
+ closeButtonLocalName = localName;
63
+ }
64
+ }
65
+ });
66
+ },
67
+ JSXElement: function JSXElement(node) {
68
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement')) {
69
+ return;
70
+ }
71
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.openingElement.name, 'JSXIdentifier')) {
72
+ return;
73
+ }
74
+ var name = node.openingElement.name.name;
75
+ if (name !== defaultImportLocalName) {
76
+ return;
77
+ }
78
+ var modalHeaderNode = null;
79
+ var closeButtonNode = null;
80
+ var _searchChildren = function searchChildren(node) {
81
+ var _iterator = _createForOfIteratorHelper(node.children),
82
+ _step;
83
+ try {
84
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
85
+ var child = _step.value;
86
+ if (modalHeaderNode && closeButtonNode) {
87
+ continue;
88
+ }
89
+ // Skip if not a JSX Element
90
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(child, 'JSXElement')) {
91
+ continue;
92
+ }
93
+
94
+ // Skip if opening element is not an identifier
95
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(child.openingElement.name, 'JSXIdentifier')) {
96
+ continue;
97
+ }
98
+
99
+ // if child is CloseButton, return true
100
+ if (child.openingElement.name.name === closeButtonLocalName) {
101
+ closeButtonNode = child;
102
+ } else if (child.openingElement.name.name === modalHeaderLocalName) {
103
+ modalHeaderNode = child;
104
+ }
105
+ if (child.children) {
106
+ _searchChildren(child);
107
+ }
108
+ }
109
+ } catch (err) {
110
+ _iterator.e(err);
111
+ } finally {
112
+ _iterator.f();
113
+ }
114
+ };
115
+ _searchChildren(node);
116
+
117
+ // If there is a close button, skip the rest, as this satisfies the rule.
118
+ if (closeButtonNode) {
119
+ return;
120
+ // No close button exists, so check the modal header
121
+ } else if (modalHeaderNode !== null) {
122
+ var prop = _jsxElement.JSXElementHelper.getAttributeByName(modalHeaderNode, PROP_NAME);
123
+
124
+ // If the prop exists
125
+ if (prop) {
126
+ var attrValue = _jsxAttribute.JSXAttribute.getValue(prop);
127
+ // If the value is a boolean with value `false`
128
+ if ((attrValue === null || attrValue === void 0 ? void 0 : attrValue.type) === 'ExpressionStatement Literal' && (attrValue === null || attrValue === void 0 ? void 0 : attrValue.value) === false) {
129
+ return context.report({
130
+ node: modalHeaderNode,
131
+ messageId: 'modalHeaderHasCloseButtonPropIsFalse',
132
+ suggest: [{
133
+ desc: setHasCloseButtonPropToTrue,
134
+ // Set to true by setting to boolean HTML/JSX attribute
135
+ fix: function fix(fixer) {
136
+ return [fixer.replaceText(prop, PROP_NAME)];
137
+ }
138
+ }]
139
+ });
140
+ }
141
+ // If the prop does not exist
142
+ } else {
143
+ return context.report({
144
+ node: modalHeaderNode,
145
+ messageId: 'modalHeaderMissingHasCloseButtonProp',
146
+ suggest: [{
147
+ desc: addHasCloseButtonProp,
148
+ fix: function fix(fixer) {
149
+ return [fixer.insertTextAfter(modalHeaderNode.openingElement.name, " ".concat(PROP_NAME))];
150
+ }
151
+ }]
152
+ });
153
+ }
154
+ // No close button or modal header exists
155
+ } else {
156
+ return context.report({
157
+ node: node,
158
+ messageId: 'noCloseButtonExists'
159
+ });
160
+ }
161
+ }
162
+ };
163
+ }
164
+ });
165
+ var _default = exports.default = rule;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::7fdb05980fdb097dac9851477f1907e4>>
3
+ * @codegen <<SignedSource::f4b6800bf45a85f5c3acea28681b1cbc>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -46,6 +46,7 @@ export default {
46
46
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
47
47
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
48
48
  '@atlaskit/design-system/use-menu-section-title': 'warn',
49
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
49
50
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
50
51
  '@atlaskit/design-system/use-popup-label': 'warn',
51
52
  '@atlaskit/design-system/use-primitives': 'warn',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::75357860fd00d6fc5060362c75d5db5e>>
3
+ * @codegen <<SignedSource::d9b89cc91a0359b1083c0020c56e1e7f>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -45,6 +45,7 @@ export default {
45
45
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
46
46
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
47
47
  '@atlaskit/design-system/use-menu-section-title': 'warn',
48
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
48
49
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
49
50
  '@atlaskit/design-system/use-popup-label': 'warn',
50
51
  '@atlaskit/design-system/use-primitives': 'warn',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::4dc3e3e8d6fc34692db49347e4785d72>>
3
+ * @codegen <<SignedSource::f697bb4e7d6f53db6d4d1f522ae0ba43>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -34,6 +34,7 @@ export default {
34
34
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
35
35
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
36
36
  '@atlaskit/design-system/use-menu-section-title': 'warn',
37
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
37
38
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
38
39
  '@atlaskit/design-system/use-popup-label': 'warn',
39
40
  '@atlaskit/design-system/use-tag-group-label': 'warn',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::1f8c75cb592edbc7ccb124c7e831e475>>
3
+ * @codegen <<SignedSource::c593f40801552ec33891506bcba81689>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -33,6 +33,7 @@ export default {
33
33
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
34
34
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
35
35
  '@atlaskit/design-system/use-menu-section-title': 'warn',
36
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
36
37
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
37
38
  '@atlaskit/design-system/use-popup-label': 'warn',
38
39
  '@atlaskit/design-system/use-tag-group-label': 'warn',
@@ -98,6 +98,21 @@ class JSXExpressionLinter {
98
98
  // Identifier isn't in the module, skip!
99
99
  return;
100
100
  }
101
+
102
+ // Specifically for the `xcss` prop we allow `xcss` values that come from a function parameter.
103
+ if (this.cssAttributeName === 'xcss' && (
104
+ // Allowing `xcss` and `${string}Xcss` values
105
+ identifier.name === 'xcss' || identifier.name.endsWith('Xcss'))) {
106
+ const sourceCode = getSourceCode(this.context);
107
+ const variable = findVariable({
108
+ identifier,
109
+ sourceCode
110
+ });
111
+ // Only allowing values where the parameter definition is the only definition
112
+ if ((variable === null || variable === void 0 ? void 0 : variable.defs.length) === 1 && (variable === null || variable === void 0 ? void 0 : variable.defs[0].type) === 'Parameter') {
113
+ return;
114
+ }
115
+ }
101
116
  if (identifier.parent.type !== 'VariableDeclarator') {
102
117
  // When variable is not in the file or coming from import
103
118
  this.context.report({
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::50c700a7a1e85949b0e5136a8c576c72>>
3
+ * @codegen <<SignedSource::4655f06909a45281bdcc9780314776c5>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import consistentCssPropUsage from './consistent-css-prop-usage';
@@ -42,6 +42,7 @@ import useHrefInLinkItem from './use-href-in-link-item';
42
42
  import useLatestXcssSyntax from './use-latest-xcss-syntax';
43
43
  import useLatestXcssSyntaxTypography from './use-latest-xcss-syntax-typography';
44
44
  import useMenuSectionTitle from './use-menu-section-title';
45
+ import useModalDialogCloseButton from './use-modal-dialog-close-button';
45
46
  import useOnboardingSpotlightLabel from './use-onboarding-spotlight-label';
46
47
  import usePopupLabel from './use-popup-label';
47
48
  import usePrimitives from './use-primitives';
@@ -90,6 +91,7 @@ export const rules = {
90
91
  'use-latest-xcss-syntax': useLatestXcssSyntax,
91
92
  'use-latest-xcss-syntax-typography': useLatestXcssSyntaxTypography,
92
93
  'use-menu-section-title': useMenuSectionTitle,
94
+ 'use-modal-dialog-close-button': useModalDialogCloseButton,
93
95
  'use-onboarding-spotlight-label': useOnboardingSpotlightLabel,
94
96
  'use-popup-label': usePopupLabel,
95
97
  'use-primitives': usePrimitives,
@@ -0,0 +1,145 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
3
+ import { isNodeOfType } from 'eslint-codemod-utils';
4
+ import { JSXAttribute } from '../../ast-nodes/jsx-attribute';
5
+ import { JSXElementHelper } from '../../ast-nodes/jsx-element';
6
+ import { createLintRule } from '../utils/create-rule';
7
+ const PROP_NAME = 'hasCloseButton';
8
+
9
+ // Lint rule message
10
+ const message = '`hasCloseButton` should be set to `true` or the `CloseButton` component should be used to make modal dialog accessible.';
11
+
12
+ // Fix messages
13
+ export const addHasCloseButtonProp = 'Add `hasCloseButton` prop.';
14
+ export const setHasCloseButtonPropToTrue = 'Set `hasCloseButton` prop to `true`.';
15
+ export const useCloseButtonOrNewProp = 'Set `hasCloseButton` prop to `true` in `ModalHeader` or use `CloseButton` export if customization is desired.';
16
+ export const ruleName = __dirname.split('/').slice(-1)[0];
17
+ const rule = createLintRule({
18
+ meta: {
19
+ name: ruleName,
20
+ type: 'suggestion',
21
+ fixable: 'code',
22
+ hasSuggestions: true,
23
+ docs: {
24
+ description: "Encourages makers to use close button in Atlassian Design System's modal dialog component.",
25
+ recommended: true,
26
+ severity: 'warn'
27
+ },
28
+ messages: {
29
+ modalHeaderMissingHasCloseButtonProp: message,
30
+ modalHeaderHasCloseButtonPropIsFalse: message,
31
+ noCloseButtonExists: message
32
+ }
33
+ },
34
+ create(context) {
35
+ // List of component's locally imported names that match
36
+ let defaultImportLocalName;
37
+ let modalHeaderLocalName;
38
+ let closeButtonLocalName;
39
+ return {
40
+ // Only run rule in files where the package is imported
41
+ ImportDeclaration(node) {
42
+ // Ignore non-modal imports
43
+ if (node.source.value !== '@atlaskit/modal-dialog') {
44
+ return;
45
+ }
46
+ node.specifiers.forEach(identifier => {
47
+ if (isNodeOfType(identifier, 'ImportDefaultSpecifier')) {
48
+ defaultImportLocalName = identifier.local.name;
49
+ } else if (isNodeOfType(identifier, 'ImportSpecifier')) {
50
+ const importName = identifier.imported.name;
51
+ const localName = identifier.local.name;
52
+ if (importName === 'ModalHeader') {
53
+ modalHeaderLocalName = localName;
54
+ } else if (importName === 'CloseButton') {
55
+ closeButtonLocalName = localName;
56
+ }
57
+ }
58
+ });
59
+ },
60
+ JSXElement(node) {
61
+ if (!isNodeOfType(node, 'JSXElement')) {
62
+ return;
63
+ }
64
+ if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
65
+ return;
66
+ }
67
+ const name = node.openingElement.name.name;
68
+ if (name !== defaultImportLocalName) {
69
+ return;
70
+ }
71
+ let modalHeaderNode = null;
72
+ let closeButtonNode = null;
73
+ const searchChildren = node => {
74
+ for (let child of node.children) {
75
+ if (modalHeaderNode && closeButtonNode) {
76
+ continue;
77
+ }
78
+ // Skip if not a JSX Element
79
+ if (!isNodeOfType(child, 'JSXElement')) {
80
+ continue;
81
+ }
82
+
83
+ // Skip if opening element is not an identifier
84
+ if (!isNodeOfType(child.openingElement.name, 'JSXIdentifier')) {
85
+ continue;
86
+ }
87
+
88
+ // if child is CloseButton, return true
89
+ if (child.openingElement.name.name === closeButtonLocalName) {
90
+ closeButtonNode = child;
91
+ } else if (child.openingElement.name.name === modalHeaderLocalName) {
92
+ modalHeaderNode = child;
93
+ }
94
+ if (child.children) {
95
+ searchChildren(child);
96
+ }
97
+ }
98
+ };
99
+ searchChildren(node);
100
+
101
+ // If there is a close button, skip the rest, as this satisfies the rule.
102
+ if (closeButtonNode) {
103
+ return;
104
+ // No close button exists, so check the modal header
105
+ } else if (modalHeaderNode !== null) {
106
+ const prop = JSXElementHelper.getAttributeByName(modalHeaderNode, PROP_NAME);
107
+
108
+ // If the prop exists
109
+ if (prop) {
110
+ const attrValue = JSXAttribute.getValue(prop);
111
+ // If the value is a boolean with value `false`
112
+ if ((attrValue === null || attrValue === void 0 ? void 0 : attrValue.type) === 'ExpressionStatement Literal' && (attrValue === null || attrValue === void 0 ? void 0 : attrValue.value) === false) {
113
+ return context.report({
114
+ node: modalHeaderNode,
115
+ messageId: 'modalHeaderHasCloseButtonPropIsFalse',
116
+ suggest: [{
117
+ desc: setHasCloseButtonPropToTrue,
118
+ // Set to true by setting to boolean HTML/JSX attribute
119
+ fix: fixer => [fixer.replaceText(prop, PROP_NAME)]
120
+ }]
121
+ });
122
+ }
123
+ // If the prop does not exist
124
+ } else {
125
+ return context.report({
126
+ node: modalHeaderNode,
127
+ messageId: 'modalHeaderMissingHasCloseButtonProp',
128
+ suggest: [{
129
+ desc: addHasCloseButtonProp,
130
+ fix: fixer => [fixer.insertTextAfter(modalHeaderNode.openingElement.name, ` ${PROP_NAME}`)]
131
+ }]
132
+ });
133
+ }
134
+ // No close button or modal header exists
135
+ } else {
136
+ return context.report({
137
+ node,
138
+ messageId: 'noCloseButtonExists'
139
+ });
140
+ }
141
+ }
142
+ };
143
+ }
144
+ });
145
+ export default rule;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::7fdb05980fdb097dac9851477f1907e4>>
3
+ * @codegen <<SignedSource::f4b6800bf45a85f5c3acea28681b1cbc>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -46,6 +46,7 @@ export default {
46
46
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
47
47
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
48
48
  '@atlaskit/design-system/use-menu-section-title': 'warn',
49
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
49
50
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
50
51
  '@atlaskit/design-system/use-popup-label': 'warn',
51
52
  '@atlaskit/design-system/use-primitives': 'warn',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::75357860fd00d6fc5060362c75d5db5e>>
3
+ * @codegen <<SignedSource::d9b89cc91a0359b1083c0020c56e1e7f>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -45,6 +45,7 @@ export default {
45
45
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
46
46
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
47
47
  '@atlaskit/design-system/use-menu-section-title': 'warn',
48
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
48
49
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
49
50
  '@atlaskit/design-system/use-popup-label': 'warn',
50
51
  '@atlaskit/design-system/use-primitives': 'warn',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::4dc3e3e8d6fc34692db49347e4785d72>>
3
+ * @codegen <<SignedSource::f697bb4e7d6f53db6d4d1f522ae0ba43>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -34,6 +34,7 @@ export default {
34
34
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
35
35
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
36
36
  '@atlaskit/design-system/use-menu-section-title': 'warn',
37
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
37
38
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
38
39
  '@atlaskit/design-system/use-popup-label': 'warn',
39
40
  '@atlaskit/design-system/use-tag-group-label': 'warn',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::1f8c75cb592edbc7ccb124c7e831e475>>
3
+ * @codegen <<SignedSource::c593f40801552ec33891506bcba81689>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -33,6 +33,7 @@ export default {
33
33
  '@atlaskit/design-system/use-latest-xcss-syntax': 'error',
34
34
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': 'warn',
35
35
  '@atlaskit/design-system/use-menu-section-title': 'warn',
36
+ '@atlaskit/design-system/use-modal-dialog-close-button': 'warn',
36
37
  '@atlaskit/design-system/use-onboarding-spotlight-label': 'warn',
37
38
  '@atlaskit/design-system/use-popup-label': 'warn',
38
39
  '@atlaskit/design-system/use-tag-group-label': 'warn',
@@ -117,6 +117,21 @@ var JSXExpressionLinter = /*#__PURE__*/function () {
117
117
  // Identifier isn't in the module, skip!
118
118
  return;
119
119
  }
120
+
121
+ // Specifically for the `xcss` prop we allow `xcss` values that come from a function parameter.
122
+ if (this.cssAttributeName === 'xcss' && (
123
+ // Allowing `xcss` and `${string}Xcss` values
124
+ identifier.name === 'xcss' || identifier.name.endsWith('Xcss'))) {
125
+ var sourceCode = getSourceCode(this.context);
126
+ var variable = findVariable({
127
+ identifier: identifier,
128
+ sourceCode: sourceCode
129
+ });
130
+ // Only allowing values where the parameter definition is the only definition
131
+ if ((variable === null || variable === void 0 ? void 0 : variable.defs.length) === 1 && (variable === null || variable === void 0 ? void 0 : variable.defs[0].type) === 'Parameter') {
132
+ return;
133
+ }
134
+ }
120
135
  if (identifier.parent.type !== 'VariableDeclarator') {
121
136
  // When variable is not in the file or coming from import
122
137
  this.context.report({
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::50c700a7a1e85949b0e5136a8c576c72>>
3
+ * @codegen <<SignedSource::4655f06909a45281bdcc9780314776c5>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import consistentCssPropUsage from './consistent-css-prop-usage';
@@ -42,6 +42,7 @@ import useHrefInLinkItem from './use-href-in-link-item';
42
42
  import useLatestXcssSyntax from './use-latest-xcss-syntax';
43
43
  import useLatestXcssSyntaxTypography from './use-latest-xcss-syntax-typography';
44
44
  import useMenuSectionTitle from './use-menu-section-title';
45
+ import useModalDialogCloseButton from './use-modal-dialog-close-button';
45
46
  import useOnboardingSpotlightLabel from './use-onboarding-spotlight-label';
46
47
  import usePopupLabel from './use-popup-label';
47
48
  import usePrimitives from './use-primitives';
@@ -90,6 +91,7 @@ export var rules = {
90
91
  'use-latest-xcss-syntax': useLatestXcssSyntax,
91
92
  'use-latest-xcss-syntax-typography': useLatestXcssSyntaxTypography,
92
93
  'use-menu-section-title': useMenuSectionTitle,
94
+ 'use-modal-dialog-close-button': useModalDialogCloseButton,
93
95
  'use-onboarding-spotlight-label': useOnboardingSpotlightLabel,
94
96
  'use-popup-label': usePopupLabel,
95
97
  'use-primitives': usePrimitives,
@@ -0,0 +1,161 @@
1
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
2
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
3
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
4
+ // eslint-disable-next-line import/no-extraneous-dependencies
5
+
6
+ import { isNodeOfType } from 'eslint-codemod-utils';
7
+ import { JSXAttribute } from '../../ast-nodes/jsx-attribute';
8
+ import { JSXElementHelper } from '../../ast-nodes/jsx-element';
9
+ import { createLintRule } from '../utils/create-rule';
10
+ var PROP_NAME = 'hasCloseButton';
11
+
12
+ // Lint rule message
13
+ var message = '`hasCloseButton` should be set to `true` or the `CloseButton` component should be used to make modal dialog accessible.';
14
+
15
+ // Fix messages
16
+ export var addHasCloseButtonProp = 'Add `hasCloseButton` prop.';
17
+ export var setHasCloseButtonPropToTrue = 'Set `hasCloseButton` prop to `true`.';
18
+ export var useCloseButtonOrNewProp = 'Set `hasCloseButton` prop to `true` in `ModalHeader` or use `CloseButton` export if customization is desired.';
19
+ export var ruleName = __dirname.split('/').slice(-1)[0];
20
+ var rule = createLintRule({
21
+ meta: {
22
+ name: ruleName,
23
+ type: 'suggestion',
24
+ fixable: 'code',
25
+ hasSuggestions: true,
26
+ docs: {
27
+ description: "Encourages makers to use close button in Atlassian Design System's modal dialog component.",
28
+ recommended: true,
29
+ severity: 'warn'
30
+ },
31
+ messages: {
32
+ modalHeaderMissingHasCloseButtonProp: message,
33
+ modalHeaderHasCloseButtonPropIsFalse: message,
34
+ noCloseButtonExists: message
35
+ }
36
+ },
37
+ create: function create(context) {
38
+ // List of component's locally imported names that match
39
+ var defaultImportLocalName;
40
+ var modalHeaderLocalName;
41
+ var closeButtonLocalName;
42
+ return {
43
+ // Only run rule in files where the package is imported
44
+ ImportDeclaration: function ImportDeclaration(node) {
45
+ // Ignore non-modal imports
46
+ if (node.source.value !== '@atlaskit/modal-dialog') {
47
+ return;
48
+ }
49
+ node.specifiers.forEach(function (identifier) {
50
+ if (isNodeOfType(identifier, 'ImportDefaultSpecifier')) {
51
+ defaultImportLocalName = identifier.local.name;
52
+ } else if (isNodeOfType(identifier, 'ImportSpecifier')) {
53
+ var importName = identifier.imported.name;
54
+ var localName = identifier.local.name;
55
+ if (importName === 'ModalHeader') {
56
+ modalHeaderLocalName = localName;
57
+ } else if (importName === 'CloseButton') {
58
+ closeButtonLocalName = localName;
59
+ }
60
+ }
61
+ });
62
+ },
63
+ JSXElement: function JSXElement(node) {
64
+ if (!isNodeOfType(node, 'JSXElement')) {
65
+ return;
66
+ }
67
+ if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
68
+ return;
69
+ }
70
+ var name = node.openingElement.name.name;
71
+ if (name !== defaultImportLocalName) {
72
+ return;
73
+ }
74
+ var modalHeaderNode = null;
75
+ var closeButtonNode = null;
76
+ var _searchChildren = function searchChildren(node) {
77
+ var _iterator = _createForOfIteratorHelper(node.children),
78
+ _step;
79
+ try {
80
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
81
+ var child = _step.value;
82
+ if (modalHeaderNode && closeButtonNode) {
83
+ continue;
84
+ }
85
+ // Skip if not a JSX Element
86
+ if (!isNodeOfType(child, 'JSXElement')) {
87
+ continue;
88
+ }
89
+
90
+ // Skip if opening element is not an identifier
91
+ if (!isNodeOfType(child.openingElement.name, 'JSXIdentifier')) {
92
+ continue;
93
+ }
94
+
95
+ // if child is CloseButton, return true
96
+ if (child.openingElement.name.name === closeButtonLocalName) {
97
+ closeButtonNode = child;
98
+ } else if (child.openingElement.name.name === modalHeaderLocalName) {
99
+ modalHeaderNode = child;
100
+ }
101
+ if (child.children) {
102
+ _searchChildren(child);
103
+ }
104
+ }
105
+ } catch (err) {
106
+ _iterator.e(err);
107
+ } finally {
108
+ _iterator.f();
109
+ }
110
+ };
111
+ _searchChildren(node);
112
+
113
+ // If there is a close button, skip the rest, as this satisfies the rule.
114
+ if (closeButtonNode) {
115
+ return;
116
+ // No close button exists, so check the modal header
117
+ } else if (modalHeaderNode !== null) {
118
+ var prop = JSXElementHelper.getAttributeByName(modalHeaderNode, PROP_NAME);
119
+
120
+ // If the prop exists
121
+ if (prop) {
122
+ var attrValue = JSXAttribute.getValue(prop);
123
+ // If the value is a boolean with value `false`
124
+ if ((attrValue === null || attrValue === void 0 ? void 0 : attrValue.type) === 'ExpressionStatement Literal' && (attrValue === null || attrValue === void 0 ? void 0 : attrValue.value) === false) {
125
+ return context.report({
126
+ node: modalHeaderNode,
127
+ messageId: 'modalHeaderHasCloseButtonPropIsFalse',
128
+ suggest: [{
129
+ desc: setHasCloseButtonPropToTrue,
130
+ // Set to true by setting to boolean HTML/JSX attribute
131
+ fix: function fix(fixer) {
132
+ return [fixer.replaceText(prop, PROP_NAME)];
133
+ }
134
+ }]
135
+ });
136
+ }
137
+ // If the prop does not exist
138
+ } else {
139
+ return context.report({
140
+ node: modalHeaderNode,
141
+ messageId: 'modalHeaderMissingHasCloseButtonProp',
142
+ suggest: [{
143
+ desc: addHasCloseButtonProp,
144
+ fix: function fix(fixer) {
145
+ return [fixer.insertTextAfter(modalHeaderNode.openingElement.name, " ".concat(PROP_NAME))];
146
+ }
147
+ }]
148
+ });
149
+ }
150
+ // No close button or modal header exists
151
+ } else {
152
+ return context.report({
153
+ node: node,
154
+ messageId: 'noCloseButtonExists'
155
+ });
156
+ }
157
+ }
158
+ };
159
+ }
160
+ });
161
+ export default rule;
@@ -54,6 +54,7 @@ export declare const plugin: {
54
54
  'use-latest-xcss-syntax': import("eslint").Rule.RuleModule;
55
55
  'use-latest-xcss-syntax-typography': import("eslint").Rule.RuleModule;
56
56
  'use-menu-section-title': import("eslint").Rule.RuleModule;
57
+ 'use-modal-dialog-close-button': import("eslint").Rule.RuleModule;
57
58
  'use-onboarding-spotlight-label': import("eslint").Rule.RuleModule;
58
59
  'use-popup-label': import("eslint").Rule.RuleModule;
59
60
  'use-primitives': import("eslint").Rule.RuleModule;
@@ -105,6 +106,7 @@ export declare const plugin: {
105
106
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
106
107
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
107
108
  '@atlaskit/design-system/use-menu-section-title': "warn";
109
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
108
110
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
109
111
  '@atlaskit/design-system/use-popup-label': "warn";
110
112
  '@atlaskit/design-system/use-primitives': "warn";
@@ -158,6 +160,7 @@ export declare const plugin: {
158
160
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
159
161
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
160
162
  '@atlaskit/design-system/use-menu-section-title': "warn";
163
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
161
164
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
162
165
  '@atlaskit/design-system/use-popup-label': "warn";
163
166
  '@atlaskit/design-system/use-primitives': "warn";
@@ -197,6 +200,7 @@ export declare const plugin: {
197
200
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
198
201
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
199
202
  '@atlaskit/design-system/use-menu-section-title': "warn";
203
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
200
204
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
201
205
  '@atlaskit/design-system/use-popup-label': "warn";
202
206
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -234,6 +238,7 @@ export declare const plugin: {
234
238
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
235
239
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
236
240
  '@atlaskit/design-system/use-menu-section-title': "warn";
241
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
237
242
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
238
243
  '@atlaskit/design-system/use-popup-label': "warn";
239
244
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -284,6 +289,7 @@ declare const configs: {
284
289
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
285
290
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
286
291
  '@atlaskit/design-system/use-menu-section-title': "warn";
292
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
287
293
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
288
294
  '@atlaskit/design-system/use-popup-label': "warn";
289
295
  '@atlaskit/design-system/use-primitives': "warn";
@@ -337,6 +343,7 @@ declare const configs: {
337
343
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
338
344
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
339
345
  '@atlaskit/design-system/use-menu-section-title': "warn";
346
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
340
347
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
341
348
  '@atlaskit/design-system/use-popup-label': "warn";
342
349
  '@atlaskit/design-system/use-primitives': "warn";
@@ -376,6 +383,7 @@ declare const configs: {
376
383
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
377
384
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
378
385
  '@atlaskit/design-system/use-menu-section-title': "warn";
386
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
379
387
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
380
388
  '@atlaskit/design-system/use-popup-label': "warn";
381
389
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -413,6 +421,7 @@ declare const configs: {
413
421
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
414
422
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
415
423
  '@atlaskit/design-system/use-menu-section-title': "warn";
424
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
416
425
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
417
426
  '@atlaskit/design-system/use-popup-label': "warn";
418
427
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -39,6 +39,7 @@ declare const _default: {
39
39
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
40
40
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
41
41
  '@atlaskit/design-system/use-menu-section-title': "warn";
42
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
42
43
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
43
44
  '@atlaskit/design-system/use-popup-label': "warn";
44
45
  '@atlaskit/design-system/use-primitives': "warn";
@@ -39,6 +39,7 @@ declare const _default: {
39
39
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
40
40
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
41
41
  '@atlaskit/design-system/use-menu-section-title': "warn";
42
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
42
43
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
43
44
  '@atlaskit/design-system/use-popup-label': "warn";
44
45
  '@atlaskit/design-system/use-primitives': "warn";
@@ -27,6 +27,7 @@ declare const _default: {
27
27
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
28
28
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
29
29
  '@atlaskit/design-system/use-menu-section-title': "warn";
30
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
30
31
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
31
32
  '@atlaskit/design-system/use-popup-label': "warn";
32
33
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -27,6 +27,7 @@ declare const _default: {
27
27
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
28
28
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
29
29
  '@atlaskit/design-system/use-menu-section-title': "warn";
30
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
30
31
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
31
32
  '@atlaskit/design-system/use-popup-label': "warn";
32
33
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -38,6 +38,7 @@ export declare const rules: {
38
38
  'use-latest-xcss-syntax': import("eslint").Rule.RuleModule;
39
39
  'use-latest-xcss-syntax-typography': import("eslint").Rule.RuleModule;
40
40
  'use-menu-section-title': import("eslint").Rule.RuleModule;
41
+ 'use-modal-dialog-close-button': import("eslint").Rule.RuleModule;
41
42
  'use-onboarding-spotlight-label': import("eslint").Rule.RuleModule;
42
43
  'use-popup-label': import("eslint").Rule.RuleModule;
43
44
  'use-primitives': import("eslint").Rule.RuleModule;
@@ -0,0 +1,7 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const addHasCloseButtonProp = "Add `hasCloseButton` prop.";
3
+ export declare const setHasCloseButtonPropToTrue = "Set `hasCloseButton` prop to `true`.";
4
+ export declare const useCloseButtonOrNewProp = "Set `hasCloseButton` prop to `true` in `ModalHeader` or use `CloseButton` export if customization is desired.";
5
+ export declare const ruleName: string;
6
+ declare const rule: Rule.RuleModule;
7
+ export default rule;
@@ -54,6 +54,7 @@ export declare const plugin: {
54
54
  'use-latest-xcss-syntax': import("eslint").Rule.RuleModule;
55
55
  'use-latest-xcss-syntax-typography': import("eslint").Rule.RuleModule;
56
56
  'use-menu-section-title': import("eslint").Rule.RuleModule;
57
+ 'use-modal-dialog-close-button': import("eslint").Rule.RuleModule;
57
58
  'use-onboarding-spotlight-label': import("eslint").Rule.RuleModule;
58
59
  'use-popup-label': import("eslint").Rule.RuleModule;
59
60
  'use-primitives': import("eslint").Rule.RuleModule;
@@ -108,6 +109,7 @@ export declare const plugin: {
108
109
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
109
110
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
110
111
  '@atlaskit/design-system/use-menu-section-title': "warn";
112
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
111
113
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
112
114
  '@atlaskit/design-system/use-popup-label': "warn";
113
115
  '@atlaskit/design-system/use-primitives': "warn";
@@ -164,6 +166,7 @@ export declare const plugin: {
164
166
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
165
167
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
166
168
  '@atlaskit/design-system/use-menu-section-title': "warn";
169
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
167
170
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
168
171
  '@atlaskit/design-system/use-popup-label': "warn";
169
172
  '@atlaskit/design-system/use-primitives': "warn";
@@ -206,6 +209,7 @@ export declare const plugin: {
206
209
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
207
210
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
208
211
  '@atlaskit/design-system/use-menu-section-title': "warn";
212
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
209
213
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
210
214
  '@atlaskit/design-system/use-popup-label': "warn";
211
215
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -246,6 +250,7 @@ export declare const plugin: {
246
250
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
247
251
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
248
252
  '@atlaskit/design-system/use-menu-section-title': "warn";
253
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
249
254
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
250
255
  '@atlaskit/design-system/use-popup-label': "warn";
251
256
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -299,6 +304,7 @@ declare const configs: {
299
304
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
300
305
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
301
306
  '@atlaskit/design-system/use-menu-section-title': "warn";
307
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
302
308
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
303
309
  '@atlaskit/design-system/use-popup-label': "warn";
304
310
  '@atlaskit/design-system/use-primitives': "warn";
@@ -355,6 +361,7 @@ declare const configs: {
355
361
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
356
362
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
357
363
  '@atlaskit/design-system/use-menu-section-title': "warn";
364
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
358
365
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
359
366
  '@atlaskit/design-system/use-popup-label': "warn";
360
367
  '@atlaskit/design-system/use-primitives': "warn";
@@ -397,6 +404,7 @@ declare const configs: {
397
404
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
398
405
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
399
406
  '@atlaskit/design-system/use-menu-section-title': "warn";
407
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
400
408
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
401
409
  '@atlaskit/design-system/use-popup-label': "warn";
402
410
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -437,6 +445,7 @@ declare const configs: {
437
445
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
438
446
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
439
447
  '@atlaskit/design-system/use-menu-section-title': "warn";
448
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
440
449
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
441
450
  '@atlaskit/design-system/use-popup-label': "warn";
442
451
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -42,6 +42,7 @@ declare const _default: {
42
42
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
43
43
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
44
44
  '@atlaskit/design-system/use-menu-section-title': "warn";
45
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
45
46
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
46
47
  '@atlaskit/design-system/use-popup-label': "warn";
47
48
  '@atlaskit/design-system/use-primitives': "warn";
@@ -42,6 +42,7 @@ declare const _default: {
42
42
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
43
43
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
44
44
  '@atlaskit/design-system/use-menu-section-title': "warn";
45
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
45
46
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
46
47
  '@atlaskit/design-system/use-popup-label': "warn";
47
48
  '@atlaskit/design-system/use-primitives': "warn";
@@ -30,6 +30,7 @@ declare const _default: {
30
30
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
31
31
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
32
32
  '@atlaskit/design-system/use-menu-section-title': "warn";
33
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
33
34
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
34
35
  '@atlaskit/design-system/use-popup-label': "warn";
35
36
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -30,6 +30,7 @@ declare const _default: {
30
30
  '@atlaskit/design-system/use-latest-xcss-syntax': "error";
31
31
  '@atlaskit/design-system/use-latest-xcss-syntax-typography': "warn";
32
32
  '@atlaskit/design-system/use-menu-section-title': "warn";
33
+ '@atlaskit/design-system/use-modal-dialog-close-button': "warn";
33
34
  '@atlaskit/design-system/use-onboarding-spotlight-label': "warn";
34
35
  '@atlaskit/design-system/use-popup-label': "warn";
35
36
  '@atlaskit/design-system/use-tag-group-label': "warn";
@@ -38,6 +38,7 @@ export declare const rules: {
38
38
  'use-latest-xcss-syntax': import("eslint").Rule.RuleModule;
39
39
  'use-latest-xcss-syntax-typography': import("eslint").Rule.RuleModule;
40
40
  'use-menu-section-title': import("eslint").Rule.RuleModule;
41
+ 'use-modal-dialog-close-button': import("eslint").Rule.RuleModule;
41
42
  'use-onboarding-spotlight-label': import("eslint").Rule.RuleModule;
42
43
  'use-popup-label': import("eslint").Rule.RuleModule;
43
44
  'use-primitives': import("eslint").Rule.RuleModule;
@@ -0,0 +1,7 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const addHasCloseButtonProp = "Add `hasCloseButton` prop.";
3
+ export declare const setHasCloseButtonPropToTrue = "Set `hasCloseButton` prop to `true`.";
4
+ export declare const useCloseButtonOrNewProp = "Set `hasCloseButton` prop to `true` in `ModalHeader` or use `CloseButton` export if customization is desired.";
5
+ export declare const ruleName: string;
6
+ declare const rule: Rule.RuleModule;
7
+ export default rule;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-design-system",
3
3
  "description": "The essential plugin for use with the Atlassian Design System.",
4
- "version": "13.0.3",
4
+ "version": "13.1.0",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
7
7
  "publishConfig": {
@@ -45,8 +45,8 @@
45
45
  "dependencies": {
46
46
  "@atlaskit/eslint-utils": "^2.0.0",
47
47
  "@atlaskit/icon": "^25.0.0",
48
- "@atlaskit/icon-lab": "^4.0.0",
49
- "@atlaskit/tokens": "^4.4.0",
48
+ "@atlaskit/icon-lab": "^4.2.0",
49
+ "@atlaskit/tokens": "^4.5.0",
50
50
  "@babel/runtime": "^7.0.0",
51
51
  "@typescript-eslint/utils": "^7.1.0",
52
52
  "ajv": "^6.12.6",