diff options
| -rw-r--r-- | admin/src/components/CheckboxListDefaultInput.tsx | 59 | ||||
| -rw-r--r-- | admin/src/components/CheckboxListEnumInput.tsx | 126 | ||||
| -rw-r--r-- | admin/src/components/CheckboxListInput.tsx | 8 | ||||
| -rw-r--r-- | admin/src/index.ts | 12 | ||||
| -rw-r--r-- | admin/src/utils/checkboxListValidator.ts | 74 | ||||
| -rw-r--r-- | package-lock.json | 559 | ||||
| -rw-r--r-- | package.json | 4 |
7 files changed, 779 insertions, 63 deletions
diff --git a/admin/src/components/CheckboxListDefaultInput.tsx b/admin/src/components/CheckboxListDefaultInput.tsx index 465d0d3..ffd0551 100644 --- a/admin/src/components/CheckboxListDefaultInput.tsx +++ b/admin/src/components/CheckboxListDefaultInput.tsx @@ -1,6 +1,6 @@ import type { ReactNode } from 'react'; -import { Box, Checkbox, Field, Flex, Typography } from '@strapi/design-system'; +import { Box, Field, MultiSelect, MultiSelectOption, Typography } from '@strapi/design-system'; import { useIntl } from 'react-intl'; type CheckboxListDefaultInputProps = { @@ -23,6 +23,9 @@ type CheckboxListDefaultInputProps = { error?: string; modifiedData?: { enum?: string[]; + options?: { + enum?: string[]; + }; }; }; @@ -51,23 +54,26 @@ const CheckboxListDefaultInput = ({ modifiedData, }: CheckboxListDefaultInputProps) => { const { formatMessage } = useIntl(); - const enumValues = Array.isArray(modifiedData?.enum) ? modifiedData.enum : []; + const enumValues = Array.isArray(modifiedData?.options?.enum) + ? modifiedData.options.enum + : Array.isArray(modifiedData?.enum) + ? modifiedData.enum + : []; const selectedValues = normalizeValue(value); + const uniqueValues = Array.from( + new Set(enumValues.filter((option) => typeof option === 'string' && option.trim().length > 0)) + ); const label = intlLabel ? formatMessage(intlLabel, intlLabel.values ?? {}) : name; const hint = description ? formatMessage(description, description.values ?? {}) : undefined; - const handleToggle = (option: string, isChecked: boolean) => { - const nextValues = isChecked - ? Array.from(new Set([...selectedValues, option])) - : selectedValues.filter((item) => item !== option); - + const handleChange = (nextValues: string[] | undefined) => { onChange({ target: { name, - value: nextValues, + value: Array.isArray(nextValues) ? nextValues : [], }, }); }; @@ -75,21 +81,28 @@ const CheckboxListDefaultInput = ({ return ( <Field.Root name={name} hint={hint} error={error} required={required}> <Field.Label action={labelAction}>{label}</Field.Label> - {enumValues.length > 0 ? ( - <Flex direction="column" gap={2} paddingTop={1} alignItems="flex-start"> - {enumValues.map((option) => ( - <Checkbox - key={option} - checked={selectedValues.includes(option)} - disabled={disabled} - onCheckedChange={(checked: boolean | 'indeterminate') => - handleToggle(option, Boolean(checked)) - } - > - {option} - </Checkbox> - ))} - </Flex> + {uniqueValues.length > 0 ? ( + <Box paddingTop={1}> + <MultiSelect + aria-label={label} + disabled={disabled} + id={name} + name={name} + onChange={handleChange} + placeholder={formatMessage({ + id: 'checkbox-list.default.placeholder', + defaultMessage: 'Select default values', + })} + value={selectedValues} + withTags + > + {uniqueValues.map((option) => ( + <MultiSelectOption key={option} value={option}> + {option} + </MultiSelectOption> + ))} + </MultiSelect> + </Box> ) : ( <Box paddingTop={1}> <Typography variant="pi" textColor="neutral500"> diff --git a/admin/src/components/CheckboxListEnumInput.tsx b/admin/src/components/CheckboxListEnumInput.tsx new file mode 100644 index 0000000..0a1ac73 --- /dev/null +++ b/admin/src/components/CheckboxListEnumInput.tsx @@ -0,0 +1,126 @@ +import type { ChangeEvent, ReactNode } from 'react'; + +import { Field, Textarea } from '@strapi/design-system'; +import { useIntl } from 'react-intl'; + +type CheckboxListEnumInputProps = { + name: string; + value?: unknown; + onChange: (eventOrPath: { target: { name: string; value: string[] } }, value?: unknown) => void; + intlLabel: { + id: string; + defaultMessage: string; + values?: Record<string, string | number | boolean | null | undefined>; + }; + description?: { + id: string; + defaultMessage: string; + values?: Record<string, string | number | boolean | null | undefined>; + } | null; + labelAction?: ReactNode; + placeholder?: { + id: string; + defaultMessage: string; + values?: Record<string, string | number | boolean | null | undefined>; + } | null; + disabled?: boolean; + error?: string; + modifiedData?: { + enum?: string[]; + options?: { + enum?: string[]; + }; + }; +}; + +const normalizeEnum = (value: unknown): string[] => { + if (Array.isArray(value)) { + return value.filter((item): item is string => typeof item === 'string'); + } + + return []; +}; + +const CheckboxListEnumInput = ({ + description = null, + disabled = false, + error = '', + intlLabel, + labelAction, + name, + onChange, + placeholder = null, + value, + modifiedData, +}: CheckboxListEnumInputProps) => { + const { formatMessage } = useIntl(); + + const fallbackEnum = normalizeEnum(modifiedData?.enum); + const resolvedEnum = normalizeEnum(value).length > 0 ? normalizeEnum(value) : fallbackEnum; + + const errorMessage = error + ? formatMessage({ + id: error, + defaultMessage: error, + }) + : ''; + + const hint = description + ? formatMessage( + { + id: description.id, + defaultMessage: description.defaultMessage, + }, + description.values + ) + : ''; + + const label = formatMessage(intlLabel, intlLabel.values ?? {}); + const formattedPlaceholder = placeholder + ? formatMessage( + { + id: placeholder.id, + defaultMessage: placeholder.defaultMessage, + }, + placeholder.values + ) + : ''; + + const inputValue = resolvedEnum.join('\n'); + + const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => { + const arrayValue = event.target.value.split('\n'); + + onChange({ + target: { + name, + value: arrayValue, + }, + }); + + if (name !== 'enum') { + onChange({ + target: { + name: 'enum', + value: arrayValue, + }, + }); + } + }; + + return ( + <Field.Root error={errorMessage} hint={hint} name={name}> + <Field.Label action={labelAction}>{label}</Field.Label> + <Textarea + disabled={disabled} + onChange={handleChange} + placeholder={formattedPlaceholder} + value={inputValue} + /> + <Field.Error /> + <Field.Hint /> + </Field.Root> + ); +}; + +export { CheckboxListEnumInput }; diff --git a/admin/src/components/CheckboxListInput.tsx b/admin/src/components/CheckboxListInput.tsx index 51a0d22..07d2776 100644 --- a/admin/src/components/CheckboxListInput.tsx +++ b/admin/src/components/CheckboxListInput.tsx @@ -26,14 +26,14 @@ const getEnumValues = (attribute: CheckboxListInputProps['attribute']): string[] return []; } - if (Array.isArray(attribute.enum)) { - return attribute.enum; - } - if (Array.isArray(attribute.options?.enum)) { return attribute.options.enum; } + if (Array.isArray(attribute.enum)) { + return attribute.enum; + } + return []; }; diff --git a/admin/src/index.ts b/admin/src/index.ts index a1c0473..6cab121 100644 --- a/admin/src/index.ts +++ b/admin/src/index.ts @@ -1,7 +1,9 @@ import { EnumerationField } from '@strapi/icons/symbols'; +import { CheckboxListEnumInput } from './components/CheckboxListEnumInput'; import { Initializer } from './components/Initializer'; import { CheckboxListDefaultInput } from './components/CheckboxListDefaultInput'; import { PLUGIN_ID } from './pluginId'; +import { checkboxListOptionsValidator } from './utils/checkboxListValidator'; export default { register(app: any) { @@ -19,6 +21,10 @@ export default { id: 'checkbox-list-default', component: CheckboxListDefaultInput, }); + ctbPlugin.apis.forms.components.add({ + id: 'checkbox-list-enum', + component: CheckboxListEnumInput, + }); } app.customFields.register({ @@ -47,8 +53,8 @@ export default { sectionTitle: null, items: [ { - name: 'enum', - type: 'textarea-enum', + name: 'options.enum', + type: 'checkbox-list-enum', size: 6, intlLabel: { id: 'form.attribute.item.enumeration.rules', @@ -58,6 +64,7 @@ export default { id: 'form.attribute.item.enumeration.placeholder', defaultMessage: 'Ex:\nmorning\nnoon\nevening', }, + defaultValue: [], validations: { required: true, }, @@ -128,6 +135,7 @@ export default { ], }, ], + validator: checkboxListOptionsValidator, }, }); }, diff --git a/admin/src/utils/checkboxListValidator.ts b/admin/src/utils/checkboxListValidator.ts new file mode 100644 index 0000000..771531f --- /dev/null +++ b/admin/src/utils/checkboxListValidator.ts @@ -0,0 +1,74 @@ +import slugify from '@sindresorhus/slugify'; +import { translatedErrors } from '@strapi/admin/strapi-admin'; +import * as yup from 'yup'; + +const GRAPHQL_ENUM_REGEX = /^[_A-Za-z][_0-9A-Za-z]*$/; + +const toRegressedEnumValue = (value?: string) => { + if (!value) { + return ''; + } + + return slugify(value, { + decamelize: false, + lowercase: false, + separator: '_', + }); +}; + +const hasUniqueValues = (values: string[]) => { + const seen = new Set<string>(); + + for (const value of values) { + if (seen.has(value)) { + return false; + } + + seen.add(value); + } + + return true; +}; + +export const checkboxListOptionsValidator = () => ({ + enum: yup + .array() + .of(yup.string()) + .min(1, translatedErrors.min.id) + .test({ + name: 'areEnumValuesUnique', + message: 'content-type-builder.error.validation.enum-duplicate', + test(values) { + if (!values) { + return false; + } + + const normalizedValues = values.map(toRegressedEnumValue); + + return hasUniqueValues(normalizedValues); + }, + }) + .test({ + name: 'doesNotHaveEmptyValues', + message: 'content-type-builder.error.validation.enum-empty-string', + test(values) { + if (!values) { + return false; + } + + return !values.map(toRegressedEnumValue).some((value) => value === ''); + }, + }) + .test({ + name: 'doesMatchRegex', + message: 'content-type-builder.error.validation.enum-regex', + test(values) { + if (!values) { + return false; + } + + return values.map(toRegressedEnumValue).every((value) => GRAPHQL_ENUM_REGEX.test(value)); + }, + }), + enumName: yup.string().nullable(), +}); diff --git a/package-lock.json b/package-lock.json index 5c4430e..92cced0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,11 @@ "version": "0.0.0", "license": "MIT", "dependencies": { + "@sindresorhus/slugify": "^2.2.1", "@strapi/design-system": "^2.0.0-rc.30", "@strapi/icons": "^2.0.0-rc.30", - "react-intl": "^7.1.14" + "react-intl": "^7.1.14", + "yup": "^0.32.11" }, "devDependencies": { "@strapi/sdk-plugin": "^5.4.0", @@ -4541,47 +4543,58 @@ } }, "node_modules/@sindresorhus/slugify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-1.1.0.tgz", - "integrity": "sha512-ujZRbmmizX26yS/HnB3P9QNlNa4+UvHh+rIse3RbOXLp8yl6n1TxB4t7NHggtVgS8QmmOtzXo48kCxZGACpkPw==", - "dev": true, + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz", + "integrity": "sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==", "license": "MIT", "dependencies": { - "@sindresorhus/transliterate": "^0.1.1", - "escape-string-regexp": "^4.0.0" + "@sindresorhus/transliterate": "^1.0.0", + "escape-string-regexp": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sindresorhus/slugify/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@sindresorhus/transliterate": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-0.1.2.tgz", - "integrity": "sha512-5/kmIOY9FF32nicXH+5yLNTX4NJ4atl7jRgqAJuIn/iyDFXBktOKDxCvyGE/EzmF4ngSUvjXxQUQlQiZ5lfw+w==", - "dev": true, + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-1.6.0.tgz", + "integrity": "sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==", "license": "MIT", "dependencies": { - "escape-string-regexp": "^2.0.0", - "lodash.deburr": "^4.1.0" + "escape-string-regexp": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@sindresorhus/transliterate/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@so-ric/colorspace": { @@ -5068,6 +5081,25 @@ } } }, + "node_modules/@strapi/admin/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/admin/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -5131,6 +5163,25 @@ "dev": true, "license": "MIT" }, + "node_modules/@strapi/cloud-cli/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/content-manager": { "version": "5.35.0", "resolved": "https://registry.npmjs.org/@strapi/content-manager/-/content-manager-5.35.0.tgz", @@ -5295,6 +5346,50 @@ } } }, + "node_modules/@strapi/content-manager/node_modules/@sindresorhus/slugify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-1.1.0.tgz", + "integrity": "sha512-ujZRbmmizX26yS/HnB3P9QNlNa4+UvHh+rIse3RbOXLp8yl6n1TxB4t7NHggtVgS8QmmOtzXo48kCxZGACpkPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/transliterate": "^0.1.1", + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@strapi/content-manager/node_modules/@sindresorhus/transliterate": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-0.1.2.tgz", + "integrity": "sha512-5/kmIOY9FF32nicXH+5yLNTX4NJ4atl7jRgqAJuIn/iyDFXBktOKDxCvyGE/EzmF4ngSUvjXxQUQlQiZ5lfw+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0", + "lodash.deburr": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@strapi/content-manager/node_modules/@sindresorhus/transliterate/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@strapi/content-manager/node_modules/@types/react": { "version": "18.3.28", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", @@ -5399,6 +5494,25 @@ } } }, + "node_modules/@strapi/content-manager/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/content-releases": { "version": "5.35.0", "resolved": "https://registry.npmjs.org/@strapi/content-releases/-/content-releases-5.35.0.tgz", @@ -5641,6 +5755,25 @@ } } }, + "node_modules/@strapi/content-releases/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/content-type-builder": { "version": "5.35.0", "resolved": "https://registry.npmjs.org/@strapi/content-type-builder/-/content-type-builder-5.35.0.tgz", @@ -5790,6 +5923,50 @@ } } }, + "node_modules/@strapi/content-type-builder/node_modules/@sindresorhus/slugify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-1.1.0.tgz", + "integrity": "sha512-ujZRbmmizX26yS/HnB3P9QNlNa4+UvHh+rIse3RbOXLp8yl6n1TxB4t7NHggtVgS8QmmOtzXo48kCxZGACpkPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/transliterate": "^0.1.1", + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@strapi/content-type-builder/node_modules/@sindresorhus/transliterate": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-0.1.2.tgz", + "integrity": "sha512-5/kmIOY9FF32nicXH+5yLNTX4NJ4atl7jRgqAJuIn/iyDFXBktOKDxCvyGE/EzmF4ngSUvjXxQUQlQiZ5lfw+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0", + "lodash.deburr": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@strapi/content-type-builder/node_modules/@sindresorhus/transliterate/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@strapi/content-type-builder/node_modules/@types/react": { "version": "18.3.28", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", @@ -5901,6 +6078,25 @@ } } }, + "node_modules/@strapi/content-type-builder/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/content-type-builder/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -6126,6 +6322,25 @@ "node": ">=14.17" } }, + "node_modules/@strapi/core/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/core/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -6436,6 +6651,25 @@ } } }, + "node_modules/@strapi/email/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/email/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -6470,6 +6704,50 @@ "npm": ">=6.0.0" } }, + "node_modules/@strapi/generators/node_modules/@sindresorhus/slugify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-1.1.0.tgz", + "integrity": "sha512-ujZRbmmizX26yS/HnB3P9QNlNa4+UvHh+rIse3RbOXLp8yl6n1TxB4t7NHggtVgS8QmmOtzXo48kCxZGACpkPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/transliterate": "^0.1.1", + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@strapi/generators/node_modules/@sindresorhus/transliterate": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-0.1.2.tgz", + "integrity": "sha512-5/kmIOY9FF32nicXH+5yLNTX4NJ4atl7jRgqAJuIn/iyDFXBktOKDxCvyGE/EzmF4ngSUvjXxQUQlQiZ5lfw+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0", + "lodash.deburr": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@strapi/generators/node_modules/@sindresorhus/transliterate/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@strapi/generators/node_modules/lodash": { "version": "4.17.23", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", @@ -6722,6 +7000,25 @@ } } }, + "node_modules/@strapi/i18n/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/i18n/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -6864,6 +7161,25 @@ "node": ">=14.17" } }, + "node_modules/@strapi/pack-up/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/permissions": { "version": "5.35.0", "resolved": "https://registry.npmjs.org/@strapi/permissions/-/permissions-5.35.0.tgz", @@ -7151,6 +7467,25 @@ } } }, + "node_modules/@strapi/review-workflows/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/sdk-plugin": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/@strapi/sdk-plugin/-/sdk-plugin-5.4.0.tgz", @@ -7213,6 +7548,25 @@ "node": ">=14.17" } }, + "node_modules/@strapi/sdk-plugin/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/strapi": { "version": "5.35.0", "resolved": "https://registry.npmjs.org/@strapi/strapi/-/strapi-5.35.0.tgz", @@ -7566,6 +7920,25 @@ "node": ">=14.17" } }, + "node_modules/@strapi/strapi/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/types": { "version": "5.35.0", "resolved": "https://registry.npmjs.org/@strapi/types/-/types-5.35.0.tgz", @@ -7965,6 +8338,50 @@ } } }, + "node_modules/@strapi/upload/node_modules/@sindresorhus/slugify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-1.1.0.tgz", + "integrity": "sha512-ujZRbmmizX26yS/HnB3P9QNlNa4+UvHh+rIse3RbOXLp8yl6n1TxB4t7NHggtVgS8QmmOtzXo48kCxZGACpkPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/transliterate": "^0.1.1", + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@strapi/upload/node_modules/@sindresorhus/transliterate": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-0.1.2.tgz", + "integrity": "sha512-5/kmIOY9FF32nicXH+5yLNTX4NJ4atl7jRgqAJuIn/iyDFXBktOKDxCvyGE/EzmF4ngSUvjXxQUQlQiZ5lfw+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0", + "lodash.deburr": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@strapi/upload/node_modules/@sindresorhus/transliterate/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@strapi/upload/node_modules/@strapi/database": { "version": "5.33.3", "resolved": "https://registry.npmjs.org/@strapi/database/-/database-5.33.3.tgz", @@ -8205,6 +8622,25 @@ "node": ">=6" } }, + "node_modules/@strapi/upload/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/upload/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -8238,6 +8674,50 @@ "npm": ">=6.0.0" } }, + "node_modules/@strapi/utils/node_modules/@sindresorhus/slugify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-1.1.0.tgz", + "integrity": "sha512-ujZRbmmizX26yS/HnB3P9QNlNa4+UvHh+rIse3RbOXLp8yl6n1TxB4t7NHggtVgS8QmmOtzXo48kCxZGACpkPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/transliterate": "^0.1.1", + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@strapi/utils/node_modules/@sindresorhus/transliterate": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-0.1.2.tgz", + "integrity": "sha512-5/kmIOY9FF32nicXH+5yLNTX4NJ4atl7jRgqAJuIn/iyDFXBktOKDxCvyGE/EzmF4ngSUvjXxQUQlQiZ5lfw+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0", + "lodash.deburr": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@strapi/utils/node_modules/@sindresorhus/transliterate/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@strapi/utils/node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -8328,6 +8808,25 @@ "node": ">=6" } }, + "node_modules/@strapi/utils/node_modules/yup": { + "version": "0.32.9", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", + "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.15", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@strapi/utils/node_modules/zod": { "version": "3.25.67", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", @@ -9062,7 +9561,6 @@ "version": "4.17.23", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.23.tgz", "integrity": "sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==", - "dev": true, "license": "MIT" }, "node_modules/@types/mdast": { @@ -16356,7 +16854,6 @@ "version": "4.17.23", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", - "dev": true, "license": "MIT" }, "node_modules/lodash.clonedeep": { @@ -17762,7 +18259,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==", - "dev": true, "license": "MIT" }, "node_modules/nanoid": { @@ -19643,7 +20139,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", - "dev": true, "license": "MIT" }, "node_modules/property-information": { @@ -22447,7 +22942,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", - "dev": true, "license": "MIT" }, "node_modules/totalist": { @@ -24315,16 +24809,15 @@ } }, "node_modules/yup": { - "version": "0.32.9", - "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz", - "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==", - "dev": true, + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.10.5", - "@types/lodash": "^4.14.165", - "lodash": "^4.17.20", - "lodash-es": "^4.17.15", + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", "nanoclone": "^0.2.1", "property-expr": "^2.0.4", "toposort": "^2.0.2" diff --git a/package.json b/package.json index e90fd78..5297f20 100644 --- a/package.json +++ b/package.json @@ -31,9 +31,11 @@ "test:ts:back": "run -T tsc -p server/tsconfig.json" }, "dependencies": { + "@sindresorhus/slugify": "^2.2.1", "@strapi/design-system": "^2.0.0-rc.30", "@strapi/icons": "^2.0.0-rc.30", - "react-intl": "^7.1.14" + "react-intl": "^7.1.14", + "yup": "^0.32.11" }, "devDependencies": { "@strapi/sdk-plugin": "^5.4.0", |
