@webbycrown/advanced-fields 1.0.1 → 1.0.2
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 +19 -6
- package/admin/src/components/AdvancedCheckbox/index.jsx +17 -37
- package/admin/src/components/AdvancedInput/index.jsx +18 -2
- package/admin/src/components/AdvancedRadio/index.jsx +17 -17
- package/admin/src/components/PluginIcon.jsx +34 -41
- package/admin/src/index.js +52 -4
- package/index.js +3 -47
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
Professional custom fields for Strapi CMS that provide advanced functionality with comprehensive validation, dynamic options, and user-friendly interfaces.
|
|
8
8
|
|
|
9
|
+
📦 **NPM Package**: [@webbycrown/advanced-fields](https://www.npmjs.com/package/@webbycrown/advanced-fields)
|
|
10
|
+
|
|
9
11
|
## ✨ Features
|
|
10
12
|
|
|
11
13
|
### 🔤 Advanced Input
|
|
@@ -14,6 +16,7 @@ Professional custom fields for Strapi CMS that provide advanced functionality wi
|
|
|
14
16
|
- **Custom Error Messages**: User-friendly validation feedback
|
|
15
17
|
- **Default Values**: Pre-filled content for new entries
|
|
16
18
|
- **Placeholder Support**: Helpful hints for content creators
|
|
19
|
+
- **Field Notes**: Display helpful notes below the field
|
|
17
20
|
- **Private Fields**: Hide sensitive data from API responses
|
|
18
21
|
|
|
19
22
|
### ☑️ Advanced Checkbox
|
|
@@ -22,6 +25,7 @@ Professional custom fields for Strapi CMS that provide advanced functionality wi
|
|
|
22
25
|
- **Min/Max Validation**: Control minimum and maximum selections
|
|
23
26
|
- **Layout Options**: Vertical, horizontal, or grid layouts
|
|
24
27
|
- **Default Selections**: Pre-select options for new entries
|
|
28
|
+
- **Field Notes**: Display helpful notes below the field
|
|
25
29
|
|
|
26
30
|
### 🔘 Advanced Radio
|
|
27
31
|
- **Single & Multiple Selection**: Choose between single or multiple radio selections
|
|
@@ -29,6 +33,7 @@ Professional custom fields for Strapi CMS that provide advanced functionality wi
|
|
|
29
33
|
- **Selection Limits**: Control minimum and maximum choices
|
|
30
34
|
- **Layout Flexibility**: Multiple visual layouts
|
|
31
35
|
- **Custom Validation**: Tailored error messages
|
|
36
|
+
- **Field Notes**: Display helpful notes below the field
|
|
32
37
|
|
|
33
38
|
## 🛠️ Installation
|
|
34
39
|
|
|
@@ -57,7 +62,7 @@ yarn add @webbycrown/advanced-fields
|
|
|
57
62
|
### Advanced Input Configuration
|
|
58
63
|
|
|
59
64
|
```javascript
|
|
60
|
-
// Example: Text validation with custom error message
|
|
65
|
+
// Example: Text validation with custom error message and field note
|
|
61
66
|
{
|
|
62
67
|
"required": true,
|
|
63
68
|
"maxLength": 255,
|
|
@@ -66,7 +71,8 @@ yarn add @webbycrown/advanced-fields
|
|
|
66
71
|
"options": {
|
|
67
72
|
"customErrorMessage": "Please enter valid text",
|
|
68
73
|
"placeholder": "Enter your text here",
|
|
69
|
-
"defaultValue": "Default text"
|
|
74
|
+
"defaultValue": "Default text",
|
|
75
|
+
"fieldNote": "This field accepts alphanumeric characters and spaces only"
|
|
70
76
|
}
|
|
71
77
|
}
|
|
72
78
|
```
|
|
@@ -74,7 +80,7 @@ yarn add @webbycrown/advanced-fields
|
|
|
74
80
|
### Advanced Checkbox Configuration
|
|
75
81
|
|
|
76
82
|
```javascript
|
|
77
|
-
// Example: Multiple checkbox with validation
|
|
83
|
+
// Example: Multiple checkbox with validation and field note
|
|
78
84
|
{
|
|
79
85
|
"required": true,
|
|
80
86
|
"options": {
|
|
@@ -83,7 +89,8 @@ yarn add @webbycrown/advanced-fields
|
|
|
83
89
|
"minChoices": 1,
|
|
84
90
|
"maxChoices": 2,
|
|
85
91
|
"layout": "vertical",
|
|
86
|
-
"defaultSelected": "1\n2"
|
|
92
|
+
"defaultSelected": "1\n2",
|
|
93
|
+
"fieldNote": "Please select at least 1 and at most 2 options"
|
|
87
94
|
}
|
|
88
95
|
}
|
|
89
96
|
```
|
|
@@ -91,14 +98,15 @@ yarn add @webbycrown/advanced-fields
|
|
|
91
98
|
### Advanced Radio Configuration
|
|
92
99
|
|
|
93
100
|
```javascript
|
|
94
|
-
// Example: Single radio with dynamic options
|
|
101
|
+
// Example: Single radio with dynamic options and field note
|
|
95
102
|
{
|
|
96
103
|
"required": true,
|
|
97
104
|
"options": {
|
|
98
105
|
"selectionType": "single",
|
|
99
106
|
"radioOptions": "small|Small\nmedium|Medium\nlarge|Large",
|
|
100
107
|
"layout": "horizontal",
|
|
101
|
-
"defaultSelected": "medium"
|
|
108
|
+
"defaultSelected": "medium",
|
|
109
|
+
"fieldNote": "Choose the size that best fits your needs"
|
|
102
110
|
}
|
|
103
111
|
}
|
|
104
112
|
```
|
|
@@ -117,6 +125,7 @@ yarn add @webbycrown/advanced-fields
|
|
|
117
125
|
| `options.defaultValue` | string | Pre-filled value | `""` |
|
|
118
126
|
| `options.placeholder` | string | Placeholder text | `""` |
|
|
119
127
|
| `options.customErrorMessage` | string | Custom error message | `""` |
|
|
128
|
+
| `options.fieldNote` | string | Helpful note displayed below field | `""` |
|
|
120
129
|
| `private` | boolean | Hide from API | `false` |
|
|
121
130
|
|
|
122
131
|
### Advanced Checkbox Options
|
|
@@ -131,6 +140,7 @@ yarn add @webbycrown/advanced-fields
|
|
|
131
140
|
| `options.maxChoices` | number | Maximum selections | `0` |
|
|
132
141
|
| `options.layout` | string | `vertical`, `horizontal`, or `grid` | `vertical` |
|
|
133
142
|
| `options.customErrorMessage` | string | Custom error message | `""` |
|
|
143
|
+
| `options.fieldNote` | string | Helpful note displayed below field | `""` |
|
|
134
144
|
| `private` | boolean | Hide from API | `false` |
|
|
135
145
|
|
|
136
146
|
### Advanced Radio Options
|
|
@@ -145,6 +155,7 @@ yarn add @webbycrown/advanced-fields
|
|
|
145
155
|
| `options.maxChoices` | number | Maximum selections | `0` |
|
|
146
156
|
| `options.layout` | string | `vertical`, `horizontal`, or `grid` | `vertical` |
|
|
147
157
|
| `options.customErrorMessage` | string | Custom error message | `""` |
|
|
158
|
+
| `options.fieldNote` | string | Helpful note displayed below field | `""` |
|
|
148
159
|
| `private` | boolean | Hide from API | `false` |
|
|
149
160
|
|
|
150
161
|
## 🔧 API Usage
|
|
@@ -259,8 +270,10 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|
|
259
270
|
- 🔘 Advanced Radio (single/multiple)
|
|
260
271
|
- 🎨 Multiple layout options
|
|
261
272
|
- ✅ Comprehensive validation system
|
|
273
|
+
- 📝 Field notes support for all field types
|
|
262
274
|
- 📱 Responsive design
|
|
263
275
|
- 🌐 Internationalization support
|
|
276
|
+
- 🚀 Published to NPM: [@webbycrown/advanced-fields](https://www.npmjs.com/package/@webbycrown/advanced-fields)
|
|
264
277
|
|
|
265
278
|
---
|
|
266
279
|
|
|
@@ -4,7 +4,7 @@ import { useIntl } from "react-intl";
|
|
|
4
4
|
import { Field, Box, Flex, Typography } from "@strapi/design-system";
|
|
5
5
|
import { useState, useEffect } from "react";
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const AdvancedCheckbox = ({
|
|
8
8
|
attribute = {},
|
|
9
9
|
description = { id: "", defaultMessage: "" },
|
|
10
10
|
disabled,
|
|
@@ -26,16 +26,12 @@ const CheckboxInput = ({
|
|
|
26
26
|
defaultSelected = "",
|
|
27
27
|
checkboxOptions = "",
|
|
28
28
|
customErrorMessage = "",
|
|
29
|
+
fieldNote = "",
|
|
29
30
|
} = attribute.options || attribute;
|
|
30
31
|
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// attributeOptions: attribute.options,
|
|
35
|
-
// checkboxType,
|
|
36
|
-
// checkboxOptions,
|
|
37
|
-
// allOptions: attribute.options || attribute
|
|
38
|
-
// });
|
|
32
|
+
// Also check attribute.options for fieldNote
|
|
33
|
+
const fieldNoteFromAttribute = attribute.options?.fieldNote || '';
|
|
34
|
+
|
|
39
35
|
|
|
40
36
|
// Initialize with default values if available
|
|
41
37
|
const getInitialValues = () => {
|
|
@@ -82,13 +78,6 @@ const CheckboxInput = ({
|
|
|
82
78
|
useEffect(() => {
|
|
83
79
|
const initialValues = getInitialValues();
|
|
84
80
|
|
|
85
|
-
console.log('AdvancedCheckbox initialization:', {
|
|
86
|
-
value,
|
|
87
|
-
defaultSelected,
|
|
88
|
-
initialValues,
|
|
89
|
-
required,
|
|
90
|
-
error
|
|
91
|
-
});
|
|
92
81
|
|
|
93
82
|
setFieldValue(initialValues);
|
|
94
83
|
|
|
@@ -182,19 +171,9 @@ const CheckboxInput = ({
|
|
|
182
171
|
const error = validateSelection(newValue);
|
|
183
172
|
setValidationError(error);
|
|
184
173
|
|
|
185
|
-
console.log('AdvancedCheckbox handleCheckboxChange:', {
|
|
186
|
-
optionValue,
|
|
187
|
-
isChecked,
|
|
188
|
-
newValue,
|
|
189
|
-
error,
|
|
190
|
-
hasInteracted: true,
|
|
191
|
-
checkboxType,
|
|
192
|
-
isInitialized
|
|
193
|
-
});
|
|
194
174
|
|
|
195
175
|
// Always trigger onChange for user interactions
|
|
196
176
|
if (onChange) {
|
|
197
|
-
console.log(onChange)
|
|
198
177
|
onChange({
|
|
199
178
|
target: {
|
|
200
179
|
value: newValue,
|
|
@@ -207,17 +186,7 @@ const CheckboxInput = ({
|
|
|
207
186
|
|
|
208
187
|
// Show validation error - prioritize Strapi's error, then our validation only after user interaction
|
|
209
188
|
const displayError = error || (hasInteracted && validationError);
|
|
210
|
-
console.log('displayError', displayError);
|
|
211
189
|
const renderCheckboxes = () => {
|
|
212
|
-
// Debug logging
|
|
213
|
-
// console.log('AdvancedCheckbox renderCheckboxes:', {
|
|
214
|
-
// checkboxType,
|
|
215
|
-
// checkboxOptions,
|
|
216
|
-
// options,
|
|
217
|
-
// attribute,
|
|
218
|
-
// attributeOptions: attribute.options,
|
|
219
|
-
// fieldValue
|
|
220
|
-
// });
|
|
221
190
|
|
|
222
191
|
const checkboxStyle = {
|
|
223
192
|
display: "flex",
|
|
@@ -389,9 +358,20 @@ const CheckboxInput = ({
|
|
|
389
358
|
{description.id ? formatMessage(description) : description.defaultMessage}
|
|
390
359
|
</Field.Hint>
|
|
391
360
|
)}
|
|
361
|
+
{(fieldNote || fieldNoteFromAttribute) && (
|
|
362
|
+
<span style={{
|
|
363
|
+
fontStyle: 'italic',
|
|
364
|
+
color: '#666',
|
|
365
|
+
fontSize: '12px',
|
|
366
|
+
display: 'block',
|
|
367
|
+
marginTop: '4px'
|
|
368
|
+
}}>
|
|
369
|
+
{fieldNote || fieldNoteFromAttribute}
|
|
370
|
+
</span>
|
|
371
|
+
)}
|
|
392
372
|
</Field.Root>
|
|
393
373
|
</Box>
|
|
394
374
|
);
|
|
395
375
|
};
|
|
396
376
|
|
|
397
|
-
export default
|
|
377
|
+
export default AdvancedCheckbox;
|
|
@@ -5,7 +5,7 @@ import { Field, Box } from "@strapi/design-system";
|
|
|
5
5
|
import { Cross } from "@strapi/icons";
|
|
6
6
|
import { useState, useEffect } from "react";
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const AdvancedInput = ({
|
|
9
9
|
attribute = {},
|
|
10
10
|
description = { id: "", defaultMessage: "" },
|
|
11
11
|
disabled,
|
|
@@ -38,8 +38,13 @@ const TextInput = ({
|
|
|
38
38
|
defaultValue = '',
|
|
39
39
|
customErrorMessage = '',
|
|
40
40
|
regex = '',
|
|
41
|
+
fieldNote = '',
|
|
41
42
|
} = options;
|
|
42
43
|
|
|
44
|
+
// Also check attribute.options for fieldNote
|
|
45
|
+
const fieldNoteFromAttribute = attribute.options?.fieldNote || '';
|
|
46
|
+
|
|
47
|
+
|
|
43
48
|
// Initialize input value
|
|
44
49
|
useEffect(() => {
|
|
45
50
|
const initialValue = value === undefined ? defaultValue : value;
|
|
@@ -155,9 +160,20 @@ const TextInput = ({
|
|
|
155
160
|
{description.id ? formatMessage(description) : description.defaultMessage}
|
|
156
161
|
</Field.Hint>
|
|
157
162
|
)}
|
|
163
|
+
{(fieldNote || fieldNoteFromAttribute) && (
|
|
164
|
+
<span style={{
|
|
165
|
+
fontStyle: 'italic',
|
|
166
|
+
color: '#666',
|
|
167
|
+
fontSize: '12px',
|
|
168
|
+
display: 'block',
|
|
169
|
+
marginTop: '4px'
|
|
170
|
+
}}>
|
|
171
|
+
{fieldNote || fieldNoteFromAttribute}
|
|
172
|
+
</span>
|
|
173
|
+
)}
|
|
158
174
|
</Field.Root>
|
|
159
175
|
</Box>
|
|
160
176
|
);
|
|
161
177
|
};
|
|
162
178
|
|
|
163
|
-
export default
|
|
179
|
+
export default AdvancedInput;
|
|
@@ -4,7 +4,7 @@ import { useIntl } from "react-intl";
|
|
|
4
4
|
import { Field, Box, Flex, Typography } from "@strapi/design-system";
|
|
5
5
|
import { useState, useEffect } from "react";
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const AdvancedRadio = ({
|
|
8
8
|
attribute = {},
|
|
9
9
|
description = { id: "", defaultMessage: "" },
|
|
10
10
|
disabled,
|
|
@@ -30,8 +30,12 @@ const RadioInput = ({
|
|
|
30
30
|
defaultSelected = "",
|
|
31
31
|
radioOptions = "",
|
|
32
32
|
customErrorMessage = "",
|
|
33
|
+
fieldNote = "",
|
|
33
34
|
} = attribute.options || attribute;
|
|
34
35
|
|
|
36
|
+
// Also check attribute.options for fieldNote
|
|
37
|
+
const fieldNoteFromAttribute = attribute.options?.fieldNote || '';
|
|
38
|
+
|
|
35
39
|
// Parse radio options
|
|
36
40
|
const options = radioOptions
|
|
37
41
|
.split("\n")
|
|
@@ -128,13 +132,6 @@ const RadioInput = ({
|
|
|
128
132
|
const error = validateSelection(newValues);
|
|
129
133
|
setValidationError(error);
|
|
130
134
|
|
|
131
|
-
// console.log('AdvancedRadio handleRadioChange:', {
|
|
132
|
-
// optionValue,
|
|
133
|
-
// isChecked,
|
|
134
|
-
// newValues,
|
|
135
|
-
// error,
|
|
136
|
-
// hasInteracted: true
|
|
137
|
-
// });
|
|
138
135
|
|
|
139
136
|
if (onChange) {
|
|
140
137
|
// Create a proper event object with name and id attributes
|
|
@@ -153,14 +150,6 @@ const RadioInput = ({
|
|
|
153
150
|
const displayError = error || (hasInteracted && validationError);
|
|
154
151
|
|
|
155
152
|
const renderRadios = () => {
|
|
156
|
-
// Debug logging
|
|
157
|
-
// console.log('AdvancedRadio renderRadios:', {
|
|
158
|
-
// radioOptions,
|
|
159
|
-
// options,
|
|
160
|
-
// attribute,
|
|
161
|
-
// attributeOptions: attribute.options,
|
|
162
|
-
// selectedValues
|
|
163
|
-
// });
|
|
164
153
|
|
|
165
154
|
const radioStyle = {
|
|
166
155
|
display: "flex",
|
|
@@ -336,9 +325,20 @@ const RadioInput = ({
|
|
|
336
325
|
{description.id ? formatMessage(description) : description.defaultMessage}
|
|
337
326
|
</Field.Hint>
|
|
338
327
|
)}
|
|
328
|
+
{(fieldNote || fieldNoteFromAttribute) && (
|
|
329
|
+
<span style={{
|
|
330
|
+
fontStyle: 'italic',
|
|
331
|
+
color: '#666',
|
|
332
|
+
fontSize: '12px',
|
|
333
|
+
display: 'block',
|
|
334
|
+
marginTop: '4px'
|
|
335
|
+
}}>
|
|
336
|
+
{fieldNote || fieldNoteFromAttribute}
|
|
337
|
+
</span>
|
|
338
|
+
)}
|
|
339
339
|
</Field.Root>
|
|
340
340
|
</Box>
|
|
341
341
|
);
|
|
342
342
|
};
|
|
343
343
|
|
|
344
|
-
export default
|
|
344
|
+
export default AdvancedRadio;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { PuzzlePiece } from '@strapi/icons';
|
|
2
1
|
import { Box } from '@strapi/design-system';
|
|
3
2
|
|
|
4
3
|
const PluginIcon = (props) => {
|
|
5
|
-
return <
|
|
4
|
+
return <AdvancedRadioIcon {...props} />;
|
|
6
5
|
};
|
|
7
6
|
|
|
8
7
|
// Advanced Input Icon - Clean text input with validation indicator
|
|
9
|
-
const
|
|
8
|
+
const AdvancedInputIcon = () => (
|
|
10
9
|
<Box
|
|
11
10
|
style={{
|
|
12
11
|
width: '28px',
|
|
@@ -20,27 +19,25 @@ const TextFieldIcon = () => (
|
|
|
20
19
|
}}
|
|
21
20
|
>
|
|
22
21
|
<svg
|
|
23
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
24
|
-
viewBox="0 0 24 24"
|
|
25
22
|
width="18"
|
|
26
23
|
height="18"
|
|
24
|
+
viewBox="0 0 32 32"
|
|
27
25
|
fill="none"
|
|
28
|
-
|
|
29
|
-
strokeWidth="2"
|
|
30
|
-
strokeLinecap="round"
|
|
31
|
-
strokeLinejoin="round"
|
|
26
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
32
27
|
>
|
|
33
|
-
<rect
|
|
34
|
-
<
|
|
35
|
-
<
|
|
36
|
-
<
|
|
37
|
-
|
|
28
|
+
<rect width="32" height="32" rx="6" fill="#4945FF" fillOpacity="0.1"/>
|
|
29
|
+
<rect x="0.5" y="0.5" width="31" height="31" rx="5.5" stroke="#4945FF" strokeOpacity="0.15"/>
|
|
30
|
+
<path d="M27 11.6364V20.3636C27 20.7494 26.8455 21.1194 26.5704 21.3922C26.2954 21.6649 25.9223 21.8182 25.5333 21.8182H17.1C17.0028 21.8182 16.9095 21.7799 16.8407 21.7117C16.772 21.6435 16.7333 21.551 16.7333 21.4545V10.5455C16.7333 10.449 16.772 10.3565 16.8407 10.2883C16.9095 10.2201 17.0028 10.1818 17.1 10.1818H25.5333C25.9223 10.1818 26.2954 10.3351 26.5704 10.6078C26.8455 10.8806 27 11.2506 27 11.6364ZM15.2667 8.72727V23.2727C15.2667 23.4656 15.1894 23.6506 15.0519 23.787C14.9144 23.9234 14.7278 24 14.5333 24C14.3388 24 14.1523 23.9234 14.0148 23.787C13.8773 23.6506 13.8 23.4656 13.8 23.2727V21.8182H6.46667C6.07768 21.8182 5.70463 21.6649 5.42958 21.3922C5.15452 21.1194 5 20.7494 5 20.3636V11.6364C5 11.2506 5.15452 10.8806 5.42958 10.6078C5.70463 10.3351 6.07768 10.1818 6.46667 10.1818H13.8V8.72727C13.8 8.53439 13.8773 8.3494 14.0148 8.21301C14.1523 8.07662 14.3388 8 14.5333 8C14.7278 8 14.9144 8.07662 15.0519 8.21301C15.1894 8.3494 15.2667 8.53439 15.2667 8.72727ZM12.3333 14.5455C12.3333 14.3526 12.2561 14.1676 12.1185 14.0312C11.981 13.8948 11.7945 13.8182 11.6 13.8182H8.66667C8.47217 13.8182 8.28565 13.8948 8.14812 14.0312C8.0106 14.1676 7.93333 14.3526 7.93333 14.5455C7.93333 14.7383 8.0106 14.9233 8.14812 15.0597C8.28565 15.1961 8.47217 15.2727 8.66667 15.2727H9.4V17.4545C9.4 17.6474 9.47726 17.8324 9.61479 17.9688C9.75232 18.1052 9.93884 18.1818 10.1333 18.1818C10.3278 18.1818 10.5144 18.1052 10.6519 17.9688C10.7894 17.8324 10.8667 17.6474 10.8667 17.4545V15.2727H11.6C11.7945 15.2727 11.981 15.1961 12.1185 15.0597C12.2561 14.9233 12.3333 14.7383 12.3333 14.5455Z" fill="#4945FF"/>
|
|
31
|
+
<mask id="path-4-inside-1_649_85" fill="white">
|
|
32
|
+
<path d="M0 6C0 2.68629 2.68629 0 6 0H10V10H0V6Z"/>
|
|
33
|
+
</mask>
|
|
34
|
+
<path d="M-2 6C-2 1.58172 1.58172 -2 6 -2H10V2H6C3.79086 2 2 3.79086 2 6H-2ZM10 10H0H10ZM-2 10V6C-2 1.58172 1.58172 -2 6 -2V2C3.79086 2 2 3.79086 2 6V10H-2ZM10 0V10V0Z" fill="#4945FF" mask="url(#path-4-inside-1_649_85)"/>
|
|
38
35
|
</svg>
|
|
39
36
|
</Box>
|
|
40
37
|
);
|
|
41
38
|
|
|
42
39
|
// Advanced Checkbox Icon - Modern checkbox with multiple states
|
|
43
|
-
const
|
|
40
|
+
const AdvancedCheckboxIcon = () => (
|
|
44
41
|
<Box
|
|
45
42
|
style={{
|
|
46
43
|
width: '28px',
|
|
@@ -54,26 +51,25 @@ const CheckIcon = () => (
|
|
|
54
51
|
}}
|
|
55
52
|
>
|
|
56
53
|
<svg
|
|
57
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
58
|
-
viewBox="0 0 24 24"
|
|
59
54
|
width="18"
|
|
60
55
|
height="18"
|
|
56
|
+
viewBox="0 0 32 32"
|
|
61
57
|
fill="none"
|
|
62
|
-
|
|
63
|
-
strokeWidth="2"
|
|
64
|
-
strokeLinecap="round"
|
|
65
|
-
strokeLinejoin="round"
|
|
58
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
66
59
|
>
|
|
67
|
-
<rect
|
|
68
|
-
<
|
|
69
|
-
<
|
|
70
|
-
|
|
60
|
+
<rect width="32" height="32" rx="6" fill="#4945FF" fillOpacity="0.1"/>
|
|
61
|
+
<rect x="0.5" y="0.5" width="31" height="31" rx="5.5" stroke="#4945FF" strokeOpacity="0.15"/>
|
|
62
|
+
<mask id="path-3-inside-1_649_76" fill="white">
|
|
63
|
+
<path d="M0 6C0 2.68629 2.68629 0 6 0H10V10H0V6Z"/>
|
|
64
|
+
</mask>
|
|
65
|
+
<path d="M-2 6C-2 1.58172 1.58172 -2 6 -2H10V2H6C3.79086 2 2 3.79086 2 6H-2ZM10 10H0H10ZM-2 10V6C-2 1.58172 1.58172 -2 6 -2V2C3.79086 2 2 3.79086 2 6V10H-2ZM10 0V10V0Z" fill="#4945FF" mask="url(#path-3-inside-1_649_76)"/>
|
|
66
|
+
<path d="M14.67 17.71L12.6275 15.6675C12.4533 15.4933 12.2317 15.4062 11.9625 15.4062C11.6933 15.4062 11.4717 15.4933 11.2975 15.6675C11.1233 15.8417 11.0362 16.0633 11.0362 16.3325C11.0362 16.6017 11.1233 16.8233 11.2975 16.9975L14.005 19.705C14.195 19.895 14.4167 19.99 14.67 19.99C14.9233 19.99 15.145 19.895 15.335 19.705L20.7025 14.3375C20.8767 14.1633 20.9637 13.9417 20.9637 13.6725C20.9637 13.4033 20.8767 13.1817 20.7025 13.0075C20.5283 12.8333 20.3067 12.7462 20.0375 12.7462C19.7683 12.7462 19.5467 12.8333 19.3725 13.0075L14.67 17.71ZM16 25.5C14.6858 25.5 13.4508 25.2505 12.295 24.7514C11.1392 24.2523 10.1337 23.5756 9.27875 22.7212C8.42375 21.8669 7.74703 20.8615 7.2486 19.705C6.75017 18.5485 6.50063 17.3135 6.5 16C6.49937 14.6865 6.7489 13.4515 7.2486 12.295C7.7483 11.1385 8.42502 10.1331 9.27875 9.27875C10.1325 8.42438 11.1379 7.74767 12.295 7.2486C13.4521 6.74953 14.6871 6.5 16 6.5C17.3129 6.5 18.5479 6.74953 19.705 7.2486C20.8621 7.74767 21.8675 8.42438 22.7212 9.27875C23.575 10.1331 24.252 11.1385 24.7523 12.295C25.2527 13.4515 25.5019 14.6865 25.5 16C25.4981 17.3135 25.2486 18.5485 24.7514 19.705C24.2542 20.8615 23.5775 21.8669 22.7212 22.7212C21.865 23.5756 20.8596 24.2526 19.705 24.7523C18.5504 25.252 17.3154 25.5013 16 25.5Z" fill="#4945FF"/>
|
|
71
67
|
</svg>
|
|
72
68
|
</Box>
|
|
73
69
|
);
|
|
74
70
|
|
|
75
71
|
// Advanced Radio Icon - Clean radio button with selection states
|
|
76
|
-
const
|
|
72
|
+
const AdvancedRadioIcon = () => (
|
|
77
73
|
<Box
|
|
78
74
|
style={{
|
|
79
75
|
width: '28px',
|
|
@@ -87,29 +83,26 @@ const MultipleChoiceIcon1 = () => (
|
|
|
87
83
|
}}
|
|
88
84
|
>
|
|
89
85
|
<svg
|
|
90
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
91
|
-
viewBox="0 0 24 24"
|
|
92
86
|
width="18"
|
|
93
87
|
height="18"
|
|
88
|
+
viewBox="0 0 32 32"
|
|
94
89
|
fill="none"
|
|
95
|
-
|
|
96
|
-
strokeWidth="2"
|
|
97
|
-
strokeLinecap="round"
|
|
98
|
-
strokeLinejoin="round"
|
|
90
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
99
91
|
>
|
|
100
|
-
<
|
|
101
|
-
<
|
|
102
|
-
<
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
92
|
+
<rect width="32" height="32" rx="6" fill="#4945FF" fillOpacity="0.1"/>
|
|
93
|
+
<rect x="0.5" y="0.5" width="31" height="31" rx="5.5" stroke="#4945FF" strokeOpacity="0.15"/>
|
|
94
|
+
<path d="M16 6.5C10.775 6.5 6.5 10.775 6.5 16C6.5 21.225 10.775 25.5 16 25.5C21.225 25.5 25.5 21.225 25.5 16C25.5 10.775 21.225 6.5 16 6.5ZM23.6 16H19.8C19.8 14.575 19.04 13.34 17.9 12.77L19.8 9.445C22.08 10.775 23.6 13.15 23.6 16ZM16 14.1C17.045 14.1 17.9 14.955 17.9 16C17.9 17.045 17.045 17.9 16 17.9C14.955 17.9 14.1 17.045 14.1 16C14.1 14.955 14.955 14.1 16 14.1ZM12.2 9.445C12.77 10.395 13.435 11.63 14.1 12.77C12.96 13.435 12.2 14.67 12.2 16H8.4C8.4 13.15 9.92 10.775 12.2 9.445ZM12.2 22.555C12.77 21.605 13.435 20.37 14.1 19.23C14.67 19.515 15.335 19.8 16 19.8C16.665 19.8 17.33 19.61 17.9 19.23L19.8 22.555C18.66 23.22 17.425 23.6 16 23.6C14.575 23.6 13.34 23.22 12.2 22.555Z" fill="#4945FF"/>
|
|
95
|
+
<mask id="path-4-inside-1_649_89" fill="white">
|
|
96
|
+
<path d="M0 6C0 2.68629 2.68629 0 6 0H10V10H0V6Z"/>
|
|
97
|
+
</mask>
|
|
98
|
+
<path d="M-2 6C-2 1.58172 1.58172 -2 6 -2H10V2H6C3.79086 2 2 3.79086 2 6H-2ZM10 10H0H10ZM-2 10V6C-2 1.58172 1.58172 -2 6 -2V2C3.79086 2 2 3.79086 2 6V10H-2ZM10 0V10V0Z" fill="#4945FF" mask="url(#path-4-inside-1_649_89)"/>
|
|
106
99
|
</svg>
|
|
107
100
|
</Box>
|
|
108
101
|
);
|
|
109
102
|
|
|
110
103
|
export {
|
|
111
104
|
PluginIcon,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
105
|
+
AdvancedCheckboxIcon,
|
|
106
|
+
AdvancedInputIcon,
|
|
107
|
+
AdvancedRadioIcon
|
|
115
108
|
};
|
package/admin/src/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { PLUGIN_ID } from './pluginId';
|
|
2
2
|
import { Initializer } from './components/Initializer';
|
|
3
|
-
import {
|
|
3
|
+
import { AdvancedCheckboxIcon, AdvancedInputIcon, AdvancedRadioIcon } from './components/PluginIcon';
|
|
4
4
|
|
|
5
5
|
// Dynamic field configuration with comprehensive options
|
|
6
6
|
const customFields = [
|
|
7
7
|
{
|
|
8
8
|
name: "input",
|
|
9
9
|
type: "string",
|
|
10
|
-
icon:
|
|
10
|
+
icon: AdvancedInputIcon,
|
|
11
11
|
pluginId: PLUGIN_ID,
|
|
12
12
|
component: () => import("./components/AdvancedInput"),
|
|
13
13
|
intlLabel: {
|
|
@@ -147,6 +147,22 @@ const customFields = [
|
|
|
147
147
|
defaultMessage: 'Enter custom error message',
|
|
148
148
|
},
|
|
149
149
|
},
|
|
150
|
+
{
|
|
151
|
+
name: 'options.fieldNote',
|
|
152
|
+
type: 'text',
|
|
153
|
+
intlLabel: {
|
|
154
|
+
id: `${PLUGIN_ID}.input.options.fieldNote.label`,
|
|
155
|
+
defaultMessage: 'Field Note',
|
|
156
|
+
},
|
|
157
|
+
description: {
|
|
158
|
+
id: `${PLUGIN_ID}.input.options.fieldNote.description`,
|
|
159
|
+
defaultMessage: 'Add a helpful note that will appear below the field',
|
|
160
|
+
},
|
|
161
|
+
placeholder: {
|
|
162
|
+
id: `${PLUGIN_ID}.input.options.fieldNote.placeholder`,
|
|
163
|
+
defaultMessage: 'Enter a note for this field',
|
|
164
|
+
},
|
|
165
|
+
},
|
|
150
166
|
{
|
|
151
167
|
name: 'private',
|
|
152
168
|
type: 'checkbox',
|
|
@@ -167,7 +183,7 @@ const customFields = [
|
|
|
167
183
|
{
|
|
168
184
|
name: "checkbox",
|
|
169
185
|
type: "json",
|
|
170
|
-
icon:
|
|
186
|
+
icon: AdvancedCheckboxIcon,
|
|
171
187
|
pluginId: PLUGIN_ID,
|
|
172
188
|
component: () => import("./components/AdvancedCheckbox"),
|
|
173
189
|
intlLabel: {
|
|
@@ -404,6 +420,22 @@ const customFields = [
|
|
|
404
420
|
defaultMessage: 'Enter custom error message',
|
|
405
421
|
},
|
|
406
422
|
},
|
|
423
|
+
{
|
|
424
|
+
name: 'options.fieldNote',
|
|
425
|
+
type: 'text',
|
|
426
|
+
intlLabel: {
|
|
427
|
+
id: `${PLUGIN_ID}.checkbox.options.fieldNote.label`,
|
|
428
|
+
defaultMessage: 'Field Note',
|
|
429
|
+
},
|
|
430
|
+
description: {
|
|
431
|
+
id: `${PLUGIN_ID}.checkbox.options.fieldNote.description`,
|
|
432
|
+
defaultMessage: 'Add a helpful note that will appear below the field',
|
|
433
|
+
},
|
|
434
|
+
placeholder: {
|
|
435
|
+
id: `${PLUGIN_ID}.checkbox.options.fieldNote.placeholder`,
|
|
436
|
+
defaultMessage: 'Enter a note for this field',
|
|
437
|
+
},
|
|
438
|
+
},
|
|
407
439
|
{
|
|
408
440
|
name: 'private',
|
|
409
441
|
type: 'checkbox',
|
|
@@ -424,7 +456,7 @@ const customFields = [
|
|
|
424
456
|
{
|
|
425
457
|
name: "radio",
|
|
426
458
|
type: "json",
|
|
427
|
-
icon:
|
|
459
|
+
icon: AdvancedRadioIcon,
|
|
428
460
|
pluginId: PLUGIN_ID,
|
|
429
461
|
component: () => import("./components/AdvancedRadio"),
|
|
430
462
|
intlLabel: {
|
|
@@ -636,6 +668,22 @@ const customFields = [
|
|
|
636
668
|
defaultMessage: 'Enter custom error message',
|
|
637
669
|
},
|
|
638
670
|
},
|
|
671
|
+
{
|
|
672
|
+
name: 'options.fieldNote',
|
|
673
|
+
type: 'text',
|
|
674
|
+
intlLabel: {
|
|
675
|
+
id: `${PLUGIN_ID}.radio.options.fieldNote.label`,
|
|
676
|
+
defaultMessage: 'Field Note',
|
|
677
|
+
},
|
|
678
|
+
description: {
|
|
679
|
+
id: `${PLUGIN_ID}.radio.options.fieldNote.description`,
|
|
680
|
+
defaultMessage: 'Add a helpful note that will appear below the field',
|
|
681
|
+
},
|
|
682
|
+
placeholder: {
|
|
683
|
+
id: `${PLUGIN_ID}.radio.options.fieldNote.placeholder`,
|
|
684
|
+
defaultMessage: 'Enter a note for this field',
|
|
685
|
+
},
|
|
686
|
+
},
|
|
639
687
|
],
|
|
640
688
|
},
|
|
641
689
|
],
|
package/index.js
CHANGED
|
@@ -28,7 +28,7 @@ const customFields = [
|
|
|
28
28
|
return options.customErrorMessage || 'Value does not match required format';
|
|
29
29
|
}
|
|
30
30
|
} catch (e) {
|
|
31
|
-
|
|
31
|
+
// Invalid regex pattern - silently ignore
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -63,15 +63,6 @@ const customFields = [
|
|
|
63
63
|
name: 'checkbox',
|
|
64
64
|
type: 'json',
|
|
65
65
|
validate: (value, { required, options = {} }) => {
|
|
66
|
-
console.log('[advanced-fields] Checkbox validation:', {
|
|
67
|
-
value,
|
|
68
|
-
required,
|
|
69
|
-
options,
|
|
70
|
-
valueType: typeof value,
|
|
71
|
-
isArray: Array.isArray(value),
|
|
72
|
-
valueLength: Array.isArray(value) ? value.length : 'N/A',
|
|
73
|
-
checkboxType: options.checkboxType
|
|
74
|
-
});
|
|
75
66
|
|
|
76
67
|
// Basic required validation
|
|
77
68
|
if (required) {
|
|
@@ -80,14 +71,12 @@ const customFields = [
|
|
|
80
71
|
(typeof value === 'string' && value.trim() === '') ||
|
|
81
72
|
value === null ||
|
|
82
73
|
value === undefined) {
|
|
83
|
-
console.log('[advanced-fields] Checkbox validation failed: required field is empty');
|
|
84
74
|
return options.customErrorMessage || 'This field is required';
|
|
85
75
|
}
|
|
86
76
|
}
|
|
87
77
|
|
|
88
78
|
// If no value and not required, no additional validation needed
|
|
89
79
|
if (!required && (!value || (Array.isArray(value) && value.length === 0))) {
|
|
90
|
-
console.log('[advanced-fields] Checkbox validation passed (no value, not required)');
|
|
91
80
|
return null;
|
|
92
81
|
}
|
|
93
82
|
|
|
@@ -101,7 +90,6 @@ const customFields = [
|
|
|
101
90
|
}
|
|
102
91
|
}
|
|
103
92
|
|
|
104
|
-
console.log('[advanced-fields] Checkbox validation passed');
|
|
105
93
|
return null;
|
|
106
94
|
}
|
|
107
95
|
},
|
|
@@ -137,18 +125,14 @@ const customFields = [
|
|
|
137
125
|
|
|
138
126
|
module.exports = {
|
|
139
127
|
register({ strapi }) {
|
|
140
|
-
console.log(`[${PLUGIN_ID}] Registering custom fields...`);
|
|
141
|
-
|
|
142
128
|
// Ensure custom fields registry is available
|
|
143
129
|
if (!strapi.customFields) {
|
|
144
|
-
console.error(`[${PLUGIN_ID}] Custom fields registry not available`);
|
|
145
130
|
return;
|
|
146
131
|
}
|
|
147
132
|
|
|
148
133
|
// Register custom fields with proper error handling
|
|
149
134
|
customFields.forEach((field) => {
|
|
150
135
|
try {
|
|
151
|
-
console.log(`[${PLUGIN_ID}] Registering field: ${field.name} (type: ${field.type})`);
|
|
152
136
|
|
|
153
137
|
const fieldConfig = {
|
|
154
138
|
name: field.name,
|
|
@@ -159,44 +143,16 @@ module.exports = {
|
|
|
159
143
|
// Add validation function if it exists
|
|
160
144
|
if (field.validate) {
|
|
161
145
|
fieldConfig.validate = field.validate;
|
|
162
|
-
console.log(`[${PLUGIN_ID}] Added validation function for field: ${field.name}`);
|
|
163
146
|
}
|
|
164
147
|
|
|
165
148
|
strapi.customFields.register(fieldConfig);
|
|
166
|
-
console.log(`[${PLUGIN_ID}] Successfully registered field: ${field.name}`);
|
|
167
149
|
} catch (error) {
|
|
168
|
-
|
|
169
|
-
console.error(`[${PLUGIN_ID}] Error details:`, error);
|
|
150
|
+
// Field registration failed - silently continue
|
|
170
151
|
}
|
|
171
152
|
});
|
|
172
|
-
|
|
173
|
-
console.log(`[${PLUGIN_ID}] All custom fields registration completed`);
|
|
174
153
|
},
|
|
175
154
|
|
|
176
155
|
bootstrap({ strapi }) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
// Wait a bit for registration to complete
|
|
180
|
-
setTimeout(() => {
|
|
181
|
-
// Verify all fields are registered only if customFields.get is available
|
|
182
|
-
if (strapi.customFields && typeof strapi.customFields.get === 'function') {
|
|
183
|
-
customFields.forEach((field) => {
|
|
184
|
-
try {
|
|
185
|
-
const registeredField = strapi.customFields.get(`${PLUGIN_ID}.${field.name}`);
|
|
186
|
-
if (registeredField) {
|
|
187
|
-
console.log(`[${PLUGIN_ID}] ✅ Field verified: ${field.name}`);
|
|
188
|
-
} else {
|
|
189
|
-
console.error(`[${PLUGIN_ID}] ❌ Field not found in registry: ${field.name}`);
|
|
190
|
-
}
|
|
191
|
-
} catch (error) {
|
|
192
|
-
console.error(`[${PLUGIN_ID}] Error verifying field ${field.name}:`, error.message);
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
} else {
|
|
196
|
-
console.log(`[${PLUGIN_ID}] Skipping field verification (customFields.get not available)`);
|
|
197
|
-
}
|
|
198
|
-
}, 100);
|
|
199
|
-
|
|
200
|
-
console.log(`[${PLUGIN_ID}] Bootstrap completed`);
|
|
156
|
+
// Bootstrap completed
|
|
201
157
|
},
|
|
202
158
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webbycrown/advanced-fields",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"strapi",
|
|
6
6
|
"plugin",
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
"./strapi-server": "./strapi-server.js"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
|
-
"dist",
|
|
29
28
|
"admin",
|
|
30
29
|
"strapi-server.js",
|
|
31
30
|
"strapi-server.mjs",
|
|
@@ -68,7 +67,7 @@
|
|
|
68
67
|
"displayName": "Advanced Fields",
|
|
69
68
|
"description": "Professional custom fields for Strapi: Advanced Input with validation, Advanced Checkbox (single/multiple), and Advanced Radio (single/multiple) with dynamic options and comprehensive configuration"
|
|
70
69
|
},
|
|
71
|
-
"description": "
|
|
70
|
+
"description": "Professional custom fields for Strapi: Advanced Input with validation, Advanced Checkbox (single/multiple), and Advanced Radio (single/multiple) with dynamic options and comprehensive configuration",
|
|
72
71
|
"license": "MIT",
|
|
73
72
|
"author": {
|
|
74
73
|
"name": "WebbyCrown",
|