kelt-ui-kit-react 1.2.8 → 1.3.1

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.
@@ -13,7 +13,7 @@ interface SearchProps {
13
13
  }
14
14
  interface FormData {
15
15
  recherche: string;
16
- [key: string]: string | number | boolean | Date;
16
+ [key: string]: string | number | boolean | Date | string[];
17
17
  }
18
18
  export declare const Search: import('react').ForwardRefExoticComponent<SearchProps & import('react').RefAttributes<{
19
19
  clearInput: (name: string) => void;
@@ -5,11 +5,13 @@ export interface SelectProps {
5
5
  label?: string;
6
6
  title?: string;
7
7
  disabled?: boolean;
8
- defaultValue?: string;
9
- value?: string;
8
+ defaultValue?: string | string[];
9
+ multiple?: boolean;
10
+ value?: string | string[];
10
11
  className?: string;
11
12
  options: SelectOptionInterface[];
13
+ onChangeMultiple?: (value: string[]) => void;
12
14
  onChange?: (value: string) => void;
13
15
  placeholder?: string;
14
16
  }
15
- export declare const Select: ({ id, label, options, className, disabled, defaultValue, onChange, value, placeholder, }: SelectProps) => JSX.Element;
17
+ export declare const Select: ({ id, label, options, className, disabled, multiple, defaultValue, onChange, onChangeMultiple, value, placeholder, }: SelectProps) => JSX.Element;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kelt-ui-kit-react",
3
3
  "type": "module",
4
- "version": "1.2.8",
4
+ "version": "1.3.1",
5
5
  "private": false,
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
package/src/form/Form.tsx CHANGED
@@ -7,11 +7,13 @@ import React, {
7
7
  } from "react";
8
8
  import { Button } from "../button/Button";
9
9
  import { Icon } from "../icon/Icon";
10
+ import { Select } from "../select/Select"; // <--- ton composant
10
11
  import "./form.css";
11
12
  import { FormInterface, FormValuesInterface } from "./form.interface";
13
+ import { Input } from "./input/Input";
12
14
 
13
15
  export type FormProps<
14
- T extends { [key: string]: string | number | boolean | Date }
16
+ T extends { [key: string]: string | number | boolean | Date | string[] }
15
17
  > = {
16
18
  className?: string;
17
19
  title?: string;
@@ -22,7 +24,7 @@ export type FormProps<
22
24
  };
23
25
 
24
26
  export const DynamicForm = forwardRef(
25
- <T extends { [key: string]: string | number | boolean | Date }>(
27
+ <T extends { [key: string]: string | number | boolean | Date | string[] }>(
26
28
  {
27
29
  initialForm,
28
30
  title,
@@ -48,27 +50,44 @@ export const DynamicForm = forwardRef(
48
50
  return initialValues;
49
51
  });
50
52
 
51
- // Stocker les références des inputs
52
53
  const inputRefs = useRef<{ [key: string]: HTMLInputElement | null }>({});
53
54
 
54
- const handleChange = useCallback(
55
+ /** Gestion des <input> */
56
+ const handleChangeInput = useCallback(
55
57
  (
56
58
  event: React.ChangeEvent<HTMLInputElement>,
57
59
  forminterface: FormInterface
58
60
  ) => {
59
- const { name, value, type, checked } = event.target;
61
+ const { name, type, checked, value } = event.target;
62
+ const newValue = type === "checkbox" ? checked : value;
63
+
60
64
  if (forminterface.onChange) {
61
- forminterface.onChange(value, name);
65
+ forminterface.onChange(newValue, name);
62
66
  }
67
+
63
68
  setValues((prevValues) => {
64
- const currentValues = prevValues || {};
65
- const updatedValues = {
66
- ...currentValues,
67
- [name]: type === "checkbox" ? checked : value,
68
- };
69
- if (onChange) {
70
- onChange(updatedValues);
71
- }
69
+ const updatedValues = { ...prevValues, [name]: newValue };
70
+ if (onChange) onChange(updatedValues);
71
+ return updatedValues;
72
+ });
73
+ },
74
+ [onChange]
75
+ );
76
+
77
+ /** Gestion des <select> */
78
+ const handleChangeSelect = useCallback(
79
+ (
80
+ newValue: string | string[],
81
+ name: string,
82
+ forminterface: FormInterface
83
+ ) => {
84
+ if (forminterface.onChange) {
85
+ forminterface.onChange(newValue, name);
86
+ }
87
+
88
+ setValues((prevValues) => {
89
+ const updatedValues = { ...prevValues, [name]: newValue };
90
+ if (onChange) onChange(updatedValues);
72
91
  return updatedValues;
73
92
  });
74
93
  },
@@ -103,7 +122,6 @@ export const DynamicForm = forwardRef(
103
122
  }));
104
123
  }, []);
105
124
 
106
- // Fonction pour donner le focus à l'élément qui devait initialement l'avoir
107
125
  const focusInitialElement = () => {
108
126
  const focusedField = initialForm.find((field) => field.focus);
109
127
  if (focusedField && inputRefs.current[focusedField.name]) {
@@ -112,7 +130,9 @@ export const DynamicForm = forwardRef(
112
130
  }, 500);
113
131
  }
114
132
  };
133
+
115
134
  const getValues = () => values;
135
+
116
136
  const updateFormValue: (values: FormValuesInterface<T>) => void = (
117
137
  values
118
138
  ) => {
@@ -121,6 +141,7 @@ export const DynamicForm = forwardRef(
121
141
  ...values,
122
142
  }));
123
143
  };
144
+
124
145
  useImperativeHandle(ref, () => ({
125
146
  resetForm,
126
147
  clearInput,
@@ -138,6 +159,7 @@ export const DynamicForm = forwardRef(
138
159
  const disabled = v.onDisabled
139
160
  ? v.onDisabled(v.value)
140
161
  : v.disabled ?? false;
162
+
141
163
  return (
142
164
  <div
143
165
  key={key}
@@ -146,24 +168,44 @@ export const DynamicForm = forwardRef(
146
168
  {v.label && <label>{v.label}</label>}
147
169
  {v.icon && <Icon classIcon={v.icon} />}
148
170
 
149
- <input
150
- ref={(el) => (inputRefs.current[v.name] = el)}
151
- name={v.name}
152
- type={v.type}
153
- placeholder={v.placeholder ?? ""}
154
- autoComplete={v.autoComplete ?? "on"}
155
- tabIndex={0}
156
- disabled={disabled}
157
- autoFocus={v.focus ?? false}
158
- required={required}
159
- step={v.step ?? "0.01"}
160
- value={values && (values[v.name] as string | number)}
161
- checked={v.type === "checkbox" ? !!values[v.name] : undefined}
162
- onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
163
- handleChange(e, v)
164
- }
165
- onInvalid={v.onInvalid ? v.onInvalid : undefined}
166
- />
171
+ {v.type === "select" ? (
172
+ <Select
173
+ id={v.name}
174
+ label={undefined}
175
+ options={v.options ?? []}
176
+ disabled={disabled}
177
+ multiple={v.multiple}
178
+ value={values[v.name] as any}
179
+ defaultValue={v.value as string | string[]}
180
+ placeholder={v.placeholder}
181
+ onChangeMultiple={(newValue) =>
182
+ handleChangeSelect(newValue, v.name, v)
183
+ }
184
+ onChange={(newValue) =>
185
+ handleChangeSelect(newValue, v.name, v)
186
+ }
187
+ />
188
+ ) : (
189
+ <Input
190
+ id={v.name}
191
+ ref={(el) => (inputRefs.current[v.name] = el)}
192
+ name={v.name}
193
+ type={v.type}
194
+ placeholder={v.placeholder ?? ""}
195
+ autoComplete={v.autoComplete ?? "off"}
196
+ tabIndex={0}
197
+ disabled={disabled}
198
+ autoFocus={v.focus ?? false}
199
+ required={required}
200
+ step={v.step ?? "0.01"}
201
+ value={values[v.name] as string | number}
202
+ checked={v.type === "checkbox" ? !!values[v.name] : undefined}
203
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
204
+ handleChangeInput(e, v)
205
+ }
206
+ onInvalid={v.onInvalid ? v.onInvalid : undefined}
207
+ />
208
+ )}
167
209
  </div>
168
210
  );
169
211
  })}
@@ -7,7 +7,7 @@ interface FormData {
7
7
  age: number;
8
8
  validate: boolean;
9
9
  password: string;
10
- [key: string]: string | number | boolean | Date; // Signature d'index ajoutée
10
+ [key: string]: string | number | boolean | Date | string[]; // Signature d'index ajoutée
11
11
  }
12
12
  export const FormView = (): JSX.Element => {
13
13
  const initialValues: FormInterface[] = [
@@ -8,4 +8,5 @@ export enum TypeInputEnum {
8
8
  CHECKBOX = "checkbox",
9
9
  RADIO = "radio",
10
10
  DATE = "date",
11
+ SELECT = "select",
11
12
  }
@@ -1,7 +1,7 @@
1
1
  import { TypeInputEnum } from "./form.enum";
2
2
 
3
3
  export type FormValuesInterface<
4
- T extends { [key: string]: string | number | boolean | Date }
4
+ T extends { [key: string]: string | number | boolean | Date | string[] }
5
5
  > = Partial<{
6
6
  [K in keyof T]: T[K];
7
7
  }>;
@@ -22,10 +22,15 @@ export interface FormInterface {
22
22
  required?: boolean;
23
23
  condition?: FormCondition;
24
24
  icon?: string;
25
+ multiple?: boolean;
26
+ options?: { value: string; label: string }[]; // <--- pour les <option>
25
27
  className?: string;
26
28
  autoComplete?: autoCompleteType;
27
29
  step?: string;
28
- onChange?: (value: string | number | boolean | Date, name?: string) => void;
30
+ onChange?: (
31
+ value: string | number | boolean | Date | string[],
32
+ name?: string
33
+ ) => void;
29
34
  onRequired?: (value: string | number | boolean | Date) => boolean;
30
35
  onDisabled?: (value: string | number | boolean | Date) => boolean;
31
36
  onInvalid?: (e: React.ChangeEvent<HTMLInputElement>) => void;
@@ -0,0 +1,76 @@
1
+ import "./input.css";
2
+
3
+ export interface InputProps {
4
+ id: string; // obligatoire pour le label for
5
+ name: string;
6
+ type?: string;
7
+ onInvalid?: (e: React.FocusEvent<HTMLInputElement>) => void;
8
+ value?: string | number;
9
+ placeholder?: string;
10
+ className?: string;
11
+ inputMode?: "text" | "numeric" | "decimal" | "email" | "tel" | "search";
12
+ disabled?: boolean;
13
+ autoFocus?: boolean;
14
+ required?: boolean;
15
+ minLength?: number;
16
+ maxLength?: number;
17
+ autoComplete?: "on" | "off";
18
+ ref?: React.Ref<HTMLInputElement>;
19
+ step?: string;
20
+ tabIndex?: number;
21
+ checked?: boolean;
22
+ onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
23
+ onBlur?: (e: React.FocusEvent<HTMLInputElement>) => void;
24
+ }
25
+
26
+ export const Input = ({
27
+ id,
28
+ name,
29
+ type = "text",
30
+ value,
31
+ onInvalid,
32
+ placeholder,
33
+ className,
34
+ inputMode,
35
+ minLength,
36
+ maxLength,
37
+ autoFocus = false,
38
+ disabled = false,
39
+ required = false,
40
+ autoComplete = "off",
41
+ ref,
42
+ tabIndex = 0,
43
+ step,
44
+ checked,
45
+ onChange,
46
+ onBlur,
47
+ }: InputProps) => {
48
+ return (
49
+ <>
50
+ <input type="text" style={{ display: "none" }} />
51
+ <input
52
+ ref={ref}
53
+ id={id}
54
+ name={name}
55
+ inputMode={inputMode ?? (type === "number" ? "numeric" : "text")}
56
+ type={type}
57
+ spellCheck="false"
58
+ value={value}
59
+ placeholder={placeholder}
60
+ disabled={disabled}
61
+ required={required}
62
+ autoComplete={autoComplete === "off" ? "fake" : autoComplete}
63
+ step={step}
64
+ tabIndex={tabIndex}
65
+ autoFocus={autoFocus}
66
+ minLength={minLength}
67
+ maxLength={maxLength}
68
+ onChange={onChange}
69
+ checked={checked}
70
+ onBlur={onBlur}
71
+ className={`input-field ${className ?? ""}`}
72
+ onInvalid={onInvalid}
73
+ />
74
+ </>
75
+ );
76
+ };
File without changes
package/src/index.ts CHANGED
@@ -14,6 +14,7 @@ export { Expands } from "./expands/Expands";
14
14
  export { FilAriane } from "./filAriane/FilAriane";
15
15
  export { DynamicForm } from "./form/Form";
16
16
  export { TypeInputEnum } from "./form/form.enum";
17
+ export { Input } from "./form/input/Input";
17
18
  export { TextArea } from "./form/textArea/TextArea";
18
19
  export { Grid } from "./grid/Grid";
19
20
  export { Header } from "./header/Header";
@@ -27,7 +27,7 @@ interface SearchProps {
27
27
 
28
28
  interface FormData {
29
29
  recherche: string;
30
- [key: string]: string | number | boolean | Date;
30
+ [key: string]: string | number | boolean | Date | string[]; // Signature d'index ajoutée
31
31
  }
32
32
 
33
33
  export const Search = forwardRef<
@@ -2,7 +2,7 @@ import { FormValuesInterface } from "../form/form.interface";
2
2
  import { Search } from "./Search";
3
3
  interface FormData {
4
4
  recherche: string;
5
- [key: string]: string | number | boolean | Date; // Signature d'index ajoutée
5
+ [key: string]: string | number | boolean | Date | string[]; // Signature d'index ajoutée
6
6
  }
7
7
  export const SearchView = (): JSX.Element => {
8
8
  const onChange = (values: FormValuesInterface<FormData>) => {
@@ -1,14 +1,18 @@
1
+ import { useRef } from "react";
1
2
  import "./select.css";
2
3
  import { SelectOptionInterface } from "./selectOption.interface";
4
+
3
5
  export interface SelectProps {
4
6
  id?: string;
5
7
  label?: string;
6
8
  title?: string;
7
9
  disabled?: boolean;
8
- defaultValue?: string;
9
- value?: string;
10
+ defaultValue?: string | string[];
11
+ multiple?: boolean;
12
+ value?: string | string[];
10
13
  className?: string;
11
14
  options: SelectOptionInterface[];
15
+ onChangeMultiple?: (value: string[]) => void;
12
16
  onChange?: (value: string) => void;
13
17
  placeholder?: string;
14
18
  }
@@ -19,27 +23,45 @@ export const Select = ({
19
23
  options,
20
24
  className,
21
25
  disabled,
26
+ multiple = false,
22
27
  defaultValue,
23
28
  onChange,
29
+ onChangeMultiple,
24
30
  value,
25
31
  placeholder,
26
32
  }: SelectProps): JSX.Element => {
33
+ const inputRefs = useRef<{ [key: string]: HTMLSelectElement | null }>({});
34
+
27
35
  const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
28
- const selectedValue = event.target.value;
29
- if (onChange) {
30
- onChange(selectedValue);
36
+ let selectedValue: string | string[];
37
+ if (multiple) {
38
+ selectedValue = Array.from(
39
+ event.target.selectedOptions,
40
+ (opt) => opt.value
41
+ );
42
+ if (onChangeMultiple) {
43
+ onChangeMultiple(selectedValue as string[]);
44
+ }
45
+ } else {
46
+ selectedValue = event.target.value;
47
+ if (onChange) {
48
+ onChange(selectedValue);
49
+ }
31
50
  }
32
51
  };
52
+
33
53
  return (
34
54
  <div id={id} className={`select-container ${className ? className : ""}`}>
35
55
  {label && <label className="select-container-label">{label}</label>}
36
56
  <select
37
57
  disabled={disabled}
38
58
  className="select-container-select"
39
- value={value ?? defaultValue ?? ""}
59
+ value={value ?? defaultValue ?? (multiple ? [] : "")}
40
60
  onChange={handleChange}
61
+ multiple={multiple}
62
+ ref={(el) => (inputRefs.current[id ?? "select"] = el)}
41
63
  >
42
- {placeholder && !defaultValue && (
64
+ {placeholder && !defaultValue && !multiple && (
43
65
  <option value="">{placeholder}</option>
44
66
  )}
45
67
  {options.map((option, index) => (