@paroicms/react-ui 0.4.4 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Accordion.d.ts +10 -0
- package/dist/{PuAccordion.jsx → Accordion.js} +5 -8
- package/dist/Alert.d.ts +10 -0
- package/dist/Alert.js +7 -0
- package/dist/Badge.d.ts +8 -0
- package/dist/Badge.js +6 -0
- package/dist/Breadcrumb.d.ts +14 -0
- package/dist/Breadcrumb.js +10 -0
- package/dist/Button.d.ts +36 -0
- package/dist/Button.js +74 -0
- package/dist/Card.d.ts +10 -0
- package/dist/Card.js +7 -0
- package/dist/Checkbox.d.ts +9 -0
- package/dist/Checkbox.js +12 -0
- package/dist/Chip.d.ts +8 -0
- package/dist/Chip.js +7 -0
- package/dist/Column.d.ts +14 -0
- package/dist/Column.js +7 -0
- package/dist/DataTable.d.ts +30 -0
- package/dist/DataTable.js +26 -0
- package/dist/DateInput.d.ts +9 -0
- package/dist/DateInput.js +7 -0
- package/dist/Dialog.d.ts +13 -0
- package/dist/Dialog.js +51 -0
- package/dist/Inplace.d.ts +12 -0
- package/dist/Inplace.js +16 -0
- package/dist/InputNumber.d.ts +10 -0
- package/dist/InputNumber.js +19 -0
- package/dist/InputText.d.ts +14 -0
- package/dist/InputText.js +11 -0
- package/dist/MenuItem.d.ts +8 -0
- package/dist/MenuItem.js +18 -0
- package/dist/MultiSelect.d.ts +18 -0
- package/dist/MultiSelect.js +53 -0
- package/dist/Panel.d.ts +11 -0
- package/dist/Panel.js +9 -0
- package/dist/PasswordInput.d.ts +8 -0
- package/dist/PasswordInput.js +10 -0
- package/dist/PopupMenu.d.ts +19 -0
- package/dist/PopupMenu.js +106 -0
- package/dist/RadioButton.d.ts +9 -0
- package/dist/RadioButton.js +12 -0
- package/dist/Select.d.ts +18 -0
- package/dist/Select.js +11 -0
- package/dist/SideMenu.d.ts +5 -0
- package/dist/SideMenu.js +13 -0
- package/dist/SortableList.d.ts +19 -0
- package/dist/SortableList.js +27 -0
- package/dist/Spinner.d.ts +2 -0
- package/dist/Spinner.js +5 -0
- package/dist/SplitButton.d.ts +25 -0
- package/dist/SplitButton.js +39 -0
- package/dist/Switch.d.ts +9 -0
- package/dist/Switch.js +12 -0
- package/dist/Tabs.d.ts +22 -0
- package/dist/Tabs.js +21 -0
- package/dist/Textarea.d.ts +8 -0
- package/dist/Textarea.js +7 -0
- package/dist/ToggleButton.d.ts +11 -0
- package/dist/ToggleButton.js +6 -0
- package/dist/ToggleGroup.d.ts +15 -0
- package/dist/ToggleGroup.js +6 -0
- package/dist/Tooltip.d.ts +10 -0
- package/dist/Tooltip.js +29 -0
- package/dist/Tree.d.ts +22 -0
- package/dist/Tree.js +43 -0
- package/dist/alert-stack.d.ts +20 -0
- package/dist/alert-stack.js +72 -0
- package/dist/index.d.ts +36 -10
- package/dist/index.js +45 -10
- package/dist/paroi-ui-lib-types.d.ts +4 -4
- package/dist/popup-positioning.d.ts +10 -0
- package/dist/popup-positioning.js +160 -0
- package/dist/react-ui-provider.d.ts +15 -0
- package/dist/react-ui-provider.js +22 -0
- package/package.json +16 -2
- package/styles/Accordion.css +46 -0
- package/styles/Alert.css +77 -0
- package/styles/Badge.css +59 -0
- package/styles/Breadcrumb.css +57 -0
- package/styles/Button.css +167 -0
- package/styles/Card.css +28 -0
- package/styles/Checkbox.css +61 -0
- package/styles/Chip.css +35 -0
- package/styles/DataTable.css +176 -0
- package/styles/DateInput.css +59 -0
- package/styles/Dialog.css +88 -0
- package/styles/Inplace.css +44 -0
- package/styles/InputNumber.css +60 -0
- package/styles/InputText.css +99 -0
- package/styles/MenuItem.css +169 -0
- package/styles/MultiSelect.css +143 -0
- package/styles/Panel.css +40 -0
- package/styles/PasswordInput.css +80 -0
- package/styles/PopupMenu.css +37 -0
- package/styles/RadioButton.css +60 -0
- package/styles/Select.css +72 -0
- package/styles/SideMenu.css +7 -0
- package/styles/SortableList.css +32 -0
- package/styles/Spinner.css +30 -0
- package/styles/SplitButton.css +137 -0
- package/styles/Switch.css +60 -0
- package/styles/Tabs.css +94 -0
- package/styles/Textarea.css +66 -0
- package/styles/ToggleButton.css +36 -0
- package/styles/ToggleGroup.css +55 -0
- package/styles/Tooltip.css +20 -0
- package/styles/Tree.css +162 -0
- package/styles/theme/base.css +40 -0
- package/styles/theme/common.css +410 -0
- package/styles/theme/index.css +15 -0
- package/styles/theme/margins.css +119 -0
- package/styles/theme/reset.css +119 -0
- package/styles/theme/tokens.css +226 -0
- package/dist/PuAccordion.d.ts +0 -9
- package/dist/PuButton.d.ts +0 -14
- package/dist/PuButton.jsx +0 -15
- package/dist/PuCheckbox.d.ts +0 -8
- package/dist/PuCheckbox.jsx +0 -13
- package/dist/PuInput.d.ts +0 -10
- package/dist/PuInput.jsx +0 -13
- package/dist/PuMenuItem.d.ts +0 -7
- package/dist/PuMenuItem.jsx +0 -33
- package/dist/PuPopupMenu.d.ts +0 -14
- package/dist/PuPopupMenu.jsx +0 -135
- package/dist/PuSelect.d.ts +0 -17
- package/dist/PuSelect.jsx +0 -24
- package/dist/PuSideMenu.d.ts +0 -4
- package/dist/PuSideMenu.jsx +0 -15
- package/dist/PuSpinner.d.ts +0 -1
- package/dist/PuSpinner.jsx +0 -3
- package/dist/svg-icons.d.ts +0 -5
- package/dist/svg-icons.jsx +0 -30
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import "../styles/Accordion.css";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
import type { MenuOption } from "./paroi-ui-lib-types.js";
|
|
4
|
+
export interface AccordionProps {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
header: MenuOption;
|
|
7
|
+
/** Initial value */
|
|
8
|
+
expanded?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function Accordion({ children, header, expanded }: AccordionProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/Accordion.css";
|
|
1
3
|
import { useAsyncEffect } from "@paroi/use-async-effect";
|
|
2
4
|
import { useRef, useState } from "react";
|
|
3
|
-
import {
|
|
4
|
-
export function
|
|
5
|
+
import { MenuItem } from "./MenuItem.js";
|
|
6
|
+
export function Accordion({ children, header, expanded }) {
|
|
5
7
|
const [isExpanded, setIsExpanded] = useState(expanded ?? false);
|
|
6
8
|
const contentRef = useRef(null);
|
|
7
9
|
useAsyncEffect(async () => {
|
|
@@ -19,12 +21,7 @@ export function PuAccordion({ children, header, expanded }) {
|
|
|
19
21
|
await startTransition(content, isExpanded);
|
|
20
22
|
}
|
|
21
23
|
}, [isExpanded]);
|
|
22
|
-
return (
|
|
23
|
-
<PuMenuItem item={header} expanded={isExpanded} onToggle={setIsExpanded}/>
|
|
24
|
-
<div className="PuAccordion-content initializing" ref={contentRef}>
|
|
25
|
-
{children}
|
|
26
|
-
</div>
|
|
27
|
-
</div>);
|
|
24
|
+
return (_jsxs("div", { className: "PaAccordion", children: [_jsx(MenuItem, { item: header, expanded: isExpanded, onToggle: setIsExpanded }), _jsx("div", { className: "PaAccordion-content initializing", ref: contentRef, children: children })] }));
|
|
28
25
|
}
|
|
29
26
|
function startTransition(content, isOpen) {
|
|
30
27
|
if (isOpen) {
|
package/dist/Alert.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import "../styles/Alert.css";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
export interface AlertProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
severity?: "info" | "success" | "warning" | "error" | "primary";
|
|
6
|
+
title?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
onClose?: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function Alert({ children, severity, title, className, onClose }: AlertProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Alert.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/Alert.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { X } from "lucide-react";
|
|
5
|
+
export function Alert({ children, severity = "info", title, className, onClose }) {
|
|
6
|
+
return (_jsxs("div", { className: clsx("PaAlert", severity, onClose && "dismissible", className), children: [onClose && (_jsx("button", { type: "button", className: "PaAlert-closeBtn", onClick: onClose, "aria-label": "Close", children: _jsx(X, { size: 16 }) })), title && _jsx("div", { className: "PaAlert-title", children: title }), _jsx("div", { className: "PaAlert-content", children: children })] }));
|
|
7
|
+
}
|
package/dist/Badge.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "../styles/Badge.css";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
export interface BadgeProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
severity?: "default" | "primary" | "accent" | "success" | "warning" | "danger" | "info" | "secondary" | "contrast";
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function Badge({ children, severity, className }: BadgeProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Badge.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/Badge.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
export function Badge({ children, severity = "default", className }) {
|
|
5
|
+
return _jsx("span", { className: clsx("PaBadge", severity, className), children: children });
|
|
6
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import "../styles/Breadcrumb.css";
|
|
3
|
+
export interface BreadcrumbItem {
|
|
4
|
+
label: string;
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
url?: string;
|
|
7
|
+
onClick?: () => void;
|
|
8
|
+
}
|
|
9
|
+
export interface BreadcrumbProps {
|
|
10
|
+
items: BreadcrumbItem[];
|
|
11
|
+
separator?: ReactNode;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function Breadcrumb({ items, separator, className, }: BreadcrumbProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import { ChevronRight } from "lucide-react";
|
|
4
|
+
import "../styles/Breadcrumb.css";
|
|
5
|
+
export function Breadcrumb({ items, separator = _jsx(ChevronRight, { size: 12 }), className, }) {
|
|
6
|
+
return (_jsx("nav", { className: clsx("PaBreadcrumb", className), "aria-label": "Breadcrumb", children: items.map((item, index) => {
|
|
7
|
+
const isLast = index === items.length - 1;
|
|
8
|
+
return (_jsxs("div", { className: "PaBreadcrumb-item", children: [isLast ? (_jsxs("span", { className: "PaBreadcrumb-current", children: [item.icon, item.label] })) : item.url ? (_jsxs("a", { href: item.url, className: "PaBreadcrumb-link", children: [item.icon, item.label] })) : item.onClick ? (_jsxs("button", { type: "button", className: "PaBreadcrumb-link", onClick: item.onClick, children: [item.icon, item.label] })) : (_jsxs("span", { className: "PaBreadcrumb-link", children: [item.icon, item.label] })), !isLast && _jsx("span", { className: "PaBreadcrumb-separator", children: separator })] }, `${item.label}:${index}`));
|
|
9
|
+
}) }));
|
|
10
|
+
}
|
package/dist/Button.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import "../styles/Button.css";
|
|
2
|
+
import { type AnchorHTMLAttributes, type ButtonHTMLAttributes, type MouseEvent, type ReactNode, type Ref } from "react";
|
|
3
|
+
export type ButtonProps = ButtonElProps | AsyncButtonElProps | AnchorElProps;
|
|
4
|
+
interface ButtonBaseProps {
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
outlined?: boolean;
|
|
9
|
+
icon?: ReactNode;
|
|
10
|
+
severity?: "primary" | "secondary" | "success" | "info" | "warning" | "danger" | "ghost";
|
|
11
|
+
}
|
|
12
|
+
export interface ButtonElProps extends ButtonBaseProps, Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "onClick"> {
|
|
13
|
+
as?: "button";
|
|
14
|
+
type?: "button" | "submit" | "reset";
|
|
15
|
+
onClick?(e: MouseEvent<HTMLButtonElement>): unknown;
|
|
16
|
+
insideFeedback?: InsideFeedback;
|
|
17
|
+
ref?: Ref<HTMLButtonElement>;
|
|
18
|
+
}
|
|
19
|
+
export interface InsideFeedback {
|
|
20
|
+
label: string;
|
|
21
|
+
autoDismiss?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface AsyncButtonElProps extends ButtonBaseProps, Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "onClick"> {
|
|
24
|
+
as: "async";
|
|
25
|
+
type?: "button";
|
|
26
|
+
onClick: (e: MouseEvent<HTMLButtonElement>) => Promise<unknown>;
|
|
27
|
+
insideFeedback?: InsideFeedback;
|
|
28
|
+
onError?: (error: unknown) => void;
|
|
29
|
+
ref?: Ref<HTMLButtonElement>;
|
|
30
|
+
}
|
|
31
|
+
export interface AnchorElProps extends ButtonBaseProps, Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "children"> {
|
|
32
|
+
as: "a";
|
|
33
|
+
ref?: Ref<HTMLAnchorElement>;
|
|
34
|
+
}
|
|
35
|
+
export declare function Button(props: ButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
export {};
|
package/dist/Button.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/Button.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { Check, Loader2 } from "lucide-react";
|
|
5
|
+
import { useCallback, useState, } from "react";
|
|
6
|
+
import { useReactUIConfig } from "./react-ui-provider.js";
|
|
7
|
+
export function Button(props) {
|
|
8
|
+
const { children, className, disabled, outlined, icon, severity = "primary", ref, ...rest } = props;
|
|
9
|
+
const { autoDismissInsideFeedbackDurationMs } = useReactUIConfig();
|
|
10
|
+
const [loading, setLoading] = useState(false);
|
|
11
|
+
const [showFeedback, setShowFeedback] = useState(false);
|
|
12
|
+
const classNames = clsx("PaBtn", severity, outlined && "outlined", disabled && "disabled", showFeedback && "feedback", className);
|
|
13
|
+
const handleAsyncClick = useCallback(async (e) => {
|
|
14
|
+
if (props.as !== "async")
|
|
15
|
+
return;
|
|
16
|
+
setLoading(true);
|
|
17
|
+
setShowFeedback(false);
|
|
18
|
+
try {
|
|
19
|
+
await props.onClick(e);
|
|
20
|
+
if (props.insideFeedback) {
|
|
21
|
+
setShowFeedback(true);
|
|
22
|
+
if (props.insideFeedback.autoDismiss) {
|
|
23
|
+
setTimeout(() => setShowFeedback(false), autoDismissInsideFeedbackDurationMs);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
props.onError?.(error);
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
setLoading(false);
|
|
32
|
+
}
|
|
33
|
+
}, [
|
|
34
|
+
props.as,
|
|
35
|
+
...(props.as === "async"
|
|
36
|
+
? [
|
|
37
|
+
props.onClick,
|
|
38
|
+
!!props.insideFeedback,
|
|
39
|
+
props.insideFeedback?.autoDismiss,
|
|
40
|
+
props.onError,
|
|
41
|
+
autoDismissInsideFeedbackDurationMs,
|
|
42
|
+
]
|
|
43
|
+
: []),
|
|
44
|
+
]);
|
|
45
|
+
const handleSyncClick = useCallback((e) => {
|
|
46
|
+
if (props.as && props.as !== "button")
|
|
47
|
+
return;
|
|
48
|
+
if (props.onClick) {
|
|
49
|
+
props.onClick(e);
|
|
50
|
+
}
|
|
51
|
+
if (props.insideFeedback) {
|
|
52
|
+
setShowFeedback(true);
|
|
53
|
+
if (props.insideFeedback.autoDismiss) {
|
|
54
|
+
setTimeout(() => setShowFeedback(false), autoDismissInsideFeedbackDurationMs);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}, [
|
|
58
|
+
props.as,
|
|
59
|
+
props.onClick,
|
|
60
|
+
...(!props.as || props.as === "button"
|
|
61
|
+
? [
|
|
62
|
+
!!props.insideFeedback,
|
|
63
|
+
props.insideFeedback?.autoDismiss,
|
|
64
|
+
autoDismissInsideFeedbackDurationMs,
|
|
65
|
+
]
|
|
66
|
+
: []),
|
|
67
|
+
]);
|
|
68
|
+
if (props.as === "a") {
|
|
69
|
+
const { as, ...anchorProps } = rest;
|
|
70
|
+
return (_jsxs("a", { ref: ref, className: classNames, ...anchorProps, children: [icon && _jsx("span", { className: "PaBtn-icon", children: icon }), children] }));
|
|
71
|
+
}
|
|
72
|
+
const { as, onClick, type = "button", insideFeedback, ...buttonProps } = rest;
|
|
73
|
+
return (_jsx("button", { ref: ref, className: classNames, disabled: disabled || loading, onClick: as === "async" ? handleAsyncClick : handleSyncClick, type: type, ...buttonProps, children: loading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 16, className: "PaBtn-spinner" }), children] })) : showFeedback && insideFeedback ? (_jsxs(_Fragment, { children: [_jsx(Check, { size: 16, className: "PaBtn-feedbackIcon" }), insideFeedback.label] })) : (_jsxs(_Fragment, { children: [icon && _jsx("span", { className: "PaBtn-icon", children: icon }), children] })) }));
|
|
74
|
+
}
|
package/dist/Card.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import "../styles/Card.css";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
export interface CardProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
header?: ReactNode;
|
|
6
|
+
title?: string;
|
|
7
|
+
subtitle?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function Card({ children, header, title, subtitle, className }: CardProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Card.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/Card.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
export function Card({ children, header, title, subtitle, className }) {
|
|
5
|
+
const hasHeader = header || title || subtitle;
|
|
6
|
+
return (_jsxs("div", { className: clsx("PaCard", className), children: [hasHeader && (_jsx("div", { className: "PaCard-header", children: header || (_jsxs(_Fragment, { children: [title && _jsx("h3", { className: "PaCard-title", children: title }), subtitle && _jsx("p", { className: "PaCard-subtitle", children: subtitle })] })) })), children] }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "../styles/Checkbox.css";
|
|
2
|
+
import type { InputHTMLAttributes } from "react";
|
|
3
|
+
export interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "type"> {
|
|
4
|
+
checked: boolean;
|
|
5
|
+
onChange: (checked: boolean) => void;
|
|
6
|
+
label?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function Checkbox({ checked, onChange, label, className, ...rest }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Checkbox.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/Checkbox.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
export function Checkbox({ checked, onChange, label, className, ...rest }) {
|
|
5
|
+
const handleChange = (e) => {
|
|
6
|
+
onChange(e.target.checked);
|
|
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 }));
|
|
12
|
+
}
|
package/dist/Chip.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "../styles/Chip.css";
|
|
2
|
+
export interface ChipProps {
|
|
3
|
+
label: string;
|
|
4
|
+
onRemove?: () => void;
|
|
5
|
+
className?: string;
|
|
6
|
+
removable?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function Chip({ label, onRemove, className, removable }: ChipProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Chip.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import { X } from "lucide-react";
|
|
4
|
+
import "../styles/Chip.css";
|
|
5
|
+
export function Chip({ label, onRemove, className, removable = true }) {
|
|
6
|
+
return (_jsxs("span", { className: clsx("PaChip", className), children: [_jsx("span", { className: "PaChip-label", children: label }), removable && onRemove && (_jsx("button", { type: "button", className: "PaChip-remove", onClick: onRemove, "aria-label": `Remove ${label}`, children: _jsx(X, { size: 12 }) }))] }));
|
|
7
|
+
}
|
package/dist/Column.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
|
+
export interface ColumnProps<T = unknown> {
|
|
3
|
+
field?: keyof T & string;
|
|
4
|
+
header?: string;
|
|
5
|
+
body?: (rowData: T) => ReactNode;
|
|
6
|
+
style?: CSSProperties;
|
|
7
|
+
sortable?: boolean;
|
|
8
|
+
bodyClassName?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Render-less component for column definition.
|
|
12
|
+
* Used for configuration only - does not render anything.
|
|
13
|
+
*/
|
|
14
|
+
export declare function Column<T>(_props: ColumnProps<T>): null;
|
package/dist/Column.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import "../styles/DataTable.css";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
export interface DataTableProps<T> {
|
|
4
|
+
value: T[];
|
|
5
|
+
dataKey: keyof T & string;
|
|
6
|
+
size?: "small" | "normal";
|
|
7
|
+
loading?: boolean;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
emptyMessage?: string;
|
|
11
|
+
paginator?: boolean;
|
|
12
|
+
rows?: number;
|
|
13
|
+
totalRecords?: number;
|
|
14
|
+
first?: number;
|
|
15
|
+
onPage?: (event: {
|
|
16
|
+
first: number;
|
|
17
|
+
rows: number;
|
|
18
|
+
}) => void;
|
|
19
|
+
rowsPerPageOptions?: number[];
|
|
20
|
+
sortField?: string;
|
|
21
|
+
sortOrder?: 1 | -1;
|
|
22
|
+
onSort?: (event: {
|
|
23
|
+
field: string;
|
|
24
|
+
order: 1 | -1;
|
|
25
|
+
}) => void;
|
|
26
|
+
onRowClick?: (row: T, event: React.MouseEvent) => void;
|
|
27
|
+
rowClassName?: (row: T) => string | undefined;
|
|
28
|
+
totalLabel?: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function DataTable<T extends object>({ value, dataKey, size, loading, children, className, emptyMessage, paginator, rows, totalRecords, first, onPage, rowsPerPageOptions, sortField, sortOrder, onSort, onRowClick, rowClassName, totalLabel, }: DataTableProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/DataTable.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { ArrowDown, ArrowUp, ChevronLeft, ChevronRight, ChevronsUpDown } from "lucide-react";
|
|
5
|
+
import { Children, isValidElement } from "react";
|
|
6
|
+
import { Select } from "./Select.js";
|
|
7
|
+
import { Spinner } from "./Spinner.js";
|
|
8
|
+
export function DataTable({ value, dataKey, size, loading, children, className, emptyMessage = "No data available", paginator, rows = 10, totalRecords, first = 0, onPage, rowsPerPageOptions, sortField, sortOrder, onSort, onRowClick, rowClassName, totalLabel, }) {
|
|
9
|
+
// Extract column definitions from children
|
|
10
|
+
const columns = [];
|
|
11
|
+
Children.forEach(children, (child) => {
|
|
12
|
+
if (isValidElement(child) && child.props) {
|
|
13
|
+
columns.push(child.props);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
const total = totalRecords ?? value.length;
|
|
17
|
+
const pageCount = Math.ceil(total / rows);
|
|
18
|
+
const currentPage = Math.floor(first / rows) + 1;
|
|
19
|
+
const handleSort = (field) => {
|
|
20
|
+
if (!field || !onSort)
|
|
21
|
+
return;
|
|
22
|
+
const newOrder = sortField === field && sortOrder === 1 ? -1 : 1;
|
|
23
|
+
onSort({ field, order: newOrder });
|
|
24
|
+
};
|
|
25
|
+
return (_jsxs("div", { className: clsx("PaDataTable-wrapper", loading && "loading"), children: [loading && (_jsx("div", { className: "PaDataTable-overlay", children: _jsx(Spinner, {}) })), _jsx("div", { className: "PaDataTable-scrollable", children: _jsxs("table", { className: clsx("PaDataTable", size, className), children: [_jsx("thead", { className: "PaDataTable-header", children: _jsx("tr", { children: columns.map((col, i) => (_jsx("th", { className: clsx("PaDataTable-headerCell", col.sortable && "sortable"), style: col.style, onClick: col.sortable ? () => handleSort(col.field) : undefined, tabIndex: 0, children: _jsxs("span", { className: "PaDataTable-headerContent", children: [col.header, col.sortable && (_jsx("span", { className: "PaDataTable-sortIcon", children: col.field === sortField ? (sortOrder === 1 ? (_jsx(ArrowDown, { size: 14 })) : (_jsx(ArrowUp, { size: 14 }))) : (_jsx(ChevronsUpDown, { size: 14 })) }))] }) }, col.field ?? i))) }) }), _jsx("tbody", { children: value.length === 0 ? (_jsx("tr", { className: "PaDataTable-emptyRow", children: _jsx("td", { colSpan: columns.length, className: "PaDataTable-emptyCell", children: emptyMessage }) })) : (value.map((row) => (_jsx("tr", { className: clsx("PaDataTable-row", onRowClick && "clickable", rowClassName?.(row)), onClick: onRowClick ? (e) => onRowClick(row, e) : undefined, children: columns.map((col, i) => (_jsx("td", { className: clsx("PaDataTable-cell", col.bodyClassName), style: col.style, children: col.body ? col.body(row) : col.field ? String(row[col.field] ?? "") : null }, col.field ?? i))) }, String(row[dataKey]))))) })] }) }), paginator && onPage && pageCount > 0 && (_jsxs("div", { className: "PaDataTable-footer", children: [_jsxs("span", { className: "PaDataTable-totalCount", children: [total, " ", totalLabel ?? "items"] }), _jsxs("div", { className: "PaDataTable-pagination", children: [_jsx("button", { type: "button", className: "PaDataTable-paginationBtn", disabled: currentPage <= 1, onClick: () => onPage({ first: first - rows, rows }), children: _jsx(ChevronLeft, { size: 16 }) }), _jsxs("span", { className: "PaDataTable-paginationText", children: ["Page ", currentPage, " of ", pageCount] }), _jsx("button", { type: "button", className: "PaDataTable-paginationBtn", disabled: currentPage >= pageCount, onClick: () => onPage({ first: first + rows, rows }), children: _jsx(ChevronRight, { size: 16 }) }), rowsPerPageOptions && rowsPerPageOptions.length > 0 && (_jsx(Select, { className: "PaDataTable-rowsPerPage", value: String(rows), options: rowsPerPageOptions.map((n) => ({ label: String(n), value: String(n) })), onChange: (val) => onPage({ first: 0, rows: Number(val) }) }))] })] }))] }));
|
|
26
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "../styles/DateInput.css";
|
|
2
|
+
import type { InputHTMLAttributes, Ref } from "react";
|
|
3
|
+
export interface DateInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
|
|
4
|
+
type: "date" | "datetime-local" | "time";
|
|
5
|
+
label?: string;
|
|
6
|
+
error?: string;
|
|
7
|
+
ref?: Ref<HTMLInputElement>;
|
|
8
|
+
}
|
|
9
|
+
export declare function DateInput({ className, label, error, type, ref, ...props }: DateInputProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/DateInput.css";
|
|
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 })] }));
|
|
7
|
+
}
|
package/dist/Dialog.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import "../styles/Dialog.css";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
export interface DialogProps {
|
|
4
|
+
visible: boolean;
|
|
5
|
+
onHide: () => void;
|
|
6
|
+
header?: ReactNode;
|
|
7
|
+
footer?: ReactNode;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
closable?: boolean;
|
|
11
|
+
size?: "sm" | "md" | "lg";
|
|
12
|
+
}
|
|
13
|
+
export declare function Dialog({ visible, onHide, header, footer, children, className, closable, size, }: DialogProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Dialog.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/Dialog.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { X } from "lucide-react";
|
|
5
|
+
import { useEffect, useRef } from "react";
|
|
6
|
+
export function Dialog({ visible, onHide, header, footer, children, className, closable = true, size, }) {
|
|
7
|
+
const dialogRef = useRef(null);
|
|
8
|
+
// Control open/close with native methods
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const dialog = dialogRef.current;
|
|
11
|
+
if (!dialog)
|
|
12
|
+
return;
|
|
13
|
+
if (visible) {
|
|
14
|
+
if (!dialog.open) {
|
|
15
|
+
dialog.showModal();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
if (dialog.open) {
|
|
20
|
+
dialog.close();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}, [visible]);
|
|
24
|
+
// Handle ESC key via native cancel event
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const dialog = dialogRef.current;
|
|
27
|
+
if (!dialog)
|
|
28
|
+
return;
|
|
29
|
+
const handleCancel = (e) => {
|
|
30
|
+
e.preventDefault(); // Prevent default close
|
|
31
|
+
if (closable) {
|
|
32
|
+
onHide();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
dialog.addEventListener("cancel", handleCancel);
|
|
36
|
+
return () => dialog.removeEventListener("cancel", handleCancel);
|
|
37
|
+
}, [closable, onHide]);
|
|
38
|
+
// Prevent body scroll when open
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (visible) {
|
|
41
|
+
document.body.style.overflow = "hidden";
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
document.body.style.overflow = "";
|
|
45
|
+
}
|
|
46
|
+
return () => {
|
|
47
|
+
document.body.style.overflow = "";
|
|
48
|
+
};
|
|
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 })] }));
|
|
51
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import "../styles/Inplace.css";
|
|
3
|
+
export interface InplaceProps {
|
|
4
|
+
display: ReactNode;
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
active?: boolean;
|
|
7
|
+
onOpen?: () => void;
|
|
8
|
+
onClose?: () => void;
|
|
9
|
+
className?: string;
|
|
10
|
+
closable?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function Inplace({ display, children, active, onOpen, onClose, className, closable, }: InplaceProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Inplace.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import "../styles/Inplace.css";
|
|
4
|
+
export function Inplace({ display, children, active = false, onOpen, onClose, className, closable = true, }) {
|
|
5
|
+
if (!active) {
|
|
6
|
+
return (
|
|
7
|
+
// biome-ignore lint/a11y/useSemanticElements: custom behavior
|
|
8
|
+
_jsx("div", { className: clsx("PaInplace", "display", className), onClick: onOpen, onKeyDown: (e) => {
|
|
9
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
10
|
+
e.preventDefault();
|
|
11
|
+
onOpen?.();
|
|
12
|
+
}
|
|
13
|
+
}, tabIndex: 0, role: "button", children: display }));
|
|
14
|
+
}
|
|
15
|
+
return (_jsxs("div", { className: clsx("PaInplace", "active", className), children: [_jsx("div", { className: "PaInplace-content", children: children }), closable && onClose && (_jsx("button", { type: "button", className: "PaInplace-close", onClick: onClose, children: "Done" }))] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { InputHTMLAttributes, Ref } from "react";
|
|
2
|
+
import "../styles/InputNumber.css";
|
|
3
|
+
export interface InputNumberProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {
|
|
4
|
+
value: number | undefined;
|
|
5
|
+
onChange: (value: number | undefined) => void;
|
|
6
|
+
label?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
ref?: Ref<HTMLInputElement>;
|
|
9
|
+
}
|
|
10
|
+
export declare function InputNumber({ className, label, error, value, onChange, min, max, step, ref, ...props }: InputNumberProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import "../styles/InputNumber.css";
|
|
4
|
+
export function InputNumber({ className, label, error, value, onChange, min, max, step, ref, ...props }) {
|
|
5
|
+
const handleChange = (e) => {
|
|
6
|
+
const val = e.target.value;
|
|
7
|
+
if (val === "") {
|
|
8
|
+
onChange(undefined);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
const num = Number(val);
|
|
12
|
+
if (!Number.isNaN(num)) {
|
|
13
|
+
onChange(num);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
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 })] }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { InputHTMLAttributes, ReactNode } from "react";
|
|
2
|
+
import "../styles/InputText.css";
|
|
3
|
+
export interface InputTextProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "onChange"> {
|
|
4
|
+
value: string;
|
|
5
|
+
onChange: (value: string) => void;
|
|
6
|
+
label?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
fullWidth?: boolean;
|
|
10
|
+
endElement?: ReactNode;
|
|
11
|
+
icon?: ReactNode;
|
|
12
|
+
iconPosition?: "left" | "right";
|
|
13
|
+
}
|
|
14
|
+
export declare function InputText({ value, onChange, label, error, className, fullWidth, endElement, icon, iconPosition, ...rest }: InputTextProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import "../styles/InputText.css";
|
|
4
|
+
export function InputText({ value, onChange, label, error, className, fullWidth = false, endElement, icon, iconPosition = "left", ...rest }) {
|
|
5
|
+
const handleChange = (e) => {
|
|
6
|
+
onChange(e.target.value);
|
|
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 })] }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "../styles/MenuItem.css";
|
|
2
|
+
import type { MenuOption } from "./paroi-ui-lib-types.js";
|
|
3
|
+
export interface MenuItemProps {
|
|
4
|
+
item: MenuOption;
|
|
5
|
+
expanded?: boolean;
|
|
6
|
+
onToggle?: (expanded: boolean) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function MenuItem({ item, expanded, onToggle }: MenuItemProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/MenuItem.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/MenuItem.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { ChevronDown, ChevronRight } from "lucide-react";
|
|
5
|
+
import { PopupMenu } from "./PopupMenu.js";
|
|
6
|
+
export function MenuItem({ item, expanded, onToggle }) {
|
|
7
|
+
let { key: id, label, icon, url, command, popupMenu, className, style, active, disabled } = item;
|
|
8
|
+
if (disabled) {
|
|
9
|
+
url = undefined;
|
|
10
|
+
command = undefined;
|
|
11
|
+
}
|
|
12
|
+
return (_jsxs("div", { className: clsx("PaMenuItem", active && "active", disabled && "disabled", className), style: style, children: [expanded !== undefined && onToggle ? (_jsx("button", { className: "PaMenuItem-left toggle", onClick: () => onToggle(!expanded), type: "button", children: expanded ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronRight, { size: 14 }) })) : icon ? (_jsx("div", { className: "PaMenuItem-left icon", children: icon })) : undefined, url ? (_jsx("a", { className: "PaMenuItem-label", href: url, onClick: url && command
|
|
13
|
+
? (ev) => {
|
|
14
|
+
ev.preventDefault();
|
|
15
|
+
command?.();
|
|
16
|
+
}
|
|
17
|
+
: undefined, children: label })) : command ? (_jsx("button", { className: "PaMenuItem-label", onClick: command, type: "button", children: label })) : (_jsx("span", { className: "PaMenuItem-label", children: label })), popupMenu && _jsx(PopupMenu, { className: "PaMenuItem-popup", items: popupMenu })] }, id));
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import "../styles/MultiSelect.css";
|
|
2
|
+
export interface MultiSelectOption {
|
|
3
|
+
value: string;
|
|
4
|
+
label: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface MultiSelectProps {
|
|
8
|
+
value: string[];
|
|
9
|
+
onChange: (value: string[]) => void;
|
|
10
|
+
options: MultiSelectOption[];
|
|
11
|
+
label?: string;
|
|
12
|
+
error?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
position?: "auto" | "top" | "bottom";
|
|
17
|
+
}
|
|
18
|
+
export declare function MultiSelect({ value, onChange, options, label, error, className, placeholder, disabled, position, }: MultiSelectProps): import("react/jsx-runtime").JSX.Element;
|