strapi-plugin-tags-custom-field 1.0.2 → 1.0.4
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/README.md +3 -3
- package/dist/admin/{TagsInput-BfjqO_MO.js → TagsInput-Bed2AKfo.js} +14 -12
- package/dist/admin/{TagsInput-CzXiRuEv.mjs → TagsInput-C96IrAdH.mjs} +14 -12
- package/dist/admin/{en-C_FVtF2u.js → en-B10Zs0Lz.js} +2 -2
- package/dist/admin/{en-BhiXf-Vq.mjs → en-vnGnUwx5.mjs} +2 -2
- package/dist/admin/index.js +5 -5
- package/dist/admin/index.mjs +5 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -25,13 +25,13 @@ Restart your Strapi server after installation.
|
|
|
25
25
|
- `maxTags` (default: `20`): maximum number of tags.
|
|
26
26
|
- `maxTagLength` (default: `40`): maximum characters per tag.
|
|
27
27
|
- `allowDuplicates` (default: `false`): allow repeated tags.
|
|
28
|
-
- `separator` (
|
|
28
|
+
- `separator` (optional): character used to split typed/pasted values.
|
|
29
29
|
- `normalizeCase` (default: `none`): `none`, `lowercase`, or `UPPERCASE`.
|
|
30
30
|
|
|
31
31
|
## Input behavior
|
|
32
32
|
|
|
33
33
|
- `Enter` adds the current tag.
|
|
34
|
-
-
|
|
34
|
+
- If configured, the separator also adds the current tag.
|
|
35
35
|
- Paste supports multiple tags (newline or configured separator).
|
|
36
36
|
|
|
37
37
|
## Data format
|
|
@@ -49,7 +49,7 @@ Example:
|
|
|
49
49
|
## Compatibility
|
|
50
50
|
|
|
51
51
|
- Strapi: `v5`
|
|
52
|
-
- Node.js: `>=18`
|
|
52
|
+
- Node.js: `>=18 <25` (18 to 24)
|
|
53
53
|
|
|
54
54
|
## Local development (plugin repo)
|
|
55
55
|
|
|
@@ -23,9 +23,8 @@ function _interopNamespace(e) {
|
|
|
23
23
|
return Object.freeze(n);
|
|
24
24
|
}
|
|
25
25
|
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const DEFAULT_MAX_TAG_LENGTH = 40;
|
|
26
|
+
const DEFAULT_MAX_TAGS = 50;
|
|
27
|
+
const DEFAULT_MAX_TAG_LENGTH = 100;
|
|
29
28
|
const parseTagsValue = (value) => {
|
|
30
29
|
if (Array.isArray(value)) {
|
|
31
30
|
return value.map((item) => String(item).trim()).filter((item) => item.length > 0);
|
|
@@ -84,14 +83,14 @@ const parsePositiveInt = (value, fallbackValue) => {
|
|
|
84
83
|
};
|
|
85
84
|
const getSplitRegex = (separator) => {
|
|
86
85
|
const characters = Array.from(/* @__PURE__ */ new Set([separator, "\n", "\r"])).filter(
|
|
87
|
-
(character) => character.length > 0
|
|
86
|
+
(character) => typeof character === "string" && character.length > 0
|
|
88
87
|
);
|
|
89
88
|
const escapedCharacters = characters.map((character) => character.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("");
|
|
90
89
|
return new RegExp(`[${escapedCharacters}]+`);
|
|
91
90
|
};
|
|
92
91
|
const parseRawTags = (rawValue, separator, normalizeCase) => rawValue.split(getSplitRegex(separator)).map((tag) => normalizeTag(tag, normalizeCase)).filter((tag) => tag.length > 0);
|
|
93
92
|
const hasSplitCharacters = (value, separator) => [separator, "\n", "\r"].some(
|
|
94
|
-
(character) => character.length > 0 && value.includes(character)
|
|
93
|
+
(character) => typeof character === "string" && character.length > 0 && value.includes(character)
|
|
95
94
|
);
|
|
96
95
|
const TagsInput = React__namespace.forwardRef(
|
|
97
96
|
({
|
|
@@ -117,7 +116,7 @@ const TagsInput = React__namespace.forwardRef(
|
|
|
117
116
|
}, [value]);
|
|
118
117
|
const fieldType = attribute?.type ?? "json";
|
|
119
118
|
const options = attribute?.options ?? {};
|
|
120
|
-
const separator = typeof options.separator === "string" && options.separator.trim().length > 0 ? options.separator.trim().charAt(0) :
|
|
119
|
+
const separator = typeof options.separator === "string" && options.separator.trim().length > 0 ? options.separator.trim().charAt(0) : void 0;
|
|
121
120
|
const maxTags = parsePositiveInt(options.maxTags, DEFAULT_MAX_TAGS);
|
|
122
121
|
const maxTagLength = parsePositiveInt(
|
|
123
122
|
options.maxTagLength,
|
|
@@ -142,7 +141,7 @@ const TagsInput = React__namespace.forwardRef(
|
|
|
142
141
|
const descriptionText = typeof description === "string" ? description : formatIntlMessage(description);
|
|
143
142
|
const hintMessage = descriptionText && descriptionText.trim().length > 0 ? descriptionText.trim() : hint ?? formatMessage({
|
|
144
143
|
id: "tags-input.hint",
|
|
145
|
-
defaultMessage: "Press Enter or type the separator to add tags. Paste multiple tags at once."
|
|
144
|
+
defaultMessage: separator ? "Press Enter or type the separator to add tags. Paste multiple tags at once." : "Press Enter to add tags. Paste multiple tags at once."
|
|
146
145
|
});
|
|
147
146
|
const shownError = error || localError;
|
|
148
147
|
const emitChange = React__namespace.useCallback(
|
|
@@ -228,7 +227,7 @@ const TagsInput = React__namespace.forwardRef(
|
|
|
228
227
|
[emitChange]
|
|
229
228
|
);
|
|
230
229
|
const onKeyDown = (event) => {
|
|
231
|
-
if (event.key === "Enter" || event.key === separator) {
|
|
230
|
+
if (event.key === "Enter" || separator && event.key === separator) {
|
|
232
231
|
event.preventDefault();
|
|
233
232
|
commitDraft();
|
|
234
233
|
}
|
|
@@ -255,6 +254,7 @@ const TagsInput = React__namespace.forwardRef(
|
|
|
255
254
|
error: shownError,
|
|
256
255
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
|
257
256
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: labelMessage }),
|
|
257
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}),
|
|
258
258
|
tags.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
259
259
|
designSystem.Box,
|
|
260
260
|
{
|
|
@@ -307,13 +307,16 @@ const TagsInput = React__namespace.forwardRef(
|
|
|
307
307
|
onBlur: commitDraft,
|
|
308
308
|
onKeyDown,
|
|
309
309
|
onPaste,
|
|
310
|
-
placeholder: placeholder ?? formatMessage(
|
|
310
|
+
placeholder: placeholder ?? (separator ? formatMessage(
|
|
311
311
|
{
|
|
312
|
-
id: "tags-input.placeholder",
|
|
312
|
+
id: "tags-input.placeholder.with-separator",
|
|
313
313
|
defaultMessage: "Type a tag and press Enter or {separator} to add it"
|
|
314
314
|
},
|
|
315
315
|
{ separator }
|
|
316
|
-
)
|
|
316
|
+
) : formatMessage({
|
|
317
|
+
id: "tags-input.placeholder.without-separator",
|
|
318
|
+
defaultMessage: "Type a tag and press Enter to add it"
|
|
319
|
+
}))
|
|
317
320
|
}
|
|
318
321
|
),
|
|
319
322
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 2, children: [
|
|
@@ -339,7 +342,6 @@ const TagsInput = React__namespace.forwardRef(
|
|
|
339
342
|
}
|
|
340
343
|
)
|
|
341
344
|
] }),
|
|
342
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}),
|
|
343
345
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
|
|
344
346
|
] })
|
|
345
347
|
}
|
|
@@ -3,9 +3,8 @@ import * as React from "react";
|
|
|
3
3
|
import { Field, Flex, Box, Tag, TextInput, Typography } from "@strapi/design-system";
|
|
4
4
|
import { Cross } from "@strapi/icons";
|
|
5
5
|
import { useIntl } from "react-intl";
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const DEFAULT_MAX_TAG_LENGTH = 40;
|
|
6
|
+
const DEFAULT_MAX_TAGS = 50;
|
|
7
|
+
const DEFAULT_MAX_TAG_LENGTH = 100;
|
|
9
8
|
const parseTagsValue = (value) => {
|
|
10
9
|
if (Array.isArray(value)) {
|
|
11
10
|
return value.map((item) => String(item).trim()).filter((item) => item.length > 0);
|
|
@@ -64,14 +63,14 @@ const parsePositiveInt = (value, fallbackValue) => {
|
|
|
64
63
|
};
|
|
65
64
|
const getSplitRegex = (separator) => {
|
|
66
65
|
const characters = Array.from(/* @__PURE__ */ new Set([separator, "\n", "\r"])).filter(
|
|
67
|
-
(character) => character.length > 0
|
|
66
|
+
(character) => typeof character === "string" && character.length > 0
|
|
68
67
|
);
|
|
69
68
|
const escapedCharacters = characters.map((character) => character.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("");
|
|
70
69
|
return new RegExp(`[${escapedCharacters}]+`);
|
|
71
70
|
};
|
|
72
71
|
const parseRawTags = (rawValue, separator, normalizeCase) => rawValue.split(getSplitRegex(separator)).map((tag) => normalizeTag(tag, normalizeCase)).filter((tag) => tag.length > 0);
|
|
73
72
|
const hasSplitCharacters = (value, separator) => [separator, "\n", "\r"].some(
|
|
74
|
-
(character) => character.length > 0 && value.includes(character)
|
|
73
|
+
(character) => typeof character === "string" && character.length > 0 && value.includes(character)
|
|
75
74
|
);
|
|
76
75
|
const TagsInput = React.forwardRef(
|
|
77
76
|
({
|
|
@@ -97,7 +96,7 @@ const TagsInput = React.forwardRef(
|
|
|
97
96
|
}, [value]);
|
|
98
97
|
const fieldType = attribute?.type ?? "json";
|
|
99
98
|
const options = attribute?.options ?? {};
|
|
100
|
-
const separator = typeof options.separator === "string" && options.separator.trim().length > 0 ? options.separator.trim().charAt(0) :
|
|
99
|
+
const separator = typeof options.separator === "string" && options.separator.trim().length > 0 ? options.separator.trim().charAt(0) : void 0;
|
|
101
100
|
const maxTags = parsePositiveInt(options.maxTags, DEFAULT_MAX_TAGS);
|
|
102
101
|
const maxTagLength = parsePositiveInt(
|
|
103
102
|
options.maxTagLength,
|
|
@@ -122,7 +121,7 @@ const TagsInput = React.forwardRef(
|
|
|
122
121
|
const descriptionText = typeof description === "string" ? description : formatIntlMessage(description);
|
|
123
122
|
const hintMessage = descriptionText && descriptionText.trim().length > 0 ? descriptionText.trim() : hint ?? formatMessage({
|
|
124
123
|
id: "tags-input.hint",
|
|
125
|
-
defaultMessage: "Press Enter or type the separator to add tags. Paste multiple tags at once."
|
|
124
|
+
defaultMessage: separator ? "Press Enter or type the separator to add tags. Paste multiple tags at once." : "Press Enter to add tags. Paste multiple tags at once."
|
|
126
125
|
});
|
|
127
126
|
const shownError = error || localError;
|
|
128
127
|
const emitChange = React.useCallback(
|
|
@@ -208,7 +207,7 @@ const TagsInput = React.forwardRef(
|
|
|
208
207
|
[emitChange]
|
|
209
208
|
);
|
|
210
209
|
const onKeyDown = (event) => {
|
|
211
|
-
if (event.key === "Enter" || event.key === separator) {
|
|
210
|
+
if (event.key === "Enter" || separator && event.key === separator) {
|
|
212
211
|
event.preventDefault();
|
|
213
212
|
commitDraft();
|
|
214
213
|
}
|
|
@@ -235,6 +234,7 @@ const TagsInput = React.forwardRef(
|
|
|
235
234
|
error: shownError,
|
|
236
235
|
children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
|
237
236
|
/* @__PURE__ */ jsx(Field.Label, { children: labelMessage }),
|
|
237
|
+
/* @__PURE__ */ jsx(Field.Hint, {}),
|
|
238
238
|
tags.length > 0 ? /* @__PURE__ */ jsx(
|
|
239
239
|
Box,
|
|
240
240
|
{
|
|
@@ -287,13 +287,16 @@ const TagsInput = React.forwardRef(
|
|
|
287
287
|
onBlur: commitDraft,
|
|
288
288
|
onKeyDown,
|
|
289
289
|
onPaste,
|
|
290
|
-
placeholder: placeholder ?? formatMessage(
|
|
290
|
+
placeholder: placeholder ?? (separator ? formatMessage(
|
|
291
291
|
{
|
|
292
|
-
id: "tags-input.placeholder",
|
|
292
|
+
id: "tags-input.placeholder.with-separator",
|
|
293
293
|
defaultMessage: "Type a tag and press Enter or {separator} to add it"
|
|
294
294
|
},
|
|
295
295
|
{ separator }
|
|
296
|
-
)
|
|
296
|
+
) : formatMessage({
|
|
297
|
+
id: "tags-input.placeholder.without-separator",
|
|
298
|
+
defaultMessage: "Type a tag and press Enter to add it"
|
|
299
|
+
}))
|
|
297
300
|
}
|
|
298
301
|
),
|
|
299
302
|
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 2, children: [
|
|
@@ -319,7 +322,6 @@ const TagsInput = React.forwardRef(
|
|
|
319
322
|
}
|
|
320
323
|
)
|
|
321
324
|
] }),
|
|
322
|
-
/* @__PURE__ */ jsx(Field.Hint, {}),
|
|
323
325
|
/* @__PURE__ */ jsx(Field.Error, {})
|
|
324
326
|
] })
|
|
325
327
|
}
|
|
@@ -6,9 +6,9 @@ const en = {
|
|
|
6
6
|
"field.tags.description": "Store tags as a JSON array",
|
|
7
7
|
"field.tags.options.behavior.section": "Tag behavior",
|
|
8
8
|
"field.tags.options.maxTags.label": "Maximum tags",
|
|
9
|
-
"field.tags.options.maxTags.description": "Maximum number of tags allowed",
|
|
9
|
+
"field.tags.options.maxTags.description": "Maximum number of tags allowed (default 50)",
|
|
10
10
|
"field.tags.options.maxTagLength.label": "Maximum tag length",
|
|
11
|
-
"field.tags.options.maxTagLength.description": "Maximum number of characters per tag",
|
|
11
|
+
"field.tags.options.maxTagLength.description": "Maximum number of characters per tag (default 100)",
|
|
12
12
|
"field.tags.options.allowDuplicates.label": "Allow duplicates",
|
|
13
13
|
"field.tags.options.allowDuplicates.description": "Allow repeated tags in the same value",
|
|
14
14
|
"field.tags.options.input.section": "Input parsing",
|
|
@@ -4,9 +4,9 @@ const en = {
|
|
|
4
4
|
"field.tags.description": "Store tags as a JSON array",
|
|
5
5
|
"field.tags.options.behavior.section": "Tag behavior",
|
|
6
6
|
"field.tags.options.maxTags.label": "Maximum tags",
|
|
7
|
-
"field.tags.options.maxTags.description": "Maximum number of tags allowed",
|
|
7
|
+
"field.tags.options.maxTags.description": "Maximum number of tags allowed (default 50)",
|
|
8
8
|
"field.tags.options.maxTagLength.label": "Maximum tag length",
|
|
9
|
-
"field.tags.options.maxTagLength.description": "Maximum number of characters per tag",
|
|
9
|
+
"field.tags.options.maxTagLength.description": "Maximum number of characters per tag (default 100)",
|
|
10
10
|
"field.tags.options.allowDuplicates.label": "Allow duplicates",
|
|
11
11
|
"field.tags.options.allowDuplicates.description": "Allow repeated tags in the same value",
|
|
12
12
|
"field.tags.options.input.section": "Input parsing",
|
package/dist/admin/index.js
CHANGED
|
@@ -66,7 +66,7 @@ const index = {
|
|
|
66
66
|
},
|
|
67
67
|
icon: PluginIcon,
|
|
68
68
|
components: {
|
|
69
|
-
Input: async () => Promise.resolve().then(() => require("./TagsInput-
|
|
69
|
+
Input: async () => Promise.resolve().then(() => require("./TagsInput-Bed2AKfo.js")).then((module2) => ({
|
|
70
70
|
default: module2.TagsInput
|
|
71
71
|
}))
|
|
72
72
|
},
|
|
@@ -85,7 +85,7 @@ const index = {
|
|
|
85
85
|
},
|
|
86
86
|
description: {
|
|
87
87
|
id: getTranslation("field.tags.options.maxTags.description"),
|
|
88
|
-
defaultMessage: "Maximum number of tags allowed"
|
|
88
|
+
defaultMessage: "Maximum number of tags allowed (default 50)"
|
|
89
89
|
},
|
|
90
90
|
name: "options.maxTags",
|
|
91
91
|
type: "number",
|
|
@@ -100,7 +100,7 @@ const index = {
|
|
|
100
100
|
id: getTranslation(
|
|
101
101
|
"field.tags.options.maxTagLength.description"
|
|
102
102
|
),
|
|
103
|
-
defaultMessage: "Maximum number of characters per tag"
|
|
103
|
+
defaultMessage: "Maximum number of characters per tag (default 100)"
|
|
104
104
|
},
|
|
105
105
|
name: "options.maxTagLength",
|
|
106
106
|
type: "number",
|
|
@@ -140,7 +140,7 @@ const index = {
|
|
|
140
140
|
},
|
|
141
141
|
name: "options.separator",
|
|
142
142
|
type: "text",
|
|
143
|
-
value: "
|
|
143
|
+
value: ""
|
|
144
144
|
},
|
|
145
145
|
{
|
|
146
146
|
intlLabel: {
|
|
@@ -209,7 +209,7 @@ const index = {
|
|
|
209
209
|
return Promise.all(
|
|
210
210
|
locales.map(async (locale) => {
|
|
211
211
|
try {
|
|
212
|
-
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-
|
|
212
|
+
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-B10Zs0Lz.js")) }), `./translations/${locale}.json`, 3);
|
|
213
213
|
return { data, locale };
|
|
214
214
|
} catch {
|
|
215
215
|
return { data: {}, locale };
|
package/dist/admin/index.mjs
CHANGED
|
@@ -64,7 +64,7 @@ const index = {
|
|
|
64
64
|
},
|
|
65
65
|
icon: PluginIcon,
|
|
66
66
|
components: {
|
|
67
|
-
Input: async () => import("./TagsInput-
|
|
67
|
+
Input: async () => import("./TagsInput-C96IrAdH.mjs").then((module) => ({
|
|
68
68
|
default: module.TagsInput
|
|
69
69
|
}))
|
|
70
70
|
},
|
|
@@ -83,7 +83,7 @@ const index = {
|
|
|
83
83
|
},
|
|
84
84
|
description: {
|
|
85
85
|
id: getTranslation("field.tags.options.maxTags.description"),
|
|
86
|
-
defaultMessage: "Maximum number of tags allowed"
|
|
86
|
+
defaultMessage: "Maximum number of tags allowed (default 50)"
|
|
87
87
|
},
|
|
88
88
|
name: "options.maxTags",
|
|
89
89
|
type: "number",
|
|
@@ -98,7 +98,7 @@ const index = {
|
|
|
98
98
|
id: getTranslation(
|
|
99
99
|
"field.tags.options.maxTagLength.description"
|
|
100
100
|
),
|
|
101
|
-
defaultMessage: "Maximum number of characters per tag"
|
|
101
|
+
defaultMessage: "Maximum number of characters per tag (default 100)"
|
|
102
102
|
},
|
|
103
103
|
name: "options.maxTagLength",
|
|
104
104
|
type: "number",
|
|
@@ -138,7 +138,7 @@ const index = {
|
|
|
138
138
|
},
|
|
139
139
|
name: "options.separator",
|
|
140
140
|
type: "text",
|
|
141
|
-
value: "
|
|
141
|
+
value: ""
|
|
142
142
|
},
|
|
143
143
|
{
|
|
144
144
|
intlLabel: {
|
|
@@ -207,7 +207,7 @@ const index = {
|
|
|
207
207
|
return Promise.all(
|
|
208
208
|
locales.map(async (locale) => {
|
|
209
209
|
try {
|
|
210
|
-
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-
|
|
210
|
+
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-vnGnUwx5.mjs") }), `./translations/${locale}.json`, 3);
|
|
211
211
|
return { data, locale };
|
|
212
212
|
} catch {
|
|
213
213
|
return { data: {}, locale };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-plugin-tags-custom-field",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Custom field plugin for Strapi 5 to manage tags (array of strings) stored as JSON array.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"strapi",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"description": "Custom field for tags (array of strings) stored as JSON array"
|
|
75
75
|
},
|
|
76
76
|
"engines": {
|
|
77
|
-
"node": ">=18
|
|
77
|
+
"node": ">=18 <25"
|
|
78
78
|
},
|
|
79
79
|
"repository": {
|
|
80
80
|
"type": "git",
|