@react-fabric/form 1.0.0-beta.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 (187) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -0
  3. package/dist/cjs/builder/FileField.js +131 -0
  4. package/dist/cjs/builder/FormField.js +119 -0
  5. package/dist/cjs/form/Controller.js +64 -0
  6. package/dist/cjs/form/Form.js +128 -0
  7. package/dist/cjs/hooks/useFileUploader.js +204 -0
  8. package/dist/cjs/hooks/useFormBuilder.js +87 -0
  9. package/dist/cjs/i18n/ar.json.js +37 -0
  10. package/dist/cjs/i18n/en.json.js +38 -0
  11. package/dist/cjs/i18n/index.js +33 -0
  12. package/dist/cjs/index.js +56 -0
  13. package/dist/cjs/input/ArrayInput.js +189 -0
  14. package/dist/cjs/input/ArrayInput.module.css +1 -0
  15. package/dist/cjs/input/AvatarInput.js +141 -0
  16. package/dist/cjs/input/Checkbox.js +83 -0
  17. package/dist/cjs/input/ColorInput.js +100 -0
  18. package/dist/cjs/input/ColorPicker.js +122 -0
  19. package/dist/cjs/input/ColorPicker.module.css +1 -0
  20. package/dist/cjs/input/Field.js +31 -0
  21. package/dist/cjs/input/File.js +165 -0
  22. package/dist/cjs/input/File.module.css +1 -0
  23. package/dist/cjs/input/Hidden.js +54 -0
  24. package/dist/cjs/input/Input.js +79 -0
  25. package/dist/cjs/input/Number.js +80 -0
  26. package/dist/cjs/input/Password.js +104 -0
  27. package/dist/cjs/input/Radio.js +70 -0
  28. package/dist/cjs/input/RadioGroup.js +31 -0
  29. package/dist/cjs/input/Range.js +169 -0
  30. package/dist/cjs/input/Search.js +109 -0
  31. package/dist/cjs/input/Slider.js +172 -0
  32. package/dist/cjs/input/Switch.js +79 -0
  33. package/dist/cjs/input/Textarea.js +87 -0
  34. package/dist/cjs/internal/ErrorIcon.js +32 -0
  35. package/dist/cjs/internal/Field.module.css +1 -0
  36. package/dist/cjs/internal/FieldWrapper.js +78 -0
  37. package/dist/cjs/internal/InputWrapper.js +113 -0
  38. package/dist/cjs/ranger/index.js +352 -0
  39. package/dist/cjs/ranger/utils.js +49 -0
  40. package/dist/cjs/select/AutoComplete.js +268 -0
  41. package/dist/cjs/select/DualList.js +238 -0
  42. package/dist/cjs/select/List.js +241 -0
  43. package/dist/cjs/select/Options.js +76 -0
  44. package/dist/cjs/select/Select.js +283 -0
  45. package/dist/cjs/select/helpers.js +41 -0
  46. package/dist/cjs/select/useSelect.js +337 -0
  47. package/dist/cjs/utils/eventHandlers.js +50 -0
  48. package/dist/cjs/utils/getColor.js +40 -0
  49. package/dist/esm/builder/FileField.js +131 -0
  50. package/dist/esm/builder/FormField.js +119 -0
  51. package/dist/esm/form/Controller.js +64 -0
  52. package/dist/esm/form/Form.js +128 -0
  53. package/dist/esm/hooks/useFileUploader.js +204 -0
  54. package/dist/esm/hooks/useFormBuilder.js +87 -0
  55. package/dist/esm/i18n/ar.json.js +31 -0
  56. package/dist/esm/i18n/en.json.js +32 -0
  57. package/dist/esm/i18n/index.js +33 -0
  58. package/dist/esm/index.js +28 -0
  59. package/dist/esm/input/ArrayInput.js +189 -0
  60. package/dist/esm/input/ArrayInput.module.css +1 -0
  61. package/dist/esm/input/AvatarInput.js +141 -0
  62. package/dist/esm/input/Checkbox.js +83 -0
  63. package/dist/esm/input/ColorInput.js +100 -0
  64. package/dist/esm/input/ColorPicker.js +122 -0
  65. package/dist/esm/input/ColorPicker.module.css +1 -0
  66. package/dist/esm/input/Field.js +31 -0
  67. package/dist/esm/input/File.js +165 -0
  68. package/dist/esm/input/File.module.css +1 -0
  69. package/dist/esm/input/Hidden.js +54 -0
  70. package/dist/esm/input/Input.js +79 -0
  71. package/dist/esm/input/Number.js +80 -0
  72. package/dist/esm/input/Password.js +104 -0
  73. package/dist/esm/input/Radio.js +70 -0
  74. package/dist/esm/input/RadioGroup.js +31 -0
  75. package/dist/esm/input/Range.js +169 -0
  76. package/dist/esm/input/Search.js +109 -0
  77. package/dist/esm/input/Slider.js +172 -0
  78. package/dist/esm/input/Switch.js +79 -0
  79. package/dist/esm/input/Textarea.js +87 -0
  80. package/dist/esm/internal/ErrorIcon.js +32 -0
  81. package/dist/esm/internal/Field.module.css +1 -0
  82. package/dist/esm/internal/FieldWrapper.js +78 -0
  83. package/dist/esm/internal/InputWrapper.js +113 -0
  84. package/dist/esm/ranger/index.js +352 -0
  85. package/dist/esm/ranger/utils.js +47 -0
  86. package/dist/esm/select/AutoComplete.js +268 -0
  87. package/dist/esm/select/DualList.js +238 -0
  88. package/dist/esm/select/List.js +241 -0
  89. package/dist/esm/select/Options.js +76 -0
  90. package/dist/esm/select/Select.js +283 -0
  91. package/dist/esm/select/helpers.js +40 -0
  92. package/dist/esm/select/useSelect.js +337 -0
  93. package/dist/esm/utils/eventHandlers.js +50 -0
  94. package/dist/esm/utils/getColor.js +39 -0
  95. package/dist/types/builder/FileField.d.ts +8 -0
  96. package/dist/types/builder/FormField.d.ts +9 -0
  97. package/dist/types/form/Controller.d.ts +20 -0
  98. package/dist/types/form/Form.d.ts +33 -0
  99. package/dist/types/hooks/useFileUploader.d.ts +23 -0
  100. package/dist/types/hooks/useFormBuilder.d.ts +16 -0
  101. package/dist/types/i18n/index.d.ts +1 -0
  102. package/dist/types/index.d.ts +27 -0
  103. package/dist/types/input/ArrayInput.d.ts +64 -0
  104. package/dist/types/input/AvatarInput.d.ts +31 -0
  105. package/dist/types/input/Checkbox.d.ts +46 -0
  106. package/dist/types/input/ColorInput.d.ts +10 -0
  107. package/dist/types/input/ColorPicker.d.ts +24 -0
  108. package/dist/types/input/Field.d.ts +41 -0
  109. package/dist/types/input/File.d.ts +17 -0
  110. package/dist/types/input/Hidden.d.ts +16 -0
  111. package/dist/types/input/Input.d.ts +9 -0
  112. package/dist/types/input/Number.d.ts +17 -0
  113. package/dist/types/input/Password.d.ts +13 -0
  114. package/dist/types/input/Radio.d.ts +42 -0
  115. package/dist/types/input/RadioGroup.d.ts +30 -0
  116. package/dist/types/input/Range.d.ts +59 -0
  117. package/dist/types/input/Search.d.ts +17 -0
  118. package/dist/types/input/Slider.d.ts +63 -0
  119. package/dist/types/input/Switch.d.ts +42 -0
  120. package/dist/types/input/Textarea.d.ts +17 -0
  121. package/dist/types/internal/ErrorIcon.d.ts +1 -0
  122. package/dist/types/internal/FieldWrapper.d.ts +1 -0
  123. package/dist/types/internal/InputWrapper.d.ts +1 -0
  124. package/dist/types/ranger/index.d.ts +70 -0
  125. package/dist/types/ranger/utils.d.ts +25 -0
  126. package/dist/types/select/AutoComplete.d.ts +17 -0
  127. package/dist/types/select/DualList.d.ts +38 -0
  128. package/dist/types/select/List.d.ts +4 -0
  129. package/dist/types/select/Options.d.ts +14 -0
  130. package/dist/types/select/Select.d.ts +2 -0
  131. package/dist/types/select/helpers.d.ts +2 -0
  132. package/dist/types/select/useSelect.d.ts +50 -0
  133. package/dist/types/types/index.d.ts +169 -0
  134. package/dist/types/types/schema.d.ts +59 -0
  135. package/dist/types/utils/eventHandlers.d.ts +11 -0
  136. package/dist/types/utils/getColor.d.ts +4 -0
  137. package/dist/types/utils/index.d.ts +2 -0
  138. package/package.json +64 -0
  139. package/src/builder/FileField.tsx +122 -0
  140. package/src/builder/FormField.tsx +161 -0
  141. package/src/form/Controller.tsx +103 -0
  142. package/src/form/Form.tsx +160 -0
  143. package/src/hooks/useFileUploader.ts +234 -0
  144. package/src/hooks/useFormBuilder.tsx +128 -0
  145. package/src/i18n/ar.json +23 -0
  146. package/src/i18n/en.json +24 -0
  147. package/src/i18n/index.ts +28 -0
  148. package/src/index.ts +54 -0
  149. package/src/input/ArrayInput.module.css +41 -0
  150. package/src/input/ArrayInput.tsx +318 -0
  151. package/src/input/AvatarInput.tsx +150 -0
  152. package/src/input/Checkbox.tsx +165 -0
  153. package/src/input/ColorInput.tsx +157 -0
  154. package/src/input/ColorPicker.module.css +51 -0
  155. package/src/input/ColorPicker.tsx +210 -0
  156. package/src/input/Field.tsx +96 -0
  157. package/src/input/File.module.css +42 -0
  158. package/src/input/File.tsx +224 -0
  159. package/src/input/Hidden.tsx +65 -0
  160. package/src/input/Input.tsx +114 -0
  161. package/src/input/Number.tsx +126 -0
  162. package/src/input/Password.tsx +150 -0
  163. package/src/input/Radio.tsx +146 -0
  164. package/src/input/RadioGroup.tsx +75 -0
  165. package/src/input/Range.tsx +276 -0
  166. package/src/input/Search.tsx +160 -0
  167. package/src/input/Slider.tsx +282 -0
  168. package/src/input/Switch.tsx +168 -0
  169. package/src/input/Textarea.tsx +127 -0
  170. package/src/internal/ErrorIcon.tsx +61 -0
  171. package/src/internal/Field.module.css +139 -0
  172. package/src/internal/FieldWrapper.tsx +84 -0
  173. package/src/internal/InputWrapper.tsx +187 -0
  174. package/src/ranger/index.tsx +514 -0
  175. package/src/ranger/utils.ts +48 -0
  176. package/src/select/AutoComplete.tsx +354 -0
  177. package/src/select/DualList.tsx +286 -0
  178. package/src/select/List.tsx +288 -0
  179. package/src/select/Options.tsx +121 -0
  180. package/src/select/Select.tsx +350 -0
  181. package/src/select/helpers.ts +36 -0
  182. package/src/select/useSelect.tsx +413 -0
  183. package/src/types/index.ts +203 -0
  184. package/src/types/schema.ts +100 -0
  185. package/src/utils/eventHandlers.ts +72 -0
  186. package/src/utils/getColor.ts +47 -0
  187. package/src/utils/index.ts +25 -0
@@ -0,0 +1,165 @@
1
+ /*
2
+ * React Fabric
3
+ * @version: 1.0.0
4
+ *
5
+ *
6
+ * The MIT License (MIT)
7
+ * Copyright (c) 2024 Adarsh Pastakia
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
10
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
11
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
13
+ * subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
16
+ * portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+
24
+ import { CoreIcons, Icon } from "@react-fabric/core";
25
+ import { type RefProp } from "@react-fabric/core/dist/types/types";
26
+ import classNames from "classnames";
27
+ import {
28
+ useCallback,
29
+ useDeferredValue,
30
+ useEffect,
31
+ useMemo,
32
+ useState,
33
+ type ChangeEvent,
34
+ } from "react";
35
+ import { ErrorIcon } from "../internal/ErrorIcon";
36
+
37
+ export interface CheckboxProps extends RefProp<HTMLInputElement> {
38
+ /**
39
+ * checkbox label
40
+ */
41
+ label?: JSX.Element | string;
42
+ /**
43
+ * checked
44
+ */
45
+ checked?: boolean;
46
+ /**
47
+ * value
48
+ */
49
+ value?: string | number;
50
+ /**
51
+ * on checked change
52
+ */
53
+ onChange?: (checked: boolean | string | number) => void;
54
+
55
+ /**
56
+ * disabled input
57
+ */
58
+ disabled?: boolean;
59
+ /**
60
+ * invalid value input
61
+ */
62
+ invalid?: boolean;
63
+ /**
64
+ * error message
65
+ */
66
+ error?: string;
67
+
68
+ /**
69
+ * field width
70
+ */
71
+ width?: number | string;
72
+
73
+ /**
74
+ * cutom checkbox icon
75
+ */
76
+ icon?: string;
77
+ /**
78
+ * cutom checkbox checked icon
79
+ */
80
+ iconChecked?: string;
81
+
82
+ name?: string;
83
+ }
84
+
85
+ export const Checkbox = ({
86
+ ref,
87
+ label,
88
+ value,
89
+ name,
90
+ checked,
91
+ invalid,
92
+ disabled,
93
+ error,
94
+ width,
95
+ icon,
96
+ iconChecked,
97
+ onChange,
98
+ ...rest
99
+ }: CheckboxProps) => {
100
+ const [actualValue, setActualValue] = useState(false);
101
+ const deferred = useDeferredValue(!!checked);
102
+
103
+ const iconOn = useMemo(
104
+ () => iconChecked ?? icon ?? CoreIcons.checkboxOn,
105
+ [icon, iconChecked],
106
+ );
107
+ const iconOff = useMemo(() => icon ?? CoreIcons.checkboxOff, [icon]);
108
+
109
+ useEffect(() => {
110
+ setActualValue(deferred);
111
+ }, [deferred]);
112
+
113
+ const handleChange = useCallback(
114
+ (e?: ChangeEvent<HTMLInputElement>) => {
115
+ setActualValue(e?.target.checked ?? false);
116
+ onChange?.(e?.target.checked ?? false);
117
+ },
118
+ [onChange, value],
119
+ );
120
+
121
+ return (
122
+ <label
123
+ className={classNames(
124
+ invalid ? "ring-danger-500" : "ring-primary-500",
125
+ disabled
126
+ ? "opacity-50 cursor-not-allowed"
127
+ : " opacity-85 hover:opacity-100 cursor-pointer",
128
+ "inline-flex gap-1 py-1 items-center relative rounded ring-offset-2 has-[:focus-visible]:ring-1",
129
+ )}
130
+ style={{ width }}
131
+ >
132
+ <input
133
+ className={classNames(
134
+ "appearance-none absolute opacity-0 inset-0 bg-transparent border-none outline-none ring-0",
135
+ )}
136
+ aria-invalid={invalid}
137
+ aria-disabled={disabled}
138
+ disabled={disabled}
139
+ aria-errormessage={error}
140
+ type="checkbox"
141
+ ref={ref}
142
+ size={1}
143
+ tabIndex={0}
144
+ name={name}
145
+ autoComplete="off"
146
+ checked={actualValue}
147
+ onChange={handleChange}
148
+ {...rest}
149
+ />
150
+ <Icon
151
+ className={classNames(
152
+ "p-0.5",
153
+ actualValue && icon && !iconChecked && "bg-primary-500 text-white",
154
+ )}
155
+ size="1.25em"
156
+ color={invalid ? "danger" : "primary"}
157
+ icon={actualValue ? iconOn : iconOff}
158
+ />
159
+ <ErrorIcon invalid={invalid} error={error} />
160
+ {label && (
161
+ <span className="flex-initial leading-none truncate">{label}</span>
162
+ )}
163
+ </label>
164
+ );
165
+ };
@@ -0,0 +1,157 @@
1
+ /*
2
+ * React Fabric
3
+ * @version: 1.0.0
4
+ *
5
+ *
6
+ * The MIT License (MIT)
7
+ * Copyright (c) 2024 Adarsh Pastakia
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
10
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
11
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
13
+ * subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
16
+ * portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+
24
+ import { CoreIcons, Dropdown, Icon } from "@react-fabric/core";
25
+ import { type RefProp } from "@react-fabric/core/dist/types/types";
26
+ import { isString } from "@react-fabric/utilities";
27
+ import classNames from "classnames";
28
+ import {
29
+ startTransition,
30
+ useCallback,
31
+ useDeferredValue,
32
+ useEffect,
33
+ useState,
34
+ } from "react";
35
+ import { type InputProps } from "../types";
36
+ import { ColorPicker, type ColorProps } from "./ColorPicker";
37
+
38
+ export interface ColorInputProps extends InputProps, ColorProps, RefProp {
39
+ /**
40
+ * show eydrop picker
41
+ */
42
+ showPicker?: boolean;
43
+ }
44
+
45
+ export const ColorInput = ({
46
+ ref,
47
+ required,
48
+ disabled,
49
+ allowClear,
50
+ invalid,
51
+ error,
52
+ value,
53
+ showPicker,
54
+ defaultColor = "",
55
+ decorateEnd,
56
+ decorateStart,
57
+ onChange,
58
+ // @ts-expect-error ignore
59
+ noOutline,
60
+ ...rest
61
+ }: ColorInputProps) => {
62
+ const [actualValue, setActualValue] = useState("");
63
+ const deferred = useDeferredValue(value ?? defaultColor);
64
+
65
+ useEffect(() => {
66
+ setActualValue(deferred ?? "");
67
+ }, [deferred]);
68
+
69
+ const handleChange = useCallback(
70
+ (e?: string) => {
71
+ setActualValue(e ?? defaultColor);
72
+ onChange != null && startTransition(() => onChange(e));
73
+ },
74
+ [onChange],
75
+ );
76
+
77
+ return (
78
+ <div
79
+ className={classNames(
80
+ "flex-content min-h-[1.5em] min-w-[3.5em] self-stretch flex items-center outline-tint-200 rounded",
81
+ !disabled && "bg-base",
82
+ !noOutline && "bg-[var(--fabric-input)] outline overflow-hidden",
83
+ )}
84
+ >
85
+ {decorateStart && (
86
+ <div
87
+ className={classNames(
88
+ "text-muted leading-none flex-content",
89
+ isString(decorateStart) && "px-2",
90
+ )}
91
+ >
92
+ {decorateStart}
93
+ </div>
94
+ )}
95
+ <Dropdown showArrow disabled={disabled}>
96
+ <button data-ref="button" className="flex-1 flex items-center">
97
+ <div
98
+ role="none"
99
+ className="h-[1.5em] min-w-[1.5em] flex-1 flex items-center justify-center self-stretch cursor-pointer m-[0.25em] rounded outline outline-tint-100"
100
+ style={{
101
+ backgroundColor: actualValue,
102
+ opacity: disabled ? 0.65 : 1,
103
+ pointerEvents: disabled ? "none" : undefined,
104
+ }}
105
+ onClick={(e) =>
106
+ (e.currentTarget.nextElementSibling as HTMLElement)?.focus()
107
+ }
108
+ >
109
+ {!actualValue && (
110
+ <Icon
111
+ size="md"
112
+ className="text-muted"
113
+ icon={CoreIcons.colorSwatch}
114
+ />
115
+ )}
116
+ </div>
117
+ </button>
118
+ <ColorPicker
119
+ {...rest}
120
+ onChange={handleChange}
121
+ defaultColor={defaultColor}
122
+ value={actualValue}
123
+ />
124
+ </Dropdown>
125
+ {!disabled && showPicker && (
126
+ <Icon
127
+ icon={CoreIcons.colorPicker}
128
+ onClick={() =>
129
+ (window as AnyObject).EyeDropper &&
130
+ new (window as AnyObject).EyeDropper()
131
+ .open()
132
+ .then((resp: AnyObject) => handleChange(resp.sRGBHex))
133
+ }
134
+ />
135
+ )}
136
+ {decorateEnd && (
137
+ <div
138
+ className={classNames(
139
+ "text-muted leading-none flex-content",
140
+ isString(decorateEnd) && "px-2",
141
+ )}
142
+ >
143
+ {decorateEnd}
144
+ </div>
145
+ )}
146
+ {!disabled && allowClear && actualValue !== defaultColor && (
147
+ <Icon
148
+ icon={CoreIcons.close}
149
+ onClick={() => handleChange()}
150
+ className={classNames(
151
+ "text-tint-500 hover:text-tint-700 p-[0.25em] flex-content",
152
+ )}
153
+ />
154
+ )}
155
+ </div>
156
+ );
157
+ };
@@ -0,0 +1,51 @@
1
+ /*
2
+ * React Fabric
3
+ * @version: 1.0.0
4
+ *
5
+ *
6
+ * The MIT License (MIT)
7
+ * Copyright (c) 2024 Adarsh Pastakia
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
10
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
11
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
13
+ * subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
16
+ * portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+
24
+ @layer comp {
25
+ .colorPicker {
26
+ --color-shadow: theme(borderColor.base);
27
+
28
+ & input {
29
+ @apply bg-base text-base !border !border-solid !rounded-sm !border-base focus:!border-primary !shadow-none;
30
+
31
+ padding: 0 4px !important;
32
+ line-height: 2;
33
+ }
34
+
35
+ & label {
36
+ @apply !text-base;
37
+ }
38
+
39
+ & :global(.flexbox-fix) {
40
+ @apply !border-t-muted justify-center;
41
+
42
+ & > div > div {
43
+ @apply text-center;
44
+ }
45
+
46
+ & span > div {
47
+ box-shadow: 0 0 1px 1px theme(borderColor.base) inset !important;
48
+ }
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,210 @@
1
+ /*
2
+ * React Fabric
3
+ * @version: 1.0.0
4
+ *
5
+ *
6
+ * The MIT License (MIT)
7
+ * Copyright (c) 2024 Adarsh Pastakia
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
10
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
11
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
13
+ * subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
16
+ * portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+
24
+ import Color from "color";
25
+ import {
26
+ memo,
27
+ startTransition,
28
+ useCallback,
29
+ useDeferredValue,
30
+ useEffect,
31
+ useState,
32
+ type FC,
33
+ } from "react";
34
+ import { SketchPicker } from "react-color";
35
+ import classes from "./ColorPicker.module.css";
36
+
37
+ export interface ColorProps {
38
+ /**
39
+ * color swatches
40
+ */
41
+ swatches?: string[];
42
+ /**
43
+ * default color
44
+ */
45
+ defaultColor?: string;
46
+ /**
47
+ * hide alpha value
48
+ */
49
+ hideAlpha?: boolean;
50
+ /**
51
+ * color value
52
+ */
53
+ value?: string;
54
+ /**
55
+ * change handler
56
+ */
57
+ onChange?: (color?: string) => void;
58
+ }
59
+
60
+ const DEFAULT_SWATCHES = [
61
+ Color("#d7323a").mix(Color("#171a1c"), 0.5).hex(),
62
+ Color("#ff781c").mix(Color("#171a1c"), 0.5).hex(),
63
+ Color("#f7b731").mix(Color("#171a1c"), 0.5).hex(),
64
+ Color("#88ab1b").mix(Color("#171a1c"), 0.5).hex(),
65
+ Color("#22aa85").mix(Color("#171a1c"), 0.5).hex(),
66
+ Color("#399bec").mix(Color("#171a1c"), 0.5).hex(),
67
+ Color("#4862c8").mix(Color("#171a1c"), 0.5).hex(),
68
+ Color("#aa66cf").mix(Color("#171a1c"), 0.5).hex(),
69
+ Color("#f43f7b").mix(Color("#171a1c"), 0.5).hex(),
70
+ Color("#a37f4f").mix(Color("#171a1c"), 0.5).hex(),
71
+
72
+ "#d7323a",
73
+ "#ff781c",
74
+ "#f7b731",
75
+ "#88ab1b",
76
+ "#22aa85",
77
+ "#399bec",
78
+ "#4862c8",
79
+ "#aa66cf",
80
+ "#f43f7b",
81
+ "#a37f4f",
82
+
83
+ Color("#d7323a").mix(Color("#f1f3f4"), 0.5).hex(),
84
+ Color("#ff781c").mix(Color("#f1f3f4"), 0.5).hex(),
85
+ Color("#f7b731").mix(Color("#f1f3f4"), 0.5).hex(),
86
+ Color("#88ab1b").mix(Color("#f1f3f4"), 0.5).hex(),
87
+ Color("#22aa85").mix(Color("#f1f3f4"), 0.5).hex(),
88
+ Color("#399bec").mix(Color("#f1f3f4"), 0.5).hex(),
89
+ Color("#4862c8").mix(Color("#f1f3f4"), 0.5).hex(),
90
+ Color("#aa66cf").mix(Color("#f1f3f4"), 0.5).hex(),
91
+ Color("#f43f7b").mix(Color("#f1f3f4"), 0.5).hex(),
92
+ Color("#a37f4f").mix(Color("#f1f3f4"), 0.5).hex(),
93
+
94
+ "#171a1c",
95
+ "#2d3439",
96
+ "#444e55",
97
+ "#5b6971",
98
+ "#71838e",
99
+ "#86959e",
100
+ "#9ca8b0",
101
+ "#b8c1c6",
102
+ "#d5dadd",
103
+ "#f1f3f4",
104
+ ];
105
+
106
+ // eslint-disable-next-line react/display-name
107
+ export const ColorPicker: FC<ColorProps> = memo(
108
+ ({
109
+ value,
110
+ onChange,
111
+ hideAlpha,
112
+ defaultColor = "#fff",
113
+ swatches = DEFAULT_SWATCHES,
114
+ }: ColorProps) => {
115
+ const [actualValue, setActualValue] = useState("");
116
+ const deferred = useDeferredValue(value ?? defaultColor);
117
+
118
+ useEffect(() => {
119
+ setActualValue(deferred ?? "");
120
+ }, [deferred]);
121
+
122
+ const handleChange = useCallback(
123
+ (e: string) => {
124
+ setActualValue(e ?? defaultColor);
125
+ onChange != null && startTransition(() => onChange(e));
126
+ },
127
+ [onChange],
128
+ );
129
+
130
+ return (
131
+ <SketchPicker
132
+ width="16rem"
133
+ className={classes.colorPicker}
134
+ styles={
135
+ {
136
+ default: {
137
+ hue: {
138
+ borderRadius: "99px",
139
+ boxShadow: "0 0 1px 1px var(--color-shadow)",
140
+ },
141
+ alpha: {
142
+ height: "1rem",
143
+ borderRadius: "99px",
144
+ backgroundColor: "var(--fabric-bg)",
145
+ boxShadow: "0 0 1px 1px var(--color-shadow)",
146
+ },
147
+ color: {
148
+ boxShadow: "0 0 1px 1px var(--color-shadow)",
149
+ },
150
+ saturation: {
151
+ boxShadow: "0 0 1px 1px var(--color-shadow)",
152
+ },
153
+ activeColor: {
154
+ boxShadow: "0 0 1px 1px var(--color-shadow)",
155
+ },
156
+ picker: {
157
+ backgroundColor: "var(--fabric-bg)",
158
+ boxShadow:
159
+ "0 0 0 1px var(--color-shadow), 0 0 8px var(--fabric-shadow)",
160
+ },
161
+ Alpha: {
162
+ alpha: {
163
+ paddingRight: "calc(1rem - 2px)",
164
+ },
165
+ slider: {
166
+ width: "calc(1rem - 2px)",
167
+ borderRadius: "99px",
168
+ height: "calc(1rem - 2px)",
169
+ transform: "none",
170
+ },
171
+ },
172
+ Hue: {
173
+ hue: {
174
+ paddingRight: "calc(1rem - 2px)",
175
+ },
176
+ slider: {
177
+ width: "calc(1rem - 2px)",
178
+ borderRadius: "99px",
179
+ height: "calc(1rem - 2px)",
180
+ transform: "none",
181
+ },
182
+ },
183
+ Saturation: {
184
+ circle: {
185
+ width: "0.5rem",
186
+ borderRadius: "99px",
187
+ height: "0.5rem",
188
+ transform: "translate(-0.25rem, -0.25rem)",
189
+ },
190
+ },
191
+ checkboard: {
192
+ white: "transparent",
193
+ black: "red",
194
+ },
195
+ },
196
+ } as AnyObject
197
+ }
198
+ color={actualValue}
199
+ presetColors={swatches}
200
+ disableAlpha={hideAlpha}
201
+ onChange={({ rgb: { a = 1, ...rgb } }) =>
202
+ setActualValue(Color(rgb).alpha(a)[a < 1 ? "hexa" : "hex"]())
203
+ }
204
+ onChangeComplete={({ rgb: { a = 1, ...rgb } }) =>
205
+ handleChange(Color(rgb).alpha(a)[a < 1 ? "hexa" : "hex"]())
206
+ }
207
+ />
208
+ );
209
+ },
210
+ );
@@ -0,0 +1,96 @@
1
+ /*
2
+ * React Fabric
3
+ * @version: 1.0.0
4
+ *
5
+ *
6
+ * The MIT License (MIT)
7
+ * Copyright (c) 2024 Adarsh Pastakia
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
10
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
11
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
13
+ * subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
16
+ * portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+
24
+ import {
25
+ type ChildrenProp,
26
+ type CssProp,
27
+ } from "@react-fabric/core/dist/types/types";
28
+ import classNames from "classnames";
29
+ import { Children, cloneElement } from "react";
30
+ import classes from "../internal/Field.module.css";
31
+ import { FieldWrapper } from "../internal/FieldWrapper";
32
+
33
+ export interface FieldProps extends ChildrenProp, CssProp {
34
+ /**
35
+ * input label
36
+ */
37
+ label?: string;
38
+ /**
39
+ * append to label end
40
+ */
41
+ appendLabel?: JSX.Element | string | number | boolean;
42
+ /**
43
+ * info label at bottom
44
+ */
45
+ info?: string;
46
+
47
+ /**
48
+ * required
49
+ */
50
+ required?: boolean;
51
+ /**
52
+ * hide outline
53
+ */
54
+ noOutline?: boolean;
55
+
56
+ /**
57
+ * field width
58
+ */
59
+ width?: number | string;
60
+ /**
61
+ * inline label and input
62
+ */
63
+ inline?: boolean;
64
+ /**
65
+ * label width for inline
66
+ */
67
+ labelWidth?: string;
68
+ /**
69
+ * dont apply bg and outline
70
+ */
71
+ plain?: boolean;
72
+ }
73
+
74
+ export const Field = ({ children, noOutline, plain, ...rest }: FieldProps) => {
75
+ return (
76
+ <FieldWrapper {...rest}>
77
+ <div
78
+ className={classNames(
79
+ classes.fieldGroup,
80
+ !plain && !noOutline && "outline",
81
+ !plain && "bg-base",
82
+ "flex flex-nowrap flex-1 rounded",
83
+ )}
84
+ >
85
+ {Children.map(
86
+ children,
87
+ (child) =>
88
+ child &&
89
+ cloneElement(child as AnyObject, {
90
+ "data-inner": true,
91
+ }),
92
+ )}
93
+ </div>
94
+ </FieldWrapper>
95
+ );
96
+ };