@sio-group/form-react 0.1.0 → 0.2.0

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +23 -82
  2. package/README.md +2 -2
  3. package/dist/index.cjs +268 -18
  4. package/dist/index.d.cts +2 -2
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.js +258 -17
  7. package/package.json +6 -5
  8. package/src/assets/scss/components/button.scss +164 -0
  9. package/src/assets/scss/components/checkbox.scss +90 -0
  10. package/src/assets/scss/components/color.scss +29 -0
  11. package/src/assets/scss/components/form-field.scss +34 -0
  12. package/src/assets/scss/components/form-states.scss +80 -0
  13. package/src/assets/scss/components/grid.scss +134 -0
  14. package/src/assets/scss/components/input.scss +112 -0
  15. package/src/assets/scss/components/link.scss +66 -0
  16. package/src/assets/scss/components/radio.scss +104 -0
  17. package/src/assets/scss/components/range.scss +52 -0
  18. package/src/assets/scss/components/select.scss +35 -0
  19. package/src/assets/scss/components/upload.scss +52 -0
  20. package/src/assets/scss/index.scss +19 -0
  21. package/src/assets/scss/tokens/_colors.scss +49 -0
  22. package/src/assets/scss/tokens/_form.scss +6 -0
  23. package/src/assets/scss/utilities/_mixins.scss +6 -0
  24. package/src/components/Button/index.tsx +106 -0
  25. package/src/components/Fields/Checkbox/index.tsx +59 -0
  26. package/src/components/Fields/Input/DateInput/index.tsx +95 -0
  27. package/src/components/Fields/Input/FileInput/index.tsx +169 -0
  28. package/src/components/Fields/Input/Input.tsx +45 -0
  29. package/src/components/Fields/Input/NumberInput/index.tsx +169 -0
  30. package/src/components/Fields/Input/RangeInput/index.tsx +77 -0
  31. package/src/components/Fields/Input/TextInput/index.tsx +65 -0
  32. package/src/components/Fields/InputWrapper/index.tsx +78 -0
  33. package/src/components/Fields/Radio/index.tsx +82 -0
  34. package/src/components/Fields/Select/index.tsx +103 -0
  35. package/src/components/Fields/Textarea/index.tsx +70 -0
  36. package/src/components/Fields/index.tsx +11 -0
  37. package/src/components/Form.tsx +163 -0
  38. package/src/components/Icon/index.tsx +16 -0
  39. package/src/components/Link/index.tsx +106 -0
  40. package/src/hooks/useConnectionStatus.ts +20 -0
  41. package/src/hooks/useForm.ts +230 -0
  42. package/src/index.ts +15 -0
  43. package/src/types/field-props.d.ts +94 -0
  44. package/src/types/field-setters.d.ts +6 -0
  45. package/src/types/field-state.d.ts +21 -0
  46. package/src/types/form-config.d.ts +30 -0
  47. package/src/types/form-layout.d.ts +6 -0
  48. package/src/types/index.ts +18 -0
  49. package/src/types/ui-props.d.ts +33 -0
  50. package/src/types/use-form-options.d.ts +3 -0
  51. package/src/utils/create-field-props.ts +115 -0
  52. package/src/utils/create-field-state.ts +99 -0
  53. package/src/utils/custom-icons.tsx +145 -0
  54. package/src/utils/file-type-icon.ts +63 -0
  55. package/src/utils/get-accept-string.ts +24 -0
  56. package/src/utils/get-column-classes.ts +21 -0
  57. package/src/utils/get-file-size.ts +9 -0
  58. package/src/utils/parse-date.ts +36 -0
  59. package/src/utils/slugify.ts +9 -0
  60. package/tsconfig.json +15 -0
package/dist/index.js CHANGED
@@ -26,20 +26,264 @@ var slugify = (string, separator = "_") => {
26
26
  return string.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9 ]/g, "").replace(/\s+/g, separator);
27
27
  };
28
28
 
29
- // src/utils/create-field-state.ts
30
- import {
31
- dateIsBiggerThan,
32
- dateIsSmallerThan,
33
- isBiggerThan,
34
- isEmail,
35
- isPattern,
36
- isRequired,
37
- isSmallerThan,
38
- isUrl
39
- } from "@sio-group/form-validation";
29
+ // ../form-validation/dist/index.js
30
+ var isRequired = (errorMessage) => (val, label = "Dit") => {
31
+ const message = errorMessage?.replace("{label}", label) || `${label} is een verplicht veld.`;
32
+ if (val === null || val === void 0) {
33
+ return message;
34
+ }
35
+ if (typeof val === "string" && val.trim().length === 0) {
36
+ return message;
37
+ }
38
+ if (typeof val === "boolean" && !val) {
39
+ return message;
40
+ }
41
+ if (Array.isArray(val) && val.length === 0) {
42
+ return message;
43
+ }
44
+ return null;
45
+ };
46
+ var isEmail = (errorMessage) => (val, label = "Dit") => {
47
+ if (val === null || val === void 0) {
48
+ return null;
49
+ }
50
+ if (typeof val !== "string") {
51
+ return errorMessage || `${label} is geen geldig e-mailadres.`;
52
+ }
53
+ const trimmed = val.trim();
54
+ if (trimmed.length === 0) {
55
+ return null;
56
+ }
57
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
58
+ return emailRegex.test(trimmed) ? null : errorMessage || `${label} is geen geldig e-mailadres.`;
59
+ };
60
+ var isUrl = (allowLocalhost = false, allowFtp = false, secureOnly = true) => (val, label = "Dit") => {
61
+ if (val === null || val === void 0) {
62
+ return null;
63
+ }
64
+ if (typeof val !== "string") {
65
+ return `${label} is geen geldige URL.`;
66
+ }
67
+ const trimmed = val.trim();
68
+ if (trimmed.length === 0) {
69
+ return null;
70
+ }
71
+ try {
72
+ const url = new URL(trimmed);
73
+ if (secureOnly && url.protocol !== "https:") {
74
+ return `${label} moet https gebruiken.`;
75
+ }
76
+ if (!allowFtp && url.protocol === "ftp") {
77
+ return `${label} mag geen ftp gebruiken.`;
78
+ }
79
+ if (!allowLocalhost && (url.hostname === "localhost" || url.hostname === "127.0.0.1")) {
80
+ return `${label} mag geen localhost zijn.`;
81
+ }
82
+ return null;
83
+ } catch {
84
+ return `${label} is geen geldige URL.`;
85
+ }
86
+ };
87
+ var isBiggerThan = (min, errorMessage) => (val, label = "Dit") => {
88
+ if (val === null || val === void 0 || val === "") {
89
+ return null;
90
+ }
91
+ const num = Number(val);
92
+ if (Number.isNaN(num)) {
93
+ return `${label} moet een geldig getal zijn.`;
94
+ }
95
+ return min <= num ? null : errorMessage?.replace("{label}", label)?.replace("{min}", min.toString()) || `${label} mag niet kleiner zijn dan ${min}.`;
96
+ };
97
+ var isSmallerThan = (max, errorMessage) => (val, label = "Dit") => {
98
+ if (val === null || val === void 0 || val === "") {
99
+ return null;
100
+ }
101
+ const num = Number(val);
102
+ if (Number.isNaN(num)) {
103
+ return `${label} moet een geldig getal zijn.`;
104
+ }
105
+ return num <= max ? null : errorMessage?.replace("{label}", label)?.replace("{max}", max.toString()) || `${label} mag niet groter zijn dan ${max}.`;
106
+ };
107
+ var parseDateValue = (val) => {
108
+ if (val instanceof Date) {
109
+ return {
110
+ type: hasExplicitTime(val) ? "datetime" : "date",
111
+ value: isNaN(val.getTime()) ? null : val
112
+ };
113
+ }
114
+ if (typeof val !== "string") {
115
+ return { type: "invalid", value: null };
116
+ }
117
+ const trimmed = val.trim();
118
+ if (trimmed === "") {
119
+ return { type: "invalid", value: null };
120
+ }
121
+ const timeRegex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/;
122
+ if (timeRegex.test(trimmed)) {
123
+ const [hours, minutes, seconds = 0] = trimmed.split(":").map(Number);
124
+ const date = /* @__PURE__ */ new Date();
125
+ date.setHours(hours, minutes, seconds, 0);
126
+ return { type: "time", value: date };
127
+ }
128
+ const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
129
+ if (dateRegex.test(trimmed)) {
130
+ const date = /* @__PURE__ */ new Date(trimmed + "T00:00:00.000Z");
131
+ return {
132
+ type: "date",
133
+ value: isNaN(date.getTime()) ? null : date
134
+ };
135
+ }
136
+ const dateTimeRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
137
+ if (dateTimeRegex.test(trimmed)) {
138
+ const date = /* @__PURE__ */ new Date(trimmed + ".000Z");
139
+ return {
140
+ type: "datetime",
141
+ value: isNaN(date.getTime()) ? null : date
142
+ };
143
+ }
144
+ return { type: "invalid", value: null };
145
+ };
146
+ function hasExplicitTime(date) {
147
+ return date.getUTCHours() !== 0 || date.getUTCMinutes() !== 0 || date.getUTCSeconds() !== 0 || date.getUTCMilliseconds() !== 0;
148
+ }
149
+ var dateIsBiggerThan = (min, errorMessage) => (val, label = "Dit") => {
150
+ if (val === null || val === void 0 || val === "") {
151
+ return null;
152
+ }
153
+ const parsed = parseDateValue(val);
154
+ if (!parsed.value) {
155
+ return `${label} moet een geldige ${parsed.type === "time" ? "tijd" : "datum"} zijn.`;
156
+ }
157
+ let formattedMin;
158
+ switch (parsed.type) {
159
+ case "time":
160
+ formattedMin = min.toLocaleTimeString("nl-NL", {
161
+ hour: "2-digit",
162
+ minute: "2-digit",
163
+ hour12: false,
164
+ timeZone: "UTC"
165
+ });
166
+ break;
167
+ case "date":
168
+ formattedMin = min.toLocaleDateString("nl-NL", { timeZone: "UTC" });
169
+ break;
170
+ case "datetime":
171
+ formattedMin = min.toLocaleString("nl-NL", {
172
+ year: "numeric",
173
+ month: "2-digit",
174
+ day: "2-digit",
175
+ hour: "2-digit",
176
+ minute: "2-digit",
177
+ hour12: false,
178
+ timeZone: "UTC"
179
+ });
180
+ break;
181
+ default:
182
+ formattedMin = min.toLocaleDateString("nl-NL", { timeZone: "UTC" });
183
+ }
184
+ if (parsed.type === "time") {
185
+ const timeValue = parsed.value.getHours() * 60 + parsed.value.getMinutes();
186
+ const minTime = min.getHours() * 60 + min.getMinutes();
187
+ return timeValue >= minTime ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMin) || `${label} mag niet voor ${formattedMin} zijn.`;
188
+ }
189
+ return min.getTime() <= parsed.value.getTime() ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMin) || `${label} mag niet voor ${formattedMin} zijn.`;
190
+ };
191
+ var dateIsSmallerThan = (max, errorMessage) => (val, label = "Dit") => {
192
+ if (val === null || val === void 0 || val === "") {
193
+ return null;
194
+ }
195
+ const parsed = parseDateValue(val);
196
+ if (!parsed.value) {
197
+ return `${label} moet een geldige ${parsed.type === "time" ? "tijd" : "datum"} zijn.`;
198
+ }
199
+ let formattedMax;
200
+ switch (parsed.type) {
201
+ case "time":
202
+ formattedMax = max.toLocaleTimeString("nl-NL", {
203
+ hour: "2-digit",
204
+ minute: "2-digit",
205
+ hour12: false,
206
+ timeZone: "UTC"
207
+ });
208
+ break;
209
+ case "date":
210
+ formattedMax = max.toLocaleDateString("nl-NL", { timeZone: "UTC" });
211
+ break;
212
+ case "datetime":
213
+ formattedMax = max.toLocaleString("nl-NL", {
214
+ year: "numeric",
215
+ month: "2-digit",
216
+ day: "2-digit",
217
+ hour: "2-digit",
218
+ minute: "2-digit",
219
+ hour12: false,
220
+ timeZone: "UTC"
221
+ });
222
+ break;
223
+ default:
224
+ formattedMax = max.toLocaleDateString("nl-NL", { timeZone: "UTC" });
225
+ }
226
+ if (parsed.type === "time") {
227
+ const timeValue = parsed.value.getHours() * 60 + parsed.value.getMinutes();
228
+ const macTime = max.getHours() * 60 + max.getMinutes();
229
+ return macTime >= timeValue ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMax) || `${label} mag niet na ${formattedMax} zijn.`;
230
+ }
231
+ return parsed.value.getTime() <= max.getTime() ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMax) || `${label} mag niet na ${formattedMax} zijn.`;
232
+ };
233
+ var isValidFile = (maxSize, accept) => (file) => {
234
+ if (!file) {
235
+ return null;
236
+ }
237
+ if (maxSize && file.size / 1024 > maxSize) {
238
+ return `${file.name} is te groot (max ${maxSize} KB).`;
239
+ }
240
+ if (accept) {
241
+ const allowed = accept.split(",").map((s) => s.trim().toLowerCase());
242
+ const ext = `.${file.name.split(".").pop()?.toLowerCase()}`;
243
+ const mime = file.type.toLowerCase();
244
+ const valid = allowed.some((pattern) => {
245
+ if (pattern === mime) return true;
246
+ if (pattern.endsWith("/*")) {
247
+ return mime.startsWith(pattern.replace("/*", "/"));
248
+ }
249
+ return pattern === ext;
250
+ });
251
+ if (!valid) {
252
+ return `${file.name} is niet toegelaten.`;
253
+ }
254
+ }
255
+ return null;
256
+ };
257
+ var isPattern = (pattern, errorMsg) => (val, label = "Dit") => {
258
+ if (val === null || val === void 0 || val === "") {
259
+ return null;
260
+ }
261
+ if (typeof val !== "string") {
262
+ return errorMsg || `${label} heeft een ongeldig patroon.`;
263
+ }
264
+ const trimmed = val.trim();
265
+ if (trimmed === "") {
266
+ return null;
267
+ }
268
+ let regex;
269
+ if (typeof pattern === "string") {
270
+ if (pattern.startsWith("/") && pattern.lastIndexOf("/") > 0) {
271
+ const lastSlash = pattern.lastIndexOf("/");
272
+ const patternBody = pattern.substring(1, lastSlash);
273
+ const flags = pattern.substring(lastSlash + 1);
274
+ const safeFlags = flags.replace("g", "");
275
+ regex = new RegExp(patternBody, safeFlags);
276
+ } else {
277
+ regex = new RegExp(pattern);
278
+ }
279
+ } else {
280
+ regex = new RegExp(pattern.source, pattern.flags.replace("g", ""));
281
+ }
282
+ return regex.test(trimmed) ? null : errorMsg || `${label} heeft een ongeldig patroon.`;
283
+ };
40
284
 
41
285
  // src/utils/parse-date.ts
42
- var parseDateValue = (val) => {
286
+ var parseDateValue2 = (val) => {
43
287
  if (val instanceof Date) {
44
288
  return isNaN(val.getTime()) ? null : val;
45
289
  }
@@ -125,8 +369,8 @@ function getDefaultValidations(config) {
125
369
  case "time":
126
370
  const min = config.config?.min;
127
371
  const max = config.config?.max;
128
- const parsedMin = parseDateValue(min);
129
- const parsedMax = parseDateValue(max);
372
+ const parsedMin = parseDateValue2(min);
373
+ const parsedMax = parseDateValue2(max);
130
374
  if (parsedMin) validations.push(dateIsBiggerThan(parsedMin));
131
375
  if (parsedMax) validations.push(dateIsSmallerThan(parsedMax));
132
376
  break;
@@ -1075,9 +1319,6 @@ var DateInput = ({
1075
1319
  );
1076
1320
  };
1077
1321
 
1078
- // src/components/Fields/Input/FileInput/index.tsx
1079
- import { isValidFile } from "@sio-group/form-validation";
1080
-
1081
1322
  // src/utils/get-accept-string.ts
1082
1323
  var getAccept = (accept) => {
1083
1324
  if (Array.isArray(accept)) {
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@sio-group/form-react",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
+ "private": false,
4
5
  "type": "module",
5
6
  "main": "./dist/index.cjs",
6
7
  "module": "./dist/index.js",
@@ -26,12 +27,12 @@
26
27
  "license": "ISC",
27
28
  "description": "",
28
29
  "dependencies": {
29
- "@sio/form-types": "0.1.0",
30
- "@sio/form-validation": "0.1.0"
30
+ "@sio-group/form-types": "0.1.3",
31
+ "@sio-group/form-validation": "0.1.3"
31
32
  },
32
33
  "peerDependencies": {
33
- "react": "^18",
34
- "react-dom": "^18"
34
+ "react": "^19",
35
+ "react-dom": "^19"
35
36
  },
36
37
  "devDependencies": {
37
38
  "@vitejs/plugin-react": "^4",
@@ -0,0 +1,164 @@
1
+ @use "../utilities/mixins" as *;
2
+ @use "../tokens/colors" as *;
3
+
4
+ :where(.btn--primary) {
5
+ --sio-btn-bg: var(--sio-btn-primary-bg);
6
+ --sio-btn-border: var(--sio-btn-primary-border);
7
+ --sio-btn-text: var(--sio-btn-primary-text);
8
+
9
+ --sio-btn-bg-hover: color-mix(in srgb, var(--sio-btn-bg) 85%, black);
10
+ --sio-btn-border-hover: color-mix(in srgb, var(--sio-btn-border) 85%, black);
11
+ --sio-btn-text-hover: var(--sio-btn-text);
12
+
13
+ --sio-btn-bg-disabled: color-mix(in srgb, var(--sio-btn-bg) 40%, white);
14
+ --sio-btn-border-disabled: color-mix(in srgb, var(--sio-btn-border) 40%, white);
15
+ --sio-btn-text-disabled: color-mix(in srgb, var(--sio-btn-text) 60%, black);
16
+ }
17
+
18
+ :where(.btn--secondary) {
19
+ --sio-btn-bg: var(--sio-btn-secondary-bg);
20
+ --sio-btn-border: var(--sio-btn-secondary-border);
21
+ --sio-btn-text: var(--sio-btn-secondary-text);
22
+
23
+ --sio-btn-bg-hover: var(--sio-btn-bg);
24
+ --sio-btn-border-hover: color-mix(in srgb, var(--sio-btn-border) 85%, black);
25
+ --sio-btn-text-hover: var(--sio-btn-text);
26
+
27
+ --sio-btn-bg-disabled: var(--sio-btn-bg);
28
+ --sio-btn-border-disabled: color-mix(in srgb, var(--sio-btn-border) 40%, white);
29
+ --sio-btn-text-disabled: color-mix(in srgb, var(--sio-btn-text) 40%, white);
30
+ }
31
+
32
+ :where(.btn--link) {
33
+ --sio-btn-bg: var(--sio-btn-link-bg);
34
+ --sio-btn-border: var(--sio-btn-link-border);
35
+ --sio-btn-text: var(--sio-btn-link-text);
36
+
37
+ --sio-btn-bg-hover: var(--sio-btn-bg);
38
+ --sio-btn-border-hover: var(--sio-btn-border);
39
+ --sio-btn-text-hover: color-mix(in srgb, var(--sio-btn-text) 85%, black);
40
+
41
+ --sio-btn-bg-disabled: var(--sio-btn-bg);
42
+ --sio-btn-border-disabled: var(--sio-btn-border);
43
+ --sio-btn-text-disabled: color-mix(in srgb, var(--sio-btn-text) 40%, white);
44
+ }
45
+
46
+ :where(.btn) {
47
+ background-color: var(--sio-btn-bg);
48
+ color: var(--sio-btn-text);
49
+ display: inline-block;
50
+ font-size: .9em;
51
+ font-weight: 500;
52
+ user-select: none;
53
+ text-align: center;
54
+ border: 1px solid var(--sio-btn-border);
55
+ padding: 2px 15px;
56
+ border-radius: 3px;
57
+ cursor: pointer;
58
+ min-height: 22px;
59
+ transition: all .3s ease-in;
60
+ text-decoration: none;
61
+ }
62
+
63
+ :where(.btn--link) {
64
+ display: inline;
65
+ font-weight: unset;
66
+ user-select: none;
67
+ text-align: left;
68
+ padding: 0;
69
+ border-radius: unset;
70
+ min-height: unset;
71
+ transition: all 0.3s ease-in;
72
+ text-decoration: underline;
73
+ }
74
+
75
+ :where(.btn:hover),
76
+ :where(.btn:active),
77
+ :where(.btn:focus),
78
+ :where(.btn.btn--active) {
79
+ background: var(--sio-btn-bg-hover, var(--sio-btn-bg));
80
+ border-color: var(--sio-btn-border-hover, var(--sio-btn-border));
81
+ color: var(--sio-btn-text-hover, var(--sio-btn-text));
82
+ }
83
+
84
+ :where(.btn:disabled),
85
+ :where(.btn.btn--disabled) {
86
+ cursor: not-allowed;
87
+
88
+ background: var(--sio-btn-bg-disabled, var(--sio-btn-bg));
89
+ border-color: var(--sio-btn-border-disabled, var(--sio-btn-border));
90
+ color: var(--sio-btn-text-disabled, var(--sio-btn-text));
91
+ }
92
+
93
+ @each $name, $color in $colors {
94
+ :where(.btn--primary.btn--#{$name}) {
95
+ --sio-btn-bg: var(--sio-color-#{$name});
96
+ --sio-btn-border: var(--sio-color-#{$name});
97
+ --sio-btn-text: var(--sio-color-white);
98
+ }
99
+ :where(.btn--secondary.btn--#{$name}) {
100
+ --sio-btn-bg: transparent;
101
+ --sio-btn-border: var(--sio-color-#{$name});
102
+ --sio-btn-text: var(--sio-color-#{$name});
103
+ }
104
+ :where(.btn--link.btn--#{$name}) {
105
+ --sio-btn-bg: transparent;
106
+ --sio-btn-border: transparent;
107
+ --sio-btn-text: var(--sio-color-#{$name});
108
+ }
109
+ }
110
+
111
+ :where(.btn--block) {
112
+ display: block;
113
+ width: 100%;
114
+ }
115
+
116
+ :where(.btn--lg) {
117
+ padding: 5px 20px;
118
+ font-size: 1.1em;
119
+ min-height: 34px;
120
+ }
121
+
122
+ :where(.btn--sm) {
123
+ padding: 2.5px 5px;
124
+ font-size: .7em;
125
+ min-height: 23px;
126
+ }
127
+
128
+ :where(.btn--loading) {
129
+ position: relative;
130
+ cursor: wait !important;
131
+ }
132
+
133
+ :where(.btn__spinner) {
134
+ display: flex;
135
+ animation: spin 1s infinite linear;
136
+ margin-right: 8px;
137
+ width: 20px;
138
+ height: 20px;
139
+ }
140
+
141
+ :where(.btn__spinner svg) {
142
+ display: block;
143
+ width: 100%;
144
+ height: 100%;
145
+ }
146
+
147
+ :where(.btn__spinner circle) {
148
+ fill: none;
149
+ stroke: currentColor;
150
+ stroke-width: 2;
151
+ stroke-dasharray: 30 100;
152
+ stroke-linecap: round;
153
+ }
154
+
155
+ :where(.btn__loading-text) {
156
+ position: absolute;
157
+ clip: rect(1px, 1px, 1px, 1px);
158
+ }
159
+
160
+ :where(.btn-group) {
161
+ display: flex;
162
+ flex-wrap: wrap;
163
+ gap: 5px;
164
+ }
@@ -0,0 +1,90 @@
1
+ :where(.form-field__checkbox label) {
2
+ position: relative;
3
+ padding-left: 32px;
4
+ }
5
+
6
+ :where(.form-field__checkbox label > div) {
7
+ display: inline;
8
+ color: var(--sio-color-black);
9
+ font-weight: normal;
10
+ }
11
+
12
+ :where(.form-field__checkbox label):before {
13
+ content: '';
14
+ background-color: var(--sio-form-bg);
15
+ position: absolute;
16
+ border-radius: var(--sio-form-border-radius);
17
+ cursor: pointer;
18
+ border: 1px solid var(--sio-form-border);
19
+ width: 17px;
20
+ height: 17px;
21
+ left: 0;
22
+ top: -1px;
23
+ }
24
+
25
+ :where(.form-field__checkbox label):after {
26
+ content: '';
27
+ position: absolute;
28
+ background-color: var(--sio-color-primary);
29
+ width: 13px;
30
+ height: 13px;
31
+ top: 2px;
32
+ left: 3px;
33
+ transform: scale(0);
34
+ border-radius: var(--sio-form-border-radius);
35
+ cursor: pointer;
36
+ transition: all .4s;
37
+ }
38
+
39
+ :where(.form-field__checkbox input[type='checkbox']) {
40
+ display: none !important;
41
+ }
42
+
43
+ :where(.form-field__checkbox.form-field--has-value label):before {
44
+ border-color: var(--sio-color-primary);
45
+ }
46
+
47
+ :where(.form-field__checkbox.form-field--has-value label):after {
48
+ transform: scale(1);
49
+ }
50
+
51
+ :where(.form-field__checkbox.form-field--has-errors label):before {
52
+ border-color: var(--sio-color-error);
53
+ background: rgba(var(--sio-color-error-rgb), .06);
54
+ }
55
+
56
+ :where(.form-field__checkbox.form-field--has-errors.form-field--has-value label):after {
57
+ border-color: var(--sio-color-error);
58
+ background: var(--sio-color-error);
59
+ }
60
+
61
+
62
+ :where(.form-field__checkbox.form-field--disabled label) {
63
+ cursor: not-allowed;
64
+ }
65
+
66
+ :where(.form-field__checkbox.form-field--disabled label):before,
67
+ :where(.form-field__checkbox.form-field--disabled label):after {
68
+ cursor: not-allowed;
69
+ }
70
+
71
+ :where(.form-field__checkbox.form-field--disabled label):before {
72
+ border-color: var(--sio-color-light-gray);
73
+ background-color: color-mix(in srgb, var(--sio-color-light-gray) 75%, white);
74
+ }
75
+
76
+ :where(.form-field__checkbox.form-field--disabled label):after {
77
+ border-color: color-mix(in srgb, var(--sio-color-light-gray) 75%, black);
78
+ background-color: color-mix(in srgb, var(--sio-color-light-gray) 75%, black);
79
+
80
+ transform: scale(0);
81
+ transition: all .4s;
82
+ }
83
+
84
+ :where(.form-field__checkbox.form-field--disabled.form-field--has-value label):before {
85
+ border-color: var(--sio-color-light-gray);
86
+ }
87
+
88
+ :where(.form-field__checkbox.form-field--disabled.form-field--has-value label):after {
89
+ transform: scale(1);
90
+ }
@@ -0,0 +1,29 @@
1
+ :where(.form-field__color .form-field__control) {
2
+ max-width: 50px;
3
+ }
4
+
5
+ :where(.form-field__color input) {
6
+ padding: 0;
7
+ border-radius: var(--sio-form-border-radius);
8
+ }
9
+
10
+ :where(.form-field__color input[type="color" i]) {
11
+ inline-size: 50px;
12
+ block-size: 25.5px;
13
+ padding: 0;
14
+ border: none;
15
+ }
16
+
17
+ :where(.form-field__color input[type="color"])::-webkit-color-swatch-wrapper {
18
+ padding-block-end: 3px;
19
+ padding-block-start: 3px;
20
+ padding-inline-start: 3px;
21
+ padding-inline-end: 3px;
22
+ padding: 3px;
23
+ border: none;
24
+ }
25
+
26
+ :where(.form-field__color input[type="color"])::-webkit-color-swatch {
27
+ border: none;
28
+ border-radius: 2px;
29
+ }
@@ -0,0 +1,34 @@
1
+ :where(.form-field) {
2
+ position: relative;
3
+ margin: 5px 0 15px 0;
4
+ }
5
+
6
+ :where(.form-field label) {
7
+ color: var(--sio-form-label);
8
+ font-size: 0.9em;
9
+ font-weight: 600;
10
+ }
11
+
12
+ :where(.form-field label span) {
13
+ color: var(--sio-color-error);
14
+ font-weight: bold;
15
+ }
16
+
17
+ :where(.form-field__description) {
18
+ color: var(--sio-color-gray);
19
+ font-weight: 200;
20
+ font-size: 0.9em;
21
+ margin-left: 10px;
22
+ white-space: pre-wrap;
23
+ }
24
+
25
+ :where(.form-field__errors) {
26
+ list-style: none;
27
+ padding: 0;
28
+ margin: 5px 0 0;
29
+ color: var(--sio-color-error);
30
+ }
31
+
32
+ :where(.form-field__errors-item) {
33
+ font-size: .9em
34
+ }