@paroicms/react-ui 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Button.js CHANGED
@@ -2,13 +2,19 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import "../styles/Button.css";
3
3
  import { clsx } from "clsx";
4
4
  import { Check, Loader2 } from "lucide-react";
5
- import { useCallback, useState, } from "react";
5
+ import { useCallback, useEffect, useState, } from "react";
6
6
  import { useReactUIConfig } from "./react-ui-provider.js";
7
7
  export function Button(props) {
8
8
  const { children, className, disabled, outlined, icon, severity = "primary", ref, ...rest } = props;
9
9
  const { autoDismissInsideFeedbackDurationMs } = useReactUIConfig();
10
10
  const [loading, setLoading] = useState(false);
11
11
  const [showFeedback, setShowFeedback] = useState(false);
12
+ // Cancel feedback when button becomes enabled
13
+ useEffect(() => {
14
+ if (!disabled && showFeedback) {
15
+ setShowFeedback(false);
16
+ }
17
+ }, [disabled, showFeedback]);
12
18
  const classNames = clsx("PaBtn", severity, outlined && "outlined", disabled && "disabled", showFeedback && "feedback", className);
13
19
  const handleAsyncClick = useCallback(async (e) => {
14
20
  if (props.as !== "async")
@@ -1,9 +1,10 @@
1
1
  import "../styles/Checkbox.css";
2
- import type { InputHTMLAttributes } from "react";
2
+ import type { ChangeEvent, InputHTMLAttributes } from "react";
3
3
  export interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "type"> {
4
4
  checked: boolean;
5
- onChange: (checked: boolean) => void;
5
+ onChange?: (checked: boolean, ev: ChangeEvent<HTMLInputElement>) => void;
6
6
  label?: string;
7
+ inputLabel?: string;
7
8
  className?: string;
8
9
  }
9
- export declare function Checkbox({ checked, onChange, label, className, ...rest }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function Checkbox({ checked, onChange, label, inputLabel, className, ...rest }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
package/dist/Checkbox.js CHANGED
@@ -1,12 +1,10 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import "../styles/Checkbox.css";
3
3
  import { clsx } from "clsx";
4
- export function Checkbox({ checked, onChange, label, className, ...rest }) {
4
+ export function Checkbox({ checked, onChange, label, inputLabel, className, ...rest }) {
5
5
  const handleChange = (e) => {
6
- onChange(e.target.checked);
6
+ onChange?.(e.target.checked, e);
7
7
  };
8
- if (label) {
9
- return (_jsxs("label", { className: clsx("PaCheckbox", className), children: [_jsx("input", { className: "PaCheckbox-input", type: "checkbox", checked: checked, onChange: handleChange, ...rest }), _jsx("span", { className: "PaCheckbox-label", children: label })] }));
10
- }
11
- return (_jsx("input", { className: clsx("PaCheckbox-input", className), type: "checkbox", checked: checked, onChange: handleChange, ...rest }));
8
+ const fieldContent = inputLabel ? (_jsxs("label", { className: clsx("PaCheckboxField", className), children: [_jsx("input", { className: "PaCheckboxInput", type: "checkbox", checked: checked, onChange: handleChange, ...rest }), _jsx("span", { className: "PaCheckboxField-label", children: inputLabel })] })) : (_jsx("input", { className: clsx("PaCheckboxInput", className), type: "checkbox", checked: checked, onChange: handleChange, ...rest }));
9
+ return (_jsx(_Fragment, { children: label ? (_jsxs("label", { className: clsx("PaField", className), children: [_jsx("span", { className: "PaField-label", children: label }), fieldContent] })) : (fieldContent) }));
12
10
  }
@@ -1,9 +1,11 @@
1
1
  import "../styles/DateInput.css";
2
- import type { InputHTMLAttributes, Ref } from "react";
3
- export interface DateInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
2
+ import type { ChangeEvent, InputHTMLAttributes, Ref } from "react";
3
+ export interface DateInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {
4
4
  type: "date" | "datetime-local" | "time";
5
+ value?: string;
6
+ onChange?: (value: string, ev: ChangeEvent<HTMLInputElement>) => void;
5
7
  label?: string;
6
8
  error?: string;
7
9
  ref?: Ref<HTMLInputElement>;
8
10
  }
9
- export declare function DateInput({ className, label, error, type, ref, ...props }: DateInputProps): import("react/jsx-runtime").JSX.Element;
11
+ export declare function DateInput({ className, label, error, type, value, onChange, ref, ...props }: DateInputProps): import("react/jsx-runtime").JSX.Element;
package/dist/DateInput.js CHANGED
@@ -1,7 +1,10 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import "../styles/DateInput.css";
3
3
  import { clsx } from "clsx";
4
- export function DateInput({ className, label, error, type, ref, ...props }) {
5
- const inputElement = (_jsx("input", { ref: ref, type: type, className: clsx("PaDateInput-field", error && "error"), ...props }));
6
- return (_jsxs("span", { className: clsx("PaDateInput", className), children: [label ? (_jsxs("label", { className: "PaDateInput-wrapper", children: [_jsx("span", { className: "PaDateInput-label", children: label }), inputElement] })) : (inputElement), error && _jsx("span", { className: "PaDateInput-error", children: error })] }));
4
+ export function DateInput({ className, label, error, type, value, onChange, ref, ...props }) {
5
+ const handleChange = (e) => {
6
+ onChange?.(e.target.value, e);
7
+ };
8
+ const inputElement = (_jsx("input", { ref: ref, type: type, className: clsx("PaDateTimeInput", error && "error", !label && className), value: value, onChange: handleChange, ...props }));
9
+ return (_jsxs(_Fragment, { children: [label ? (_jsxs("label", { className: clsx("PaField", error && "error", className), children: [_jsx("span", { className: "PaField-label", children: label }), inputElement] })) : (inputElement), error && _jsx("span", { className: "PaFieldError", children: error })] }));
7
10
  }
package/dist/Dialog.d.ts CHANGED
@@ -8,6 +8,8 @@ export interface DialogProps {
8
8
  children: ReactNode;
9
9
  className?: string;
10
10
  closable?: boolean;
11
- size?: "sm" | "md" | "lg";
11
+ /** Default size is "md" */
12
+ size?: DialogSize;
12
13
  }
14
+ export type DialogSize = "sm" | "md" | "lg" | "innerContent";
13
15
  export declare function Dialog({ visible, onHide, header, footer, children, className, closable, size, }: DialogProps): import("react/jsx-runtime").JSX.Element;
package/dist/Dialog.js CHANGED
@@ -3,7 +3,7 @@ import "../styles/Dialog.css";
3
3
  import { clsx } from "clsx";
4
4
  import { X } from "lucide-react";
5
5
  import { useEffect, useRef } from "react";
6
- export function Dialog({ visible, onHide, header, footer, children, className, closable = true, size, }) {
6
+ export function Dialog({ visible, onHide, header, footer, children, className, closable = true, size = "md", }) {
7
7
  const dialogRef = useRef(null);
8
8
  // Control open/close with native methods
9
9
  useEffect(() => {
@@ -47,5 +47,12 @@ export function Dialog({ visible, onHide, header, footer, children, className, c
47
47
  document.body.style.overflow = "";
48
48
  };
49
49
  }, [visible]);
50
- return (_jsxs("dialog", { ref: dialogRef, className: clsx("PaDialog", size && `size-${size}`, className), children: [(header || closable) && (_jsxs("div", { className: "PaDialog-header", children: [header && _jsx("div", { className: "PaDialog-title", children: header }), closable && (_jsx("button", { type: "button", className: "PaDialog-close", onClick: onHide, "aria-label": "Close", children: _jsx(X, { size: 18 }) }))] })), _jsx("div", { className: "PaDialog-content", children: children }), footer && _jsx("div", { className: "PaDialog-footer", children: footer })] }));
50
+ const sizeClass = size === "innerContent"
51
+ ? undefined
52
+ : size === "sm"
53
+ ? "sizeSm"
54
+ : size === "lg"
55
+ ? "sizeLg"
56
+ : "sizeMd";
57
+ return (_jsxs("dialog", { ref: dialogRef, className: clsx("PaDialog", sizeClass, className), children: [(header || closable) && (_jsxs("div", { className: "PaDialog-header", children: [header && _jsx("div", { className: "PaDialog-title", children: header }), closable && (_jsx("button", { type: "button", className: "PaDialog-close", onClick: onHide, "aria-label": "Close", children: _jsx(X, { size: 18 }) }))] })), _jsx("div", { className: "PaDialog-content", children: children }), footer && _jsx("div", { className: "PaDialog-footer", children: footer })] }));
51
58
  }
@@ -1,8 +1,8 @@
1
- import type { InputHTMLAttributes, Ref } from "react";
1
+ import type { ChangeEvent, InputHTMLAttributes, Ref } from "react";
2
2
  import "../styles/InputNumber.css";
3
3
  export interface InputNumberProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {
4
4
  value: number | undefined;
5
- onChange: (value: number | undefined) => void;
5
+ onChange?: (value: number | undefined, ev: ChangeEvent<HTMLInputElement>) => void;
6
6
  label?: string;
7
7
  error?: string;
8
8
  ref?: Ref<HTMLInputElement>;
@@ -1,19 +1,19 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { clsx } from "clsx";
3
3
  import "../styles/InputNumber.css";
4
4
  export function InputNumber({ className, label, error, value, onChange, min, max, step, ref, ...props }) {
5
5
  const handleChange = (e) => {
6
6
  const val = e.target.value;
7
7
  if (val === "") {
8
- onChange(undefined);
8
+ onChange?.(undefined, e);
9
9
  }
10
10
  else {
11
11
  const num = Number(val);
12
12
  if (!Number.isNaN(num)) {
13
- onChange(num);
13
+ onChange?.(num, e);
14
14
  }
15
15
  }
16
16
  };
17
- const inputElement = (_jsx("input", { ref: ref, type: "number", className: clsx("PaInputNumber-field", error && "error"), value: value ?? "", onChange: handleChange, min: min, max: max, step: step, ...props }));
18
- return (_jsxs("span", { className: clsx("PaInputNumber", className), children: [label ? (_jsxs("label", { className: "PaInputNumber-wrapper", children: [_jsx("span", { className: "PaInputNumber-label", children: label }), inputElement] })) : (inputElement), error && _jsx("span", { className: "PaInputNumber-error", children: error })] }));
17
+ const inputElement = (_jsx("input", { ref: ref, type: "number", className: clsx("PaNumberInput", error && "error", !label && className), value: value ?? "", onChange: handleChange, min: min, max: max, step: step, ...props }));
18
+ return (_jsxs(_Fragment, { children: [label ? (_jsxs("label", { className: clsx("PaField", error && "error", className), children: [_jsx("span", { className: "PaField-label", children: label }), inputElement] })) : (inputElement), error && _jsx("span", { className: "PaFieldError", children: error })] }));
19
19
  }
@@ -1,14 +1,13 @@
1
- import type { InputHTMLAttributes, ReactNode } from "react";
1
+ import type { ChangeEvent, InputHTMLAttributes, ReactNode } from "react";
2
2
  import "../styles/InputText.css";
3
3
  export interface InputTextProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "onChange"> {
4
4
  value: string;
5
- onChange: (value: string) => void;
5
+ onChange?: (value: string, ev: ChangeEvent<HTMLInputElement>) => void;
6
6
  label?: string;
7
7
  error?: string;
8
8
  className?: string;
9
- fullWidth?: boolean;
10
9
  endElement?: ReactNode;
11
10
  icon?: ReactNode;
12
11
  iconPosition?: "left" | "right";
13
12
  }
14
- export declare function InputText({ value, onChange, label, error, className, fullWidth, endElement, icon, iconPosition, ...rest }: InputTextProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare function InputText({ value, onChange, label, error, className, endElement, icon, iconPosition, ...rest }: InputTextProps): import("react/jsx-runtime").JSX.Element;
package/dist/InputText.js CHANGED
@@ -1,11 +1,12 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { clsx } from "clsx";
3
3
  import "../styles/InputText.css";
4
- export function InputText({ value, onChange, label, error, className, fullWidth = false, endElement, icon, iconPosition = "left", ...rest }) {
4
+ export function InputText({ value, onChange, label, error, className, endElement, icon, iconPosition = "left", ...rest }) {
5
5
  const handleChange = (e) => {
6
- onChange(e.target.value);
6
+ onChange?.(e.target.value, e);
7
7
  };
8
- const inputElement = (_jsx("input", { className: "PaInputText-field", value: value, onChange: handleChange, ...rest }));
9
- const fieldContent = endElement ? (_jsxs("span", { className: "PaInputText-row", children: [inputElement, endElement] })) : icon ? (_jsxs("span", { className: clsx("PaInputText-iconWrapper", iconPosition === "right" && "iconRight"), children: [_jsx("span", { className: "PaInputText-icon", children: icon }), inputElement] })) : (inputElement);
10
- return (_jsxs("span", { className: clsx("PaInputText", error && "error", fullWidth && "fullWidth", className), children: [label ? (_jsxs("label", { className: "PaInputText-wrapper", children: [_jsx("span", { className: "PaInputText-label", children: label }), fieldContent] })) : (fieldContent), error && _jsx("span", { className: "PaInputText-error", children: error })] }));
8
+ const inputElement = (_jsx("input", { className: "PaTextInput", value: value, onChange: handleChange, ...rest }));
9
+ const hasWrapper = Boolean(endElement || icon);
10
+ const fieldContent = endElement ? (_jsxs("span", { className: "PaTextField-row", children: [inputElement, endElement] })) : icon ? (_jsxs("span", { className: clsx("PaTextField-iconWrapper", iconPosition === "right" && "iconRight"), children: [_jsx("span", { className: "PaTextField-icon", children: icon }), inputElement] })) : (inputElement);
11
+ return (_jsxs(_Fragment, { children: [label ? (_jsxs("label", { className: clsx("PaTextField PaField", error && "error", className), children: [_jsx("span", { className: "PaField-label", children: label }), fieldContent] })) : hasWrapper ? (_jsx("span", { className: clsx("PaTextField", error && "error", className), children: fieldContent })) : (_jsx("input", { className: clsx("PaTextInput", className), value: value, onChange: handleChange, ...rest })), error && _jsx("span", { className: "PaFieldError", children: error })] }));
11
12
  }
@@ -6,7 +6,7 @@ export interface MultiSelectOption {
6
6
  }
7
7
  export interface MultiSelectProps {
8
8
  value: string[];
9
- onChange: (value: string[]) => void;
9
+ onChange?: (value: string[]) => void;
10
10
  options: MultiSelectOption[];
11
11
  label?: string;
12
12
  error?: string;
@@ -30,14 +30,14 @@ export function MultiSelect({ value, onChange, options, label, error, className,
30
30
  }, [position]);
31
31
  const toggleOption = (optionValue) => {
32
32
  if (value.includes(optionValue)) {
33
- onChange(value.filter((v) => v !== optionValue));
33
+ onChange?.(value.filter((v) => v !== optionValue));
34
34
  }
35
35
  else {
36
- onChange([...value, optionValue]);
36
+ onChange?.([...value, optionValue]);
37
37
  }
38
38
  };
39
39
  const removeValue = (optionValue) => {
40
- onChange(value.filter((v) => v !== optionValue));
40
+ onChange?.(value.filter((v) => v !== optionValue));
41
41
  };
42
42
  const selectedOptions = options.filter((opt) => value.includes(opt.value));
43
43
  const controlElement = (_jsxs(_Fragment, { children: [_jsxs("span", { className: "PaMultiSelect-control", onClick: () => !disabled && dropdownRef.current?.togglePopover(), onKeyDown: (e) => {
@@ -1,8 +1,10 @@
1
1
  import "../styles/PasswordInput.css";
2
- import { type InputHTMLAttributes, type Ref } from "react";
3
- export interface PasswordInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
2
+ import { type ChangeEvent, type InputHTMLAttributes, type Ref } from "react";
3
+ export interface PasswordInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {
4
+ value?: string;
5
+ onChange?: (value: string, ev: ChangeEvent<HTMLInputElement>) => void;
4
6
  label?: string;
5
7
  error?: string;
6
8
  ref?: Ref<HTMLInputElement>;
7
9
  }
8
- export declare function PasswordInput({ className, label, error, ref, ...props }: PasswordInputProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function PasswordInput({ className, label, error, value, onChange, ref, ...props }: PasswordInputProps): import("react/jsx-runtime").JSX.Element;
@@ -1,10 +1,13 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import "../styles/PasswordInput.css";
3
3
  import { clsx } from "clsx";
4
4
  import { Eye, EyeOff } from "lucide-react";
5
5
  import { useState } from "react";
6
- export function PasswordInput({ className, label, error, ref, ...props }) {
6
+ export function PasswordInput({ className, label, error, value, onChange, ref, ...props }) {
7
7
  const [visible, setVisible] = useState(false);
8
- const inputWithToggle = (_jsxs("span", { className: clsx("PaPasswordInput-inputWrapper", error && "error"), children: [_jsx("input", { ref: ref, type: visible ? "text" : "password", className: "PaPasswordInput-input", ...props }), _jsx("button", { type: "button", className: "PaPasswordInput-toggle", onClick: () => setVisible(!visible), tabIndex: -1, "aria-label": visible ? "Hide password" : "Show password", children: visible ? _jsx(EyeOff, { size: 16 }) : _jsx(Eye, { size: 16 }) })] }));
9
- return (_jsxs("span", { className: clsx("PaPasswordInput", className), children: [label ? (_jsxs("label", { className: "PaPasswordInput-wrapper", children: [_jsx("span", { className: "PaPasswordInput-label", children: label }), inputWithToggle] })) : (inputWithToggle), error && _jsx("span", { className: "PaPasswordInput-error", children: error })] }));
8
+ const handleChange = (e) => {
9
+ onChange?.(e.target.value, e);
10
+ };
11
+ const inputWithToggle = (_jsxs("span", { className: clsx("PaPasswordInput-inputWrapper", error && "error"), children: [_jsx("input", { ref: ref, type: visible ? "text" : "password", className: "PaPasswordInput-input", value: value, onChange: handleChange, ...props }), _jsx("button", { type: "button", className: "PaPasswordInput-toggle", onClick: () => setVisible(!visible), tabIndex: -1, "aria-label": visible ? "Hide password" : "Show password", children: visible ? _jsx(EyeOff, { size: 16 }) : _jsx(Eye, { size: 16 }) })] }));
12
+ return (_jsxs(_Fragment, { children: [label ? (_jsxs("label", { className: clsx("PaPasswordInput PaField", error && "error", className), children: [_jsx("span", { className: "PaField-label", children: label }), inputWithToggle] })) : (inputWithToggle), error && _jsx("span", { className: "PaFieldError", children: error })] }));
10
13
  }
@@ -1,9 +1,9 @@
1
- import type { InputHTMLAttributes } from "react";
1
+ import type { ChangeEvent, InputHTMLAttributes } from "react";
2
2
  import "../styles/RadioButton.css";
3
3
  export interface RadioButtonProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {
4
4
  checked: boolean;
5
- onChange: (checked: boolean) => void;
6
- label?: string;
5
+ onChange?: (checked: boolean, ev: ChangeEvent<HTMLInputElement>) => void;
6
+ inputLabel?: string;
7
7
  className?: string;
8
8
  }
9
- export declare function RadioButton({ checked, onChange, label, className, ...rest }: RadioButtonProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function RadioButton({ checked, onChange, inputLabel, className, ...rest }: RadioButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -1,12 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { clsx } from "clsx";
3
3
  import "../styles/RadioButton.css";
4
- export function RadioButton({ checked, onChange, label, className, ...rest }) {
4
+ export function RadioButton({ checked, onChange, inputLabel, className, ...rest }) {
5
5
  const handleChange = (e) => {
6
- onChange(e.target.checked);
6
+ onChange?.(e.target.checked, e);
7
7
  };
8
- if (label) {
9
- return (_jsxs("label", { className: clsx("PaRadioButton", className), children: [_jsx("input", { className: "PaRadioButton-input", type: "radio", checked: checked, onChange: handleChange, ...rest }), _jsx("span", { className: "PaRadioButton-label", children: label })] }));
8
+ if (inputLabel) {
9
+ return (_jsxs("label", { className: clsx("PaRadioButton", className), children: [_jsx("input", { className: "PaRadioInput", type: "radio", checked: checked, onChange: handleChange, ...rest }), _jsx("span", { className: "PaRadioButton-label", children: inputLabel })] }));
10
10
  }
11
- return (_jsx("input", { className: clsx("PaRadioButton-input", className), type: "radio", checked: checked, onChange: handleChange, ...rest }));
11
+ return (_jsx("input", { className: clsx("PaRadioInput", className), type: "radio", checked: checked, onChange: handleChange, ...rest }));
12
12
  }
package/dist/Select.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import "../styles/Select.css";
2
- import type { SelectHTMLAttributes } from "react";
2
+ import type { ChangeEvent, SelectHTMLAttributes } from "react";
3
3
  export interface SelectOption {
4
4
  value: string;
5
5
  label: string;
@@ -7,12 +7,11 @@ export interface SelectOption {
7
7
  }
8
8
  export interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "onChange"> {
9
9
  value: string;
10
- onChange: (value: string) => void;
10
+ onChange?: (value: string, ev: ChangeEvent<HTMLSelectElement>) => void;
11
11
  options: SelectOption[];
12
12
  label?: string;
13
13
  error?: string;
14
14
  className?: string;
15
- fullWidth?: boolean;
16
15
  placeholder?: string;
17
16
  }
18
- export declare function Select({ value, onChange, options, label, error, className, fullWidth, placeholder, ...rest }: SelectProps): import("react/jsx-runtime").JSX.Element;
17
+ export declare function Select({ value, onChange, options, label, error, className, placeholder, ...rest }: SelectProps): import("react/jsx-runtime").JSX.Element;
package/dist/Select.js CHANGED
@@ -1,11 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import "../styles/Select.css";
3
3
  import { clsx } from "clsx";
4
4
  import { ChevronDown } from "lucide-react";
5
- export function Select({ value, onChange, options, label, error, className, fullWidth = false, placeholder, ...rest }) {
5
+ export function Select({ value, onChange, options, label, error, className, placeholder, ...rest }) {
6
6
  const handleChange = (e) => {
7
- onChange(e.target.value);
7
+ onChange?.(e.target.value, e);
8
8
  };
9
- const selectWithIcon = (_jsxs("span", { className: "PaSelect-fieldWrapper", children: [_jsxs("select", { className: "PaSelect-field", value: value, onChange: handleChange, ...rest, children: [placeholder && (_jsx("option", { value: "", disabled: true, children: placeholder })), options.map((option) => (_jsx("option", { value: option.value, disabled: option.disabled, children: option.label }, option.value)))] }), _jsx(ChevronDown, { className: "PaSelect-icon", size: 16 })] }));
10
- return (_jsxs("span", { className: clsx("PaSelect", error && "error", fullWidth && "fullWidth", className), children: [label ? (_jsxs("label", { className: "PaSelect-wrapper", children: [_jsx("span", { className: "PaSelect-label", children: label }), selectWithIcon] })) : (selectWithIcon), error && _jsx("span", { className: "PaSelect-error", children: error })] }));
9
+ const selectWithIcon = (_jsxs("span", { className: "PaSelectField-wrapper", children: [_jsxs("select", { className: "PaSelect", value: value, onChange: handleChange, ...rest, children: [placeholder && (_jsx("option", { value: "", disabled: true, children: placeholder })), options.map((option) => (_jsx("option", { value: option.value, disabled: option.disabled, children: option.label }, option.value)))] }), _jsx(ChevronDown, { className: "PaSelectField-icon", size: 16 })] }));
10
+ return (_jsxs(_Fragment, { children: [label ? (_jsxs("label", { className: clsx("PaSelectField PaField", error && "error", className), children: [_jsx("span", { className: "PaField-label", children: label }), selectWithIcon] })) : (_jsx("span", { className: clsx("PaSelectField", error && "error", className), children: selectWithIcon })), error && _jsx("span", { className: "PaFieldError", children: error })] }));
11
11
  }
package/dist/Switch.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import type { InputHTMLAttributes } from "react";
1
+ import type { ChangeEvent, InputHTMLAttributes } from "react";
2
2
  import "../styles/Switch.css";
3
3
  export interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {
4
4
  checked: boolean;
5
- onChange: (checked: boolean) => void;
5
+ onChange?: (checked: boolean, ev: ChangeEvent<HTMLInputElement>) => void;
6
6
  label?: string;
7
7
  className?: string;
8
8
  }
package/dist/Switch.js CHANGED
@@ -3,7 +3,7 @@ import { clsx } from "clsx";
3
3
  import "../styles/Switch.css";
4
4
  export function Switch({ checked, onChange, label, className, ...rest }) {
5
5
  const handleChange = (e) => {
6
- onChange(e.target.checked);
6
+ onChange?.(e.target.checked, e);
7
7
  };
8
8
  if (label) {
9
9
  return (_jsxs("label", { className: clsx("PaSwitch", className), children: [_jsx("input", { className: "PaSwitch-input", type: "checkbox", checked: checked, onChange: handleChange, ...rest }), _jsx("span", { className: "PaSwitch-track", children: _jsx("span", { className: "PaSwitch-thumb" }) }), _jsx("span", { className: "PaSwitch-label", children: label })] }));
@@ -1,8 +1,10 @@
1
1
  import "../styles/Textarea.css";
2
- import type { Ref, TextareaHTMLAttributes } from "react";
3
- export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
2
+ import type { ChangeEvent, Ref, TextareaHTMLAttributes } from "react";
3
+ export interface TextareaProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange"> {
4
+ value?: string;
5
+ onChange?: (value: string, ev: ChangeEvent<HTMLTextAreaElement>) => void;
4
6
  label?: string;
5
7
  error?: string;
6
8
  ref?: Ref<HTMLTextAreaElement>;
7
9
  }
8
- export declare function Textarea({ className, label, error, ref, ...props }: TextareaProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function Textarea({ className, label, error, value, onChange, ref, ...props }: TextareaProps): import("react/jsx-runtime").JSX.Element;
package/dist/Textarea.js CHANGED
@@ -1,7 +1,10 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import "../styles/Textarea.css";
3
3
  import { clsx } from "clsx";
4
- export function Textarea({ className, label, error, ref, ...props }) {
5
- const textareaElement = (_jsx("textarea", { ref: ref, className: clsx("PaTextarea-field", error && "error"), ...props }));
6
- return (_jsxs("span", { className: clsx("PaTextarea", className), children: [label ? (_jsxs("label", { className: "PaTextarea-wrapper", children: [_jsx("span", { className: "PaTextarea-label", children: label }), textareaElement] })) : (textareaElement), error && _jsx("span", { className: "PaTextarea-error", children: error })] }));
4
+ export function Textarea({ className, label, error, value, onChange, ref, ...props }) {
5
+ const handleChange = (e) => {
6
+ onChange?.(e.target.value, e);
7
+ };
8
+ const textareaElement = (_jsx("textarea", { ref: ref, className: clsx("PaTextarea", error && "error", !label && className), value: value, onChange: handleChange, ...props }));
9
+ return (_jsxs(_Fragment, { children: [label ? (_jsxs("label", { className: clsx("PaField", error && "error", className), children: [_jsx("span", { className: "PaField-label", children: label }), textareaElement] })) : (textareaElement), error && _jsx("span", { className: "PaFieldError", children: error })] }));
7
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paroicms/react-ui",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "React UI toolkit for ParoiCMS.",
5
5
  "keywords": [
6
6
  "paroicms",
@@ -25,7 +25,7 @@
25
25
  "dev": "tsc --watch --preserveWatchOutput"
26
26
  },
27
27
  "dependencies": {
28
- "@paroicms/public-anywhere-lib": "0.41.0",
28
+ "@paroicms/public-anywhere-lib": "0.41.1",
29
29
  "clsx": "~2.1.1",
30
30
  "lucide-react": "~0.562.0",
31
31
  "react-sortablejs": "~6.1.4",
@@ -36,11 +36,11 @@
36
36
  "react-dom": ">=18.0.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@types/react": "~19.2.7",
39
+ "@types/react": "~19.2.8",
40
40
  "@types/react-dom": "~19.2.3",
41
- "@types/sortablejs": "^1.15.8",
42
- "react": "~19.2.0",
43
- "react-dom": "~19.2.0",
41
+ "@types/sortablejs": "^1.15.9",
42
+ "react": "~19.2.3",
43
+ "react-dom": "~19.2.3",
44
44
  "rimraf": "~6.1.2",
45
45
  "typescript": "~5.9.3"
46
46
  },
@@ -1,7 +1,7 @@
1
1
  /* ========================================
2
2
  Checkbox Component
3
3
  ======================================== */
4
- .PaCheckbox {
4
+ .PaCheckboxField {
5
5
  display: inline-flex;
6
6
  gap: var(--space-2);
7
7
  align-items: center;
@@ -9,7 +9,7 @@
9
9
  user-select: none;
10
10
  }
11
11
 
12
- .PaCheckbox-input {
12
+ .PaCheckboxInput {
13
13
  display: flex;
14
14
  flex-shrink: 0;
15
15
  align-items: center;
@@ -24,7 +24,7 @@
24
24
  border-radius: var(--radius-sm);
25
25
  transition: all var(--transition);
26
26
 
27
- &:hover {
27
+ &:hover:not(:disabled) {
28
28
  border-color: var(--color-primary);
29
29
  }
30
30
 
@@ -55,7 +55,8 @@
55
55
  }
56
56
  }
57
57
 
58
- .PaCheckbox-label {
59
- font-size: var(--text-sm);
60
- color: var(--color-text);
58
+ .PaCheckboxGroup {
59
+ display: flex;
60
+ flex-wrap: wrap;
61
+ gap: var(--space-3);
61
62
  }
@@ -1,25 +1,7 @@
1
1
  /* ========================================
2
2
  DateInput Component
3
3
  ======================================== */
4
- .PaDateInput {
5
- display: flex;
6
- flex-direction: column;
7
- gap: var(--space-2);
8
- }
9
-
10
- .PaDateInput-wrapper {
11
- display: flex;
12
- flex-direction: column;
13
- gap: var(--space-2);
14
- }
15
-
16
- .PaDateInput-label {
17
- font-size: var(--text-sm);
18
- font-weight: var(--font-medium);
19
- color: var(--color-text);
20
- }
21
-
22
- .PaDateInput-field {
4
+ .PaDateTimeInput {
23
5
  padding: var(--space-2) var(--space-3);
24
6
  font-family: inherit;
25
7
  font-size: var(--text-base);
@@ -32,7 +14,7 @@
32
14
  border-color var(--transition),
33
15
  box-shadow var(--transition);
34
16
 
35
- &:hover {
17
+ &:hover:not(:disabled) {
36
18
  border-color: var(--color-primary);
37
19
  }
38
20
 
@@ -52,8 +34,3 @@
52
34
  border-color: var(--color-danger);
53
35
  }
54
36
  }
55
-
56
- .PaDateInput-error {
57
- font-size: var(--text-xs);
58
- color: var(--color-danger);
59
- }
package/styles/Dialog.css CHANGED
@@ -24,18 +24,18 @@
24
24
  }
25
25
 
26
26
  /* Size variants */
27
- &.size-sm {
28
- width: 320px;
27
+ &.sizeSm {
28
+ width: 480px;
29
29
  max-width: 100%;
30
30
  }
31
31
 
32
- &.size-md {
33
- width: 480px;
32
+ &.sizeMd {
33
+ width: 640px;
34
34
  max-width: 100%;
35
35
  }
36
36
 
37
- &.size-lg {
38
- width: 640px;
37
+ &.sizeLg {
38
+ width: 800px;
39
39
  max-width: 100%;
40
40
  }
41
41
  }
@@ -45,7 +45,7 @@
45
45
  gap: var(--space-4);
46
46
  align-items: center;
47
47
  justify-content: space-between;
48
- padding: var(--space-4) var(--space-5);
48
+ padding: var(--space-3) var(--space-5);
49
49
  border-bottom: 1px solid var(--color-border-light);
50
50
  }
51
51
 
@@ -59,6 +59,8 @@
59
59
  display: flex;
60
60
  align-items: center;
61
61
  justify-content: center;
62
+ width: 40px;
63
+ height: 40px;
62
64
  padding: var(--space-1);
63
65
  color: var(--color-text-muted);
64
66
  cursor: pointer;
@@ -1,25 +1,7 @@
1
1
  /* ========================================
2
2
  InputNumber Component
3
3
  ======================================== */
4
- .PaInputNumber {
5
- display: flex;
6
- flex-direction: column;
7
- gap: var(--space-2);
8
- }
9
-
10
- .PaInputNumber-wrapper {
11
- display: flex;
12
- flex-direction: column;
13
- gap: var(--space-2);
14
- }
15
-
16
- .PaInputNumber-label {
17
- font-size: var(--text-sm);
18
- font-weight: var(--font-medium);
19
- color: var(--color-text);
20
- }
21
-
22
- .PaInputNumber-field {
4
+ .PaNumberInput {
23
5
  width: 100%;
24
6
  padding: var(--space-2) var(--space-3);
25
7
  font-family: inherit;
@@ -33,7 +15,7 @@
33
15
  border-color var(--transition),
34
16
  box-shadow var(--transition);
35
17
 
36
- &:hover {
18
+ &:hover:not(:disabled) {
37
19
  border-color: var(--color-primary);
38
20
  }
39
21
 
@@ -53,8 +35,3 @@
53
35
  border-color: var(--color-danger);
54
36
  }
55
37
  }
56
-
57
- .PaInputNumber-error {
58
- font-size: var(--text-xs);
59
- color: var(--color-danger);
60
- }
@@ -1,33 +1,17 @@
1
1
  /* ========================================
2
2
  InputText Component
3
3
  ======================================== */
4
- .PaInputText {
4
+ .PaTextField {
5
5
  display: flex;
6
6
  flex-direction: column;
7
7
  gap: var(--space-2);
8
8
 
9
- &.error .PaInputText-field {
9
+ &.error .PaTextInput {
10
10
  border-color: var(--color-danger);
11
11
  }
12
-
13
- &.fullWidth {
14
- width: 100%;
15
- }
16
- }
17
-
18
- .PaInputText-wrapper {
19
- display: flex;
20
- flex-direction: column;
21
- gap: var(--space-2);
22
- }
23
-
24
- .PaInputText-label {
25
- font-size: var(--text-sm);
26
- font-weight: var(--font-medium);
27
- color: var(--color-text);
28
12
  }
29
13
 
30
- .PaInputText-field {
14
+ .PaTextInput {
31
15
  width: 100%;
32
16
  padding: var(--space-2) var(--space-3);
33
17
  font-family: inherit;
@@ -41,7 +25,7 @@
41
25
  border-color var(--transition),
42
26
  box-shadow var(--transition);
43
27
 
44
- &:hover {
28
+ &:hover:not(:disabled) {
45
29
  border-color: var(--color-primary);
46
30
  }
47
31
 
@@ -50,43 +34,44 @@
50
34
  border-color: var(--color-primary);
51
35
  box-shadow: 0 0 0 3px var(--color-primary-light);
52
36
  }
53
- }
54
37
 
55
- .PaInputText-error {
56
- font-size: var(--text-xs);
57
- color: var(--color-danger);
38
+ &:disabled {
39
+ cursor: not-allowed;
40
+ background: var(--color-bg-subtle);
41
+ opacity: 0.7;
42
+ }
58
43
  }
59
44
 
60
- .PaInputText-row {
45
+ .PaTextField-row {
61
46
  display: flex;
62
47
  gap: var(--space-1);
63
48
 
64
- .PaInputText-field {
49
+ .PaTextInput {
65
50
  flex: 1;
66
51
  min-width: 0;
67
52
  }
68
53
  }
69
54
 
70
- .PaInputText-iconWrapper {
55
+ .PaTextField-iconWrapper {
71
56
  position: relative;
72
57
  display: flex;
73
58
 
74
- .PaInputText-field {
59
+ .PaTextInput {
75
60
  padding-left: var(--space-10);
76
61
  }
77
62
 
78
- &.iconRight .PaInputText-icon {
63
+ &.iconRight .PaTextField-icon {
79
64
  right: var(--space-3);
80
65
  left: auto;
81
66
  }
82
67
 
83
- &.iconRight .PaInputText-field {
68
+ &.iconRight .PaTextInput {
84
69
  padding-right: var(--space-10);
85
70
  padding-left: var(--space-3);
86
71
  }
87
72
  }
88
73
 
89
- .PaInputText-icon {
74
+ .PaTextField-icon {
90
75
  position: absolute;
91
76
  top: 50%;
92
77
  left: var(--space-3);
@@ -7,18 +7,6 @@
7
7
  gap: var(--space-2);
8
8
  }
9
9
 
10
- .PaPasswordInput-wrapper {
11
- display: flex;
12
- flex-direction: column;
13
- gap: var(--space-2);
14
- }
15
-
16
- .PaPasswordInput-label {
17
- font-size: var(--text-sm);
18
- font-weight: var(--font-medium);
19
- color: var(--color-text);
20
- }
21
-
22
10
  .PaPasswordInput-inputWrapper {
23
11
  position: relative;
24
12
  display: flex;
@@ -43,7 +31,7 @@
43
31
  border-color var(--transition),
44
32
  box-shadow var(--transition);
45
33
 
46
- &:hover {
34
+ &:hover:not(:disabled) {
47
35
  border-color: var(--color-primary);
48
36
  }
49
37
 
@@ -52,6 +40,12 @@
52
40
  border-color: var(--color-primary);
53
41
  box-shadow: 0 0 0 3px var(--color-primary-light);
54
42
  }
43
+
44
+ &:disabled {
45
+ cursor: not-allowed;
46
+ background: var(--color-bg-subtle);
47
+ opacity: 0.7;
48
+ }
55
49
  }
56
50
 
57
51
  .PaPasswordInput-toggle {
@@ -73,8 +67,3 @@
73
67
  color: var(--color-text);
74
68
  }
75
69
  }
76
-
77
- .PaPasswordInput-error {
78
- font-size: var(--text-xs);
79
- color: var(--color-danger);
80
- }
@@ -9,7 +9,7 @@
9
9
  user-select: none;
10
10
  }
11
11
 
12
- .PaRadioButton-input {
12
+ .PaRadioInput {
13
13
  display: flex;
14
14
  flex-shrink: 0;
15
15
  align-items: center;
@@ -24,7 +24,7 @@
24
24
  border-radius: var(--radius-full);
25
25
  transition: all var(--transition);
26
26
 
27
- &:hover {
27
+ &:hover:not(:disabled) {
28
28
  border-color: var(--color-primary);
29
29
  }
30
30
 
@@ -54,7 +54,8 @@
54
54
  }
55
55
  }
56
56
 
57
- .PaRadioButton-label {
58
- font-size: var(--text-sm);
59
- color: var(--color-text);
57
+ .PaRadioGroup {
58
+ display: flex;
59
+ flex-wrap: wrap;
60
+ gap: var(--space-3);
60
61
  }
package/styles/Select.css CHANGED
@@ -1,37 +1,21 @@
1
1
  /* ========================================
2
2
  Select Component
3
3
  ======================================== */
4
- .PaSelect {
4
+ .PaSelectField {
5
5
  display: flex;
6
6
  flex-direction: column;
7
7
  gap: var(--space-2);
8
8
 
9
- &.error .PaSelect-field {
9
+ &.error .PaSelect {
10
10
  border-color: var(--color-danger);
11
11
  }
12
-
13
- &.fullWidth {
14
- width: 100%;
15
- }
16
- }
17
-
18
- .PaSelect-wrapper {
19
- display: flex;
20
- flex-direction: column;
21
- gap: var(--space-2);
22
12
  }
23
13
 
24
- .PaSelect-label {
25
- font-size: var(--text-sm);
26
- font-weight: var(--font-medium);
27
- color: var(--color-text);
28
- }
29
-
30
- .PaSelect-fieldWrapper {
14
+ .PaSelectField-wrapper {
31
15
  position: relative;
32
16
  }
33
17
 
34
- .PaSelect-field {
18
+ .PaSelect {
35
19
  width: 100%;
36
20
  padding: var(--space-2) var(--space-8) var(--space-2) var(--space-3);
37
21
  font-family: inherit;
@@ -44,7 +28,7 @@
44
28
  border-radius: var(--radius);
45
29
  transition: border-color var(--transition);
46
30
 
47
- &:hover {
31
+ &:hover:not(:disabled) {
48
32
  border-color: var(--color-primary);
49
33
  }
50
34
 
@@ -53,9 +37,15 @@
53
37
  border-color: var(--color-primary);
54
38
  box-shadow: 0 0 0 3px var(--color-primary-light);
55
39
  }
40
+
41
+ &:disabled {
42
+ cursor: not-allowed;
43
+ background: var(--color-bg-subtle);
44
+ opacity: 0.7;
45
+ }
56
46
  }
57
47
 
58
- .PaSelect-icon {
48
+ .PaSelectField-icon {
59
49
  position: absolute;
60
50
  top: 50%;
61
51
  right: var(--space-3);
@@ -65,8 +55,3 @@
65
55
  pointer-events: none;
66
56
  transform: translateY(-50%);
67
57
  }
68
-
69
- .PaSelect-error {
70
- font-size: var(--text-xs);
71
- color: var(--color-danger);
72
- }
@@ -2,24 +2,6 @@
2
2
  Textarea Component
3
3
  ======================================== */
4
4
  .PaTextarea {
5
- display: flex;
6
- flex-direction: column;
7
- gap: var(--space-2);
8
- }
9
-
10
- .PaTextarea-wrapper {
11
- display: flex;
12
- flex-direction: column;
13
- gap: var(--space-2);
14
- }
15
-
16
- .PaTextarea-label {
17
- font-size: var(--text-sm);
18
- font-weight: var(--font-medium);
19
- color: var(--color-text);
20
- }
21
-
22
- .PaTextarea-field {
23
5
  width: 100%;
24
6
  min-height: 120px;
25
7
  padding: var(--space-3);
@@ -39,7 +21,7 @@
39
21
  color: var(--color-text-light);
40
22
  }
41
23
 
42
- &:hover {
24
+ &:hover:not(:disabled) {
43
25
  border-color: var(--color-primary);
44
26
  }
45
27
 
@@ -59,8 +41,3 @@
59
41
  border-color: var(--color-danger);
60
42
  }
61
43
  }
62
-
63
- .PaTextarea-error {
64
- font-size: var(--text-xs);
65
- color: var(--color-danger);
66
- }
@@ -0,0 +1,29 @@
1
+ /* ========================================
2
+ PaField - Form Field Layout Block
3
+ ======================================== */
4
+ .PaField {
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: var(--space-2);
8
+
9
+ &:not(:last-child) {
10
+ margin-bottom: var(--space-4);
11
+ }
12
+ }
13
+
14
+ .PaField-label {
15
+ display: block;
16
+ font-size: var(--text-xs);
17
+ font-weight: var(--font-semibold);
18
+ color: var(--color-text-muted);
19
+ text-transform: uppercase;
20
+ letter-spacing: 0.03em;
21
+ }
22
+
23
+ /* ========================================
24
+ PaFieldError - Field Error Message Block
25
+ ======================================== */
26
+ .PaFieldError {
27
+ font-size: var(--text-xs);
28
+ color: var(--color-danger);
29
+ }
@@ -13,3 +13,4 @@
13
13
  @import "./base.css" layer(base);
14
14
  @import "./common.css" layer(common);
15
15
  @import "./margins.css";
16
+ @import "./field.css";