eslint-plugin-smarthr 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [1.4.2](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v1.4.1...eslint-plugin-smarthr-v1.4.2) (2025-03-27)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * smarthr-uiのCheckbox,Comboboxに対応する ([#550](https://github.com/kufu/tamatebako/issues/550)) ([3978a12](https://github.com/kufu/tamatebako/commit/3978a120e4be158a4e9bd602bb1055b55600a41b))
11
+
12
+ ## [1.4.1](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v1.4.0...eslint-plugin-smarthr-v1.4.1) (2025-03-25)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * tailwind-variantsでtv以外のimportを行った際、エラーになる問題を修正する ([#536](https://github.com/kufu/tamatebako/issues/536)) ([83efcf6](https://github.com/kufu/tamatebako/commit/83efcf671938ca471265af9c05bd47fbcce55fb9))
18
+
5
19
  ## [1.4.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v1.3.0...eslint-plugin-smarthr-v1.4.0) (2025-03-06)
6
20
 
7
21
 
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "eslint-plugin-smarthr",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "author": "SmartHR",
5
5
  "license": "MIT",
6
6
  "description": "A sharable ESLint plugin for SmartHR",
7
7
  "main": "index.js",
8
8
  "engines": {
9
- "node": ">=20.18.3"
9
+ "node": ">=20.19.0"
10
10
  },
11
11
  "scripts": {
12
12
  "test": "jest"
@@ -37,5 +37,5 @@
37
37
  "eslintplugin",
38
38
  "smarthr"
39
39
  ],
40
- "gitHead": "49a1837e61d27cf7f1476d2026a63164542df55d"
40
+ "gitHead": "63fb01426aa3a021599ac0e224a0f1946ee9081f"
41
41
  }
@@ -6,8 +6,8 @@ const EXPECTED_NAMES = {
6
6
  '(s|S)elect$': 'Select$',
7
7
  'InputFile$': 'InputFile$',
8
8
  'RadioButtonPanel$': 'RadioButtonPanel$',
9
- 'Check(b|B)ox$': 'CheckBox$',
10
- 'Combo(b|B)ox$': 'ComboBox$',
9
+ 'Check(b|B)ox$': 'Checkbox$',
10
+ 'Combo(b|B)ox$': 'Combobox$',
11
11
  '(Date|Wareki)Picker$': '(Date|Wareki)Picker$',
12
12
  'TimePicker$': 'TimePicker$',
13
13
  'DropZone$': 'DropZone$',
@@ -23,11 +23,11 @@ const EXPECTED_NAMES = {
23
23
  '(i|I)nput$': 'Input$',
24
24
  '(t|T)extarea$': 'Textarea$',
25
25
  '(s|S)elect$': 'Select$',
26
- InputFile$: 'InputFile$',
27
- RadioButton$: 'RadioButton$',
28
- RadioButtonPanel$: 'RadioButtonPanel$',
29
- 'Check(b|B)ox$': 'CheckBox$',
30
- 'Combo(b|B)ox$': 'ComboBox$',
26
+ 'InputFile$': 'InputFile$',
27
+ 'RadioButton$': 'RadioButton$',
28
+ 'RadioButtonPanel$': 'RadioButtonPanel$',
29
+ 'Check(b|B)ox$': 'Checkbox$',
30
+ 'Combo(b|B)ox$': 'Combobox$',
31
31
  '(Date|Wareki)Picker$': '(Date|Wareki)Picker$',
32
32
  TimePicker$: 'TimePicker$',
33
33
  DropZone$: 'DropZone$',
@@ -32,7 +32,7 @@
32
32
  <Select />
33
33
  </Section>
34
34
 
35
- // RadioButton, CheckBoxはFieldsetでグルーピングする必要があるためNG
35
+ // RadioButton, CheckboxはFieldsetでグルーピングする必要があるためNG
36
36
  <FormControl title="any heading">
37
37
  <RadioButton>{a.label}</RadioButton>
38
38
  </FormControl>
@@ -40,14 +40,14 @@
40
40
  // FormControlが複数の入力要素を持ってしまっているのでNG
41
41
  <FormControl title="any heading">
42
42
  <Input />
43
- <ComboBox />
43
+ <Combobox />
44
44
  </FormControl>
45
45
 
46
46
 
47
47
  // FormControlがネストしてしまっているのでNG
48
48
  <FormControl>
49
49
  <SubFormControl>
50
- <CheckBox />
50
+ <Checkbox />
51
51
  </SubFormControl>
52
52
  </FormControl>
53
53
 
@@ -97,7 +97,7 @@
97
97
  </FormControl>
98
98
  </Section>
99
99
 
100
- // smarthr-ui/CheckBox はlabelを含むため、なんの入力要素かが単独で伝えられるので
100
+ // smarthr-ui/Checkbox はlabelを含むため、なんの入力要素かが単独で伝えられるので
101
101
  // FormControl・Fieldsetで囲む必要はない (囲んでも問題はない)
102
- <CheckBox />
102
+ <Checkbox />
103
103
  ```
@@ -5,8 +5,8 @@ const EXPECTED_LABELED_INPUT_NAMES = {
5
5
  'RadioButtons$': '(RadioButtons)$',
6
6
  'RadioButtonPanel$': '(RadioButtonPanel)$',
7
7
  'RadioButtonPanels$': '(RadioButtonPanels)$',
8
- 'Check(B|b)ox$': '(CheckBox)$',
9
- 'Check(B|b)ox(e)?s$': '(CheckBoxes)$',
8
+ 'Check(b|B)ox$': '(Checkbox)$',
9
+ 'Check(b|B)ox(e)?s$': '(Checkboxes)$',
10
10
  }
11
11
  const EXPECTED_INPUT_NAMES = {
12
12
  '(I|^i)nput$': '(Input)$',
@@ -14,7 +14,7 @@ const EXPECTED_INPUT_NAMES = {
14
14
  '(T|^t)extarea$': '(Textarea)$',
15
15
  '(S|^s)elect$': '(Select)$',
16
16
  'InputFile$': '(InputFile)$',
17
- 'Combo(b|B)ox$': '(ComboBox)$',
17
+ 'Combo(b|B)ox$': '(Combobox)$',
18
18
  '(Date|Wareki)Picker$': '((Date|Wareki)Picker)$',
19
19
  'TimePicker$': '(TimePicker)$',
20
20
  ...EXPECTED_LABELED_INPUT_NAMES,
@@ -236,7 +236,7 @@ module.exports = {
236
236
  const layoutSectionAttribute = !isSection && name.match(LAYOUT_COMPONENT_REGEX) && openingElement.attributes.find(findAsSectioning)
237
237
 
238
238
  if (isSection || layoutSectionAttribute) {
239
- // HINT: smarthr-ui/CheckBoxはlabelを単独で持つため、FormControl系でラップをする必要はない
239
+ // HINT: smarthr-ui/Checkboxはlabelを単独で持つため、FormControl系でラップをする必要はない
240
240
  // HINT: 擬似的にラベルが設定されている場合、無視する
241
241
  if (!isCheckbox && !isPseudoLabel) {
242
242
  const actualName = isSection ? name : `<${name} ${layoutSectionAttribute.name.name}="${layoutSectionAttribute.value.value}">`
@@ -288,7 +288,7 @@ module.exports = {
288
288
  }
289
289
  }
290
290
  case 'Program': {
291
- // HINT: smarthr-ui/CheckBoxはlabelを単独で持つため、FormControl系でラップをする必要はない
291
+ // HINT: smarthr-ui/Checkboxはlabelを単独で持つため、FormControl系でラップをする必要はない
292
292
  // HINT: 擬似的にラベルが設定されている場合、無視する
293
293
  if (!isCheckbox && !isPseudoLabel) {
294
294
  const isSelect = !isRadio && nodeName.match(SELECT_REGEX)
@@ -5,11 +5,13 @@ const EXPECTED_NAMES = {
5
5
  'SearchInput$': 'SearchInput$',
6
6
  '(t|T)extarea$': 'Textarea$',
7
7
  'FieldSet$': 'FieldSet$',
8
- 'ComboBox$': 'ComboBox$',
8
+ 'Combo(b|B)ox$': 'Combobox$',
9
9
  '(Date|Wareki)Picker$': '(Date|Wareki)Picker$',
10
10
  'TimePicker$': 'TimePicker$',
11
11
  }
12
- const INPUT_TAG_REGEX = /((i|I)nput|(t|T)extarea|FieldSet|ComboBox|(Date|Wareki|Time)Picker)$/
12
+ const INPUT_TAG_REGEX = /((i|I)nput|(t|T)extarea|FieldSet|Combo(b|B)ox|(Date|Wareki|Time)Picker)$/
13
+ const SEARCH_INPUT_REGEX = /SearchInput$/
14
+ const COMBOBOX_REGEX = /Combo(b|B)ox$/
13
15
 
14
16
  /**
15
17
  * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
@@ -25,60 +27,54 @@ module.exports = {
25
27
  JSXOpeningElement: (node) => {
26
28
  const name = node.name.name
27
29
 
28
- if (!name) {
29
- return
30
- }
31
-
32
- if (!name.match(INPUT_TAG_REGEX)) {
33
- return
34
- }
35
-
36
- const placeholder = node.attributes.find((a) => a.name?.name === 'placeholder')
37
-
38
- if (placeholder) {
39
- if (name.match(/SearchInput$/)) {
40
- const tooltipMessage = node.attributes.find((a) => a.name?.name === 'tooltipMessage')
30
+ if (name && INPUT_TAG_REGEX.test(name)) {
31
+ const placeholder = node.attributes.find((a) => a.name?.name === 'placeholder')
41
32
 
42
- if (!tooltipMessage) {
43
- context.report({
44
- node: placeholder,
45
- message: `${name} にはplaceholder属性を単独で利用せず、tooltipMessageオプションのみ、もしくはplaceholderとtooltipMessageの併用を検討してください。 (例: '<${name} tooltipMessage="ヒント" />', '<${name} tooltipMessage={hint} placeholder={hint} />')`,
46
- })
47
- }
48
- } else if (name.match(/ComboBox$/)) {
49
- let defaultItem
50
- let dropdownHelpMessage
33
+ if (placeholder) {
34
+ if (SEARCH_INPUT_REGEX.test(name)) {
35
+ const tooltipMessage = node.attributes.find((a) => a.name?.name === 'tooltipMessage')
51
36
 
52
- node.attributes.forEach((a) => {
53
- switch(a.name?.name) {
54
- case 'defaultItem':
55
- defaultItem = a
56
- break
57
- case 'dropdownHelpMessage':
58
- dropdownHelpMessage = a
59
- break
37
+ if (!tooltipMessage) {
38
+ context.report({
39
+ node: placeholder,
40
+ message: `${name} にはplaceholder属性を単独で利用せず、tooltipMessageオプションのみ、もしくはplaceholderとtooltipMessageの併用を検討してください。 (例: '<${name} tooltipMessage="ヒント" />', '<${name} tooltipMessage={hint} placeholder={hint} />')`,
41
+ })
60
42
  }
61
- })
43
+ } else if (COMBOBOX_REGEX.test(name)) {
44
+ let defaultItem
45
+ let dropdownHelpMessage
62
46
 
63
- if (defaultItem) {
64
- context.report({
65
- node: placeholder,
66
- message: `${name} にはdefaultItemが設定されているため、placeholder属性を閲覧出来ません。削除してください。`,
47
+ node.attributes.forEach((a) => {
48
+ switch(a.name?.name) {
49
+ case 'defaultItem':
50
+ defaultItem = a
51
+ break
52
+ case 'dropdownHelpMessage':
53
+ dropdownHelpMessage = a
54
+ break
55
+ }
67
56
  })
68
- } else if (!dropdownHelpMessage) {
69
- context.report({
70
- node: placeholder,
71
- message: `${name} にはplaceholder属性は設定せず、以下のいずれか、もしくは組み合わせての対応を検討してください。
57
+
58
+ if (defaultItem) {
59
+ context.report({
60
+ node: placeholder,
61
+ message: `${name} にはdefaultItemが設定されているため、placeholder属性を閲覧出来ません。削除してください。`,
62
+ })
63
+ } else if (!dropdownHelpMessage) {
64
+ context.report({
65
+ node: placeholder,
66
+ message: `${name} にはplaceholder属性は設定せず、以下のいずれか、もしくは組み合わせての対応を検討してください。
72
67
  - 選択肢をどんな値で絞り込めるかの説明をしたい場合は dropdownHelpMessage 属性に変更してください。
73
68
  - 空の値の説明のためにplaceholderを利用している場合は defaultItem 属性に変更してください。
74
69
  - 上記以外の説明を行いたい場合、ヒント用要素を設置してください。(例: '<div><${name} /><Hint>ヒント</Hint></div>')`,
70
+ })
71
+ }
72
+ } else {
73
+ context.report({
74
+ node: placeholder,
75
+ message: `${name} にはplaceholder属性は設定せず、別途ヒント用要素の利用を検討してください。(例: '<div><${name} /><Hint>ヒント</Hint></div>')`,
75
76
  })
76
77
  }
77
- } else {
78
- context.report({
79
- node: placeholder,
80
- message: `${name} にはplaceholder属性は設定せず、別途ヒント用要素の利用を検討してください。(例: '<div><${name} /><Hint>ヒント</Hint></div>')`,
81
- })
82
78
  }
83
79
  }
84
80
  },
@@ -4,7 +4,7 @@ const TV_COMPONENTS_METHOD = 'tv'
4
4
  const TV_COMPONENTS = 'tailwind-variants'
5
5
  const TV_RESULT_CONST_NAME_REGEX = /(C|c)lassNameGenerator$/
6
6
 
7
- const findValidImportNameNode = (s) => s.type === 'ImportSpecifier' && s.local.name === TV_COMPONENTS_METHOD
7
+ const findValidImportNameNode = (s) => s.type === 'ImportSpecifier' && s.imported.name === TV_COMPONENTS_METHOD && s.local.name !== TV_COMPONENTS_METHOD
8
8
 
9
9
  const checkImportTailwindVariants = (node, context) => {
10
10
  }
@@ -43,7 +43,7 @@ module.exports = {
43
43
  return {
44
44
  ImportDeclaration: (node) => {
45
45
  if (node.source.value === TV_COMPONENTS) {
46
- if (!node.specifiers.some(findValidImportNameNode)) {
46
+ if (node.specifiers.some(findValidImportNameNode)) {
47
47
  context.report({
48
48
  node,
49
49
  message: `${TV_COMPONENTS} をimportする際は、名称が"${TV_COMPONENTS_METHOD}" となるようにしてください。例: "import { ${TV_COMPONENTS_METHOD} } from '${TV_COMPONENTS}'"`,
@@ -27,8 +27,8 @@ ruleTester.run('a11y-input-has-name-attribute', rule, {
27
27
  { code: `import { Select as HogeSelect } from './hoge'` },
28
28
  { code: `import { InputFile as HogeInputFile } from './hoge'` },
29
29
  { code: `import { HogeRadioButton as FugaRadioButton } from './hoge'` },
30
- { code: `import { CheckBox as FugaCheckBox } from './hoge'` },
31
- { code: `import { HogeComboBox as FugaComboBox } from './hoge'` },
30
+ { code: `import { Checkbox as FugaCheckbox } from './hoge'` },
31
+ { code: `import { HogeCombobox as FugaCombobox } from './hoge'` },
32
32
  { code: `import { DatePicker as HogeDatePicker } from './hoge'` },
33
33
  { code: `import { WarekiPicker as HogeWarekiPicker } from './hoge'` },
34
34
  { code: `import { HogeDropZone as HogeFugaDropZone } from './hoge'` },
@@ -62,9 +62,9 @@ ruleTester.run('a11y-input-has-name-attribute', rule, {
62
62
  - InputFileが型の場合、'import type { InputFile as HogeInputFileFuga }' もしくは 'import { type InputFile as HogeInputFileFuga }' のように明示的に型であることを宣言してください。名称変更が不要になります` } ] },
63
63
  { code: `import { HogeRadioButton as FugaRadioButtonAbc } from './hoge'`, errors: [ { message: `FugaRadioButtonAbcを正規表現 "/RadioButton$/" がmatchする名称に変更してください。
64
64
  - HogeRadioButtonが型の場合、'import type { HogeRadioButton as FugaRadioButtonAbc }' もしくは 'import { type HogeRadioButton as FugaRadioButtonAbc }' のように明示的に型であることを宣言してください。名称変更が不要になります` } ] },
65
- { code: `import { CheckBox as FugaCheckBoxHoge } from './hoge'`, errors: [ { message: `FugaCheckBoxHogeを正規表現 "/CheckBox$/" がmatchする名称に変更してください。
65
+ { code: `import { CheckBox as FugaCheckBoxHoge } from './hoge'`, errors: [ { message: `FugaCheckBoxHogeを正規表現 "/Checkbox$/" がmatchする名称に変更してください。
66
66
  - CheckBoxが型の場合、'import type { CheckBox as FugaCheckBoxHoge }' もしくは 'import { type CheckBox as FugaCheckBoxHoge }' のように明示的に型であることを宣言してください。名称変更が不要になります` } ] },
67
- { code: `import { HogeComboBox as ComboBoxFuga } from './hoge'`, errors: [ { message: `ComboBoxFugaを正規表現 "/ComboBox$/" がmatchする名称に変更してください。
67
+ { code: `import { HogeComboBox as ComboBoxFuga } from './hoge'`, errors: [ { message: `ComboBoxFugaを正規表現 "/Combobox$/" がmatchする名称に変更してください。
68
68
  - HogeComboBoxが型の場合、'import type { HogeComboBox as ComboBoxFuga }' もしくは 'import { type HogeComboBox as ComboBoxFuga }' のように明示的に型であることを宣言してください。名称変更が不要になります` } ] },
69
69
  { code: `import { DatePicker as HogeDatePickerFuga } from './hoge'`, errors: [ { message: `HogeDatePickerFugaを正規表現 "/(Date|Wareki)Picker$/" がmatchする名称に変更してください。
70
70
  - DatePickerが型の場合、'import type { DatePicker as HogeDatePickerFuga }' もしくは 'import { type DatePicker as HogeDatePickerFuga }' のように明示的に型であることを宣言してください。名称変更が不要になります` } ] },
@@ -13,13 +13,13 @@ const ruleTester = new RuleTester({
13
13
  const noLabeledInput = (name) => `${name} を、smarthr-ui/FormControl もしくはそれを拡張したコンポーネントが囲むようマークアップを変更してください。
14
14
  - FormControlで入力要素を囲むことでラベルと入力要素が適切に紐づき、操作性が高まります
15
15
  - ${name}が入力要素とラベル・タイトル・説明など含む概念を表示するコンポーネントの場合、コンポーネント名を/((FormGroup)$|(FormControl)$|((F|^f)ieldset)$)/とマッチするように修正してください
16
- - ${name}が入力要素自体を表現するコンポーネントの一部である場合、ルートとなるコンポーネントの名称を/((I|^i)nput$|SearchInput$|(T|^t)extarea$|(S|^s)elect$|InputFile$|Combo(b|B)ox$|(Date|Wareki)Picker$|TimePicker$|RadioButton$|RadioButtons$|RadioButtonPanel$|RadioButtonPanels$|Check(B|b)ox$|Check(B|b)ox(e)?s$)/とマッチするように修正してください
16
+ - ${name}が入力要素自体を表現するコンポーネントの一部である場合、ルートとなるコンポーネントの名称を/((I|^i)nput$|SearchInput$|(T|^t)extarea$|(S|^s)elect$|InputFile$|Combo(b|B)ox$|(Date|Wareki)Picker$|TimePicker$|RadioButton$|RadioButtons$|RadioButtonPanel$|RadioButtonPanels$|Check(b|B)ox$|Check(b|B)ox(e)?s$)/とマッチするように修正してください
17
17
  - 上記のいずれの方法も適切ではない場合、${name}のtitle属性に "どんな値を入力すれば良いのか" の説明を設定してください
18
18
  - 例: <${name} title="姓を全角カタカナのみで入力してください" />`
19
19
  const noLabeledSelect = (name) => `${name} を、smarthr-ui/FormControl もしくはそれを拡張したコンポーネントが囲むようマークアップを変更してください。
20
20
  - FormControlで入力要素を囲むことでラベルと入力要素が適切に紐づき、操作性が高まります
21
21
  - ${name}が入力要素とラベル・タイトル・説明など含む概念を表示するコンポーネントの場合、コンポーネント名を/((FormGroup)$|(FormControl)$|((F|^f)ieldset)$)/とマッチするように修正してください
22
- - ${name}が入力要素自体を表現するコンポーネントの一部である場合、ルートとなるコンポーネントの名称を/((I|^i)nput$|SearchInput$|(T|^t)extarea$|(S|^s)elect$|InputFile$|Combo(b|B)ox$|(Date|Wareki)Picker$|TimePicker$|RadioButton$|RadioButtons$|RadioButtonPanel$|RadioButtonPanels$|Check(B|b)ox$|Check(B|b)ox(e)?s$)/とマッチするように修正してください
22
+ - ${name}が入力要素自体を表現するコンポーネントの一部である場合、ルートとなるコンポーネントの名称を/((I|^i)nput$|SearchInput$|(T|^t)extarea$|(S|^s)elect$|InputFile$|Combo(b|B)ox$|(Date|Wareki)Picker$|TimePicker$|RadioButton$|RadioButtons$|RadioButtonPanel$|RadioButtonPanels$|Check(b|B)ox$|Check(b|B)ox(e)?s$)/とマッチするように修正してください
23
23
  - 上記のいずれの方法も適切ではない場合、${name}のtitle属性に "どんな値を選択すれば良いのか" の説明を設定してください
24
24
  - 例: <${name} title="検索対象を選択してください" />`
25
25
  const invalidPureCheckboxInFormControl = (name) => `HogeFormControl が ${name} を含んでいます。smarthr-ui/FormControl を smarthr-ui/Fieldset に変更し、正しくグルーピングされるように修正してください。
@@ -40,7 +40,7 @@ const noLabeledInputInFieldset = (name) => `HogeFieldset が ラベルを持た
40
40
  - 方法1: HogeFieldset を smarthr-ui/FormControl、もしくはそれを拡張したコンポーネントに変更してください
41
41
  - 方法2: ${name} がlabel要素を含むコンポーネントである場合、名称を/(Form(Control|Group))$/にマッチするものに変更してください
42
42
  - smarthr-ui/FormControl、smarthr-ui/FormGroup はlabel要素を内包しています
43
- - 方法3: ${name} がRadioButton、もしくはCheckboxを表すコンポーネントの場合、名称を/(RadioButton$|RadioButtons$|RadioButtonPanel$|RadioButtonPanels$|Check(B|b)ox$|Check(B|b)ox(e)?s$)/にマッチするものに変更してください
43
+ - 方法3: ${name} がRadioButton、もしくはCheckboxを表すコンポーネントの場合、名称を/(RadioButton$|RadioButtons$|RadioButtonPanel$|RadioButtonPanels$|Check(b|B)ox$|Check(b|B)ox(e)?s$)/にマッチするものに変更してください
44
44
  - smarthr-ui/RadioButton、smarthr-ui/RadioButtonPanel、smarthr-ui/Checkbox はlabel要素を内包しています
45
45
  - 方法4: HogeFieldset が smarthr-ui/Fieldset、もしくはそれを拡張しているコンポーネントではない場合、名称を /Fieldset$/ にマッチしないものに変更してください
46
46
  - 方法5: 別途label要素が存在し、それらと紐づけたい場合はlabel要素のhtmlFor属性、${name}のid属性に同じ文字列を指定してください。この文字列はhtml内で一意である必要があります
@@ -50,7 +50,7 @@ const noLabeledInputInFieldsetWithSelect = (name) => `HogeFieldset が ラベル
50
50
  - 方法1: HogeFieldset を smarthr-ui/FormControl、もしくはそれを拡張したコンポーネントに変更してください
51
51
  - 方法2: ${name} がlabel要素を含むコンポーネントである場合、名称を/(Form(Control|Group))$/にマッチするものに変更してください
52
52
  - smarthr-ui/FormControl、smarthr-ui/FormGroup はlabel要素を内包しています
53
- - 方法3: ${name} がRadioButton、もしくはCheckboxを表すコンポーネントの場合、名称を/(RadioButton$|RadioButtons$|RadioButtonPanel$|RadioButtonPanels$|Check(B|b)ox$|Check(B|b)ox(e)?s$)/にマッチするものに変更してください
53
+ - 方法3: ${name} がRadioButton、もしくはCheckboxを表すコンポーネントの場合、名称を/(RadioButton$|RadioButtons$|RadioButtonPanel$|RadioButtonPanels$|Check(b|B)ox$|Check(b|B)ox(e)?s$)/にマッチするものに変更してください
54
54
  - smarthr-ui/RadioButton、smarthr-ui/RadioButtonPanel、smarthr-ui/Checkbox はlabel要素を内包しています
55
55
  - 方法4: HogeFieldset が smarthr-ui/Fieldset、もしくはそれを拡張しているコンポーネントではない場合、名称を /Fieldset$/ にマッチしないものに変更してください
56
56
  - 方法5: 別途label要素が存在し、それらと紐づけたい場合はlabel要素のhtmlFor属性、${name}のid属性に同じ文字列を指定してください。この文字列はhtml内で一意である必要があります
@@ -74,7 +74,7 @@ const invalidChildreninFormControl = (children) => `FormControl が、${children
74
74
  - FormControlではなく、smarthr-ui/Fieldset、もしくはsmarthr-ui/Section + smarthr-ui/Heading などでのマークアップを検討してください
75
75
  - 方法2: 親要素であるFormControlがsmarthr-ui/FormControlを拡張したコンポーネントではない場合、コンポーネント名を/(Form(Control|Group))$/と一致しない名称に変更してください`
76
76
  const requireMultiInputInFormControlWithRoleGroup = () => `HogeFormControl内に入力要素が2個以上存在しないため、'role=\"group\"'を削除してください。'role=\"group\"'は複数の入力要素を一つのグループとして扱うための属性です。
77
- - HogeFormControl内に2つ以上の入力要素が存在する場合、入力要素を含むコンポーネント名全てを/((I|^i)nput$|SearchInput$|(T|^t)extarea$|(S|^s)elect$|InputFile$|Combo(b|B)ox$|(Date|Wareki)Picker$|TimePicker$|RadioButton$|RadioButtons$|RadioButtonPanel$|RadioButtonPanels$|Check(B|b)ox$|Check(B|b)ox(e)?s$)/、もしくは/((FormGroup)$|(FormControl)$|((F|^f)ieldset)$)/にマッチする名称に変更してください`
77
+ - HogeFormControl内に2つ以上の入力要素が存在する場合、入力要素を含むコンポーネント名全てを/((I|^i)nput$|SearchInput$|(T|^t)extarea$|(S|^s)elect$|InputFile$|Combo(b|B)ox$|(Date|Wareki)Picker$|TimePicker$|RadioButton$|RadioButtons$|RadioButtonPanel$|RadioButtonPanels$|Check(b|B)ox$|Check(b|B)ox(e)?s$)/、もしくは/((FormGroup)$|(FormControl)$|((F|^f)ieldset)$)/にマッチする名称に変更してください`
78
78
 
79
79
  ruleTester.run('a11y-input-in-form-control', rule, {
80
80
  valid: [
@@ -88,7 +88,7 @@ ruleTester.run('a11y-input-in-form-control', rule, {
88
88
  { code: 'const HogeSelect = styled(Select)``' },
89
89
  { code: 'const HogeRadioButton = styled(FugaRadioButton)``' },
90
90
  { code: 'const HogeRadioButtonPanel = styled(FugaRadioButtonPanel)``' },
91
- { code: 'const HogeCheckBox = styled(FugaCheckbox)``' },
91
+ { code: 'const HogeCheckbox = styled(FugaCheckBox)``' },
92
92
  { code: 'const DatePicker = styled(AnyDatePicker)``' },
93
93
  { code: 'const WarekiPicker = styled(AnyWarekiPicker)``' },
94
94
  { code: '<input type="hidden" />' },
@@ -140,7 +140,7 @@ ruleTester.run('a11y-input-in-form-control', rule, {
140
140
  ],
141
141
  invalid: [
142
142
  { code: `import hoge from 'styled-components'`, errors: [ { message: `styled-components をimportする際は、名称が"styled" となるようにしてください。例: "import styled from 'styled-components'"` } ] },
143
- { code: `import { ComboBox as ComboBoxHoge } from './hoge'`, errors: [ { message: `ComboBoxHogeを正規表現 "/(ComboBox)$/" がmatchする名称に変更してください。
143
+ { code: `import { ComboBox as ComboBoxHoge } from './hoge'`, errors: [ { message: `ComboBoxHogeを正規表現 "/(Combobox)$/" がmatchする名称に変更してください。
144
144
  - ComboBoxが型の場合、'import type { ComboBox as ComboBoxHoge }' もしくは 'import { type ComboBox as ComboBoxHoge }' のように明示的に型であることを宣言してください。名称変更が不要になります` } ] },
145
145
  { code: 'const RadioButton = styled(FugaRadioButtonPanel)``', errors: [
146
146
  { message: `RadioButtonを正規表現 "/(RadioButtonPanel)$/" がmatchする名称に変更してください。` },
@@ -157,8 +157,8 @@ ruleTester.run('a11y-input-in-form-control', rule, {
157
157
  { code: '<select />', errors: [ { message: noLabeledSelect('select') } ] },
158
158
  { code: '<HogeSelect />', errors: [ { message: noLabeledSelect('HogeSelect') } ] },
159
159
  { code: '<HogeInputFile />', errors: [ { message: noLabeledInput('HogeInputFile') } ] },
160
- { code: '<HogeComboBox />', errors: [ { message: noLabeledInput('HogeComboBox') } ] },
161
- { code: '<HogeComboBox inputAttributes={{ any }} />', errors: [ { message: noLabeledInput('HogeComboBox') } ] },
160
+ { code: '<HogeCombobox />', errors: [ { message: noLabeledInput('HogeCombobox') } ] },
161
+ { code: '<HogeCombobox inputAttributes={{ any }} />', errors: [ { message: noLabeledInput('HogeCombobox') } ] },
162
162
  { code: '<HogeDatePicker />', errors: [ { message: noLabeledInput('HogeDatePicker') } ] },
163
163
  { code: '<HogeWarekiPicker />', errors: [ { message: noLabeledInput('HogeWarekiPicker') } ] },
164
164
  { code: '<HogeFormControl><Input type="checkbox" /><Input type="checkbox" /></HogeFormControl>', errors: [ { message: invalidPureCheckboxInFormControl('Input') } ] },
@@ -18,7 +18,7 @@ ruleTester.run('a11y-prohibit-input-placeholder', rule, {
18
18
  { code: `import { Input as HogeInput } from './hoge'` },
19
19
  { code: `import { HogeSearchInput as FugaSearchInput } from './hoge'` },
20
20
  { code: `import { HogeTextarea as FugaHogeTextarea } from './hoge'` },
21
- { code: `import { ComboBox as FugaHogeComboBox } from './hoge'` },
21
+ { code: `import { Combobox as FugaHogeCombobox } from './hoge'` },
22
22
  { code: `import { AbcDatePicker as StyledDatePicker } from './hoge'` },
23
23
  { code: `import { AbcWarekiPicker as StyledWarekiPicker } from './hoge'` },
24
24
  { code: 'const HogeInput = styled.input``' },
@@ -28,7 +28,7 @@ ruleTester.run('a11y-prohibit-input-placeholder', rule, {
28
28
  { code: 'const HogeTextarea = styled(Textarea)``' },
29
29
  { code: 'const hoge = styled.fieldset``' },
30
30
  { code: 'const HogeFieldSet = styled(FieldSet)``' },
31
- { code: 'const HogeComboBox = styled(ComboBox)``' },
31
+ { code: 'const HogeCombobox = styled(ComboBox)``' },
32
32
  { code: 'const HogeSearchInput = styled(SearchInput)``' },
33
33
  { code: `<input />` },
34
34
  { code: `<textarea />` },
@@ -57,8 +57,8 @@ ruleTester.run('a11y-prohibit-input-placeholder', rule, {
57
57
  - SearchInputが型の場合、'import type { SearchInput as Hoge }' もしくは 'import { type SearchInput as Hoge }' のように明示的に型であることを宣言してください。名称変更が不要になります` } ] },
58
58
  { code: `import { HogeTextarea as HogeTextareaFuga } from './hoge'`, errors: [ { message: `HogeTextareaFugaを正規表現 "/Textarea$/" がmatchする名称に変更してください。
59
59
  - HogeTextareaが型の場合、'import type { HogeTextarea as HogeTextareaFuga }' もしくは 'import { type HogeTextarea as HogeTextareaFuga }' のように明示的に型であることを宣言してください。名称変更が不要になります` } ] },
60
- { code: `import { HogeComboBox as ComboBoxFuga } from './hoge'`, errors: [ { message: `ComboBoxFugaを正規表現 "/ComboBox$/" がmatchする名称に変更してください。
61
- - HogeComboBoxが型の場合、'import type { HogeComboBox as ComboBoxFuga }' もしくは 'import { type HogeComboBox as ComboBoxFuga }' のように明示的に型であることを宣言してください。名称変更が不要になります` } ] },
60
+ { code: `import { HogeCombobox as ComboboxFuga } from './hoge'`, errors: [ { message: `ComboboxFugaを正規表現 "/Combobox$/" がmatchする名称に変更してください。
61
+ - HogeComboboxが型の場合、'import type { HogeCombobox as ComboboxFuga }' もしくは 'import { type HogeCombobox as ComboboxFuga }' のように明示的に型であることを宣言してください。名称変更が不要になります` } ] },
62
62
  { code: `import { DatePicker as HogeDatePickerFuga } from './hoge'`, errors: [ { message: `HogeDatePickerFugaを正規表現 "/(Date|Wareki)Picker$/" がmatchする名称に変更してください。
63
63
  - DatePickerが型の場合、'import type { DatePicker as HogeDatePickerFuga }' もしくは 'import { type DatePicker as HogeDatePickerFuga }' のように明示的に型であることを宣言してください。名称変更が不要になります` } ] },
64
64
  { code: `import { WarekiPicker as HogeWarekiPickerFuga } from './hoge'`, errors: [ { message: `HogeWarekiPickerFugaを正規表現 "/(Date|Wareki)Picker$/" がmatchする名称に変更してください。
@@ -68,7 +68,7 @@ ruleTester.run('a11y-prohibit-input-placeholder', rule, {
68
68
  { code: 'const Hoge = styled.textarea``', errors: [ { message: `Hogeを正規表現 "/Textarea$/" がmatchする名称に変更してください。` } ] },
69
69
  { code: 'const Hoge = styled(StyledTextarea)``', errors: [ { message: `Hogeを正規表現 "/Textarea$/" がmatchする名称に変更してください。` } ] },
70
70
  { code: 'const Hoge = styled(FieldSet)``', errors: [ { message: `Hogeを正規表現 "/FieldSet$/" がmatchする名称に変更してください。` } ] },
71
- { code: 'const Hoge = styled(ComboBox)``', errors: [ { message: `Hogeを正規表現 "/ComboBox$/" がmatchする名称に変更してください。` } ] },
71
+ { code: 'const Hoge = styled(Combobox)``', errors: [ { message: `Hogeを正規表現 "/Combobox$/" がmatchする名称に変更してください。` } ] },
72
72
  {
73
73
  code: 'const Hoge = styled(SearchInput)``',
74
74
  errors: [
@@ -14,6 +14,7 @@ const ruleTester = new RuleTester({
14
14
  ruleTester.run('best-practice-for-button-element', rule, {
15
15
  valid: [
16
16
  { code: `import { tv } from 'tailwind-variants'` },
17
+ { code: `import { defaultConfig } from 'tailwind-variants'` },
17
18
  { code: `const classNameGenerator = tv()` },
18
19
  { code: `const xxxClassNameGenerator = tv()` },
19
20
  { code: `const hoge = useMemo(() => classNameGenerator(), [])` },