react-input-chips 0.3.4 → 1.0.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/License CHANGED
@@ -1,9 +1,9 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 [B-Meet]
3
+ Copyright (c) 2026 [B-Meet]
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "react-input-chip-beta"), to deal
6
+ of this software and associated documentation files (the "react-input-chips"), to deal
7
7
  in the Software without restriction, including without limitation the rights
8
8
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
9
  copies of the Software, and to permit persons to whom the Software is
package/README.md CHANGED
@@ -28,15 +28,9 @@ Install react-input-chips with npm
28
28
 
29
29
  You just need to import the `<InputChips/>` component in the file you want the **react-input-chip** in and pass the required props that's it. All set!
30
30
 
31
- **One important thing** for the default styling of the `<InputChips/>` is that you need to explicitly add CSS file import in the parent or higher or the same component.
32
- The following is the path to it
33
-
34
- ```bash
35
- import "../node_modules/react-input-chips/dist/index.css";
36
- ```
31
+ **Note:** Styles are now automatically injected, so no need to import the CSS file manually!
37
32
 
38
33
  Hers is the simple plain example
39
-
40
34
  ```javascript
41
35
  import { useState } from "react";
42
36
  import { InputChips } from "react-input-chips";
@@ -112,7 +106,13 @@ I have for you here all the props supported as of now. (\* these are required pr
112
106
  | nextPlaceholder | - | Placeholder after the first chip is created |
113
107
  | removeBtnSvg | is an `SVG` which looks like close/X | You can add any HTML element as of now, but it is better to add an `SVG` element |
114
108
  | chipStyles | - | You add any styles supported by CSS will be added as inline styles for the chip hence, the highest priority is given to your styles |
109
+ | chipClassName | - | Class name for individual chips |
115
110
  | containerStyles | - | You can add the CSS styles for the whole input container itself |
111
+ | containerClassName | - | Class name for the container wrapper |
112
+ | inputStyle | - | Inline styles for the input field |
113
+ | inputClassName | - | Class name for the input field |
114
+ | closeBtnStyle | - | Inline styles for the close button |
115
+ | closeBtnClassName | - | Class name for the close button |
116
116
  | errorMsg | - | It's the error message you want to display and expects a string as its value |
117
117
 
118
118
  keysToTriggerChipConversion - Allowed key codes
package/dist/index.d.ts CHANGED
@@ -16,8 +16,14 @@ interface TInputChips {
16
16
  containerStyles?: React.CSSProperties;
17
17
  backspaceToRemoveChip?: boolean;
18
18
  errorMsg?: string;
19
+ chipClassName?: string;
20
+ inputStyle?: React.CSSProperties;
21
+ inputClassName?: string;
22
+ closeBtnStyle?: React.CSSProperties;
23
+ closeBtnClassName?: string;
24
+ containerClassName?: string;
19
25
  }
20
26
 
21
- declare const InputChips: ({ chips, setChips, inputValue, setInputValue, keysToTriggerChipConversion, validate, disabled, placeholder, nextPlaceholder, removeBtnSvg, chipStyles, containerStyles, backspaceToRemoveChip, errorMsg, }: TInputChips) => react_jsx_runtime.JSX.Element;
27
+ declare const InputChips: ({ chips, setChips, inputValue, setInputValue, keysToTriggerChipConversion, validate, disabled, placeholder, nextPlaceholder, removeBtnSvg, chipStyles, chipClassName, containerStyles, containerClassName, inputStyle, inputClassName, closeBtnStyle, closeBtnClassName, backspaceToRemoveChip, errorMsg, }: TInputChips) => react_jsx_runtime.JSX.Element;
22
28
 
23
29
  export { InputChips };
package/dist/index.js CHANGED
@@ -1,3 +1,31 @@
1
+ // src/components/InputChip.tsx
2
+ import React from "react";
3
+
4
+ // #style-inject:#style-inject
5
+ function styleInject(css, { insertAt } = {}) {
6
+ if (!css || typeof document === "undefined") return;
7
+ const head = document.head || document.getElementsByTagName("head")[0];
8
+ const style = document.createElement("style");
9
+ style.type = "text/css";
10
+ if (insertAt === "top") {
11
+ if (head.firstChild) {
12
+ head.insertBefore(style, head.firstChild);
13
+ } else {
14
+ head.appendChild(style);
15
+ }
16
+ } else {
17
+ head.appendChild(style);
18
+ }
19
+ if (style.styleSheet) {
20
+ style.styleSheet.cssText = css;
21
+ } else {
22
+ style.appendChild(document.createTextNode(css));
23
+ }
24
+ }
25
+
26
+ // src/components/styles.css
27
+ styleInject(".ric-chip-input-wrapper {\n gap: 4px;\n flex: 2;\n padding: 5px;\n overflow: auto;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n border: 1px solid #BBBBBB;\n border-radius: 4px;\n max-width: 650px;\n min-width: 300px;\n transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;\n &.ric-chip-input-wrapper-focus {\n border-color: #4a90e2;\n box-shadow: 0 0 0 1px #4a90e2;\n }\n .ric-chip {\n background: #e5e5e5;\n border-radius: 4px;\n color: #333333;\n display: flex;\n gap: 0.5rem;\n align-items: center;\n justify-content: space-between;\n max-width: max-content;\n padding: 6px;\n }\n .ric-chip-input {\n border: none;\n outline: none;\n flex: 1;\n padding: 0 8px;\n height: 30px;\n }\n .ric-closeBtn {\n outline: none;\n border: none;\n background: none;\n height: 18px;\n width: 18px;\n object-fit: cover;\n cursor: pointer;\n display: grid;\n place-items: center;\n }\n}\n.ric-chip-input-wrapper-error {\n border: 2px solid red;\n}\n.ric-error-msg-wrapper {\n margin: 0;\n font-size: 12px;\n color: red;\n}\n");
28
+
1
29
  // src/components/InputChip.tsx
2
30
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
31
  var InputChips = ({
@@ -12,10 +40,18 @@ var InputChips = ({
12
40
  nextPlaceholder,
13
41
  removeBtnSvg,
14
42
  chipStyles,
43
+ chipClassName,
15
44
  containerStyles,
45
+ containerClassName,
46
+ inputStyle,
47
+ inputClassName,
48
+ closeBtnStyle,
49
+ closeBtnClassName,
16
50
  backspaceToRemoveChip = false,
17
51
  errorMsg
18
52
  }) => {
53
+ const inputRef = React.useRef(null);
54
+ const [isFocused, setIsFocused] = React.useState(false);
19
55
  const handleInputChange = (e) => {
20
56
  const value = e.target.value;
21
57
  if (keysToTriggerChipConversion.includes("Space")) {
@@ -25,12 +61,14 @@ var InputChips = ({
25
61
  }
26
62
  };
27
63
  const handleInputKeyDown = (e) => {
28
- if (backspaceToRemoveChip && e.key === "Backspace" && inputValue.trim() === "") {
29
- setChips((prevState) => {
30
- const updatedChips = [...prevState];
31
- updatedChips.pop();
32
- return updatedChips;
33
- });
64
+ if (backspaceToRemoveChip && e.key === "Backspace" && inputValue.trim() === "" && chips.length > 0) {
65
+ e.preventDefault();
66
+ const updatedChips = [...chips];
67
+ updatedChips.pop();
68
+ setChips(updatedChips);
69
+ return;
70
+ }
71
+ if (e.key === "ArrowLeft" && inputValue.trim() === "" && chips.length > 0) {
34
72
  }
35
73
  const isKeyAllowed = (key) => {
36
74
  return keysToTriggerChipConversion.includes(
@@ -40,12 +78,14 @@ var InputChips = ({
40
78
  if (isKeyAllowed(e.code) && (!validate || validate())) {
41
79
  let chip = inputValue.trim();
42
80
  if (keysToTriggerChipConversion.some((key) => key.length === 1)) {
43
- const regex = new RegExp(
44
- `[${keysToTriggerChipConversion.filter((key) => key.length === 1).map(
45
- (key) => key.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&")
46
- ).join("")}]`,
47
- "g"
48
- );
81
+ const regex = React.useMemo(() => {
82
+ return new RegExp(
83
+ `[${keysToTriggerChipConversion.filter((key) => key.length === 1).map(
84
+ (key) => key.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&")
85
+ ).join("")}]`,
86
+ "g"
87
+ );
88
+ }, [keysToTriggerChipConversion]);
49
89
  chip = chip.replace(regex, "");
50
90
  }
51
91
  if (chip) {
@@ -66,14 +106,15 @@ var InputChips = ({
66
106
  /* @__PURE__ */ jsxs(
67
107
  "section",
68
108
  {
69
- className: errorMsg?.length ? "chip-input-wrapper chip-input-wrapper-error" : "chip-input-wrapper",
109
+ className: `${errorMsg?.length ? "ric-chip-input-wrapper ric-chip-input-wrapper-error" : "ric-chip-input-wrapper"} ${isFocused ? "ric-chip-input-wrapper-focus" : ""} ${containerClassName || ""}`,
70
110
  style: containerStyles ?? {},
111
+ onClick: () => inputRef.current?.focus(),
71
112
  children: [
72
113
  chips.map((chip, index) => /* @__PURE__ */ jsxs(
73
114
  "div",
74
115
  {
75
116
  "data-testid": `input-value-chip-${index}`,
76
- className: "chip",
117
+ className: `ric-chip ${chipClassName || ""}`,
77
118
  style: chipStyles ?? {},
78
119
  children: [
79
120
  chip,
@@ -81,9 +122,11 @@ var InputChips = ({
81
122
  "button",
82
123
  {
83
124
  type: "button",
84
- className: "closeBtn",
125
+ className: `ric-closeBtn ${closeBtnClassName || ""}`,
126
+ style: closeBtnStyle ?? {},
85
127
  "data-testid": `remove-chip-btn-${index}`,
86
128
  onClick: (e) => removeChip(e, chip + index),
129
+ "aria-label": `Remove chip ${chip}`,
87
130
  children: removeBtnSvg || /* @__PURE__ */ jsxs(
88
131
  "svg",
89
132
  {
@@ -107,19 +150,23 @@ var InputChips = ({
107
150
  /* @__PURE__ */ jsx(
108
151
  "input",
109
152
  {
110
- className: "chip-input",
153
+ ref: inputRef,
154
+ className: `ric-chip-input ${inputClassName || ""}`,
155
+ style: inputStyle ?? {},
111
156
  type: "text",
112
157
  placeholder: disabled ? "" : chips.length ? nextPlaceholder : placeholder,
113
158
  value: inputValue,
114
159
  onChange: handleInputChange,
115
160
  onKeyDown: handleInputKeyDown,
116
- disabled
161
+ disabled,
162
+ onFocus: () => setIsFocused(true),
163
+ onBlur: () => setIsFocused(false)
117
164
  }
118
165
  )
119
166
  ]
120
167
  }
121
168
  ),
122
- errorMsg?.length && /* @__PURE__ */ jsx("p", { className: "error-msg-wrapper", children: errorMsg })
169
+ errorMsg?.length && /* @__PURE__ */ jsx("p", { className: "ric-error-msg-wrapper", children: errorMsg })
123
170
  ] });
124
171
  };
125
172
  var InputChip_default = InputChips;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/InputChip.tsx"],"sourcesContent":["import React from 'react';\nimport './styles.css';\nimport {TInputChips, AllowedKeys} from '../types';\n\nconst InputChips = ({\n chips,\n setChips,\n inputValue,\n setInputValue,\n keysToTriggerChipConversion = ['Enter', 'Comma'],\n validate,\n disabled = false,\n placeholder,\n nextPlaceholder,\n removeBtnSvg,\n chipStyles,\n containerStyles,\n backspaceToRemoveChip = false,\n errorMsg,\n}: TInputChips) => {\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n\n if (keysToTriggerChipConversion.includes('Space')) {\n setInputValue(value.trim());\n } else {\n setInputValue(value);\n }\n };\n\n const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (\n backspaceToRemoveChip &&\n e.key === 'Backspace' &&\n inputValue.trim() === ''\n ) {\n setChips((prevState) => {\n const updatedChips = [...prevState];\n updatedChips.pop();\n return updatedChips;\n });\n }\n\n const isKeyAllowed = (key: string): key is AllowedKeys => {\n return (keysToTriggerChipConversion as AllowedKeys[]).includes(\n key as AllowedKeys\n );\n };\n\n if (isKeyAllowed(e.code) && (!validate || validate())) {\n let chip = inputValue.trim();\n\n if (keysToTriggerChipConversion.some((key) => key.length === 1)) {\n const regex = new RegExp(\n `[${keysToTriggerChipConversion\n .filter((key) => key.length === 1)\n .map((key) =>\n key.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&')\n )\n .join('')}]`,\n 'g'\n );\n chip = chip.replace(regex, '');\n }\n\n if (chip) {\n setChips([...chips, chip]);\n setInputValue('');\n }\n\n e.preventDefault();\n }\n };\n\n const removeChip = (\n e: React.MouseEvent<HTMLButtonElement, MouseEvent>,\n chipToRemove: string\n ) => {\n e.preventDefault();\n const filteredChips = chips.filter(\n (chip, index) => chip + index !== chipToRemove\n );\n setChips(filteredChips);\n };\n\n return (\n <>\n <section\n className={\n errorMsg?.length\n ? 'chip-input-wrapper chip-input-wrapper-error'\n : 'chip-input-wrapper'\n }\n style={containerStyles ?? {}}\n >\n {chips.map((chip, index) => (\n <div\n key={chip + index}\n data-testid={`input-value-chip-${index}`}\n className=\"chip\"\n style={chipStyles ?? {}}\n >\n {chip}\n <button\n type=\"button\"\n className=\"closeBtn\"\n data-testid={`remove-chip-btn-${index}`}\n onClick={(e) => removeChip(e, chip + index)}\n >\n {removeBtnSvg || (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 24 24\"\n height={15}\n >\n <path fill=\"none\" d=\"M0 0h24v24H0z\"></path>\n <path d=\"M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"></path>\n </svg>\n )}\n </button>\n </div>\n ))}\n <input\n className=\"chip-input\"\n type=\"text\"\n placeholder={\n disabled\n ? ''\n : chips.length\n ? nextPlaceholder\n : placeholder\n }\n value={inputValue}\n onChange={handleInputChange}\n onKeyDown={handleInputKeyDown}\n disabled={disabled}\n />\n </section>\n {errorMsg?.length && (\n <p className=\"error-msg-wrapper\">{errorMsg}</p>\n )}\n </>\n );\n};\n\nexport default InputChips;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/components/InputChip.tsx","#style-inject:#style-inject","../src/components/styles.css"],"sourcesContent":["import React from 'react';\nimport './styles.css';\nimport { TInputChips, AllowedKeys } from '../types';\n\nconst InputChips = ({\n chips,\n setChips,\n inputValue,\n setInputValue,\n keysToTriggerChipConversion = ['Enter', 'Comma'],\n validate,\n disabled = false,\n placeholder,\n nextPlaceholder,\n removeBtnSvg,\n chipStyles,\n chipClassName,\n containerStyles,\n containerClassName,\n inputStyle,\n inputClassName,\n closeBtnStyle,\n closeBtnClassName,\n backspaceToRemoveChip = false,\n errorMsg,\n}: TInputChips) => {\n const inputRef = React.useRef<HTMLInputElement>(null);\n const [isFocused, setIsFocused] = React.useState(false);\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n\n if (keysToTriggerChipConversion.includes('Space')) {\n setInputValue(value.trim());\n } else {\n setInputValue(value);\n }\n };\n\n const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (\n backspaceToRemoveChip &&\n e.key === 'Backspace' &&\n inputValue.trim() === '' &&\n chips.length > 0\n ) {\n e.preventDefault();\n const updatedChips = [...chips];\n updatedChips.pop();\n setChips(updatedChips);\n return;\n }\n\n if (e.key === 'ArrowLeft' && inputValue.trim() === '' && chips.length > 0) {\n // Logic to select last chip could be added here, but for now we are just cleaning up\n }\n\n const isKeyAllowed = (key: string): key is AllowedKeys => {\n return (keysToTriggerChipConversion as AllowedKeys[]).includes(\n key as AllowedKeys\n );\n };\n\n if (isKeyAllowed(e.code) && (!validate || validate())) {\n let chip = inputValue.trim();\n\n if (keysToTriggerChipConversion.some((key) => key.length === 1)) {\n const regex = React.useMemo(() => {\n return new RegExp(\n `[${keysToTriggerChipConversion\n .filter((key) => key.length === 1)\n .map((key) =>\n key.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&')\n )\n .join('')}]`,\n 'g'\n );\n }, [keysToTriggerChipConversion]);\n\n chip = chip.replace(regex, '');\n }\n\n if (chip) {\n setChips([...chips, chip]);\n setInputValue('');\n }\n\n e.preventDefault();\n }\n };\n\n const removeChip = (\n e: React.MouseEvent<HTMLButtonElement, MouseEvent>,\n chipToRemove: string\n ) => {\n e.preventDefault();\n const filteredChips = chips.filter(\n (chip, index) => chip + index !== chipToRemove\n );\n setChips(filteredChips);\n };\n\n return (\n <>\n <section\n className={`${errorMsg?.length\n ? 'ric-chip-input-wrapper ric-chip-input-wrapper-error'\n : 'ric-chip-input-wrapper'\n } ${isFocused ? 'ric-chip-input-wrapper-focus' : ''} ${containerClassName || ''}`}\n style={containerStyles ?? {}}\n onClick={() => inputRef.current?.focus()}\n >\n {chips.map((chip, index) => (\n <div\n key={chip + index}\n data-testid={`input-value-chip-${index}`}\n className={`ric-chip ${chipClassName || ''}`}\n style={chipStyles ?? {}}\n >\n {chip}\n <button\n type=\"button\"\n className={`ric-closeBtn ${closeBtnClassName || ''}`}\n style={closeBtnStyle ?? {}}\n data-testid={`remove-chip-btn-${index}`}\n onClick={(e) => removeChip(e, chip + index)}\n aria-label={`Remove chip ${chip}`}\n >\n {removeBtnSvg || (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 24 24\"\n height={15}\n >\n <path fill=\"none\" d=\"M0 0h24v24H0z\"></path>\n <path d=\"M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"></path>\n </svg>\n )}\n </button>\n </div>\n ))}\n <input\n ref={inputRef}\n className={`ric-chip-input ${inputClassName || ''}`}\n style={inputStyle ?? {}}\n type=\"text\"\n placeholder={\n disabled\n ? ''\n : chips.length\n ? nextPlaceholder\n : placeholder\n }\n value={inputValue}\n onChange={handleInputChange}\n onKeyDown={handleInputKeyDown}\n disabled={disabled}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n />\n </section>\n {errorMsg?.length && (\n <p className=\"ric-error-msg-wrapper\">{errorMsg}</p>\n )}\n </>\n );\n};\n\nexport default InputChips;\n","\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\".ric-chip-input-wrapper {\\n gap: 4px;\\n flex: 2;\\n padding: 5px;\\n overflow: auto;\\n display: flex;\\n flex-wrap: wrap;\\n align-items: center;\\n border: 1px solid #BBBBBB;\\n border-radius: 4px;\\n max-width: 650px;\\n min-width: 300px;\\n transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;\\n &.ric-chip-input-wrapper-focus {\\n border-color: #4a90e2;\\n box-shadow: 0 0 0 1px #4a90e2;\\n }\\n .ric-chip {\\n background: #e5e5e5;\\n border-radius: 4px;\\n color: #333333;\\n display: flex;\\n gap: 0.5rem;\\n align-items: center;\\n justify-content: space-between;\\n max-width: max-content;\\n padding: 6px;\\n }\\n .ric-chip-input {\\n border: none;\\n outline: none;\\n flex: 1;\\n padding: 0 8px;\\n height: 30px;\\n }\\n .ric-closeBtn {\\n outline: none;\\n border: none;\\n background: none;\\n height: 18px;\\n width: 18px;\\n object-fit: cover;\\n cursor: pointer;\\n display: grid;\\n place-items: center;\\n }\\n}\\n.ric-chip-input-wrapper-error {\\n border: 2px solid red;\\n}\\n.ric-error-msg-wrapper {\\n margin: 0;\\n font-size: 12px;\\n color: red;\\n}\\n\")"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-input-chips",
3
3
  "private": false,
4
- "version": "0.3.4",
4
+ "version": "1.0.0",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -47,7 +47,8 @@
47
47
  "build": "tsup",
48
48
  "lint": "eslint .",
49
49
  "preview": "vite preview",
50
- "bundle": "tsup src/index.ts"
50
+ "bundle": "tsup src/index.ts",
51
+ "test": "vitest"
51
52
  },
52
53
  "dependencies": {
53
54
  "react": "^18.3.1",
@@ -55,6 +56,10 @@
55
56
  },
56
57
  "devDependencies": {
57
58
  "@eslint/js": "^9.13.0",
59
+ "@testing-library/dom": "^10.4.1",
60
+ "@testing-library/jest-dom": "^6.9.1",
61
+ "@testing-library/react": "^16.3.2",
62
+ "@testing-library/user-event": "^14.6.1",
58
63
  "@types/react": "^18.3.12",
59
64
  "@types/react-dom": "^18.3.1",
60
65
  "@vitejs/plugin-react-swc": "^3.5.0",
@@ -62,9 +67,11 @@
62
67
  "eslint-plugin-react-hooks": "^5.0.0",
63
68
  "eslint-plugin-react-refresh": "^0.4.14",
64
69
  "globals": "^15.11.0",
70
+ "jsdom": "^28.0.0",
65
71
  "tsup": "^8.3.5",
66
72
  "typescript": "~5.6.2",
67
73
  "typescript-eslint": "^8.11.0",
68
- "vite": "^5.4.10"
74
+ "vite": "^5.4.10",
75
+ "vitest": "^4.0.18"
69
76
  }
70
- }
77
+ }
@@ -0,0 +1,63 @@
1
+ import { render, screen, fireEvent } from '@testing-library/react';
2
+ import '@testing-library/jest-dom';
3
+ import { useState } from 'react';
4
+ import { describe, it, expect, vi } from 'vitest';
5
+ import InputChips from './InputChip';
6
+
7
+ // Wrapper component to manage state for testing
8
+ const TestWrapper = (props: any) => {
9
+ const [chips, setChips] = useState<string[]>(props.initialChips || []);
10
+ const [inputValue, setInputValue] = useState('');
11
+
12
+ return (
13
+ <InputChips
14
+ chips={chips}
15
+ setChips={setChips}
16
+ inputValue={inputValue}
17
+ setInputValue={setInputValue}
18
+ {...props}
19
+ />
20
+ );
21
+ };
22
+
23
+ describe('InputChips', () => {
24
+ it('renders correctly', () => {
25
+ render(<TestWrapper />);
26
+ const input = screen.getByRole('textbox');
27
+ expect(input).toBeInTheDocument();
28
+ });
29
+
30
+ it('adds a chip when Enter is pressed', () => {
31
+ render(<TestWrapper />);
32
+ const input = screen.getByRole('textbox');
33
+ fireEvent.change(input, { target: { value: 'test-chip' } });
34
+ fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
35
+
36
+ expect(screen.getByText('test-chip')).toBeInTheDocument();
37
+ });
38
+
39
+ it('removes a chip when delete button is clicked', () => {
40
+ render(<TestWrapper initialChips={['chip1']} />);
41
+ const deleteBtn = screen.getByTestId('remove-chip-btn-0');
42
+ fireEvent.click(deleteBtn);
43
+ expect(screen.queryByText('chip1')).not.toBeInTheDocument();
44
+ });
45
+
46
+ it('removes the last chip on Backspace when input is empty', () => {
47
+ render(<TestWrapper initialChips={['chip1']} backspaceToRemoveChip={true} />);
48
+ const input = screen.getByRole('textbox');
49
+ fireEvent.keyDown(input, { key: 'Backspace', code: 'Backspace' });
50
+ expect(screen.queryByText('chip1')).not.toBeInTheDocument();
51
+ });
52
+
53
+ it('validates input before adding chip', () => {
54
+ const validate = vi.fn().mockReturnValue(false);
55
+ render(<TestWrapper validate={validate} />);
56
+ const input = screen.getByRole('textbox');
57
+ fireEvent.change(input, { target: { value: 'invalid' } });
58
+ fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
59
+
60
+ expect(screen.queryByText('invalid')).not.toBeInTheDocument();
61
+ expect(validate).toHaveBeenCalled();
62
+ });
63
+ });
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import './styles.css';
3
- import {TInputChips, AllowedKeys} from '../types';
3
+ import { TInputChips, AllowedKeys } from '../types';
4
4
 
5
5
  const InputChips = ({
6
6
  chips,
@@ -14,10 +14,19 @@ const InputChips = ({
14
14
  nextPlaceholder,
15
15
  removeBtnSvg,
16
16
  chipStyles,
17
+ chipClassName,
17
18
  containerStyles,
19
+ containerClassName,
20
+ inputStyle,
21
+ inputClassName,
22
+ closeBtnStyle,
23
+ closeBtnClassName,
18
24
  backspaceToRemoveChip = false,
19
25
  errorMsg,
20
26
  }: TInputChips) => {
27
+ const inputRef = React.useRef<HTMLInputElement>(null);
28
+ const [isFocused, setIsFocused] = React.useState(false);
29
+
21
30
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
22
31
  const value = e.target.value;
23
32
 
@@ -32,13 +41,18 @@ const InputChips = ({
32
41
  if (
33
42
  backspaceToRemoveChip &&
34
43
  e.key === 'Backspace' &&
35
- inputValue.trim() === ''
44
+ inputValue.trim() === '' &&
45
+ chips.length > 0
36
46
  ) {
37
- setChips((prevState) => {
38
- const updatedChips = [...prevState];
39
- updatedChips.pop();
40
- return updatedChips;
41
- });
47
+ e.preventDefault();
48
+ const updatedChips = [...chips];
49
+ updatedChips.pop();
50
+ setChips(updatedChips);
51
+ return;
52
+ }
53
+
54
+ if (e.key === 'ArrowLeft' && inputValue.trim() === '' && chips.length > 0) {
55
+ // Logic to select last chip could be added here, but for now we are just cleaning up
42
56
  }
43
57
 
44
58
  const isKeyAllowed = (key: string): key is AllowedKeys => {
@@ -51,15 +65,18 @@ const InputChips = ({
51
65
  let chip = inputValue.trim();
52
66
 
53
67
  if (keysToTriggerChipConversion.some((key) => key.length === 1)) {
54
- const regex = new RegExp(
55
- `[${keysToTriggerChipConversion
56
- .filter((key) => key.length === 1)
57
- .map((key) =>
58
- key.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
59
- )
60
- .join('')}]`,
61
- 'g'
62
- );
68
+ const regex = React.useMemo(() => {
69
+ return new RegExp(
70
+ `[${keysToTriggerChipConversion
71
+ .filter((key) => key.length === 1)
72
+ .map((key) =>
73
+ key.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
74
+ )
75
+ .join('')}]`,
76
+ 'g'
77
+ );
78
+ }, [keysToTriggerChipConversion]);
79
+
63
80
  chip = chip.replace(regex, '');
64
81
  }
65
82
 
@@ -86,26 +103,28 @@ const InputChips = ({
86
103
  return (
87
104
  <>
88
105
  <section
89
- className={
90
- errorMsg?.length
91
- ? 'chip-input-wrapper chip-input-wrapper-error'
92
- : 'chip-input-wrapper'
93
- }
106
+ className={`${errorMsg?.length
107
+ ? 'ric-chip-input-wrapper ric-chip-input-wrapper-error'
108
+ : 'ric-chip-input-wrapper'
109
+ } ${isFocused ? 'ric-chip-input-wrapper-focus' : ''} ${containerClassName || ''}`}
94
110
  style={containerStyles ?? {}}
111
+ onClick={() => inputRef.current?.focus()}
95
112
  >
96
113
  {chips.map((chip, index) => (
97
114
  <div
98
115
  key={chip + index}
99
116
  data-testid={`input-value-chip-${index}`}
100
- className="chip"
117
+ className={`ric-chip ${chipClassName || ''}`}
101
118
  style={chipStyles ?? {}}
102
119
  >
103
120
  {chip}
104
121
  <button
105
122
  type="button"
106
- className="closeBtn"
123
+ className={`ric-closeBtn ${closeBtnClassName || ''}`}
124
+ style={closeBtnStyle ?? {}}
107
125
  data-testid={`remove-chip-btn-${index}`}
108
126
  onClick={(e) => removeChip(e, chip + index)}
127
+ aria-label={`Remove chip ${chip}`}
109
128
  >
110
129
  {removeBtnSvg || (
111
130
  <svg
@@ -123,23 +142,27 @@ const InputChips = ({
123
142
  </div>
124
143
  ))}
125
144
  <input
126
- className="chip-input"
145
+ ref={inputRef}
146
+ className={`ric-chip-input ${inputClassName || ''}`}
147
+ style={inputStyle ?? {}}
127
148
  type="text"
128
149
  placeholder={
129
150
  disabled
130
151
  ? ''
131
152
  : chips.length
132
- ? nextPlaceholder
133
- : placeholder
153
+ ? nextPlaceholder
154
+ : placeholder
134
155
  }
135
156
  value={inputValue}
136
157
  onChange={handleInputChange}
137
158
  onKeyDown={handleInputKeyDown}
138
159
  disabled={disabled}
160
+ onFocus={() => setIsFocused(true)}
161
+ onBlur={() => setIsFocused(false)}
139
162
  />
140
163
  </section>
141
164
  {errorMsg?.length && (
142
- <p className="error-msg-wrapper">{errorMsg}</p>
165
+ <p className="ric-error-msg-wrapper">{errorMsg}</p>
143
166
  )}
144
167
  </>
145
168
  );
@@ -1,4 +1,4 @@
1
- .chip-input-wrapper {
1
+ .ric-chip-input-wrapper {
2
2
  gap: 4px;
3
3
  flex: 2;
4
4
  padding: 5px;
@@ -10,8 +10,14 @@
10
10
  border-radius: 4px;
11
11
  max-width: 650px;
12
12
  min-width: 300px;
13
+ transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
13
14
 
14
- .chip {
15
+ &.ric-chip-input-wrapper-focus {
16
+ border-color: #4a90e2;
17
+ box-shadow: 0 0 0 1px #4a90e2;
18
+ }
19
+
20
+ .ric-chip {
15
21
  background: #e5e5e5;
16
22
  border-radius: 4px;
17
23
  color: #333333;
@@ -23,7 +29,7 @@
23
29
  padding: 6px;
24
30
  }
25
31
 
26
- .chip-input {
32
+ .ric-chip-input {
27
33
  border: none;
28
34
  outline: none;
29
35
  flex: 1;
@@ -31,7 +37,7 @@
31
37
  height: 30px;
32
38
  }
33
39
 
34
- .closeBtn {
40
+ .ric-closeBtn {
35
41
  outline: none;
36
42
  border: none;
37
43
  background: none;
@@ -44,11 +50,11 @@
44
50
  }
45
51
  }
46
52
 
47
- .chip-input-wrapper-error {
53
+ .ric-chip-input-wrapper-error {
48
54
  border: 2px solid red
49
55
  }
50
56
 
51
- .error-msg-wrapper {
57
+ .ric-error-msg-wrapper {
52
58
  margin: 0;
53
59
  font-size: 12px;
54
60
  color: red
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -33,4 +33,10 @@ export interface TInputChips {
33
33
  containerStyles?: React.CSSProperties;
34
34
  backspaceToRemoveChip?: boolean;
35
35
  errorMsg?: string;
36
+ chipClassName?: string;
37
+ inputStyle?: React.CSSProperties;
38
+ inputClassName?: string;
39
+ closeBtnStyle?: React.CSSProperties;
40
+ closeBtnClassName?: string;
41
+ containerClassName?: string;
36
42
  }
package/dist/index.css DELETED
@@ -1,52 +0,0 @@
1
- /* src/components/styles.css */
2
- .chip-input-wrapper {
3
- gap: 4px;
4
- flex: 2;
5
- padding: 5px;
6
- overflow: auto;
7
- display: flex;
8
- flex-wrap: wrap;
9
- align-items: center;
10
- border: 1px solid #BBBBBB;
11
- border-radius: 4px;
12
- max-width: 650px;
13
- min-width: 300px;
14
- .chip {
15
- background: #e5e5e5;
16
- border-radius: 4px;
17
- color: #333333;
18
- display: flex;
19
- gap: 0.5rem;
20
- align-items: center;
21
- justify-content: space-between;
22
- max-width: max-content;
23
- padding: 6px;
24
- }
25
- .chip-input {
26
- border: none;
27
- outline: none;
28
- flex: 1;
29
- padding: 0 8px;
30
- height: 30px;
31
- }
32
- .closeBtn {
33
- outline: none;
34
- border: none;
35
- background: none;
36
- height: 18px;
37
- width: 18px;
38
- object-fit: cover;
39
- cursor: pointer;
40
- display: grid;
41
- place-items: center;
42
- }
43
- }
44
- .chip-input-wrapper-error {
45
- border: 2px solid red;
46
- }
47
- .error-msg-wrapper {
48
- margin: 0;
49
- font-size: 12px;
50
- color: red;
51
- }
52
- /*# sourceMappingURL=index.css.map */
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/styles.css"],"sourcesContent":[".chip-input-wrapper {\n gap: 4px;\n flex: 2;\n padding: 5px;\n overflow: auto;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n border: 1px solid #BBBBBB;\n border-radius: 4px;\n max-width: 650px;\n min-width: 300px;\n\n .chip {\n background: #e5e5e5;\n border-radius: 4px;\n color: #333333;\n display: flex;\n gap: 0.5rem;\n align-items: center;\n justify-content: space-between;\n max-width: max-content;\n padding: 6px;\n }\n\n .chip-input {\n border: none;\n outline: none;\n flex: 1;\n padding: 0 8px;\n height: 30px;\n }\n\n .closeBtn {\n outline: none;\n border: none;\n background: none;\n height: 18px;\n width: 18px;\n object-fit: cover;\n cursor: pointer;\n display: grid;\n place-items: center;\n }\n}\n\n.chip-input-wrapper-error {\n border: 2px solid red\n}\n\n.error-msg-wrapper {\n margin: 0;\n font-size: 12px;\n color: red\n}"],"mappings":";AAAA,CAAC;AACE,OAAK;AACL,QAAM;AACN,WAAS;AACT,YAAU;AACV,WAAS;AACT,aAAW;AACX,eAAa;AACb,UAAQ,IAAI,MAAM;AAClB,iBAAe;AACf,aAAW;AACX,aAAW;AAEX,GAAC;AACE,gBAAY;AACZ,mBAAe;AACf,WAAO;AACP,aAAS;AACT,SAAK;AACL,iBAAa;AACb,qBAAiB;AACjB,eAAW;AACX,aAAS;AACZ;AAEA,GAAC;AACE,YAAQ;AACR,aAAS;AACT,UAAM;AACN,aAAS,EAAE;AACX,YAAQ;AACX;AAEA,GAAC;AACE,aAAS;AACT,YAAQ;AACR,gBAAY;AACZ,YAAQ;AACR,WAAO;AACP,gBAAY;AACZ,YAAQ;AACR,aAAS;AACT,iBAAa;AAChB;AACH;AAEA,CAAC;AACE,UAAQ,IAAI,MAAM;AACrB;AAEA,CAAC;AACE,UAAQ;AACR,aAAW;AACX,SAAO;AACV;","names":[]}