UNPKG

strapi-plugin-tagsinput

Version:
1 lines 14.4 kB
{"version":3,"file":"Input-DUnG8vg6.mjs","sources":["../../admin/src/components/styles/global.js","../../admin/src/components/Input.jsx"],"sourcesContent":["import { createGlobalStyle, css } from \"styled-components\";\n\nconst light = css`\n :root {\n --primary: #7b79ff;\n --secondary: rgb(255, 255, 255);\n --text: #32324d;\n --input-background: #ffffff;\n --input-border: #dcdce4;\n --tag-background: #f0f0ff;\n --tag-text: #4945ff;\n --suggestion-background: #ffffff;\n --suggestion-hover: #f6f6f9;\n }\n`;\n\nconst dark = css`\n :root {\n --primary: #7b79ff;\n --secondary: rgb(33, 33, 52);\n --text: #ffffff;\n --input-background: #181826;\n --input-border: #4a4a6a;\n --tag-background: #7b79ff;\n --tag-text: #ffffff;\n --suggestion-background: #181826;\n --suggestion-hover: #212134;\n }\n`;\n\nconst styles = css`\n .react-tagsinput {\n width: 100%;\n border: 1px solid var(--input-border);\n border-radius: 4px;\n overflow: hidden;\n padding-left: 5px;\n padding-top: 5px;\n }\n\n .react-tagsinput--focused {\n outline: 3px solid var(--primary);\n }\n\n .react-tagsinput-tag {\n background-color: var(--tag-background);\n border-radius: 2px;\n border: 1px solid var(--tag-background);\n color: var(--tag-text);\n display: inline-block;\n font-family: sans-serif;\n font-size: 13px;\n font-weight: 400;\n margin-bottom: 5px;\n margin-right: 5px;\n padding: 5px;\n }\n\n .react-tagsinput-remove {\n cursor: pointer;\n font-weight: bold;\n }\n\n .react-tagsinput-tag a::before {\n content: \" ×\";\n }\n\n .react-tagsinput-input {\n background: transparent;\n border: 0;\n color: var(--text);\n font-family: sans-serif;\n font-size: 13px;\n font-weight: 400;\n margin-bottom: 6px;\n margin-top: 1px;\n outline: none;\n padding: 5px;\n width: 100%;\n }\n\n .react-tagsinput > span {\n display: flex;\n flex-flow: wrap;\n }\n\n .react-autosuggest__container {\n display: flex;\n flex-direction: column;\n flex: auto;\n }\n\n .react-autosuggest__suggestions-container {\n position: absolute;\n z-index: 200;\n width: 280px;\n margin: 0;\n padding: 0;\n list-style-type: none;\n background-color: var(--suggestion-background);\n }\n\n .react-autosuggest__suggestions-container--open {\n border: 1px solid var(--input-border);\n }\n\n .react-autosuggest__suggestion {\n cursor: pointer;\n padding: 10px 20px;\n }\n\n .react-autosuggest__suggestion > span {\n font-size: 13px;\n font-weight: 400;\n }\n\n .react-autosuggest__suggestion--highlighted,\n .react-autosuggest__suggestion--focused {\n background-color: var(--suggestion-hover);\n }\n`;\n\nexport const getStyling = (theme) => {\n let themeStyle = light;\n\n switch (theme) {\n case 'dark':\n themeStyle = dark;\n break;\n default:\n themeStyle = light;\n }\n\n return createGlobalStyle`\n ${themeStyle}\n ${styles}\n `;\n};\n","import React, { useState, useRef, useEffect } from \"react\";\nimport PropTypes from \"prop-types\";\nimport axios from \"axios\";\nimport { Flex, Field } from \"@strapi/design-system\";\nimport { useIntl } from \"react-intl\";\nimport TagsInput from \"react-tagsinput\";\nimport Autosuggest from \"react-autosuggest\";\nimport { getStyling } from \"./styles/global\";\n\nconst ThemeStyle = getStyling(localStorage.getItem(\"STRAPI_THEME\"));\n\nconst Tags = ({\n attribute,\n description,\n error,\n label,\n labelAction,\n name,\n onChange,\n required,\n value,\n}) => {\n const { formatMessage } = useIntl();\n const apiUrl = attribute?.options?.apiUrl || \"\";\n const attrName = apiUrl.slice(apiUrl.lastIndexOf(\"=\") + 1) || \"name\";\n const inputEle = useRef(null);\n\n const [tags, setTags] = useState(() => {\n try {\n const values = typeof value === \"string\" ? JSON.parse(value) : value;\n return Array.isArray(values) ? values.map((v) => v[attrName] || v.name || v) : [];\n } catch (e) {\n return [];\n }\n });\n\n const [suggestions, setSuggestions] = useState([]);\n\n useEffect(() => {\n const suggestionsContainer = document.querySelector(\n \".react-autosuggest__suggestions-container\"\n );\n if (suggestionsContainer && inputEle.current) {\n suggestionsContainer.style.top = `${inputEle.current.offsetHeight + 5}px`;\n }\n\n const handleClickOutside = (event) => {\n const tagsInput = document.querySelector(\".react-tagsinput\");\n if (tagsInput) {\n tagsInput.classList.toggle(\n \"react-tagsinput--focused\",\n inputEle.current?.contains(event.target)\n );\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\n }, []);\n\n const handleTagsChange = async (newTags) => {\n const lastTag = newTags[newTags.length - 1];\n const suggestionsArray = suggestions.data || [];\n const existingTag = suggestionsArray.find(\n (s) => s[attrName]?.toLowerCase() === lastTag.toLowerCase()\n );\n\n if (!existingTag) {\n if (apiUrl) {\n try {\n const response = await axios.post(apiUrl, {\n data: {\n [attrName]: lastTag,\n },\n });\n\n setSuggestions((prevSuggestions) => {\n const newSuggestionsData = [...(prevSuggestions.data || []), response.data.data];\n return { ...prevSuggestions, data: newSuggestionsData };\n });\n\n newTags[newTags.length - 1] = response.data.data[attrName];\n } catch (error) {\n console.error(\"Error creating new tag:\", error);\n // Don't remove the tag if API call fails, allow it to be added locally\n }\n } else {\n // If there's no apiUrl, just add the new tag to the suggestions\n setSuggestions((prevSuggestions) => {\n const newSuggestion = { id: Date.now(), [attrName]: lastTag };\n const newSuggestionsData = [...(prevSuggestions.data || []), newSuggestion];\n return { ...prevSuggestions, data: newSuggestionsData };\n });\n }\n }\n\n setTags(newTags);\n\n const value = JSON.stringify(newTags.map((tag) => ({ [attrName]: tag })));\n\n onChange({\n target: {\n name,\n value,\n type: attribute.type,\n },\n });\n };\n\n const getSuggestions = async () => {\n if (!apiUrl) return;\n try {\n const res = await axios.get(apiUrl);\n setSuggestions(res.data);\n } catch (err) {\n setSuggestions({ data: [] });\n }\n };\n\n const autocompleteRenderInput = (props) => {\n const handleOnChange = (e, { newValue, method }) => {\n if (method === \"enter\") {\n e.preventDefault();\n } else {\n props.onChange(e);\n }\n };\n\n const inputValue = (props.value && props.value.trim()) || \"\";\n const inputLength = inputValue.length;\n\n let s = suggestions.data || [];\n if (s.length <= 0) {\n getSuggestions();\n }\n\n if (inputLength > 0) {\n s = s\n .filter((state) => {\n const suggestionName = state[attrName] || \"\";\n return suggestionName.toLowerCase().slice(0, inputLength) === inputValue;\n })\n .map((state) => ({\n id: state.id,\n [attrName]: state[attrName] || \"\",\n }));\n }\n \n return (\n <Autosuggest\n ref={props.ref}\n suggestions={s}\n shouldRenderSuggestions={(value) => value && value.trim().length > 0}\n getSuggestionValue={(s) => s[attrName]}\n renderSuggestion={(s) => <span>{s[attrName]}</span>}\n inputProps={{ ...props, onChange: handleOnChange }}\n onSuggestionSelected={(_, { suggestion }) => props.addTag(suggestion[attrName])}\n onSuggestionsFetchRequested={() => {}}\n />\n );\n };\n\n return (\n <>\n <Field.Root\n name={name}\n id={name}\n error={error}\n hint={description && formatMessage({ id: description })}\n required={required}\n >\n <Flex\n direction=\"column\"\n alignItems=\"stretch\"\n gap={1}\n style={{ position: \"relative\" }}\n ref={inputEle}\n >\n {label && <Field.Label action={labelAction}>{formatMessage({ id: label, defaultMessage: \"Tags\" })}</Field.Label>}\n <ThemeStyle />\n <Flex direction=\"column\">\n <TagsInput\n value={tags}\n onChange={handleTagsChange}\n onlyUnique\n renderInput={autocompleteRenderInput}\n />\n </Flex>\n <Field.Hint />\n <Field.Error />\n </Flex>\n </Field.Root>\n </>\n );\n};\n\nTags.defaultProps = {\n description: null,\n disabled: false,\n error: null,\n labelAction: null,\n required: false,\n value: \"\",\n};\n\nTags.propTypes = {\n label: PropTypes.object.isRequired,\n onChange: PropTypes.func.isRequired,\n attribute: PropTypes.object.isRequired,\n name: PropTypes.string.isRequired,\n description: PropTypes.object,\n error: PropTypes.string,\n labelAction: PropTypes.object,\n required: PropTypes.bool,\n value: PropTypes.string,\n};\n\nexport default Tags;\n"],"names":["error","value","s"],"mappings":"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"}