uibee 2.10.5 → 2.12.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.
- package/dist/src/components/inputs/checkbox.d.ts +9 -1
- package/dist/src/components/inputs/checkbox.js +21 -3
- package/dist/src/components/inputs/input.d.ts +1 -0
- package/dist/src/components/inputs/input.js +2 -2
- package/dist/src/components/inputs/radio.d.ts +9 -1
- package/dist/src/components/inputs/radio.js +10 -3
- package/dist/src/components/inputs/range.d.ts +1 -0
- package/dist/src/components/inputs/range.js +2 -2
- package/dist/src/components/inputs/select.d.ts +2 -1
- package/dist/src/components/inputs/select.js +2 -2
- package/dist/src/components/inputs/shared/fieldWrapper.d.ts +2 -1
- package/dist/src/components/inputs/shared/fieldWrapper.js +2 -2
- package/dist/src/components/inputs/shared/selectionWrapper.d.ts +2 -1
- package/dist/src/components/inputs/shared/selectionWrapper.js +2 -2
- package/dist/src/components/inputs/switch.d.ts +1 -0
- package/dist/src/components/inputs/switch.js +2 -2
- package/dist/src/components/inputs/tagInput.d.ts +2 -1
- package/dist/src/components/inputs/tagInput.js +2 -2
- package/dist/src/components/inputs/textarea.d.ts +1 -0
- package/dist/src/components/inputs/textarea.js +2 -2
- package/dist/src/globals.css +9 -0
- package/package.json +1 -1
- package/src/components/inputs/checkbox.tsx +67 -5
- package/src/components/inputs/input.tsx +3 -1
- package/src/components/inputs/radio.tsx +55 -3
- package/src/components/inputs/range.tsx +3 -1
- package/src/components/inputs/select.tsx +3 -0
- package/src/components/inputs/shared/fieldWrapper.tsx +7 -0
- package/src/components/inputs/shared/selectionWrapper.tsx +8 -1
- package/src/components/inputs/switch.tsx +3 -1
- package/src/components/inputs/tagInput.tsx +3 -0
- package/src/components/inputs/textarea.tsx +3 -1
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type CheckboxOption = {
|
|
2
|
+
label: string;
|
|
3
|
+
value: string | number;
|
|
4
|
+
};
|
|
5
|
+
export type CheckboxProps = Omit<React.ComponentProps<'input'>, 'name' | 'onChange' | 'value'> & {
|
|
2
6
|
name: string;
|
|
3
7
|
label?: string;
|
|
4
8
|
error?: string;
|
|
5
9
|
info?: string;
|
|
10
|
+
description?: string;
|
|
6
11
|
className?: string;
|
|
12
|
+
options: CheckboxOption[];
|
|
13
|
+
value?: (string | number)[];
|
|
14
|
+
onChange?: (value: (string | number)[]) => void;
|
|
7
15
|
};
|
|
8
16
|
export default function Checkbox(props: CheckboxProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Check } from 'lucide-react';
|
|
3
|
-
import { SelectionWrapper } from './shared';
|
|
3
|
+
import { SelectionWrapper, FieldWrapper } from './shared';
|
|
4
4
|
export default function Checkbox(props) {
|
|
5
|
-
const {
|
|
6
|
-
|
|
5
|
+
const { options, onChange, value, label, description, error, info, name, className, ...rest } = props;
|
|
6
|
+
const selectedValues = Array.isArray(value) ? value : [];
|
|
7
|
+
return (_jsx(FieldWrapper, { label: label, name: name, required: rest.required, info: info, description: description, error: error, className: className, children: _jsx("div", { className: 'flex flex-col gap-2', children: options.map((option) => (_jsx(CheckboxItem, { name: name, value: option.value, label: option.label, checked: selectedValues.includes(option.value), disabled: rest.disabled, onChange: (e) => {
|
|
8
|
+
if (!onChange)
|
|
9
|
+
return;
|
|
10
|
+
const isChecked = e.target.checked;
|
|
11
|
+
let newValues = [...selectedValues];
|
|
12
|
+
if (isChecked) {
|
|
13
|
+
newValues.push(option.value);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
newValues = newValues.filter((v) => v !== option.value);
|
|
17
|
+
}
|
|
18
|
+
onChange(newValues);
|
|
19
|
+
}, className: 'mb-0' }, option.value))) }) }));
|
|
20
|
+
}
|
|
21
|
+
function CheckboxItem(props) {
|
|
22
|
+
const { name, label, error, info, description, className, ...inputProps } = props;
|
|
23
|
+
const id = inputProps.value ? `${name}-${inputProps.value}` : name;
|
|
24
|
+
return (_jsx(SelectionWrapper, { label: label, name: id, required: inputProps.required, info: info, description: description, error: error, className: className, disabled: inputProps.disabled, children: _jsxs("div", { className: 'relative flex items-center', children: [_jsx("input", { ...inputProps, id: id, name: name, type: 'checkbox', className: `
|
|
7
25
|
peer appearance-none h-5 w-5 rounded border border-login-500 bg-login-500/50
|
|
8
26
|
checked:bg-login checked:border-login
|
|
9
27
|
focus:outline-none focus:ring-2 focus:ring-login/50
|
|
@@ -6,7 +6,7 @@ import DateTimePickerPopup from './shared/dateTimePickerPopup';
|
|
|
6
6
|
import ColorPickerPopup from './shared/colorPickerPopup';
|
|
7
7
|
import useClickOutside from '../../hooks/useClickOutside';
|
|
8
8
|
export default function Input(props) {
|
|
9
|
-
const { name, label, error, className, icon, info, ...inputProps } = props;
|
|
9
|
+
const { name, label, error, className, icon, info, description, ...inputProps } = props;
|
|
10
10
|
const { type = 'text', value } = inputProps;
|
|
11
11
|
const localRef = useRef(null);
|
|
12
12
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -105,7 +105,7 @@ export default function Input(props) {
|
|
|
105
105
|
return `${dd}.${MM}.${yyyy} ${hh}:${mm}`;
|
|
106
106
|
return value;
|
|
107
107
|
}
|
|
108
|
-
return (_jsx(FieldWrapper, { label: label, name: name, required: inputProps.required, info: info, error: error, className: className, children: _jsxs("div", { className: 'relative flex items-center', ref: containerRef, children: [displayIcon && (_jsx("div", { className: `
|
|
108
|
+
return (_jsx(FieldWrapper, { label: label, name: name, required: inputProps.required, info: info, error: error, description: description, className: className, children: _jsxs("div", { className: 'relative flex items-center', ref: containerRef, children: [displayIcon && (_jsx("div", { className: `
|
|
109
109
|
absolute left-3 text-login-200
|
|
110
110
|
${isClickableType && !inputProps.disabled ? 'cursor-pointer hover:text-login-text' : 'pointer-events-none'}
|
|
111
111
|
`, onClick: handleIconClick, children: displayIcon })), _jsx("input", { ...inputProps, ref: localRef, id: name, name: isClickableType ? undefined : name, type: isClickableType ? 'text' : type, value: isDateType ? getDateDisplayValue() : value, readOnly: isClickableType, onClick: () => isClickableType && !inputProps.disabled && setIsOpen(true), title: label, "aria-invalid": !!error, "aria-describedby": error ? `${name}-error` : undefined, className: `
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type RadioOption = {
|
|
2
|
+
label: string;
|
|
3
|
+
value: string | number;
|
|
4
|
+
};
|
|
5
|
+
export type RadioProps = Omit<React.ComponentProps<'input'>, 'name' | 'onChange' | 'value'> & {
|
|
2
6
|
name: string;
|
|
3
7
|
label?: string;
|
|
4
8
|
error?: string;
|
|
5
9
|
info?: string;
|
|
10
|
+
description?: string;
|
|
6
11
|
className?: string;
|
|
12
|
+
options: RadioOption[];
|
|
13
|
+
value?: string | number | null;
|
|
14
|
+
onChange?: (value: string | number) => void;
|
|
7
15
|
};
|
|
8
16
|
export default function Radio(props: RadioProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { SelectionWrapper } from './shared';
|
|
2
|
+
import { SelectionWrapper, FieldWrapper } from './shared';
|
|
3
3
|
export default function Radio(props) {
|
|
4
|
-
const {
|
|
4
|
+
const { options, onChange, value, label, description, error, info, name, className, ...rest } = props;
|
|
5
|
+
return (_jsx(FieldWrapper, { label: label, name: name, required: rest.required, info: info, description: description, error: error, className: className, children: _jsx("div", { className: 'flex flex-col gap-2', children: options.map((option) => (_jsx(RadioItem, { name: name, value: option.value, label: option.label, checked: value === option.value, disabled: rest.disabled, onChange: () => {
|
|
6
|
+
if (onChange)
|
|
7
|
+
onChange(option.value);
|
|
8
|
+
}, className: 'mb-0' }, option.value))) }) }));
|
|
9
|
+
}
|
|
10
|
+
function RadioItem(props) {
|
|
11
|
+
const { name, label, error, info, description, className, ...inputProps } = props;
|
|
5
12
|
const { value } = inputProps;
|
|
6
13
|
const id = `${name}-${value}`;
|
|
7
|
-
return (_jsx(SelectionWrapper, { label: label, name: id, required: inputProps.required, info: info, error: error, className: className, disabled: inputProps.disabled, children: _jsxs("div", { className: 'relative flex items-center', children: [_jsx("input", { ...inputProps, id: id, name: name, type: 'radio', className: `
|
|
14
|
+
return (_jsx(SelectionWrapper, { label: label, name: id, required: inputProps.required, info: info, description: description, error: error, className: className, disabled: inputProps.disabled, children: _jsxs("div", { className: 'relative flex items-center', children: [_jsx("input", { ...inputProps, id: id, name: name, type: 'radio', className: `
|
|
8
15
|
peer appearance-none h-5 w-5 rounded-full border border-login-500 bg-login-500/50
|
|
9
16
|
checked:bg-login checked:border-login
|
|
10
17
|
focus:outline-none focus:ring-2 focus:ring-login/50
|
|
@@ -4,6 +4,7 @@ export type RangeProps = Omit<React.ComponentProps<'input'>, 'name'> & {
|
|
|
4
4
|
error?: string;
|
|
5
5
|
className?: string;
|
|
6
6
|
info?: string;
|
|
7
|
+
description?: string;
|
|
7
8
|
showValue?: boolean;
|
|
8
9
|
};
|
|
9
10
|
export default function Range(props: RangeProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { FieldWrapper } from './shared';
|
|
3
3
|
export default function Range(props) {
|
|
4
|
-
const { name, label, error, className, info, showValue = true, ...inputProps } = props;
|
|
4
|
+
const { name, label, error, className, info, description, showValue = true, ...inputProps } = props;
|
|
5
5
|
const { min = 0, max = 100, step = 1, value = 0 } = inputProps;
|
|
6
|
-
return (_jsx(FieldWrapper, { label: label, name: name, required: inputProps.required, info: info, error: error, className: className, children: _jsxs("div", { className: 'flex items-center gap-4', children: [_jsx("input", { ...inputProps, id: name, name: name, type: 'range', min: min, max: max, step: step, value: value, title: label, "aria-invalid": !!error, "aria-describedby": error ? `${name}-error` : undefined, className: `
|
|
6
|
+
return (_jsx(FieldWrapper, { label: label, name: name, required: inputProps.required, info: info, description: description, error: error, className: className, children: _jsxs("div", { className: 'flex items-center gap-4', children: [_jsx("input", { ...inputProps, id: name, name: name, type: 'range', min: min, max: max, step: step, value: value, title: label, "aria-invalid": !!error, "aria-describedby": error ? `${name}-error` : undefined, className: `
|
|
7
7
|
flex-1 h-2 bg-login-500 rounded-lg appearance-none cursor-pointer
|
|
8
8
|
accent-login
|
|
9
9
|
[&::-webkit-slider-thumb]:appearance-none
|
|
@@ -15,7 +15,8 @@ export type SelectProps = {
|
|
|
15
15
|
required?: boolean;
|
|
16
16
|
placeholder?: string;
|
|
17
17
|
info?: string;
|
|
18
|
+
description?: string;
|
|
18
19
|
clearable?: boolean;
|
|
19
20
|
searchable?: boolean;
|
|
20
21
|
};
|
|
21
|
-
export default function Select({ label, name, value, onChange, options, error, className, disabled, required, placeholder, info, clearable, searchable, }: SelectProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export default function Select({ label, name, value, onChange, options, error, className, disabled, required, placeholder, info, description, clearable, searchable, }: SelectProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -5,7 +5,7 @@ import Image from 'next/image';
|
|
|
5
5
|
import { useClickOutside } from '../../hooks';
|
|
6
6
|
import { ChevronDown, X, Search } from 'lucide-react';
|
|
7
7
|
import { FieldWrapper } from './shared';
|
|
8
|
-
export default function Select({ label, name, value, onChange, options, error, className, disabled, required, placeholder = 'Select an option', info, clearable = true, searchable = true, }) {
|
|
8
|
+
export default function Select({ label, name, value, onChange, options, error, className, disabled, required, placeholder = 'Select an option', info, description, clearable = true, searchable = true, }) {
|
|
9
9
|
const [isOpen, setIsOpen] = useState(false);
|
|
10
10
|
const [searchTerm, setSearchTerm] = useState('');
|
|
11
11
|
const [selectedOption, setSelectedOption] = useState(options.find(opt => opt.value === value));
|
|
@@ -37,7 +37,7 @@ export default function Select({ label, name, value, onChange, options, error, c
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
const filteredOptions = options.filter(option => option.label.toLowerCase().includes(searchTerm.toLowerCase()));
|
|
40
|
-
return (_jsxs(FieldWrapper, { label: label, name: name, required: required, info: info, error: error, className: className, children: [_jsxs("div", { className: 'relative', ref: containerRef, children: [_jsxs("button", { type: 'button', onClick: () => !disabled && setIsOpen(!isOpen), disabled: disabled, "aria-haspopup": 'listbox', "aria-expanded": isOpen, "aria-labelledby": label ? undefined : name, className: `
|
|
40
|
+
return (_jsxs(FieldWrapper, { label: label, name: name, required: required, info: info, description: description, error: error, className: className, children: [_jsxs("div", { className: 'relative', ref: containerRef, children: [_jsxs("button", { type: 'button', onClick: () => !disabled && setIsOpen(!isOpen), disabled: disabled, "aria-haspopup": 'listbox', "aria-expanded": isOpen, "aria-labelledby": label ? undefined : name, className: `
|
|
41
41
|
w-full rounded-md bg-login-500/50 border border-login-500
|
|
42
42
|
text-login-text text-left
|
|
43
43
|
focus:outline-none focus:border-login focus:ring-1 focus:ring-login
|
|
@@ -5,8 +5,9 @@ interface FieldWrapperProps {
|
|
|
5
5
|
required?: boolean;
|
|
6
6
|
info?: string;
|
|
7
7
|
error?: string;
|
|
8
|
+
description?: string;
|
|
8
9
|
children: ReactNode;
|
|
9
10
|
className?: string;
|
|
10
11
|
}
|
|
11
|
-
export default function FieldWrapper({ label, name, required, info, error, children, className, }: FieldWrapperProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export default function FieldWrapper({ label, name, required, info, error, description, children, className, }: FieldWrapperProps): import("react/jsx-runtime").JSX.Element;
|
|
12
13
|
export {};
|
|
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import InputLabel from './inputLabel';
|
|
3
3
|
import InputInfo from './inputInfo';
|
|
4
4
|
import InputError from './inputError';
|
|
5
|
-
export default function FieldWrapper({ label, name, required, info, error, children, className, }) {
|
|
6
|
-
return (_jsxs("div", { className: `flex flex-col gap-1 w-full relative ${className || ''}`, children: [(label || info) && (_jsxs("div", { className: 'flex items-center justify-between mb-1', children: [label && (_jsx(InputLabel, { label: label, name: name, required: required, className: 'ml-1' })), info && _jsx(InputInfo, { info: info })] })), children, _jsx(InputError, { error: error, id: `${name}-error` })] }));
|
|
5
|
+
export default function FieldWrapper({ label, name, required, info, error, description, children, className, }) {
|
|
6
|
+
return (_jsxs("div", { className: `flex flex-col gap-1 w-full relative ${className || ''}`, children: [(label || info) && (_jsxs("div", { className: 'flex items-center justify-between mb-1', children: [label && (_jsx(InputLabel, { label: label, name: name, required: required, className: 'ml-1' })), info && _jsx(InputInfo, { info: info })] })), description && (_jsx("p", { className: 'text-sm text-login-100 ml-1 mb-1', children: description })), children, _jsx(InputError, { error: error, id: `${name}-error` })] }));
|
|
7
7
|
}
|
|
@@ -5,10 +5,11 @@ interface SelectionWrapperProps {
|
|
|
5
5
|
required?: boolean;
|
|
6
6
|
info?: string;
|
|
7
7
|
error?: string;
|
|
8
|
+
description?: string;
|
|
8
9
|
children: ReactNode;
|
|
9
10
|
className?: string;
|
|
10
11
|
disabled?: boolean;
|
|
11
12
|
hideError?: boolean;
|
|
12
13
|
}
|
|
13
|
-
export default function SelectionWrapper({ label, name, required, info, error, children, className, disabled, hideError, }: SelectionWrapperProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export default function SelectionWrapper({ label, name, required, info, error, description, children, className, disabled, hideError, }: SelectionWrapperProps): import("react/jsx-runtime").JSX.Element;
|
|
14
15
|
export {};
|
|
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import InputLabel from './inputLabel';
|
|
3
3
|
import InputInfo from './inputInfo';
|
|
4
4
|
import InputError from './inputError';
|
|
5
|
-
export default function SelectionWrapper({ label, name, required, info, error, children, className, disabled, hideError, }) {
|
|
6
|
-
return (_jsxs("div", { className: `flex flex-col gap-1 ${className || ''}`, children: [_jsxs("div", { className: 'flex items-
|
|
5
|
+
export default function SelectionWrapper({ label, name, required, info, error, description, children, className, disabled, hideError, }) {
|
|
6
|
+
return (_jsxs("div", { className: `flex flex-col gap-1 ${className || ''}`, children: [_jsxs("div", { className: 'flex items-start justify-between mb-1', children: [_jsxs("div", { className: 'flex items-center gap-2', children: [children, label && (_jsx(InputLabel, { label: label, name: name, required: required, disabled: disabled, className: 'select-none cursor-pointer' }))] }), info && _jsx(InputInfo, { info: info })] }), description && (_jsx("p", { className: 'text-xs text-login-200 ml-7 -mt-1 mb-1', children: description })), !hideError && _jsx(InputError, { error: error })] }));
|
|
7
7
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { SelectionWrapper } from './shared';
|
|
3
3
|
export default function Switch(props) {
|
|
4
|
-
const { name, label, error, info, className, switchOnly, ...inputProps } = props;
|
|
5
|
-
return (_jsx(SelectionWrapper, { label: label, name: name, required: inputProps.required, info: info, error: error, hideError: switchOnly, className: className, disabled: inputProps.disabled, children: _jsxs("label", { className: `relative inline-flex items-center cursor-pointer ${switchOnly ? 'h-fit' : 'h-10.5'}`, children: [_jsx("input", { ...inputProps, type: 'checkbox', id: name, name: name, className: 'sr-only peer' }), _jsx("div", { className: `
|
|
4
|
+
const { name, label, error, info, description, className, switchOnly, ...inputProps } = props;
|
|
5
|
+
return (_jsx(SelectionWrapper, { label: label, name: name, required: inputProps.required, info: info, description: description, error: error, hideError: switchOnly, className: className, disabled: inputProps.disabled, children: _jsxs("label", { className: `relative inline-flex items-center cursor-pointer ${switchOnly ? 'h-fit' : 'h-10.5'}`, children: [_jsx("input", { ...inputProps, type: 'checkbox', id: name, name: name, className: 'sr-only peer' }), _jsx("div", { className: `
|
|
6
6
|
w-11 h-6 bg-login-500/50 rounded-full peer
|
|
7
7
|
peer-checked:after:translate-x-full peer-checked:after:border-white
|
|
8
8
|
after:content-[''] after:absolute ${switchOnly ? 'after:top-0.5' : 'after:top-2.75'} after:left-0.5
|
|
@@ -9,5 +9,6 @@ export type TagInputProps = {
|
|
|
9
9
|
disabled?: boolean;
|
|
10
10
|
required?: boolean;
|
|
11
11
|
info?: string;
|
|
12
|
+
description?: string;
|
|
12
13
|
};
|
|
13
|
-
export default function TagInput({ label, name, value, onChange, placeholder, error, className, disabled, required, info, }: TagInputProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export default function TagInput({ label, name, value, onChange, placeholder, error, className, disabled, required, info, description, }: TagInputProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import { X } from 'lucide-react';
|
|
5
5
|
import { FieldWrapper } from './shared';
|
|
6
|
-
export default function TagInput({ label, name, value = [], onChange, placeholder = 'Add...', error, className, disabled, required, info, }) {
|
|
6
|
+
export default function TagInput({ label, name, value = [], onChange, placeholder = 'Add...', error, className, disabled, required, info, description, }) {
|
|
7
7
|
const [inputValue, setInputValue] = useState('');
|
|
8
8
|
function handleKeyDown(e) {
|
|
9
9
|
if ((e.key === 'Enter' || e.key === ',') && inputValue.trim()) {
|
|
@@ -29,7 +29,7 @@ export default function TagInput({ label, name, value = [], onChange, placeholde
|
|
|
29
29
|
if (onChange)
|
|
30
30
|
onChange(newValue);
|
|
31
31
|
}
|
|
32
|
-
return (_jsxs(FieldWrapper, { label: label, name: name, required: required, info: info, error: error, className: className, children: [_jsxs("div", { className: `
|
|
32
|
+
return (_jsxs(FieldWrapper, { label: label, name: name, required: required, info: info, description: description, error: error, className: className, children: [_jsxs("div", { className: `
|
|
33
33
|
flex flex-wrap gap-2 p-2 rounded-md bg-login-500/50 border border-login-500
|
|
34
34
|
text-login-text min-h-10.5
|
|
35
35
|
focus-within:border-login focus-within:ring-1 focus-within:ring-login
|
|
@@ -4,6 +4,7 @@ export type TextareaProps = Omit<React.ComponentProps<'textarea'>, 'name'> & {
|
|
|
4
4
|
error?: string;
|
|
5
5
|
className?: string;
|
|
6
6
|
info?: string;
|
|
7
|
+
description?: string;
|
|
7
8
|
type?: 'markdown' | 'json' | 'text';
|
|
8
9
|
};
|
|
9
10
|
export default function Textarea(props: TextareaProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -13,12 +13,12 @@ function isValidJson(str) {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
export default function Textarea(props) {
|
|
16
|
-
const { name, label, error, className, info, type = 'text', rows = 4, ...textareaProps } = props;
|
|
16
|
+
const { name, label, error, className, info, description, type = 'text', rows = 4, ...textareaProps } = props;
|
|
17
17
|
const { value } = textareaProps;
|
|
18
18
|
const [preview, setPreview] = useState(false);
|
|
19
19
|
const jsonError = type === 'json' && value ? isValidJson(value) : undefined;
|
|
20
20
|
const displayError = jsonError || error;
|
|
21
|
-
return (_jsx(FieldWrapper, { label: label, name: name, required: textareaProps.required, info: info, error: displayError, className: className, children: _jsxs("div", { className: 'relative', children: [type === 'markdown' && (_jsx("div", { className: 'absolute right-2 top-2 z-10 flex gap-2', children: _jsx("button", { type: 'button', onClick: () => setPreview(!preview), className: 'p-1 rounded hover:bg-login-500/50 text-login-text transition-colors', title: preview ? 'Edit' : 'Preview', children: preview ? _jsx(Pencil, { size: 16 }) : _jsx(Eye, { size: 16 }) }) })), type === 'markdown' && preview ? (_jsx("div", { className: `
|
|
21
|
+
return (_jsx(FieldWrapper, { label: label, name: name, required: textareaProps.required, info: info, description: description, error: displayError, className: className, children: _jsxs("div", { className: 'relative', children: [type === 'markdown' && (_jsx("div", { className: 'absolute right-2 top-2 z-10 flex gap-2', children: _jsx("button", { type: 'button', onClick: () => setPreview(!preview), className: 'p-1 rounded hover:bg-login-500/50 text-login-text transition-colors', title: preview ? 'Edit' : 'Preview', children: preview ? _jsx(Pencil, { size: 16 }) : _jsx(Eye, { size: 16 }) }) })), type === 'markdown' && preview ? (_jsx("div", { className: `
|
|
22
22
|
w-full rounded-md bg-login-500/50 border border-login-500
|
|
23
23
|
text-login-text
|
|
24
24
|
p-3
|
package/dist/src/globals.css
CHANGED
|
@@ -1028,6 +1028,9 @@
|
|
|
1028
1028
|
.-mt-0\.5 {
|
|
1029
1029
|
margin-top: calc(var(--spacing) * -0.5);
|
|
1030
1030
|
}
|
|
1031
|
+
.-mt-1 {
|
|
1032
|
+
margin-top: calc(var(--spacing) * -1);
|
|
1033
|
+
}
|
|
1031
1034
|
.mt-1 {
|
|
1032
1035
|
margin-top: calc(var(--spacing) * 1);
|
|
1033
1036
|
}
|
|
@@ -1040,6 +1043,9 @@
|
|
|
1040
1043
|
.mr-\[0\.3rem\] {
|
|
1041
1044
|
margin-right: 0.3rem;
|
|
1042
1045
|
}
|
|
1046
|
+
.mb-0 {
|
|
1047
|
+
margin-bottom: calc(var(--spacing) * 0);
|
|
1048
|
+
}
|
|
1043
1049
|
.mb-1 {
|
|
1044
1050
|
margin-bottom: calc(var(--spacing) * 1);
|
|
1045
1051
|
}
|
|
@@ -1058,6 +1064,9 @@
|
|
|
1058
1064
|
.ml-1 {
|
|
1059
1065
|
margin-left: calc(var(--spacing) * 1);
|
|
1060
1066
|
}
|
|
1067
|
+
.ml-7 {
|
|
1068
|
+
margin-left: calc(var(--spacing) * 7);
|
|
1069
|
+
}
|
|
1061
1070
|
.page-container {
|
|
1062
1071
|
display: grid;
|
|
1063
1072
|
grid-template-columns: 1fr 1rem minmax(0, 72rem) 1rem 1fr;
|
package/package.json
CHANGED
|
@@ -1,23 +1,85 @@
|
|
|
1
1
|
import { Check } from 'lucide-react'
|
|
2
|
-
import { SelectionWrapper } from './shared'
|
|
2
|
+
import { SelectionWrapper, FieldWrapper } from './shared'
|
|
3
3
|
|
|
4
|
-
export type
|
|
4
|
+
export type CheckboxOption = {
|
|
5
|
+
label: string
|
|
6
|
+
value: string | number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type CheckboxItemProps = Omit<React.ComponentProps<'input'>, 'name'> & {
|
|
5
10
|
name: string
|
|
6
11
|
label?: string
|
|
7
12
|
error?: string
|
|
8
13
|
info?: string
|
|
14
|
+
description?: string
|
|
9
15
|
className?: string
|
|
10
16
|
}
|
|
11
17
|
|
|
18
|
+
export type CheckboxProps = Omit<React.ComponentProps<'input'>, 'name' | 'onChange' | 'value'> & {
|
|
19
|
+
name: string
|
|
20
|
+
label?: string
|
|
21
|
+
error?: string
|
|
22
|
+
info?: string
|
|
23
|
+
description?: string
|
|
24
|
+
className?: string
|
|
25
|
+
options: CheckboxOption[]
|
|
26
|
+
value?: (string | number)[]
|
|
27
|
+
onChange?: (value: (string | number)[]) => void
|
|
28
|
+
}
|
|
29
|
+
|
|
12
30
|
export default function Checkbox(props: CheckboxProps) {
|
|
13
|
-
const {
|
|
31
|
+
const { options, onChange, value, label, description, error, info, name, className, ...rest } = props
|
|
32
|
+
const selectedValues = Array.isArray(value) ? value : []
|
|
14
33
|
|
|
15
34
|
return (
|
|
16
|
-
<
|
|
35
|
+
<FieldWrapper
|
|
17
36
|
label={label}
|
|
18
37
|
name={name}
|
|
38
|
+
required={rest.required}
|
|
39
|
+
info={info}
|
|
40
|
+
description={description}
|
|
41
|
+
error={error}
|
|
42
|
+
className={className}
|
|
43
|
+
>
|
|
44
|
+
<div className='flex flex-col gap-2'>
|
|
45
|
+
{options.map((option) => (
|
|
46
|
+
<CheckboxItem
|
|
47
|
+
key={option.value}
|
|
48
|
+
name={name}
|
|
49
|
+
value={option.value}
|
|
50
|
+
label={option.label}
|
|
51
|
+
checked={selectedValues.includes(option.value)}
|
|
52
|
+
disabled={rest.disabled}
|
|
53
|
+
onChange={(e) => {
|
|
54
|
+
if (!onChange) return
|
|
55
|
+
const isChecked = e.target.checked
|
|
56
|
+
let newValues = [...selectedValues]
|
|
57
|
+
if (isChecked) {
|
|
58
|
+
newValues.push(option.value)
|
|
59
|
+
} else {
|
|
60
|
+
newValues = newValues.filter((v) => v !== option.value)
|
|
61
|
+
}
|
|
62
|
+
onChange(newValues)
|
|
63
|
+
}}
|
|
64
|
+
className='mb-0'
|
|
65
|
+
/>
|
|
66
|
+
))}
|
|
67
|
+
</div>
|
|
68
|
+
</FieldWrapper>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function CheckboxItem(props: CheckboxItemProps) {
|
|
73
|
+
const { name, label, error, info, description, className, ...inputProps } = props
|
|
74
|
+
const id = inputProps.value ? `${name}-${inputProps.value}` : name
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<SelectionWrapper
|
|
78
|
+
label={label}
|
|
79
|
+
name={id}
|
|
19
80
|
required={inputProps.required}
|
|
20
81
|
info={info}
|
|
82
|
+
description={description}
|
|
21
83
|
error={error}
|
|
22
84
|
className={className}
|
|
23
85
|
disabled={inputProps.disabled}
|
|
@@ -25,7 +87,7 @@ export default function Checkbox(props: CheckboxProps) {
|
|
|
25
87
|
<div className='relative flex items-center'>
|
|
26
88
|
<input
|
|
27
89
|
{...inputProps}
|
|
28
|
-
id={
|
|
90
|
+
id={id}
|
|
29
91
|
name={name}
|
|
30
92
|
type='checkbox'
|
|
31
93
|
className={`
|
|
@@ -12,10 +12,11 @@ export type InputProps = Omit<React.ComponentProps<'input'>, 'name'> & {
|
|
|
12
12
|
className?: string
|
|
13
13
|
icon?: JSX.Element
|
|
14
14
|
info?: string
|
|
15
|
+
description?: string
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export default function Input(props: InputProps) {
|
|
18
|
-
const { name, label, error, className, icon, info, ...inputProps } = props
|
|
19
|
+
const { name, label, error, className, icon, info, description, ...inputProps } = props
|
|
19
20
|
const { type = 'text', value } = inputProps
|
|
20
21
|
const localRef = useRef<HTMLInputElement>(null)
|
|
21
22
|
const [isOpen, setIsOpen] = useState(false)
|
|
@@ -130,6 +131,7 @@ export default function Input(props: InputProps) {
|
|
|
130
131
|
required={inputProps.required}
|
|
131
132
|
info={info}
|
|
132
133
|
error={error}
|
|
134
|
+
description={description}
|
|
133
135
|
className={className}
|
|
134
136
|
>
|
|
135
137
|
<div className='relative flex items-center' ref={containerRef}>
|
|
@@ -1,15 +1,66 @@
|
|
|
1
|
-
import { SelectionWrapper } from './shared'
|
|
1
|
+
import { SelectionWrapper, FieldWrapper } from './shared'
|
|
2
2
|
|
|
3
|
-
export type
|
|
3
|
+
export type RadioOption = {
|
|
4
|
+
label: string
|
|
5
|
+
value: string | number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type RadioItemProps = Omit<React.ComponentProps<'input'>, 'name'> & {
|
|
9
|
+
name: string
|
|
10
|
+
label?: string
|
|
11
|
+
error?: string
|
|
12
|
+
info?: string
|
|
13
|
+
description?: string
|
|
14
|
+
className?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type RadioProps = Omit<React.ComponentProps<'input'>, 'name' | 'onChange' | 'value'> & {
|
|
4
18
|
name: string
|
|
5
19
|
label?: string
|
|
6
20
|
error?: string
|
|
7
21
|
info?: string
|
|
22
|
+
description?: string
|
|
8
23
|
className?: string
|
|
24
|
+
options: RadioOption[]
|
|
25
|
+
value?: string | number | null
|
|
26
|
+
onChange?: (value: string | number) => void
|
|
9
27
|
}
|
|
10
28
|
|
|
11
29
|
export default function Radio(props: RadioProps) {
|
|
12
|
-
const {
|
|
30
|
+
const { options, onChange, value, label, description, error, info, name, className, ...rest } = props
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<FieldWrapper
|
|
34
|
+
label={label}
|
|
35
|
+
name={name}
|
|
36
|
+
required={rest.required}
|
|
37
|
+
info={info}
|
|
38
|
+
description={description}
|
|
39
|
+
error={error}
|
|
40
|
+
className={className}
|
|
41
|
+
>
|
|
42
|
+
<div className='flex flex-col gap-2'>
|
|
43
|
+
{options.map((option) => (
|
|
44
|
+
<RadioItem
|
|
45
|
+
key={option.value}
|
|
46
|
+
name={name}
|
|
47
|
+
value={option.value}
|
|
48
|
+
label={option.label}
|
|
49
|
+
checked={value === option.value}
|
|
50
|
+
disabled={rest.disabled}
|
|
51
|
+
onChange={() => {
|
|
52
|
+
if (onChange) onChange(option.value)
|
|
53
|
+
}}
|
|
54
|
+
className='mb-0'
|
|
55
|
+
/>
|
|
56
|
+
))}
|
|
57
|
+
</div>
|
|
58
|
+
</FieldWrapper>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function RadioItem(props: RadioItemProps) {
|
|
63
|
+
const { name, label, error, info, description, className, ...inputProps } = props
|
|
13
64
|
const { value } = inputProps
|
|
14
65
|
const id = `${name}-${value}`
|
|
15
66
|
|
|
@@ -19,6 +70,7 @@ export default function Radio(props: RadioProps) {
|
|
|
19
70
|
name={id}
|
|
20
71
|
required={inputProps.required}
|
|
21
72
|
info={info}
|
|
73
|
+
description={description}
|
|
22
74
|
error={error}
|
|
23
75
|
className={className}
|
|
24
76
|
disabled={inputProps.disabled}
|
|
@@ -6,11 +6,12 @@ export type RangeProps = Omit<React.ComponentProps<'input'>, 'name'> & {
|
|
|
6
6
|
error?: string
|
|
7
7
|
className?: string
|
|
8
8
|
info?: string
|
|
9
|
+
description?: string
|
|
9
10
|
showValue?: boolean
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export default function Range(props: RangeProps) {
|
|
13
|
-
const { name, label, error, className, info, showValue = true, ...inputProps } = props
|
|
14
|
+
const { name, label, error, className, info, description, showValue = true, ...inputProps } = props
|
|
14
15
|
const { min = 0, max = 100, step = 1, value = 0 } = inputProps
|
|
15
16
|
|
|
16
17
|
return (
|
|
@@ -19,6 +20,7 @@ export default function Range(props: RangeProps) {
|
|
|
19
20
|
name={name}
|
|
20
21
|
required={inputProps.required}
|
|
21
22
|
info={info}
|
|
23
|
+
description={description}
|
|
22
24
|
error={error}
|
|
23
25
|
className={className}
|
|
24
26
|
>
|
|
@@ -24,6 +24,7 @@ export type SelectProps = {
|
|
|
24
24
|
required?: boolean
|
|
25
25
|
placeholder?: string
|
|
26
26
|
info?: string
|
|
27
|
+
description?: string
|
|
27
28
|
clearable?: boolean
|
|
28
29
|
searchable?: boolean
|
|
29
30
|
}
|
|
@@ -40,6 +41,7 @@ export default function Select({
|
|
|
40
41
|
required,
|
|
41
42
|
placeholder = 'Select an option',
|
|
42
43
|
info,
|
|
44
|
+
description,
|
|
43
45
|
clearable = true,
|
|
44
46
|
searchable = true,
|
|
45
47
|
}: SelectProps) {
|
|
@@ -89,6 +91,7 @@ export default function Select({
|
|
|
89
91
|
name={name}
|
|
90
92
|
required={required}
|
|
91
93
|
info={info}
|
|
94
|
+
description={description}
|
|
92
95
|
error={error}
|
|
93
96
|
className={className}
|
|
94
97
|
>
|
|
@@ -9,6 +9,7 @@ interface FieldWrapperProps {
|
|
|
9
9
|
required?: boolean
|
|
10
10
|
info?: string
|
|
11
11
|
error?: string
|
|
12
|
+
description?: string
|
|
12
13
|
children: ReactNode
|
|
13
14
|
className?: string
|
|
14
15
|
}
|
|
@@ -19,6 +20,7 @@ export default function FieldWrapper({
|
|
|
19
20
|
required,
|
|
20
21
|
info,
|
|
21
22
|
error,
|
|
23
|
+
description,
|
|
22
24
|
children,
|
|
23
25
|
className,
|
|
24
26
|
}: FieldWrapperProps) {
|
|
@@ -37,6 +39,11 @@ export default function FieldWrapper({
|
|
|
37
39
|
{info && <InputInfo info={info} />}
|
|
38
40
|
</div>
|
|
39
41
|
)}
|
|
42
|
+
{description && (
|
|
43
|
+
<p className='text-sm text-login-100 ml-1 mb-1'>
|
|
44
|
+
{description}
|
|
45
|
+
</p>
|
|
46
|
+
)}
|
|
40
47
|
{children}
|
|
41
48
|
<InputError error={error} id={`${name}-error`} />
|
|
42
49
|
</div>
|
|
@@ -9,6 +9,7 @@ interface SelectionWrapperProps {
|
|
|
9
9
|
required?: boolean
|
|
10
10
|
info?: string
|
|
11
11
|
error?: string
|
|
12
|
+
description?: string
|
|
12
13
|
children: ReactNode
|
|
13
14
|
className?: string
|
|
14
15
|
disabled?: boolean
|
|
@@ -21,6 +22,7 @@ export default function SelectionWrapper({
|
|
|
21
22
|
required,
|
|
22
23
|
info,
|
|
23
24
|
error,
|
|
25
|
+
description,
|
|
24
26
|
children,
|
|
25
27
|
className,
|
|
26
28
|
disabled,
|
|
@@ -28,7 +30,7 @@ export default function SelectionWrapper({
|
|
|
28
30
|
}: SelectionWrapperProps) {
|
|
29
31
|
return (
|
|
30
32
|
<div className={`flex flex-col gap-1 ${className || ''}`}>
|
|
31
|
-
<div className='flex items-
|
|
33
|
+
<div className='flex items-start justify-between mb-1'>
|
|
32
34
|
<div className='flex items-center gap-2'>
|
|
33
35
|
{children}
|
|
34
36
|
{label && (
|
|
@@ -43,6 +45,11 @@ export default function SelectionWrapper({
|
|
|
43
45
|
</div>
|
|
44
46
|
{info && <InputInfo info={info} />}
|
|
45
47
|
</div>
|
|
48
|
+
{description && (
|
|
49
|
+
<p className='text-xs text-login-200 ml-7 -mt-1 mb-1'>
|
|
50
|
+
{description}
|
|
51
|
+
</p>
|
|
52
|
+
)}
|
|
46
53
|
{!hideError && <InputError error={error} />}
|
|
47
54
|
</div>
|
|
48
55
|
)
|
|
@@ -5,12 +5,13 @@ export type SwitchProps = Omit<React.ComponentProps<'input'>, 'name'> & {
|
|
|
5
5
|
label?: string
|
|
6
6
|
error?: string
|
|
7
7
|
info?: string
|
|
8
|
+
description?: string
|
|
8
9
|
className?: string
|
|
9
10
|
switchOnly?: boolean
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export default function Switch(props: SwitchProps) {
|
|
13
|
-
const { name, label, error, info, className, switchOnly, ...inputProps } = props
|
|
14
|
+
const { name, label, error, info, description, className, switchOnly, ...inputProps } = props
|
|
14
15
|
|
|
15
16
|
return (
|
|
16
17
|
<SelectionWrapper
|
|
@@ -18,6 +19,7 @@ export default function Switch(props: SwitchProps) {
|
|
|
18
19
|
name={name}
|
|
19
20
|
required={inputProps.required}
|
|
20
21
|
info={info}
|
|
22
|
+
description={description}
|
|
21
23
|
error={error}
|
|
22
24
|
hideError={switchOnly}
|
|
23
25
|
className={className}
|
|
@@ -15,6 +15,7 @@ export type TagInputProps = {
|
|
|
15
15
|
disabled?: boolean
|
|
16
16
|
required?: boolean
|
|
17
17
|
info?: string
|
|
18
|
+
description?: string
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export default function TagInput({
|
|
@@ -28,6 +29,7 @@ export default function TagInput({
|
|
|
28
29
|
disabled,
|
|
29
30
|
required,
|
|
30
31
|
info,
|
|
32
|
+
description,
|
|
31
33
|
}: TagInputProps) {
|
|
32
34
|
const [inputValue, setInputValue] = useState('')
|
|
33
35
|
|
|
@@ -58,6 +60,7 @@ export default function TagInput({
|
|
|
58
60
|
name={name}
|
|
59
61
|
required={required}
|
|
60
62
|
info={info}
|
|
63
|
+
description={description}
|
|
61
64
|
error={error}
|
|
62
65
|
className={className}
|
|
63
66
|
>
|
|
@@ -9,6 +9,7 @@ export type TextareaProps = Omit<React.ComponentProps<'textarea'>, 'name'> & {
|
|
|
9
9
|
error?: string
|
|
10
10
|
className?: string
|
|
11
11
|
info?: string
|
|
12
|
+
description?: string
|
|
12
13
|
type?: 'markdown' | 'json' | 'text'
|
|
13
14
|
}
|
|
14
15
|
|
|
@@ -22,7 +23,7 @@ function isValidJson(str: string): string | null {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export default function Textarea(props: TextareaProps) {
|
|
25
|
-
const { name, label, error, className, info, type = 'text', rows = 4, ...textareaProps } = props
|
|
26
|
+
const { name, label, error, className, info, description, type = 'text', rows = 4, ...textareaProps } = props
|
|
26
27
|
const { value } = textareaProps
|
|
27
28
|
const [preview, setPreview] = useState(false)
|
|
28
29
|
|
|
@@ -35,6 +36,7 @@ export default function Textarea(props: TextareaProps) {
|
|
|
35
36
|
name={name}
|
|
36
37
|
required={textareaProps.required}
|
|
37
38
|
info={info}
|
|
39
|
+
description={description}
|
|
38
40
|
error={displayError}
|
|
39
41
|
className={className}
|
|
40
42
|
>
|