@adyen/eslint-plugin-bento 2.22.0 → 2.24.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 (85) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +31 -15
  3. package/configs/vue-recommended.js +16 -0
  4. package/configs/vue-strict.js +17 -1
  5. package/index.js +3 -0
  6. package/package.json +3 -3
  7. package/rules/deprecation-bento-tag-variant-enum/README.md +69 -0
  8. package/rules/deprecation-bento-tag-variant-enum/deprecation-bento-tag-variant-enum.js +167 -0
  9. package/rules/deprecation-filter-bar-deprecated-props/README.md +7 -0
  10. package/rules/deprecation-filter-bar-deprecated-props/deprecation-filter-bar-deprecated-props.js +14 -3
  11. package/rules/vue-no-redundant-dialog-v-if/README.md +55 -0
  12. package/rules/vue-no-redundant-dialog-v-if/vue-no-redundant-dialog-v-if.js +150 -0
  13. package/rules/vue-no-use-bento-translation-overrides/README.md +14 -0
  14. package/rules/vue-no-use-bento-translation-overrides/vue-no-use-bento-translation-overrides.js +93 -0
  15. package/utils/component-slot-migration.js +22 -4
  16. package/rules/deprecation-bento-data-grid-cell-action-menu-item-handler/__tests__/deprecation-bento-data-grid-cell-action-menu-item-handler.vue +0 -63
  17. package/rules/deprecation-bento-data-grid-cell-action-menu-item-handler/__tests__/eslint.config.js +0 -26
  18. package/rules/deprecation-bento-data-grid-cell-action-menu-item-handler/deprecation-bento-data-grid-cell-action-menu-item-handler.integration.test.ts +0 -24
  19. package/rules/deprecation-bento-data-grid-cell-action-menu-item-handler/deprecation-bento-data-grid-cell-action-menu-item-handler.test.ts +0 -116
  20. package/rules/deprecation-bento-date-range-picker-has-actions-prop/__tests__/deprecation-bento-date-range-picker-has-actions-prop.vue +0 -10
  21. package/rules/deprecation-bento-date-range-picker-has-actions-prop/__tests__/eslint.config.js +0 -29
  22. package/rules/deprecation-bento-date-range-picker-has-actions-prop/__tests__/remove/deprecation-bento-date-range-picker-has-actions-prop.vue +0 -11
  23. package/rules/deprecation-bento-date-range-picker-has-actions-prop/__tests__/remove/eslint.config.js +0 -29
  24. package/rules/deprecation-bento-date-range-picker-has-actions-prop/deprecation-bento-date-range-picker-has-actions-prop.integration.test.ts +0 -47
  25. package/rules/deprecation-bento-date-range-picker-has-actions-prop/deprecation-bento-date-range-picker-has-actions-prop.test.ts +0 -176
  26. package/rules/deprecation-bento-dropdown-size-prop/__tests__/deprecation-bento-dropdown-size-prop.vue +0 -9
  27. package/rules/deprecation-bento-dropdown-size-prop/__tests__/eslint.config.js +0 -26
  28. package/rules/deprecation-bento-dropdown-size-prop/deprecation-bento-dropdown-size-prop.integration.test.ts +0 -33
  29. package/rules/deprecation-bento-dropdown-size-prop/deprecation-bento-dropdown-size-prop.test.ts +0 -101
  30. package/rules/deprecation-bento-popover-modifiers-prop/__tests__/deprecation-bento-popover-modifiers-prop.vue +0 -9
  31. package/rules/deprecation-bento-popover-modifiers-prop/__tests__/eslint.config.js +0 -26
  32. package/rules/deprecation-bento-popover-modifiers-prop/deprecation-bento-popover-modifiers-prop.integration.test.ts +0 -24
  33. package/rules/deprecation-bento-popover-modifiers-prop/deprecation-bento-popover-modifiers-prop.test.ts +0 -109
  34. package/rules/deprecation-bento-timeline-item-variant-prop/__tests__/deprecation-bento-timeline-item-variant-prop.vue +0 -9
  35. package/rules/deprecation-bento-timeline-item-variant-prop/__tests__/eslint.config.js +0 -26
  36. package/rules/deprecation-bento-timeline-item-variant-prop/deprecation-bento-timeline-item-variant-prop.integration.test.ts +0 -35
  37. package/rules/deprecation-bento-timeline-item-variant-prop/deprecation-bento-timeline-item-variant-prop.test.ts +0 -141
  38. package/rules/deprecation-components-aria-label-prop/__tests__/deprecation-components-aria-label-prop.vue +0 -25
  39. package/rules/deprecation-components-aria-label-prop/__tests__/eslint.config.js +0 -26
  40. package/rules/deprecation-components-aria-label-prop/deprecation-components-aria-label-prop.integration.test.ts +0 -36
  41. package/rules/deprecation-components-aria-label-prop/deprecation-components-aria-label-prop.test.ts +0 -194
  42. package/rules/deprecation-components-error-prop/__tests__/deprecation-components-error-prop.vue +0 -17
  43. package/rules/deprecation-components-error-prop/__tests__/eslint.config.js +0 -26
  44. package/rules/deprecation-components-error-prop/deprecation-components-error-prop.integration.test.ts +0 -41
  45. package/rules/deprecation-components-error-prop/deprecation-components-error-prop.test.ts +0 -153
  46. package/rules/deprecation-components-has-error-prop/__tests__/deprecation-components-has-error-prop.vue +0 -13
  47. package/rules/deprecation-components-has-error-prop/__tests__/eslint.config.js +0 -26
  48. package/rules/deprecation-components-has-error-prop/deprecation-components-has-error-prop.integration.test.ts +0 -37
  49. package/rules/deprecation-components-has-error-prop/deprecation-components-has-error-prop.test.ts +0 -122
  50. package/rules/deprecation-components-input-emit/__tests__/deprecation-components-input-emit.vue +0 -22
  51. package/rules/deprecation-components-input-emit/__tests__/eslint.config.js +0 -25
  52. package/rules/deprecation-components-input-emit/deprecation-components-input-emit.integration.test.ts +0 -43
  53. package/rules/deprecation-components-input-emit/deprecation-components-input-emit.test.ts +0 -320
  54. package/rules/deprecation-components-value-prop/__tests__/deprecation-components-value-prop.vue +0 -69
  55. package/rules/deprecation-components-value-prop/__tests__/eslint.config.js +0 -25
  56. package/rules/deprecation-components-value-prop/deprecation-components-value-prop.integration.test.ts +0 -37
  57. package/rules/deprecation-components-value-prop/deprecation-components-value-prop.test.ts +0 -480
  58. package/rules/deprecation-country-custom-usage/__tests__/deprecation-country-custom-usage.vue +0 -93
  59. package/rules/deprecation-country-custom-usage/__tests__/eslint.config.js +0 -25
  60. package/rules/deprecation-country-custom-usage/deprecation-country-custom-usage.integration.test.ts +0 -22
  61. package/rules/deprecation-country-custom-usage/deprecation-country-custom-usage.test.ts +0 -380
  62. package/rules/deprecation-currency-default-slot/__tests__/deprecation-currency-default-slot.vue +0 -7
  63. package/rules/deprecation-currency-default-slot/__tests__/eslint.config.js +0 -24
  64. package/rules/deprecation-currency-default-slot/deprecation-currency-default-slot.integration.test.ts +0 -29
  65. package/rules/deprecation-currency-default-slot/deprecation-currency-default-slot.test.ts +0 -136
  66. package/rules/deprecation-filter-bar-deprecated-props/__tests__/deprecation-filter-bar-deprecated-props.vue +0 -62
  67. package/rules/deprecation-filter-bar-deprecated-props/__tests__/eslint.config.js +0 -25
  68. package/rules/deprecation-filter-bar-deprecated-props/deprecation-filter-bar-deprecated-props.integration.test.ts +0 -22
  69. package/rules/deprecation-filter-bar-deprecated-props/deprecation-filter-bar-deprecated-props.test.ts +0 -467
  70. package/rules/deprecation-input-filter-dropdown-options/__tests__/deprecation-input-filter-dropdown-options.vue +0 -46
  71. package/rules/deprecation-input-filter-dropdown-options/__tests__/eslint.config.js +0 -26
  72. package/rules/deprecation-input-filter-dropdown-options/deprecation-input-filter-dropdown-options.integration.test.ts +0 -27
  73. package/rules/deprecation-input-filter-dropdown-options/deprecation-input-filter-dropdown-options.test.ts +0 -392
  74. package/rules/deprecation-tag-default-slot/__tests__/deprecation-tag-default-slot.vue +0 -5
  75. package/rules/deprecation-tag-default-slot/__tests__/eslint.config.js +0 -24
  76. package/rules/deprecation-tag-default-slot/deprecation-tag-default-slot.integration.test.ts +0 -29
  77. package/rules/deprecation-tag-default-slot/deprecation-tag-default-slot.test.ts +0 -145
  78. package/rules/tailwind-v3-to-bento/__tests__/eslint.config.js +0 -24
  79. package/rules/tailwind-v3-to-bento/__tests__/tailwind-v3-to-bento.vue +0 -15
  80. package/rules/tailwind-v3-to-bento/tailwind-v3-to-bento.integration.test.ts +0 -29
  81. package/rules/tailwind-v3-to-bento/tailwind-v3-to-bento.test.ts +0 -403
  82. package/rules/vue-old-spacer-tokens/__tests__/eslint.config.js +0 -24
  83. package/rules/vue-old-spacer-tokens/__tests__/vue-old-spacer-tokens.vue +0 -5
  84. package/rules/vue-old-spacer-tokens/vue-old-spacer-tokens.integration.test.ts +0 -29
  85. package/rules/vue-old-spacer-tokens/vue-old-spacer-tokens.test.ts +0 -77
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.24.0 (2026-09-09)
4
+
5
+ ### Features
6
+
7
+ - added `useBentoTranslationOverrides` composable to override translated strings in vue 3 ([e0cb22fc0](https://github.com/Adyen/bento/commit/e0cb22fc0))
8
+ - added rule to deprecate `bento-tag` white variant ([20867ed09](https://github.com/Adyen/bento/commit/20867ed09))
9
+
10
+ ### Miscellaneous Chores
11
+
12
+ - added `vue-prefer-no-redundant-v-if-for-dialog` eslint rule ([f21cf44a6](https://github.com/Adyen/bento/commit/f21cf44a6))
13
+
14
+ ### ❤️ Thank You
15
+
16
+ - erice
17
+ - gerald
18
+ - mafalda
19
+
20
+
21
+ ## 2.23.0 (2026-08-17)
22
+
23
+ ### Features
24
+
25
+ - updated `deprecation-filter-bar-deprecated-props` rule to check also for configs with enums ([5259ab283](https://github.com/Adyen/bento/commit/5259ab283))
26
+
27
+ ### Miscellaneous Chores
28
+
29
+ - enabled strict `@adyen/eslint-plugin-bento` plugin ESLint rules to enforce deprecations ([974a8e49e](https://github.com/Adyen/bento/commit/974a8e49e))
30
+
31
+ ### ❤️ Thank You
32
+
33
+ - daver
34
+
35
+
3
36
  ## 2.22.0 (2026-07-29)
4
37
 
5
38
  ### Bug Fixes
package/README.md CHANGED
@@ -19,7 +19,7 @@ npm install --save-dev eslint@9 vue-eslint-parser@10 @adyen/eslint-plugin-bento@
19
19
 
20
20
  ### Flat config recommended (`eslint.config.js`)
21
21
 
22
- All rules are set to `warn`
22
+ Deprecation rules are set to `warn`. Restricted APIs remain errors.
23
23
 
24
24
  ```javascript
25
25
  const { defineConfig } = require('eslint/config');
@@ -97,6 +97,12 @@ module.exports = defineConfig([
97
97
 
98
98
  ## Rules
99
99
 
100
+ ### `@adyen/bento/vue-no-use-bento-translation-overrides`
101
+
102
+ Disallow importing the restricted `useBentoTranslationOverrides` composable without approval from the Bento team. This
103
+ API is only intended for teams building SDKs or component libraries for external customers and must not be used in Adyen
104
+ products.
105
+
100
106
  ### `@adyen/bento/vue-old-spacer-tokens`
101
107
 
102
108
  Disallow the use of ADL space utility classes in favor of Bento _spacer_ utility classes.
@@ -109,6 +115,12 @@ Disallow the use of the `default` slot in `bento-currency` instances.
109
115
 
110
116
  Disallow the use of the `default` slot in `bento-tag` instances.
111
117
 
118
+ ### `@adyen/bento/vue-no-redundant-dialog-v-if`
119
+
120
+ Disallow a `v-if` that duplicates the `is-open` binding on `bento-modal`, `bento-modal-fullscreen` and
121
+ `bento-sidepanel`. These components render a native `<dialog>`, so the `v-if` only unmounts them before their closing
122
+ animation can run. Reported with an IDE suggestion to remove the directive, not an autofix.
123
+
112
124
  ### `@adyen/bento/tailwind-v3-to-bento`
113
125
 
114
126
  Replace Tailwind CSS v3 utility classes with Bento design token equivalents. Covers spacing, border radius, border
@@ -119,23 +131,27 @@ warning — use the `bento-typography` component instead.
119
131
 
120
132
  ### Recommended (`vue-recommended`)
121
133
 
122
- | Rule | Severity |
123
- | ------------------------------------------------ | -------- |
124
- | `@adyen/bento/deprecation-components-input-emit` | `warn` |
125
- | `@adyen/bento/deprecation-components-value-prop` | `warn` |
126
- | `@adyen/bento/deprecation-currency-default-slot` | `warn` |
127
- | `@adyen/bento/deprecation-tag-default-slot` | `warn` |
128
- | `@adyen/bento/vue-old-spacer-tokens` | `warn` |
134
+ | Rule | Severity |
135
+ | ----------------------------------------------------- | -------- |
136
+ | `@adyen/bento/deprecation-components-input-emit` | `warn` |
137
+ | `@adyen/bento/deprecation-components-value-prop` | `warn` |
138
+ | `@adyen/bento/deprecation-currency-default-slot` | `warn` |
139
+ | `@adyen/bento/deprecation-tag-default-slot` | `warn` |
140
+ | `@adyen/bento/vue-no-use-bento-translation-overrides` | `error` |
141
+ | `@adyen/bento/vue-no-redundant-dialog-v-if` | `warn` |
142
+ | `@adyen/bento/vue-old-spacer-tokens` | `warn` |
129
143
 
130
144
  ### Strict (`vue-strict`)
131
145
 
132
- | Rule | Severity |
133
- | ------------------------------------------------ | -------- |
134
- | `@adyen/bento/deprecation-components-input-emit` | `error` |
135
- | `@adyen/bento/deprecation-components-value-prop` | `error` |
136
- | `@adyen/bento/deprecation-currency-default-slot` | `error` |
137
- | `@adyen/bento/deprecation-tag-default-slot` | `error` |
138
- | `@adyen/bento/vue-old-spacer-tokens` | `error` |
146
+ | Rule | Severity |
147
+ | ----------------------------------------------------- | -------- |
148
+ | `@adyen/bento/deprecation-components-input-emit` | `error` |
149
+ | `@adyen/bento/deprecation-components-value-prop` | `error` |
150
+ | `@adyen/bento/deprecation-currency-default-slot` | `error` |
151
+ | `@adyen/bento/deprecation-tag-default-slot` | `error` |
152
+ | `@adyen/bento/vue-no-use-bento-translation-overrides` | `error` |
153
+ | `@adyen/bento/vue-no-redundant-dialog-v-if` | `error` |
154
+ | `@adyen/bento/vue-old-spacer-tokens` | `error` |
139
155
 
140
156
  ### Tailwind (`tailwind`)
141
157
 
@@ -1,4 +1,17 @@
1
+ /** @type {import('eslint').Linter.Config[]} */
1
2
  module.exports = [
3
+ {
4
+ name: '@bento/adyen/recommended-restricted-apis',
5
+ files: ['*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}', '**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}'],
6
+ plugins: {
7
+ get '@adyen/bento'() {
8
+ return require('../index');
9
+ },
10
+ },
11
+ rules: {
12
+ '@adyen/bento/vue-no-use-bento-translation-overrides': 'error',
13
+ },
14
+ },
2
15
  {
3
16
  name: '@bento/adyen/recommended',
4
17
  files: ['*.vue', '**/*.vue'],
@@ -11,6 +24,7 @@ module.exports = [
11
24
  },
12
25
  },
13
26
  rules: {
27
+ '@adyen/bento/deprecation-bento-tag-variant-enum': 'warn',
14
28
  '@adyen/bento/deprecation-bento-data-grid-cell-action-menu-item-handler': 'warn',
15
29
  '@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop': 'warn',
16
30
  '@adyen/bento/deprecation-input-filter-dropdown-options': 'warn',
@@ -26,6 +40,8 @@ module.exports = [
26
40
  '@adyen/bento/deprecation-components-value-prop': 'warn',
27
41
  '@adyen/bento/deprecation-currency-default-slot': 'warn',
28
42
  '@adyen/bento/deprecation-tag-default-slot': 'warn',
43
+ '@adyen/bento/vue-no-use-bento-translation-overrides': 'error',
44
+ '@adyen/bento/vue-no-redundant-dialog-v-if': 'warn',
29
45
  '@adyen/bento/vue-old-spacer-tokens': 'warn',
30
46
  },
31
47
  },
@@ -1,4 +1,17 @@
1
+ /** @type {import('eslint').Linter.Config[]} */
1
2
  module.exports = [
3
+ {
4
+ name: '@bento/adyen/strict-restricted-apis',
5
+ files: ['*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}', '**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}'],
6
+ plugins: {
7
+ get '@adyen/bento'() {
8
+ return require('../index');
9
+ },
10
+ },
11
+ rules: {
12
+ '@adyen/bento/vue-no-use-bento-translation-overrides': 'error',
13
+ },
14
+ },
2
15
  {
3
16
  name: '@bento/adyen/strict',
4
17
  files: ['*.vue', '**/*.vue'],
@@ -11,8 +24,9 @@ module.exports = [
11
24
  },
12
25
  },
13
26
  rules: {
27
+ '@adyen/bento/deprecation-bento-tag-variant-enum': 'error',
14
28
  '@adyen/bento/deprecation-bento-data-grid-cell-action-menu-item-handler': 'error',
15
- '@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop': 'error',
29
+ '@adyen/bento/deprecation-bento-date-range-picker-has-actions-prop': ['error', { action: 'remove' }],
16
30
  '@adyen/bento/deprecation-input-filter-dropdown-options': 'error',
17
31
  '@adyen/bento/deprecation-bento-dropdown-size-prop': 'error',
18
32
  '@adyen/bento/deprecation-bento-timeline-item-variant-prop': 'error',
@@ -26,6 +40,8 @@ module.exports = [
26
40
  '@adyen/bento/deprecation-components-value-prop': 'error',
27
41
  '@adyen/bento/deprecation-currency-default-slot': 'error',
28
42
  '@adyen/bento/deprecation-tag-default-slot': 'error',
43
+ '@adyen/bento/vue-no-use-bento-translation-overrides': 'error',
44
+ '@adyen/bento/vue-no-redundant-dialog-v-if': 'error',
29
45
  '@adyen/bento/vue-old-spacer-tokens': 'error',
30
46
  },
31
47
  },
package/index.js CHANGED
@@ -12,6 +12,7 @@ const plugin = {
12
12
  tailwind: require('./configs/tailwind'),
13
13
  },
14
14
  rules: {
15
+ 'deprecation-bento-tag-variant-enum': require('./rules/deprecation-bento-tag-variant-enum/deprecation-bento-tag-variant-enum'),
15
16
  'deprecation-bento-data-grid-cell-action-menu-item-handler': require('./rules/deprecation-bento-data-grid-cell-action-menu-item-handler/deprecation-bento-data-grid-cell-action-menu-item-handler'),
16
17
  'deprecation-bento-date-range-picker-has-actions-prop': require('./rules/deprecation-bento-date-range-picker-has-actions-prop/deprecation-bento-date-range-picker-has-actions-prop'),
17
18
  'deprecation-input-filter-dropdown-options': require('./rules/deprecation-input-filter-dropdown-options/deprecation-input-filter-dropdown-options'),
@@ -27,6 +28,8 @@ const plugin = {
27
28
  'deprecation-components-value-prop': require('./rules/deprecation-components-value-prop/deprecation-components-value-prop'),
28
29
  'deprecation-currency-default-slot': require('./rules/deprecation-currency-default-slot/deprecation-currency-default-slot'),
29
30
  'deprecation-tag-default-slot': require('./rules/deprecation-tag-default-slot/deprecation-tag-default-slot'),
31
+ 'vue-no-use-bento-translation-overrides': require('./rules/vue-no-use-bento-translation-overrides/vue-no-use-bento-translation-overrides'),
32
+ 'vue-no-redundant-dialog-v-if': require('./rules/vue-no-redundant-dialog-v-if/vue-no-redundant-dialog-v-if'),
30
33
  'vue-old-spacer-tokens': require('./rules/vue-old-spacer-tokens/vue-old-spacer-tokens'),
31
34
  'tailwind-v3-to-bento': require('./rules/tailwind-v3-to-bento/tailwind-v3-to-bento'),
32
35
  },
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.24.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",
@@ -0,0 +1,69 @@
1
+ # deprecation-bento-tag-variant-enum
2
+
3
+ ## Description
4
+
5
+ The white `bento-tag` variant and the `BentoTagVariant.WHITE` enum member are deprecated. Use the `grey` variant or the
6
+ `'grey'` string literal instead.
7
+
8
+ ## Rule details
9
+
10
+ The rule reports and can autofix the following usages:
11
+
12
+ - `BentoTagVariant.WHITE` in scripts and template expressions.
13
+ - Static `variant="white"` attributes on `bento-tag` and `BentoTag`.
14
+ - Named bindings such as `:variant="'white'"` and `v-bind:variant="'white'"`.
15
+ - Object bindings such as `v-bind="{ variant: 'white' }"`.
16
+ - `BentoTagProps` object literals whose `variant` is `'white'` or `BentoTagVariant.WHITE`.
17
+
18
+ The rule does not report `variant="white"` on unrelated components or other `BentoTagVariant` members. Values that can
19
+ only be determined at runtime cannot be safely autofixed.
20
+
21
+ ## Incorrect
22
+
23
+ ```vue
24
+ <template>
25
+ <bento-tag variant="white" />
26
+ <bento-tag :variant="'white'" />
27
+ <bento-tag v-bind="{ variant: 'white' }" />
28
+ <bento-tag :variant="BentoTagVariant.WHITE" />
29
+ </template>
30
+
31
+ <script setup lang="ts">
32
+ import { type BentoTagProps, BentoTagVariant } from '@adyen/bento-vue2';
33
+
34
+ const tagProps: BentoTagProps = { variant: 'white' };
35
+ const enumTagProps: BentoTagProps = { variant: BentoTagVariant.WHITE };
36
+ </script>
37
+ ```
38
+
39
+ ## Correct
40
+
41
+ ```vue
42
+ <template>
43
+ <bento-tag variant="grey" />
44
+ <bento-tag :variant="'grey'" />
45
+ <bento-tag v-bind="{ variant: 'grey' }" />
46
+ </template>
47
+
48
+ <script setup lang="ts">
49
+ import type { BentoTagProps } from '@adyen/bento-vue2';
50
+
51
+ const tagProps: BentoTagProps = { variant: 'grey' };
52
+ </script>
53
+ ```
54
+
55
+ ## Configuration
56
+
57
+ The rule is enabled as a warning in the recommended Bento Vue config and as an error in the strict config.
58
+
59
+ To enable autofix explicitly:
60
+
61
+ ```javascript
62
+ export default [
63
+ {
64
+ rules: {
65
+ '@adyen/bento/deprecation-bento-tag-variant-enum': ['warn', { autofix: true }],
66
+ },
67
+ },
68
+ ];
69
+ ```
@@ -0,0 +1,167 @@
1
+ /**
2
+ * @typedef {import('eslint').Rule.RuleContext} RuleContext
3
+ */
4
+ /**
5
+ * @typedef {import('eslint-plugin-vue/lib/utils').RuleModule} RuleModule
6
+ */
7
+
8
+ const VueUtils = require('eslint-plugin-vue/lib/utils');
9
+
10
+ const findWhiteVariantProperty = properties =>
11
+ properties.find(
12
+ property =>
13
+ property.type === 'Property' &&
14
+ !property.computed &&
15
+ ((property.key.type === 'Identifier' && property.key.name === 'variant') ||
16
+ (property.key.type === 'Literal' && property.key.value === 'variant')) &&
17
+ property.value.type === 'Literal' &&
18
+ property.value.value === 'white'
19
+ );
20
+
21
+ /** @type {RuleModule} */
22
+ module.exports = {
23
+ meta: {
24
+ type: 'suggestion',
25
+ docs: {
26
+ description: 'Deprecates the white bento-tag variant and BentoTagVariant.WHITE',
27
+ category: 'Deprecations',
28
+ url: 'https://github.com/Adyen/bento/blob/main/packages/eslint/rules/deprecation-bento-tag-variant-enum/README.md',
29
+ recommended: true,
30
+ },
31
+ messages: {
32
+ deprecationWithReplacement: `The "{{name}}" enum member is deprecated. Please use "{{replacement}}" instead.`,
33
+ whiteVariant: `The "white" bento-tag variant is deprecated. Please use "grey" instead.`,
34
+ },
35
+ fixable: 'code',
36
+ schema: [
37
+ {
38
+ type: 'object',
39
+ properties: {
40
+ autofix: {
41
+ type: 'boolean',
42
+ default: false,
43
+ },
44
+ },
45
+ additionalProperties: false,
46
+ },
47
+ ],
48
+ },
49
+
50
+ /** @param {RuleContext} context */
51
+ create(context) {
52
+ const options = context.options[0] || {};
53
+ const autofix = options.autofix === true;
54
+
55
+ const REPLACEMENT_MAP = {
56
+ WHITE: "'grey'",
57
+ };
58
+
59
+ const enumName = 'BentoTagVariant';
60
+
61
+ const visitor = {
62
+ [`MemberExpression[object.name="${enumName}"]`](node) {
63
+ if (node.computed && node.property.type !== 'Literal') {
64
+ return;
65
+ }
66
+
67
+ const memberName = node.computed ? node.property.value : node.property.name;
68
+ const replacement = REPLACEMENT_MAP[memberName];
69
+ if (replacement) {
70
+ context.report({
71
+ node,
72
+ messageId: 'deprecationWithReplacement',
73
+ data: { name: `${enumName}.${memberName}`, replacement },
74
+ ...(autofix && {
75
+ fix(fixer) {
76
+ return fixer.replaceText(node, replacement);
77
+ },
78
+ }),
79
+ });
80
+ }
81
+ },
82
+ VariableDeclarator(node) {
83
+ const typeName = node.id?.typeAnnotation?.typeAnnotation?.typeName;
84
+ if (
85
+ typeName?.type !== 'Identifier' ||
86
+ typeName.name !== 'BentoTagProps' ||
87
+ node.init?.type !== 'ObjectExpression'
88
+ ) {
89
+ return;
90
+ }
91
+
92
+ const variantProperty = findWhiteVariantProperty(node.init.properties);
93
+ if (variantProperty?.type !== 'Property') {
94
+ return;
95
+ }
96
+
97
+ context.report({
98
+ node: variantProperty.value,
99
+ messageId: 'whiteVariant',
100
+ ...(autofix && {
101
+ fix(fixer) {
102
+ return fixer.replaceText(variantProperty.value, "'grey'");
103
+ },
104
+ }),
105
+ });
106
+ },
107
+ [`VElement:matches([name="bento-tag"], [name="BentoTag"]) > VStartTag > VAttribute[directive=false][key.name="variant"]`](
108
+ node
109
+ ) {
110
+ if (node.value?.value !== 'white') {
111
+ return;
112
+ }
113
+
114
+ context.report({
115
+ node,
116
+ messageId: 'whiteVariant',
117
+ ...(autofix && {
118
+ fix(fixer) {
119
+ return fixer.replaceText(node, 'variant="grey"');
120
+ },
121
+ }),
122
+ });
123
+ },
124
+ [`VElement:matches([name="bento-tag"], [name="BentoTag"]) > VStartTag > VAttribute[directive=true][key.name.name="bind"][key.argument.name="variant"]`](
125
+ node
126
+ ) {
127
+ const expression = node.value?.expression;
128
+ if (expression?.type !== 'Literal' || expression.value !== 'white') {
129
+ return;
130
+ }
131
+
132
+ context.report({
133
+ node,
134
+ messageId: 'whiteVariant',
135
+ ...(autofix && {
136
+ fix(fixer) {
137
+ return fixer.replaceText(expression, "'grey'");
138
+ },
139
+ }),
140
+ });
141
+ },
142
+ [`VElement:matches([name="bento-tag"], [name="BentoTag"]) > VStartTag > VAttribute[directive=true][key.name.name="bind"]`](
143
+ node
144
+ ) {
145
+ if (node.key.argument || node.value?.expression?.type !== 'ObjectExpression') {
146
+ return;
147
+ }
148
+
149
+ const variantProperty = findWhiteVariantProperty(node.value.expression.properties);
150
+ if (variantProperty?.type !== 'Property') {
151
+ return;
152
+ }
153
+
154
+ context.report({
155
+ node: variantProperty.value,
156
+ messageId: 'whiteVariant',
157
+ ...(autofix && {
158
+ fix(fixer) {
159
+ return fixer.replaceText(variantProperty.value, "'grey'");
160
+ },
161
+ }),
162
+ });
163
+ },
164
+ };
165
+ return VueUtils.defineTemplateBodyVisitor(context, visitor, visitor);
166
+ },
167
+ };
@@ -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
  }
@@ -0,0 +1,55 @@
1
+ # @adyen/bento/vue-no-redundant-dialog-v-if
2
+
3
+ > Disallow a redundant `v-if` next to `is-open` on components rendering a native dialog
4
+
5
+ - This rule is included in the `vue-recommended` (`warn`) and `vue-strict` (`error`) configurations
6
+ - 💡 This rule provides an IDE suggestion (not an autofix), so `--fix` leaves the code untouched
7
+
8
+ The following components render a native HTML `<dialog>` element:
9
+
10
+ - `bento-modal`
11
+ - `bento-modal-fullscreen`
12
+ - `bento-sidepanel`
13
+
14
+ A closed `<dialog>` is hidden by the browser and its content is not rendered, so `is-open` alone is enough to control
15
+ visibility. Pairing it with a `v-if` on the same value unmounts the component the moment it closes, which cancels the
16
+ closing animation.
17
+
18
+ This rule only reports a `v-if` whose expression is identical to the `is-open` binding, because that is the only case
19
+ where removing the directive provably keeps the same behaviour. A `v-if` driven by another condition (for example
20
+ `v-if="hasPermission"`) is left alone, as is an element whose `v-if` is followed by a `v-else` or `v-else-if` branch.
21
+
22
+ ## ✗ BAD
23
+
24
+ <!-- prettier-ignore -->
25
+ ```html
26
+ <template>
27
+ <bento-modal v-if="isOpen" :is-open="isOpen" />
28
+
29
+ <bento-modal-fullscreen v-if="isOpen" :is-open="isOpen" />
30
+
31
+ <bento-sidepanel v-if="isOpen" :is-open="isOpen" />
32
+ </template>
33
+ ```
34
+
35
+ ## ✓ Good
36
+
37
+ <!-- prettier-ignore -->
38
+ ```html
39
+ <template>
40
+ <bento-modal :is-open="isOpen" />
41
+
42
+ <bento-modal-fullscreen :is-open="isOpen" />
43
+
44
+ <bento-sidepanel :is-open="isOpen" />
45
+ </template>
46
+ ```
47
+
48
+ A `v-if` on an unrelated condition is still valid, since it does not duplicate `is-open`:
49
+
50
+ <!-- prettier-ignore -->
51
+ ```html
52
+ <template>
53
+ <bento-modal v-if="hasPermission" :is-open="isOpen" />
54
+ </template>
55
+ ```