strapi-plugin-tags-custom-field 1.0.1 → 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 CHANGED
@@ -25,15 +25,14 @@ 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` (default: `,`): character used to split typed/pasted values.
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
- - The configured separator also adds the current tag.
34
+ - If configured, the separator also adds the current tag.
35
35
  - Paste supports multiple tags (newline or configured separator).
36
- - `Backspace` on empty input removes the last tag.
37
36
 
38
37
  ## Data format
39
38
 
@@ -50,7 +49,7 @@ Example:
50
49
  ## Compatibility
51
50
 
52
51
  - Strapi: `v5`
53
- - Node.js: `>=18`
52
+ - Node.js: `>=18 <25` (18 to 24)
54
53
 
55
54
  ## Local development (plugin repo)
56
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 DEFAULT_SEPARATOR = ",";
27
- const DEFAULT_MAX_TAGS = 20;
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,22 +83,24 @@ 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
  ({
98
97
  attribute,
98
+ description,
99
99
  disabled = false,
100
100
  error,
101
101
  hint,
102
102
  intlLabel,
103
+ label,
103
104
  name,
104
105
  onChange,
105
106
  placeholder,
@@ -115,7 +116,7 @@ const TagsInput = React__namespace.forwardRef(
115
116
  }, [value]);
116
117
  const fieldType = attribute?.type ?? "json";
117
118
  const options = attribute?.options ?? {};
118
- const separator = typeof options.separator === "string" && options.separator.trim().length > 0 ? options.separator.trim().charAt(0) : DEFAULT_SEPARATOR;
119
+ const separator = typeof options.separator === "string" && options.separator.trim().length > 0 ? options.separator.trim().charAt(0) : void 0;
119
120
  const maxTags = parsePositiveInt(options.maxTags, DEFAULT_MAX_TAGS);
120
121
  const maxTagLength = parsePositiveInt(
121
122
  options.maxTagLength,
@@ -123,13 +124,24 @@ const TagsInput = React__namespace.forwardRef(
123
124
  );
124
125
  const allowDuplicates = parseBoolean(options.allowDuplicates, false);
125
126
  const normalizeCase = normalizeCaseValue(options.normalizeCase);
126
- const label = intlLabel?.id || intlLabel?.defaultMessage ? formatMessage({
127
- id: intlLabel?.id ?? `${name}.label`,
128
- defaultMessage: intlLabel?.defaultMessage ?? "Tags"
129
- }) : "Tags";
130
- const hintMessage = hint ?? formatMessage({
127
+ const formatIntlMessage = React__namespace.useCallback(
128
+ (message) => {
129
+ if (!message?.id && !message?.defaultMessage) {
130
+ return void 0;
131
+ }
132
+ return formatMessage({
133
+ id: message.id ?? `${name}.label`,
134
+ defaultMessage: message.defaultMessage ?? "Tags"
135
+ });
136
+ },
137
+ [formatMessage, name]
138
+ );
139
+ const labelText = typeof label === "string" ? label : formatIntlMessage(label) ?? formatIntlMessage(intlLabel);
140
+ const labelMessage = labelText && labelText.trim().length > 0 ? labelText.trim() : "Tags";
141
+ const descriptionText = typeof description === "string" ? description : formatIntlMessage(description);
142
+ const hintMessage = descriptionText && descriptionText.trim().length > 0 ? descriptionText.trim() : hint ?? formatMessage({
131
143
  id: "tags-input.hint",
132
- 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."
133
145
  });
134
146
  const shownError = error || localError;
135
147
  const emitChange = React__namespace.useCallback(
@@ -149,58 +161,53 @@ const TagsInput = React__namespace.forwardRef(
149
161
  if (rawTags.length === 0) {
150
162
  return false;
151
163
  }
164
+ const nextTags = [...tags];
152
165
  let didChange = false;
153
- setTags((currentTags) => {
154
- const nextTags = [...currentTags];
155
- for (const rawTag of rawTags) {
156
- if (nextTags.length >= maxTags) {
157
- setLocalError(
158
- formatMessage(
159
- {
160
- id: "tags-input.error.max-tags",
161
- defaultMessage: "You can only add up to {maxTags} tags."
162
- },
163
- { maxTags }
164
- )
165
- );
166
- break;
167
- }
168
- if (rawTag.length > maxTagLength) {
169
- setLocalError(
170
- formatMessage(
171
- {
172
- id: "tags-input.error.max-length",
173
- defaultMessage: "Each tag must be at most {maxLength} characters."
174
- },
175
- { maxLength: maxTagLength }
176
- )
177
- );
178
- continue;
179
- }
180
- const duplicateIndex = nextTags.findIndex(
181
- (tag) => tag.toLowerCase() === rawTag.toLowerCase()
166
+ let nextError;
167
+ for (const rawTag of rawTags) {
168
+ if (nextTags.length >= maxTags) {
169
+ nextError = formatMessage(
170
+ {
171
+ id: "tags-input.error.max-tags",
172
+ defaultMessage: "You can only add up to {maxTags} tags."
173
+ },
174
+ { maxTags }
182
175
  );
183
- if (duplicateIndex !== -1 && !allowDuplicates) {
184
- setLocalError(
185
- formatMessage({
186
- id: "tags-input.error.duplicate",
187
- defaultMessage: "Duplicate tags are not allowed."
188
- })
189
- );
190
- continue;
191
- }
192
- nextTags.push(rawTag);
193
- didChange = true;
176
+ break;
194
177
  }
195
- if (didChange) {
196
- setLocalError(void 0);
197
- emitChange(nextTags);
178
+ if (rawTag.length > maxTagLength) {
179
+ nextError = formatMessage(
180
+ {
181
+ id: "tags-input.error.max-length",
182
+ defaultMessage: "Each tag must be at most {maxLength} characters."
183
+ },
184
+ { maxLength: maxTagLength }
185
+ );
186
+ continue;
198
187
  }
199
- return didChange ? nextTags : currentTags;
200
- });
188
+ const duplicateIndex = nextTags.findIndex(
189
+ (tag) => tag.toLowerCase() === rawTag.toLowerCase()
190
+ );
191
+ if (duplicateIndex !== -1 && !allowDuplicates) {
192
+ nextError = formatMessage({
193
+ id: "tags-input.error.duplicate",
194
+ defaultMessage: "Duplicate tags are not allowed."
195
+ });
196
+ continue;
197
+ }
198
+ nextTags.push(rawTag);
199
+ didChange = true;
200
+ }
201
+ if (didChange) {
202
+ setTags(nextTags);
203
+ setLocalError(void 0);
204
+ emitChange(nextTags);
205
+ } else if (nextError) {
206
+ setLocalError(nextError);
207
+ }
201
208
  return didChange;
202
209
  },
203
- [allowDuplicates, emitChange, formatMessage, maxTagLength, maxTags]
210
+ [allowDuplicates, emitChange, formatMessage, maxTagLength, maxTags, tags]
204
211
  );
205
212
  const commitDraft = React__namespace.useCallback(() => {
206
213
  const parsedTags = parseRawTags(draft, separator, normalizeCase);
@@ -219,26 +226,11 @@ const TagsInput = React__namespace.forwardRef(
219
226
  },
220
227
  [emitChange]
221
228
  );
222
- const removeLastTag = React__namespace.useCallback(() => {
223
- setTags((currentTags) => {
224
- if (currentTags.length === 0) {
225
- return currentTags;
226
- }
227
- const nextTags = currentTags.slice(0, currentTags.length - 1);
228
- emitChange(nextTags);
229
- setLocalError(void 0);
230
- return nextTags;
231
- });
232
- }, [emitChange]);
233
229
  const onKeyDown = (event) => {
234
- if (event.key === "Enter" || event.key === separator) {
230
+ if (event.key === "Enter" || separator && event.key === separator) {
235
231
  event.preventDefault();
236
232
  commitDraft();
237
233
  }
238
- if (event.key === "Backspace" && draft.length === 0 && !disabled) {
239
- event.preventDefault();
240
- removeLastTag();
241
- }
242
234
  };
243
235
  const onPaste = (event) => {
244
236
  const pastedText = event.clipboardData.getData("text");
@@ -247,7 +239,10 @@ const TagsInput = React__namespace.forwardRef(
247
239
  }
248
240
  event.preventDefault();
249
241
  const parsedTags = parseRawTags(pastedText, separator, normalizeCase);
250
- addTags(parsedTags);
242
+ const added = addTags(parsedTags);
243
+ if (added) {
244
+ setDraft("");
245
+ }
251
246
  };
252
247
  return /* @__PURE__ */ jsxRuntime.jsx(
253
248
  designSystem.Field.Root,
@@ -258,7 +253,8 @@ const TagsInput = React__namespace.forwardRef(
258
253
  hint: hintMessage,
259
254
  error: shownError,
260
255
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
261
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: label }),
256
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: labelMessage }),
257
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}),
262
258
  tags.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
263
259
  designSystem.Box,
264
260
  {
@@ -311,13 +307,16 @@ const TagsInput = React__namespace.forwardRef(
311
307
  onBlur: commitDraft,
312
308
  onKeyDown,
313
309
  onPaste,
314
- placeholder: placeholder ?? formatMessage(
310
+ placeholder: placeholder ?? (separator ? formatMessage(
315
311
  {
316
- id: "tags-input.placeholder",
312
+ id: "tags-input.placeholder.with-separator",
317
313
  defaultMessage: "Type a tag and press Enter or {separator} to add it"
318
314
  },
319
315
  { separator }
320
- )
316
+ ) : formatMessage({
317
+ id: "tags-input.placeholder.without-separator",
318
+ defaultMessage: "Type a tag and press Enter to add it"
319
+ }))
321
320
  }
322
321
  ),
323
322
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 2, children: [
@@ -343,7 +342,6 @@ const TagsInput = React__namespace.forwardRef(
343
342
  }
344
343
  )
345
344
  ] }),
346
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}),
347
345
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
348
346
  ] })
349
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 DEFAULT_SEPARATOR = ",";
7
- const DEFAULT_MAX_TAGS = 20;
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,22 +63,24 @@ 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
  ({
78
77
  attribute,
78
+ description,
79
79
  disabled = false,
80
80
  error,
81
81
  hint,
82
82
  intlLabel,
83
+ label,
83
84
  name,
84
85
  onChange,
85
86
  placeholder,
@@ -95,7 +96,7 @@ const TagsInput = React.forwardRef(
95
96
  }, [value]);
96
97
  const fieldType = attribute?.type ?? "json";
97
98
  const options = attribute?.options ?? {};
98
- const separator = typeof options.separator === "string" && options.separator.trim().length > 0 ? options.separator.trim().charAt(0) : DEFAULT_SEPARATOR;
99
+ const separator = typeof options.separator === "string" && options.separator.trim().length > 0 ? options.separator.trim().charAt(0) : void 0;
99
100
  const maxTags = parsePositiveInt(options.maxTags, DEFAULT_MAX_TAGS);
100
101
  const maxTagLength = parsePositiveInt(
101
102
  options.maxTagLength,
@@ -103,13 +104,24 @@ const TagsInput = React.forwardRef(
103
104
  );
104
105
  const allowDuplicates = parseBoolean(options.allowDuplicates, false);
105
106
  const normalizeCase = normalizeCaseValue(options.normalizeCase);
106
- const label = intlLabel?.id || intlLabel?.defaultMessage ? formatMessage({
107
- id: intlLabel?.id ?? `${name}.label`,
108
- defaultMessage: intlLabel?.defaultMessage ?? "Tags"
109
- }) : "Tags";
110
- const hintMessage = hint ?? formatMessage({
107
+ const formatIntlMessage = React.useCallback(
108
+ (message) => {
109
+ if (!message?.id && !message?.defaultMessage) {
110
+ return void 0;
111
+ }
112
+ return formatMessage({
113
+ id: message.id ?? `${name}.label`,
114
+ defaultMessage: message.defaultMessage ?? "Tags"
115
+ });
116
+ },
117
+ [formatMessage, name]
118
+ );
119
+ const labelText = typeof label === "string" ? label : formatIntlMessage(label) ?? formatIntlMessage(intlLabel);
120
+ const labelMessage = labelText && labelText.trim().length > 0 ? labelText.trim() : "Tags";
121
+ const descriptionText = typeof description === "string" ? description : formatIntlMessage(description);
122
+ const hintMessage = descriptionText && descriptionText.trim().length > 0 ? descriptionText.trim() : hint ?? formatMessage({
111
123
  id: "tags-input.hint",
112
- 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."
113
125
  });
114
126
  const shownError = error || localError;
115
127
  const emitChange = React.useCallback(
@@ -129,58 +141,53 @@ const TagsInput = React.forwardRef(
129
141
  if (rawTags.length === 0) {
130
142
  return false;
131
143
  }
144
+ const nextTags = [...tags];
132
145
  let didChange = false;
133
- setTags((currentTags) => {
134
- const nextTags = [...currentTags];
135
- for (const rawTag of rawTags) {
136
- if (nextTags.length >= maxTags) {
137
- setLocalError(
138
- formatMessage(
139
- {
140
- id: "tags-input.error.max-tags",
141
- defaultMessage: "You can only add up to {maxTags} tags."
142
- },
143
- { maxTags }
144
- )
145
- );
146
- break;
147
- }
148
- if (rawTag.length > maxTagLength) {
149
- setLocalError(
150
- formatMessage(
151
- {
152
- id: "tags-input.error.max-length",
153
- defaultMessage: "Each tag must be at most {maxLength} characters."
154
- },
155
- { maxLength: maxTagLength }
156
- )
157
- );
158
- continue;
159
- }
160
- const duplicateIndex = nextTags.findIndex(
161
- (tag) => tag.toLowerCase() === rawTag.toLowerCase()
146
+ let nextError;
147
+ for (const rawTag of rawTags) {
148
+ if (nextTags.length >= maxTags) {
149
+ nextError = formatMessage(
150
+ {
151
+ id: "tags-input.error.max-tags",
152
+ defaultMessage: "You can only add up to {maxTags} tags."
153
+ },
154
+ { maxTags }
162
155
  );
163
- if (duplicateIndex !== -1 && !allowDuplicates) {
164
- setLocalError(
165
- formatMessage({
166
- id: "tags-input.error.duplicate",
167
- defaultMessage: "Duplicate tags are not allowed."
168
- })
169
- );
170
- continue;
171
- }
172
- nextTags.push(rawTag);
173
- didChange = true;
156
+ break;
174
157
  }
175
- if (didChange) {
176
- setLocalError(void 0);
177
- emitChange(nextTags);
158
+ if (rawTag.length > maxTagLength) {
159
+ nextError = formatMessage(
160
+ {
161
+ id: "tags-input.error.max-length",
162
+ defaultMessage: "Each tag must be at most {maxLength} characters."
163
+ },
164
+ { maxLength: maxTagLength }
165
+ );
166
+ continue;
178
167
  }
179
- return didChange ? nextTags : currentTags;
180
- });
168
+ const duplicateIndex = nextTags.findIndex(
169
+ (tag) => tag.toLowerCase() === rawTag.toLowerCase()
170
+ );
171
+ if (duplicateIndex !== -1 && !allowDuplicates) {
172
+ nextError = formatMessage({
173
+ id: "tags-input.error.duplicate",
174
+ defaultMessage: "Duplicate tags are not allowed."
175
+ });
176
+ continue;
177
+ }
178
+ nextTags.push(rawTag);
179
+ didChange = true;
180
+ }
181
+ if (didChange) {
182
+ setTags(nextTags);
183
+ setLocalError(void 0);
184
+ emitChange(nextTags);
185
+ } else if (nextError) {
186
+ setLocalError(nextError);
187
+ }
181
188
  return didChange;
182
189
  },
183
- [allowDuplicates, emitChange, formatMessage, maxTagLength, maxTags]
190
+ [allowDuplicates, emitChange, formatMessage, maxTagLength, maxTags, tags]
184
191
  );
185
192
  const commitDraft = React.useCallback(() => {
186
193
  const parsedTags = parseRawTags(draft, separator, normalizeCase);
@@ -199,26 +206,11 @@ const TagsInput = React.forwardRef(
199
206
  },
200
207
  [emitChange]
201
208
  );
202
- const removeLastTag = React.useCallback(() => {
203
- setTags((currentTags) => {
204
- if (currentTags.length === 0) {
205
- return currentTags;
206
- }
207
- const nextTags = currentTags.slice(0, currentTags.length - 1);
208
- emitChange(nextTags);
209
- setLocalError(void 0);
210
- return nextTags;
211
- });
212
- }, [emitChange]);
213
209
  const onKeyDown = (event) => {
214
- if (event.key === "Enter" || event.key === separator) {
210
+ if (event.key === "Enter" || separator && event.key === separator) {
215
211
  event.preventDefault();
216
212
  commitDraft();
217
213
  }
218
- if (event.key === "Backspace" && draft.length === 0 && !disabled) {
219
- event.preventDefault();
220
- removeLastTag();
221
- }
222
214
  };
223
215
  const onPaste = (event) => {
224
216
  const pastedText = event.clipboardData.getData("text");
@@ -227,7 +219,10 @@ const TagsInput = React.forwardRef(
227
219
  }
228
220
  event.preventDefault();
229
221
  const parsedTags = parseRawTags(pastedText, separator, normalizeCase);
230
- addTags(parsedTags);
222
+ const added = addTags(parsedTags);
223
+ if (added) {
224
+ setDraft("");
225
+ }
231
226
  };
232
227
  return /* @__PURE__ */ jsx(
233
228
  Field.Root,
@@ -238,7 +233,8 @@ const TagsInput = React.forwardRef(
238
233
  hint: hintMessage,
239
234
  error: shownError,
240
235
  children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
241
- /* @__PURE__ */ jsx(Field.Label, { children: label }),
236
+ /* @__PURE__ */ jsx(Field.Label, { children: labelMessage }),
237
+ /* @__PURE__ */ jsx(Field.Hint, {}),
242
238
  tags.length > 0 ? /* @__PURE__ */ jsx(
243
239
  Box,
244
240
  {
@@ -291,13 +287,16 @@ const TagsInput = React.forwardRef(
291
287
  onBlur: commitDraft,
292
288
  onKeyDown,
293
289
  onPaste,
294
- placeholder: placeholder ?? formatMessage(
290
+ placeholder: placeholder ?? (separator ? formatMessage(
295
291
  {
296
- id: "tags-input.placeholder",
292
+ id: "tags-input.placeholder.with-separator",
297
293
  defaultMessage: "Type a tag and press Enter or {separator} to add it"
298
294
  },
299
295
  { separator }
300
- )
296
+ ) : formatMessage({
297
+ id: "tags-input.placeholder.without-separator",
298
+ defaultMessage: "Type a tag and press Enter to add it"
299
+ }))
301
300
  }
302
301
  ),
303
302
  /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 2, children: [
@@ -323,7 +322,6 @@ const TagsInput = React.forwardRef(
323
322
  }
324
323
  )
325
324
  ] }),
326
- /* @__PURE__ */ jsx(Field.Hint, {}),
327
325
  /* @__PURE__ */ jsx(Field.Error, {})
328
326
  ] })
329
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",
@@ -66,7 +66,7 @@ const index = {
66
66
  },
67
67
  icon: PluginIcon,
68
68
  components: {
69
- Input: async () => Promise.resolve().then(() => require("./TagsInput-BGUydL2t.js")).then((module2) => ({
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-C_FVtF2u.js")) }), `./translations/${locale}.json`, 3);
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 };
@@ -64,7 +64,7 @@ const index = {
64
64
  },
65
65
  icon: PluginIcon,
66
66
  components: {
67
- Input: async () => import("./TagsInput-CCehyU5Y.mjs").then((module) => ({
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-BhiXf-Vq.mjs") }), `./translations/${locale}.json`, 3);
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.1",
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.0.0"
77
+ "node": ">=18 <25"
78
78
  },
79
79
  "repository": {
80
80
  "type": "git",