@adyen/eslint-plugin-bento 2.22.0 → 2.23.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,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.23.0 (2026-08-17)
4
+
5
+ ### Features
6
+
7
+ - updated `deprecation-filter-bar-deprecated-props` rule to check also for configs with enums ([5259ab283](https://github.com/Adyen/bento/commit/5259ab283))
8
+
9
+ ### Miscellaneous Chores
10
+
11
+ - enabled strict `@adyen/eslint-plugin-bento` plugin ESLint rules to enforce deprecations ([974a8e49e](https://github.com/Adyen/bento/commit/974a8e49e))
12
+
13
+ ### ❤️ Thank You
14
+
15
+ - daver
16
+
17
+
3
18
  ## 2.22.0 (2026-07-29)
4
19
 
5
20
  ### Bug Fixes
@@ -1,3 +1,4 @@
1
+ /** @type {import('eslint').Linter.Config[]} */
1
2
  module.exports = [
2
3
  {
3
4
  name: '@bento/adyen/recommended',
@@ -1,3 +1,4 @@
1
+ /** @type {import('eslint').Linter.Config[]} */
1
2
  module.exports = [
2
3
  {
3
4
  name: '@bento/adyen/strict',
@@ -12,7 +13,7 @@ module.exports = [
12
13
  },
13
14
  rules: {
14
15
  '@adyen/bento/deprecation-bento-data-grid-cell-action-menu-item-handler': 'error',
15
- '@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop': 'error',
16
+ '@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop': ['error', { action: 'remove' }],
16
17
  '@adyen/bento/deprecation-input-filter-dropdown-options': 'error',
17
18
  '@adyen/bento/deprecation-bento-dropdown-size-prop': 'error',
18
19
  '@adyen/bento/deprecation-bento-timeline-item-variant-prop': 'error',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adyen/eslint-plugin-bento",
3
- "version": "2.22.0",
3
+ "version": "2.23.0",
4
4
  "description": "Adyen Bento ESLint rules",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -30,8 +30,8 @@
30
30
  "@types/eslint": "9.6.1",
31
31
  "@types/estree": "1.0.6",
32
32
  "@types/node": "24.9.0",
33
- "@typescript-eslint/eslint-plugin": "8.52.0",
34
- "@typescript-eslint/parser": "8.52.0",
33
+ "@typescript-eslint/eslint-plugin": "8.61.0",
34
+ "@typescript-eslint/parser": "8.61.0",
35
35
  "@vitest/eslint-plugin": "1.1.25",
36
36
  "@vitest/coverage-v8": "3.2.6",
37
37
  "eslint": "9.39.0",
@@ -61,4 +61,11 @@ const config = [
61
61
  options: { listboxItems: [] },
62
62
  },
63
63
  ];
64
+
65
+ const values = [
66
+ {
67
+ field: 'status',
68
+ value: 'active',
69
+ },
70
+ ];
64
71
  ```
@@ -20,6 +20,16 @@ function getStaticPropertyName(prop) {
20
20
  return prop.key.type === 'Identifier' ? prop.key.name : prop.key.type === 'Literal' ? String(prop.key.value) : null;
21
21
  }
22
22
 
23
+ function isBentoFilterItemType(node) {
24
+ return (
25
+ node?.type === 'MemberExpression' &&
26
+ !node.computed &&
27
+ node.object.type === 'Identifier' &&
28
+ node.object.name === 'BentoFilterItemType' &&
29
+ node.property.type === 'Identifier'
30
+ );
31
+ }
32
+
23
33
  /** @type {RuleModule} */
24
34
  module.exports = {
25
35
  meta: {
@@ -88,9 +98,10 @@ module.exports = {
88
98
  const filterType = propertyMap.type?.value;
89
99
  const isFilterConfig =
90
100
  propertyMap.field &&
91
- filterType?.type === 'Literal' &&
92
- typeof filterType.value === 'string' &&
93
- filterType.value.endsWith('Filter');
101
+ ((filterType?.type === 'Literal' &&
102
+ typeof filterType.value === 'string' &&
103
+ filterType.value.endsWith('Filter')) ||
104
+ isBentoFilterItemType(filterType));
94
105
  if (!isFilterConfig) {
95
106
  return;
96
107
  }
@@ -133,6 +133,16 @@ describe('@adyen/bento/deprecation-filter-bar-deprecated-props', () => {
133
133
  <template><div /></template>
134
134
  `,
135
135
  },
136
+ {
137
+ name: 'Valid: unrelated enum member with a similar name',
138
+ filename: 'test.vue',
139
+ code: `
140
+ <script setup>
141
+ const config = [{ field: 'name', type: OtherFilterItemType.INPUT, value: 'test' }];
142
+ </script>
143
+ <template><bento-filter-bar :config="config" /></template>
144
+ `,
145
+ },
136
146
  {
137
147
  name: 'Valid: unrelated object with value property (no false positive)',
138
148
  filename: 'test.vue',
@@ -186,6 +196,21 @@ describe('@adyen/bento/deprecation-filter-bar-deprecated-props', () => {
186
196
  `,
187
197
  errors: [{ messageId: 'deprecationConfigValue' }],
188
198
  },
199
+ {
200
+ name: 'Invalid: value property in BentoFilterItemType enum config item',
201
+ filename: 'test.vue',
202
+ code: `
203
+ <script setup>
204
+ const config = [{
205
+ field: 'name',
206
+ type: BentoFilterItemType.INPUT,
207
+ value: 'test',
208
+ }];
209
+ </script>
210
+ <template><bento-filter-bar :config="config" /></template>
211
+ `,
212
+ errors: [{ messageId: 'deprecationConfigValue' }],
213
+ },
189
214
  // "value" inside filter config items (inline template)
190
215
  {
191
216
  name: 'Invalid: value property in filter config item (inline template)',
@@ -42,6 +42,24 @@ describe('@adyen/bento/deprecation-tag-default-slot should suggest the usage of
42
42
  <bento-tag :label="thisIsMyVariableWithText" variant="blue" />
43
43
  `,
44
44
  },
45
+ {
46
+ name: 'BentoTag with named "icon" slot',
47
+ filename: 'test.vue',
48
+ code: `
49
+ <template>
50
+ <bento-tag
51
+ v-if="errorCounter != null"
52
+ class="b-tabs__tab-error-counter"
53
+ variant="red"
54
+ :label="errorCounter"
55
+ >
56
+ <template #icon>
57
+ <cross-circle-fill-icon aria-hidden="true" />
58
+ </template>
59
+ </bento-tag>
60
+ </template>
61
+ `,
62
+ },
45
63
  ],
46
64
  invalid: [
47
65
  {
@@ -6,6 +6,7 @@ const j = require('jscodeshift');
6
6
  */
7
7
 
8
8
  /**
9
+ * @typedef {import('vue-eslint-parser').AST.VElement} VElement
9
10
  * @typedef {import('vue-eslint-parser').AST.VText} VText
10
11
  * @typedef {import('vue-eslint-parser').AST.VExpressionContainer} VExpressionContainer
11
12
  */
@@ -26,10 +27,23 @@ module.exports = {
26
27
  */
27
28
  componentSlotMigration({ propertyName, context, template, alwaysExpression = false }) {
28
29
  return node => {
29
- if (!node.children.length) {
30
- return;
30
+ /**
31
+ * @param {VElement | VText | VExpressionContainer} child
32
+ * @returns {boolean}
33
+ */
34
+ function isNamedSlot(child) {
35
+ return (
36
+ child.type === 'VElement' &&
37
+ child.name === 'template' &&
38
+ child.startTag.attributes.some(
39
+ attribute => attribute.directive && attribute.key.name.name === 'slot'
40
+ )
41
+ );
31
42
  }
32
43
 
44
+ // Named slots are not default slot content and should not trigger migration.
45
+ const contentNodes = node.children.filter(child => !isNamedSlot(child));
46
+
33
47
  // Turned true if one of the children is an expression
34
48
  let hasExpression = false;
35
49
 
@@ -72,7 +86,11 @@ module.exports = {
72
86
 
73
87
  // Remove empty nodes
74
88
  /** @type { Array<VText | VExpressionContainer> } */
75
- const filteredNodes = node.children.filter(removeEmptyVTextNodes);
89
+ const filteredNodes = contentNodes.filter(removeEmptyVTextNodes);
90
+
91
+ if (!filteredNodes.length) {
92
+ return;
93
+ }
76
94
 
77
95
  // Get all content and concat
78
96
  const slotContent = (() => {
@@ -80,7 +98,7 @@ module.exports = {
80
98
  return transformNodeToText(filteredNodes[0])?.trim();
81
99
  }
82
100
 
83
- const content = node.children
101
+ const content = contentNodes
84
102
  // eslint-disable-next-line @typescript-eslint/no-shadow
85
103
  .map((/** @type {VText | VExpressionContainer} */ node) => transformNodeToText(node, true))
86
104
  .join('')