@paroicms/react-ui 0.5.0 → 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 +7 -1
- package/dist/Checkbox.d.ts +4 -3
- package/dist/Checkbox.js +5 -7
- package/dist/DateInput.d.ts +5 -3
- package/dist/DateInput.js +7 -4
- package/dist/Dialog.d.ts +4 -2
- package/dist/Dialog.js +30 -27
- package/dist/InputNumber.d.ts +2 -2
- package/dist/InputNumber.js +5 -5
- package/dist/InputText.d.ts +3 -4
- package/dist/InputText.js +7 -6
- package/dist/MultiSelect.d.ts +3 -2
- package/dist/MultiSelect.js +27 -24
- package/dist/PasswordInput.d.ts +5 -3
- package/dist/PasswordInput.js +7 -4
- package/dist/PopupMenu.d.ts +3 -4
- package/dist/PopupMenu.js +13 -51
- package/dist/RadioButton.d.ts +4 -4
- package/dist/RadioButton.js +5 -5
- package/dist/Select.d.ts +3 -4
- package/dist/Select.js +5 -5
- package/dist/SplitButton.d.ts +1 -0
- package/dist/SplitButton.js +12 -15
- package/dist/Switch.d.ts +2 -2
- package/dist/Switch.js +1 -1
- package/dist/Textarea.d.ts +5 -3
- package/dist/Textarea.js +7 -4
- package/dist/Tooltip.d.ts +1 -1
- package/dist/Tooltip.js +11 -32
- package/dist/alert-stack.d.ts +3 -1
- package/dist/alert-stack.js +2 -2
- package/dist/popup-positioning.d.ts +10 -0
- package/dist/popup-positioning.js +160 -0
- package/package.json +6 -6
- package/styles/Alert.css +1 -0
- package/styles/Checkbox.css +7 -6
- package/styles/DateInput.css +2 -25
- package/styles/Dialog.css +35 -22
- package/styles/InputNumber.css +2 -25
- package/styles/InputText.css +16 -31
- package/styles/MultiSelect.css +8 -23
- package/styles/PasswordInput.css +7 -18
- package/styles/RadioButton.css +6 -5
- package/styles/Select.css +12 -27
- package/styles/SplitButton.css +2 -8
- package/styles/Textarea.css +1 -24
- package/styles/Tooltip.css +4 -18
- package/styles/Tree.css +4 -3
- package/styles/theme/field.css +29 -0
- package/styles/theme/index.css +1 -0
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")
|
package/dist/Checkbox.d.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
9
|
-
|
|
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
|
}
|
package/dist/DateInput.d.ts
CHANGED
|
@@ -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
|
|
6
|
-
|
|
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
|
-
|
|
11
|
+
/** Default size is "md" */
|
|
12
|
+
size?: DialogSize;
|
|
12
13
|
}
|
|
13
|
-
export
|
|
14
|
+
export type DialogSize = "sm" | "md" | "lg" | "innerContent";
|
|
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,39 +3,38 @@ 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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export function Dialog({ visible, onHide, header, footer, children, className, closable = true, modal = true, }) {
|
|
10
|
-
// Track this dialog's position in the stack for ESC key handling
|
|
11
|
-
const dialogIdRef = useRef(undefined);
|
|
6
|
+
export function Dialog({ visible, onHide, header, footer, children, className, closable = true, size = "md", }) {
|
|
7
|
+
const dialogRef = useRef(null);
|
|
8
|
+
// Control open/close with native methods
|
|
12
9
|
useEffect(() => {
|
|
10
|
+
const dialog = dialogRef.current;
|
|
11
|
+
if (!dialog)
|
|
12
|
+
return;
|
|
13
13
|
if (visible) {
|
|
14
|
-
|
|
14
|
+
if (!dialog.open) {
|
|
15
|
+
dialog.showModal();
|
|
16
|
+
}
|
|
15
17
|
}
|
|
16
|
-
|
|
17
|
-
if (
|
|
18
|
-
|
|
19
|
-
if (dialogIdRef.current === dialogStackCounter) {
|
|
20
|
-
dialogStackCounter--;
|
|
21
|
-
}
|
|
22
|
-
dialogIdRef.current = undefined;
|
|
18
|
+
else {
|
|
19
|
+
if (dialog.open) {
|
|
20
|
+
dialog.close();
|
|
23
21
|
}
|
|
24
|
-
}
|
|
22
|
+
}
|
|
25
23
|
}, [visible]);
|
|
26
|
-
// Handle
|
|
24
|
+
// Handle ESC key via native cancel event
|
|
27
25
|
useEffect(() => {
|
|
28
|
-
|
|
26
|
+
const dialog = dialogRef.current;
|
|
27
|
+
if (!dialog)
|
|
29
28
|
return;
|
|
30
|
-
const
|
|
31
|
-
//
|
|
32
|
-
if (
|
|
29
|
+
const handleCancel = (e) => {
|
|
30
|
+
e.preventDefault(); // Prevent default close
|
|
31
|
+
if (closable) {
|
|
33
32
|
onHide();
|
|
34
33
|
}
|
|
35
34
|
};
|
|
36
|
-
|
|
37
|
-
return () =>
|
|
38
|
-
}, [
|
|
35
|
+
dialog.addEventListener("cancel", handleCancel);
|
|
36
|
+
return () => dialog.removeEventListener("cancel", handleCancel);
|
|
37
|
+
}, [closable, onHide]);
|
|
39
38
|
// Prevent body scroll when open
|
|
40
39
|
useEffect(() => {
|
|
41
40
|
if (visible) {
|
|
@@ -48,8 +47,12 @@ export function Dialog({ visible, onHide, header, footer, children, className, c
|
|
|
48
47
|
document.body.style.overflow = "";
|
|
49
48
|
};
|
|
50
49
|
}, [visible]);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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 })] }));
|
|
55
58
|
}
|
package/dist/InputNumber.d.ts
CHANGED
|
@@ -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
|
|
5
|
+
onChange?: (value: number | undefined, ev: ChangeEvent<HTMLInputElement>) => void;
|
|
6
6
|
label?: string;
|
|
7
7
|
error?: string;
|
|
8
8
|
ref?: Ref<HTMLInputElement>;
|
package/dist/InputNumber.js
CHANGED
|
@@ -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("
|
|
18
|
-
return (_jsxs(
|
|
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
|
}
|
package/dist/InputText.d.ts
CHANGED
|
@@ -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
|
|
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,
|
|
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,
|
|
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: "
|
|
9
|
-
const
|
|
10
|
-
|
|
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
|
}
|
package/dist/MultiSelect.d.ts
CHANGED
|
@@ -6,12 +6,13 @@ export interface MultiSelectOption {
|
|
|
6
6
|
}
|
|
7
7
|
export interface MultiSelectProps {
|
|
8
8
|
value: string[];
|
|
9
|
-
onChange
|
|
9
|
+
onChange?: (value: string[]) => void;
|
|
10
10
|
options: MultiSelectOption[];
|
|
11
11
|
label?: string;
|
|
12
12
|
error?: string;
|
|
13
13
|
className?: string;
|
|
14
14
|
placeholder?: string;
|
|
15
15
|
disabled?: boolean;
|
|
16
|
+
position?: "auto" | "top" | "bottom";
|
|
16
17
|
}
|
|
17
|
-
export declare function MultiSelect({ value, onChange, options, label, error, className, placeholder, disabled, }: MultiSelectProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export declare function MultiSelect({ value, onChange, options, label, error, className, placeholder, disabled, position, }: MultiSelectProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/MultiSelect.js
CHANGED
|
@@ -3,48 +3,51 @@ import "../styles/MultiSelect.css";
|
|
|
3
3
|
import { clsx } from "clsx";
|
|
4
4
|
import { ChevronDown, X } from "lucide-react";
|
|
5
5
|
import { useEffect, useRef, useState } from "react";
|
|
6
|
-
|
|
6
|
+
import { Checkbox } from "./Checkbox.js";
|
|
7
|
+
import { computePopupPosition, setupPopoverPositioning } from "./popup-positioning.js";
|
|
8
|
+
export function MultiSelect({ value, onChange, options, label, error, className, placeholder, disabled, position, }) {
|
|
7
9
|
const [open, setOpen] = useState(false);
|
|
8
10
|
const containerRef = useRef(null);
|
|
9
|
-
|
|
11
|
+
const dropdownRef = useRef(null);
|
|
12
|
+
const dropdownId = useRef(`pa-multiselect-${Math.random().toString(36).substring(2, 9)}`);
|
|
10
13
|
useEffect(() => {
|
|
11
|
-
|
|
14
|
+
const dropdown = dropdownRef.current;
|
|
15
|
+
const container = containerRef.current;
|
|
16
|
+
if (!dropdown || !container)
|
|
12
17
|
return;
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
setOpen(false);
|
|
16
|
-
}
|
|
18
|
+
const handleToggle = (e) => {
|
|
19
|
+
setOpen(e.newState === "open");
|
|
17
20
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
dropdown.addEventListener("toggle", handleToggle);
|
|
22
|
+
const cleanupPositioning = setupPopoverPositioning(dropdown, () => {
|
|
23
|
+
dropdown.style.width = `${container.offsetWidth}px`;
|
|
24
|
+
return computePopupPosition(container, dropdown, position ?? "auto", "vertical");
|
|
25
|
+
});
|
|
26
|
+
return () => {
|
|
27
|
+
dropdown.removeEventListener("toggle", handleToggle);
|
|
28
|
+
cleanupPositioning();
|
|
29
|
+
};
|
|
30
|
+
}, [position]);
|
|
21
31
|
const toggleOption = (optionValue) => {
|
|
22
32
|
if (value.includes(optionValue)) {
|
|
23
|
-
onChange(value.filter((v) => v !== optionValue));
|
|
33
|
+
onChange?.(value.filter((v) => v !== optionValue));
|
|
24
34
|
}
|
|
25
35
|
else {
|
|
26
|
-
onChange([...value, optionValue]);
|
|
36
|
+
onChange?.([...value, optionValue]);
|
|
27
37
|
}
|
|
28
38
|
};
|
|
29
39
|
const removeValue = (optionValue) => {
|
|
30
|
-
onChange(value.filter((v) => v !== optionValue));
|
|
40
|
+
onChange?.(value.filter((v) => v !== optionValue));
|
|
31
41
|
};
|
|
32
42
|
const selectedOptions = options.filter((opt) => value.includes(opt.value));
|
|
33
|
-
const controlElement = (_jsxs(_Fragment, { children: [_jsxs("span", { className:
|
|
34
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
43
|
+
const controlElement = (_jsxs(_Fragment, { children: [_jsxs("span", { className: "PaMultiSelect-control", onClick: () => !disabled && dropdownRef.current?.togglePopover(), onKeyDown: (e) => {
|
|
44
|
+
if ((e.key === "Enter" || e.key === " ") && !disabled) {
|
|
35
45
|
e.preventDefault();
|
|
36
|
-
|
|
37
|
-
setOpen(!open);
|
|
46
|
+
dropdownRef.current?.togglePopover();
|
|
38
47
|
}
|
|
39
48
|
}, tabIndex: disabled ? -1 : 0, role: "combobox", "aria-expanded": open, "aria-haspopup": "listbox", children: [_jsx("span", { className: "PaMultiSelect-values", children: selectedOptions.length > 0 ? (selectedOptions.map((opt) => (_jsxs("span", { className: "PaMultiSelect-chip", children: [opt.label, _jsx("button", { type: "button", className: "PaMultiSelect-chipRemove", onClick: (e) => {
|
|
40
49
|
e.stopPropagation();
|
|
41
50
|
removeValue(opt.value);
|
|
42
|
-
}, "aria-label": `Remove ${opt.label}`, children: _jsx(X, { size: 12 }) })] }, opt.value)))) : (_jsx("span", { className: "PaMultiSelect-placeholder", children: placeholder })) }), _jsx(ChevronDown, { className: "PaMultiSelect-icon", size: 16 })] }),
|
|
43
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
44
|
-
e.preventDefault();
|
|
45
|
-
if (!option.disabled)
|
|
46
|
-
toggleOption(option.value);
|
|
47
|
-
}
|
|
48
|
-
}, tabIndex: option.disabled ? -1 : 0, role: "option", "aria-selected": value.includes(option.value), children: [_jsx("span", { className: "PaMultiSelect-checkbox", children: value.includes(option.value) && "✓" }), option.label] }, option.value))) }))] }));
|
|
51
|
+
}, "aria-label": `Remove ${opt.label}`, children: _jsx(X, { size: 12 }) })] }, opt.value)))) : (_jsx("span", { className: "PaMultiSelect-placeholder", children: placeholder })) }), _jsx(ChevronDown, { className: "PaMultiSelect-icon", size: 16 })] }), _jsx("span", { ref: dropdownRef, id: dropdownId.current, className: "PaMultiSelect-dropdown", role: "listbox", popover: "auto", children: options.map((option) => (_jsxs("label", { className: clsx("PaMultiSelect-option", value.includes(option.value) && "selected", option.disabled && "disabled"), children: [_jsx(Checkbox, { checked: value.includes(option.value), onChange: () => toggleOption(option.value), disabled: option.disabled }), option.label] }, option.value))) })] }));
|
|
49
52
|
return (_jsxs("span", { ref: containerRef, className: clsx("PaMultiSelect", error && "error", disabled && "disabled", className), children: [label ? (_jsxs("label", { className: "PaMultiSelect-wrapper", children: [_jsx("span", { className: "PaMultiSelect-label", children: label }), controlElement] })) : (controlElement), error && _jsx("span", { className: "PaMultiSelect-error", children: error })] }));
|
|
50
53
|
}
|
package/dist/PasswordInput.d.ts
CHANGED
|
@@ -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;
|
package/dist/PasswordInput.js
CHANGED
|
@@ -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
|
|
9
|
-
|
|
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
|
}
|
package/dist/PopupMenu.d.ts
CHANGED
|
@@ -5,9 +5,8 @@ export interface PopupMenuProps {
|
|
|
5
5
|
items: MenuNode[];
|
|
6
6
|
className?: string;
|
|
7
7
|
id?: string;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
position?: "bottom" | "top";
|
|
8
|
+
/** Position of the popup relative to the trigger. Default is 'auto'. */
|
|
9
|
+
position?: "auto" | "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
|
|
11
10
|
/** Optional custom trigger element. If provided, it will be used instead of the default button. */
|
|
12
11
|
children?: ReactNode;
|
|
13
12
|
ref?: Ref<PopupMenuRef>;
|
|
@@ -17,4 +16,4 @@ export interface PopupMenuRef {
|
|
|
17
16
|
show: (event: MouseEvent) => void;
|
|
18
17
|
hide: () => void;
|
|
19
18
|
}
|
|
20
|
-
export declare function PopupMenu({ items, className, id,
|
|
19
|
+
export declare function PopupMenu({ items, className, id, position, children, ref, }: PopupMenuProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/PopupMenu.js
CHANGED
|
@@ -5,28 +5,13 @@ import { ChevronRight, ChevronsDown } from "lucide-react";
|
|
|
5
5
|
import { cloneElement, isValidElement, useEffect, useImperativeHandle, useRef, } from "react";
|
|
6
6
|
import { Button } from "./Button.js";
|
|
7
7
|
import { MenuItem } from "./MenuItem.js";
|
|
8
|
+
import { computePopupPosition, setupPopoverPositioning } from "./popup-positioning.js";
|
|
8
9
|
const isPopoverSupported = typeof HTMLElement !== "undefined" && "showPopover" in HTMLElement.prototype;
|
|
9
10
|
if (!isPopoverSupported) {
|
|
10
11
|
console?.error("PopupMenu: Popover API is not supported in this browser.");
|
|
11
12
|
}
|
|
12
13
|
let seq = 0;
|
|
13
|
-
|
|
14
|
-
* Utility function to configure popup positioning
|
|
15
|
-
*/
|
|
16
|
-
function setupPopoverPositioning(element, getPosition) {
|
|
17
|
-
const handleToggle = (e) => {
|
|
18
|
-
const newState = e.newState;
|
|
19
|
-
if (newState === "open") {
|
|
20
|
-
const position = getPosition();
|
|
21
|
-
element.style.position = "absolute";
|
|
22
|
-
element.style.top = `${position.top}px`;
|
|
23
|
-
element.style.left = `${position.left}px`;
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
element.addEventListener("toggle", handleToggle);
|
|
27
|
-
return () => element.removeEventListener("toggle", handleToggle);
|
|
28
|
-
}
|
|
29
|
-
export function PopupMenu({ items, className, id, autoPosition = true, position = "bottom", children, ref, }) {
|
|
14
|
+
export function PopupMenu({ items, className, id, position = "auto", children, ref, }) {
|
|
30
15
|
const menuRef = useRef(null);
|
|
31
16
|
const triggerRef = useRef(null);
|
|
32
17
|
const menuIdRef = useRef(undefined);
|
|
@@ -55,28 +40,12 @@ export function PopupMenu({ items, className, id, autoPosition = true, position
|
|
|
55
40
|
}));
|
|
56
41
|
// Position popover when it opens
|
|
57
42
|
useEffect(() => {
|
|
58
|
-
if (!autoPosition || !menuRef.current || !triggerRef.current)
|
|
59
|
-
return;
|
|
60
43
|
const menuEl = menuRef.current;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// Position above the trigger
|
|
67
|
-
const menuHeight = menuEl.offsetHeight || 150; // Fallback height
|
|
68
|
-
return {
|
|
69
|
-
top: rect.top + window.scrollY - menuHeight - 8,
|
|
70
|
-
left: rect.left + window.scrollX,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
// Default: position below
|
|
74
|
-
return {
|
|
75
|
-
top: rect.bottom + window.scrollY,
|
|
76
|
-
left: rect.left + window.scrollX,
|
|
77
|
-
};
|
|
78
|
-
});
|
|
79
|
-
}, [autoPosition, position]);
|
|
44
|
+
const triggerEl = triggerRef.current;
|
|
45
|
+
if (!menuEl || !triggerEl)
|
|
46
|
+
return;
|
|
47
|
+
return setupPopoverPositioning(menuEl, () => computePopupPosition(triggerEl, menuEl, position, "corner"));
|
|
48
|
+
}, [position]);
|
|
80
49
|
const triggerProps = {
|
|
81
50
|
popoverTarget: menuIdRef.current,
|
|
82
51
|
popoverTargetAction: "toggle",
|
|
@@ -125,20 +94,13 @@ function PopupMenuItemWrapper({ item, onHide }) {
|
|
|
125
94
|
}
|
|
126
95
|
// Handle submenu positioning with Popover API
|
|
127
96
|
useEffect(() => {
|
|
128
|
-
if (!subMenuRef.current || !item.subMenu)
|
|
129
|
-
return;
|
|
130
97
|
const subMenuEl = subMenuRef.current;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
left: rect.right + 5, // 5px gap
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
return { top: 0, left: 0 };
|
|
141
|
-
});
|
|
98
|
+
if (!subMenuEl || !item.subMenu)
|
|
99
|
+
return;
|
|
100
|
+
const parentEl = subMenuEl.parentElement;
|
|
101
|
+
if (!parentEl)
|
|
102
|
+
return;
|
|
103
|
+
return setupPopoverPositioning(subMenuEl, () => computePopupPosition(parentEl, subMenuEl, "right", "cardinal"));
|
|
142
104
|
}, [item.subMenu]);
|
|
143
105
|
return (_jsxs("div", { className: "PaPopupMenu-item", popoverTargetAction: "toggle", popoverTarget: subMenuId.current, children: [_jsx(MenuItem, { item: itemWithSubmenuHandling }), item.subMenu && (_jsx("div", { className: "PaPopupMenu-submenu", popover: "auto", id: subMenuId.current, ref: subMenuRef, children: item.subMenu.map((subItem) => (_jsx(PopupMenuItemWrapper, { item: subItem, onHide: onHide }, subItem.key))) }))] }));
|
|
144
106
|
}
|
package/dist/RadioButton.d.ts
CHANGED
|
@@ -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
|
|
6
|
-
|
|
5
|
+
onChange?: (checked: boolean, ev: ChangeEvent<HTMLInputElement>) => void;
|
|
6
|
+
inputLabel?: string;
|
|
7
7
|
className?: string;
|
|
8
8
|
}
|
|
9
|
-
export declare function RadioButton({ checked, onChange,
|
|
9
|
+
export declare function RadioButton({ checked, onChange, inputLabel, className, ...rest }: RadioButtonProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/RadioButton.js
CHANGED
|
@@ -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,
|
|
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 (
|
|
9
|
-
return (_jsxs("label", { className: clsx("PaRadioButton", className), children: [_jsx("input", { className: "
|
|
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("
|
|
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
|
|
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,
|
|
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,
|
|
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: "
|
|
10
|
-
return (_jsxs("
|
|
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/SplitButton.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export interface SplitAnchorElProps extends SplitButtonBaseProps, Omit<AnchorElP
|
|
|
11
11
|
interface SplitButtonBaseProps {
|
|
12
12
|
items: SplitButtonItem[];
|
|
13
13
|
className?: string;
|
|
14
|
+
position?: "auto" | "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
|
|
14
15
|
}
|
|
15
16
|
export interface SplitButtonItem {
|
|
16
17
|
label: string;
|