@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,53 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/MultiSelect.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { ChevronDown, X } from "lucide-react";
|
|
5
|
+
import { useEffect, useRef, useState } from "react";
|
|
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, }) {
|
|
9
|
+
const [open, setOpen] = useState(false);
|
|
10
|
+
const containerRef = useRef(null);
|
|
11
|
+
const dropdownRef = useRef(null);
|
|
12
|
+
const dropdownId = useRef(`pa-multiselect-${Math.random().toString(36).substring(2, 9)}`);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const dropdown = dropdownRef.current;
|
|
15
|
+
const container = containerRef.current;
|
|
16
|
+
if (!dropdown || !container)
|
|
17
|
+
return;
|
|
18
|
+
const handleToggle = (e) => {
|
|
19
|
+
setOpen(e.newState === "open");
|
|
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]);
|
|
31
|
+
const toggleOption = (optionValue) => {
|
|
32
|
+
if (value.includes(optionValue)) {
|
|
33
|
+
onChange(value.filter((v) => v !== optionValue));
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
onChange([...value, optionValue]);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const removeValue = (optionValue) => {
|
|
40
|
+
onChange(value.filter((v) => v !== optionValue));
|
|
41
|
+
};
|
|
42
|
+
const selectedOptions = options.filter((opt) => value.includes(opt.value));
|
|
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) {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
dropdownRef.current?.togglePopover();
|
|
47
|
+
}
|
|
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) => {
|
|
49
|
+
e.stopPropagation();
|
|
50
|
+
removeValue(opt.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))) })] }));
|
|
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 })] }));
|
|
53
|
+
}
|
package/dist/Panel.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import "../styles/Panel.css";
|
|
3
|
+
export interface PanelProps {
|
|
4
|
+
header: ReactNode;
|
|
5
|
+
collapsed?: boolean;
|
|
6
|
+
onToggle?: () => void;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
collapsible?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function Panel({ header, collapsed, onToggle, children, className, collapsible, }: PanelProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Panel.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import { ChevronDown, ChevronRight } from "lucide-react";
|
|
4
|
+
import "../styles/Panel.css";
|
|
5
|
+
export function Panel({ header, collapsed = false, onToggle, children, className, collapsible = true, }) {
|
|
6
|
+
const isCollapsible = collapsible && onToggle;
|
|
7
|
+
const headerContent = (_jsxs(_Fragment, { children: [isCollapsible && (_jsx("span", { className: "PaPanel-chevron", children: collapsed ? _jsx(ChevronRight, { size: 16 }) : _jsx(ChevronDown, { size: 16 }) })), _jsx("span", { className: "PaPanel-title", children: header })] }));
|
|
8
|
+
return (_jsxs("div", { className: clsx("PaPanel", collapsed && "collapsed", className), children: [isCollapsible ? (_jsx("button", { type: "button", className: clsx("PaPanel-header", "collapsible"), onClick: onToggle, "aria-expanded": !collapsed, children: headerContent })) : (_jsx("div", { className: "PaPanel-header", children: headerContent })), !collapsed && _jsx("div", { className: "PaPanel-content", children: children })] }));
|
|
9
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "../styles/PasswordInput.css";
|
|
2
|
+
import { type InputHTMLAttributes, type Ref } from "react";
|
|
3
|
+
export interface PasswordInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
|
|
4
|
+
label?: string;
|
|
5
|
+
error?: string;
|
|
6
|
+
ref?: Ref<HTMLInputElement>;
|
|
7
|
+
}
|
|
8
|
+
export declare function PasswordInput({ className, label, error, ref, ...props }: PasswordInputProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/PasswordInput.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { Eye, EyeOff } from "lucide-react";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
export function PasswordInput({ className, label, error, ref, ...props }) {
|
|
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 })] }));
|
|
10
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import "../styles/PopupMenu.css";
|
|
2
|
+
import { type MouseEvent, type ReactNode, type Ref } from "react";
|
|
3
|
+
import type { MenuNode } from "./paroi-ui-lib-types.js";
|
|
4
|
+
export interface PopupMenuProps {
|
|
5
|
+
items: MenuNode[];
|
|
6
|
+
className?: string;
|
|
7
|
+
id?: string;
|
|
8
|
+
/** Position of the popup relative to the trigger. Default is 'auto'. */
|
|
9
|
+
position?: "auto" | "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
|
|
10
|
+
/** Optional custom trigger element. If provided, it will be used instead of the default button. */
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
ref?: Ref<PopupMenuRef>;
|
|
13
|
+
}
|
|
14
|
+
export interface PopupMenuRef {
|
|
15
|
+
toggle: (event: MouseEvent) => void;
|
|
16
|
+
show: (event: MouseEvent) => void;
|
|
17
|
+
hide: () => void;
|
|
18
|
+
}
|
|
19
|
+
export declare function PopupMenu({ items, className, id, position, children, ref, }: PopupMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/PopupMenu.css";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { ChevronRight, ChevronsDown } from "lucide-react";
|
|
5
|
+
import { cloneElement, isValidElement, useEffect, useImperativeHandle, useRef, } from "react";
|
|
6
|
+
import { Button } from "./Button.js";
|
|
7
|
+
import { MenuItem } from "./MenuItem.js";
|
|
8
|
+
import { computePopupPosition, setupPopoverPositioning } from "./popup-positioning.js";
|
|
9
|
+
const isPopoverSupported = typeof HTMLElement !== "undefined" && "showPopover" in HTMLElement.prototype;
|
|
10
|
+
if (!isPopoverSupported) {
|
|
11
|
+
console?.error("PopupMenu: Popover API is not supported in this browser.");
|
|
12
|
+
}
|
|
13
|
+
let seq = 0;
|
|
14
|
+
export function PopupMenu({ items, className, id, position = "auto", children, ref, }) {
|
|
15
|
+
const menuRef = useRef(null);
|
|
16
|
+
const triggerRef = useRef(null);
|
|
17
|
+
const menuIdRef = useRef(undefined);
|
|
18
|
+
if (menuIdRef.current === undefined) {
|
|
19
|
+
menuIdRef.current = id ?? `pa-popup-menu-${++seq}`;
|
|
20
|
+
}
|
|
21
|
+
const toggle = (_ev) => {
|
|
22
|
+
if (menuRef.current) {
|
|
23
|
+
menuRef.current.togglePopover();
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const show = (_ev) => {
|
|
27
|
+
if (menuRef.current) {
|
|
28
|
+
menuRef.current.showPopover();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const hide = () => {
|
|
32
|
+
if (menuRef.current) {
|
|
33
|
+
menuRef.current.hidePopover();
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
useImperativeHandle(ref, () => ({
|
|
37
|
+
toggle,
|
|
38
|
+
show,
|
|
39
|
+
hide,
|
|
40
|
+
}));
|
|
41
|
+
// Position popover when it opens
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const menuEl = menuRef.current;
|
|
44
|
+
const triggerEl = triggerRef.current;
|
|
45
|
+
if (!menuEl || !triggerEl)
|
|
46
|
+
return;
|
|
47
|
+
return setupPopoverPositioning(menuEl, () => computePopupPosition(triggerEl, menuEl, position, "corner"));
|
|
48
|
+
}, [position]);
|
|
49
|
+
const triggerProps = {
|
|
50
|
+
popoverTarget: menuIdRef.current,
|
|
51
|
+
popoverTargetAction: "toggle",
|
|
52
|
+
};
|
|
53
|
+
// Render custom trigger if provided, otherwise use default button
|
|
54
|
+
const renderTrigger = () => {
|
|
55
|
+
if (children && isValidElement(children)) {
|
|
56
|
+
return cloneElement(children, {
|
|
57
|
+
ref: triggerRef,
|
|
58
|
+
"aria-controls": menuIdRef.current,
|
|
59
|
+
"aria-haspopup": true,
|
|
60
|
+
...triggerProps,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return (_jsx(Button, { ref: triggerRef, className: clsx(className, "borderless"), outlined: true, severity: "secondary", "aria-label": "unfold", "aria-controls": menuIdRef.current, "aria-haspopup": true, ...triggerProps, children: _jsx(ChevronsDown, { size: 16 }) }));
|
|
64
|
+
};
|
|
65
|
+
return (_jsxs(_Fragment, { children: [renderTrigger(), _jsx("div", { className: "PaPopupMenu", ref: menuRef, id: menuIdRef.current, popover: "auto", children: _jsx("div", { className: "PaPopupMenu-content", children: items.map((item) => (_jsx(PopupMenuItemWrapper, { item: item, onHide: hide }, item.key))) }) })] }));
|
|
66
|
+
}
|
|
67
|
+
function PopupMenuItemWrapper({ item, onHide }) {
|
|
68
|
+
const subMenuRef = useRef(null);
|
|
69
|
+
const subMenuId = useRef(`pa-submenu-${item.key}-${Math.random().toString(36).substring(2, 9)}`);
|
|
70
|
+
// For items with submenu, override the command to toggle the submenu
|
|
71
|
+
const itemWithSubmenuHandling = { ...item };
|
|
72
|
+
if (item.subMenu && item.subMenu.length > 0) {
|
|
73
|
+
// Create submenu trigger icon
|
|
74
|
+
const originalIcon = item.icon;
|
|
75
|
+
itemWithSubmenuHandling.icon = originalIcon || _jsx(ChevronRight, { size: 14 });
|
|
76
|
+
// Create a command that opens the submenu
|
|
77
|
+
const originalCommand = item.command;
|
|
78
|
+
itemWithSubmenuHandling.command = () => {
|
|
79
|
+
if (originalCommand) {
|
|
80
|
+
originalCommand();
|
|
81
|
+
}
|
|
82
|
+
// Will be handled by popovertarget attribute
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// For regular items, add onHide to the command
|
|
87
|
+
const originalCommand = item.command;
|
|
88
|
+
itemWithSubmenuHandling.command = () => {
|
|
89
|
+
if (originalCommand) {
|
|
90
|
+
originalCommand();
|
|
91
|
+
}
|
|
92
|
+
onHide();
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// Handle submenu positioning with Popover API
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
const subMenuEl = subMenuRef.current;
|
|
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"));
|
|
104
|
+
}, [item.subMenu]);
|
|
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))) }))] }));
|
|
106
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { InputHTMLAttributes } from "react";
|
|
2
|
+
import "../styles/RadioButton.css";
|
|
3
|
+
export interface RadioButtonProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {
|
|
4
|
+
checked: boolean;
|
|
5
|
+
onChange: (checked: boolean) => void;
|
|
6
|
+
label?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function RadioButton({ checked, onChange, label, className, ...rest }: RadioButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import "../styles/RadioButton.css";
|
|
4
|
+
export function RadioButton({ checked, onChange, label, className, ...rest }) {
|
|
5
|
+
const handleChange = (e) => {
|
|
6
|
+
onChange(e.target.checked);
|
|
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 })] }));
|
|
10
|
+
}
|
|
11
|
+
return (_jsx("input", { className: clsx("PaRadioButton-input", className), type: "radio", checked: checked, onChange: handleChange, ...rest }));
|
|
12
|
+
}
|
package/dist/Select.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import "../styles/Select.css";
|
|
2
|
+
import type { SelectHTMLAttributes } from "react";
|
|
3
|
+
export interface SelectOption {
|
|
4
|
+
value: string;
|
|
5
|
+
label: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "onChange"> {
|
|
9
|
+
value: string;
|
|
10
|
+
onChange: (value: string) => void;
|
|
11
|
+
options: SelectOption[];
|
|
12
|
+
label?: string;
|
|
13
|
+
error?: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
fullWidth?: boolean;
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function Select({ value, onChange, options, label, error, className, fullWidth, placeholder, ...rest }: SelectProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Select.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/Select.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { ChevronDown } from "lucide-react";
|
|
5
|
+
export function Select({ value, onChange, options, label, error, className, fullWidth = false, placeholder, ...rest }) {
|
|
6
|
+
const handleChange = (e) => {
|
|
7
|
+
onChange(e.target.value);
|
|
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 })] }));
|
|
11
|
+
}
|
package/dist/SideMenu.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/SideMenu.css";
|
|
3
|
+
import { Accordion } from "./Accordion.js";
|
|
4
|
+
import { MenuItem } from "./MenuItem.js";
|
|
5
|
+
export function SideMenu({ menu }) {
|
|
6
|
+
return (_jsx(_Fragment, { children: menu.map((child) => (_jsx(AccordionOrMenuItem, { item: child }, child.key))) }));
|
|
7
|
+
}
|
|
8
|
+
function AccordionOrMenuItem({ item }) {
|
|
9
|
+
if (item.subMenu) {
|
|
10
|
+
return (_jsx(Accordion, { header: item, expanded: item.expanded, children: item.subMenu.map((child) => (_jsx(AccordionOrMenuItem, { item: child }, child.key))) }));
|
|
11
|
+
}
|
|
12
|
+
return _jsx(MenuItem, { item: item });
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import "../styles/SortableList.css";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
export interface SortableListProps<T> {
|
|
4
|
+
/** Items to display and reorder */
|
|
5
|
+
items: T[];
|
|
6
|
+
/** Callback when items are reordered */
|
|
7
|
+
onReorder: (items: T[]) => void;
|
|
8
|
+
/** Field name used as unique key for each item */
|
|
9
|
+
keyField: keyof T & string;
|
|
10
|
+
/** Render function for each item */
|
|
11
|
+
renderItem: (item: T, index: number) => ReactNode;
|
|
12
|
+
/** Layout direction */
|
|
13
|
+
direction?: "row" | "column";
|
|
14
|
+
/** Container class name */
|
|
15
|
+
className?: string;
|
|
16
|
+
/** Class name applied to each item wrapper */
|
|
17
|
+
itemClassName?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function SortableList<T extends object>({ items, onReorder, keyField, renderItem, direction, className, itemClassName, }: SortableListProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/SortableList.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import { ReactSortable } from "react-sortablejs";
|
|
6
|
+
export function SortableList({ items, onReorder, keyField, renderItem, direction = "column", className, itemClassName, }) {
|
|
7
|
+
const [sortableItems, setSortableItems] = useState(() => items.map((item) => ({
|
|
8
|
+
id: String(item[keyField]),
|
|
9
|
+
data: item,
|
|
10
|
+
})));
|
|
11
|
+
// Sync external items to internal state
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
setSortableItems(items.map((item) => ({
|
|
14
|
+
id: String(item[keyField]),
|
|
15
|
+
data: item,
|
|
16
|
+
})));
|
|
17
|
+
}, [items, keyField]);
|
|
18
|
+
const handleSetList = (newList) => {
|
|
19
|
+
// Ignore empty list updates from ReactSortable during initialization
|
|
20
|
+
if (newList.length === 0 && sortableItems.length > 0) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
setSortableItems(newList);
|
|
24
|
+
onReorder(newList.map((item) => item.data));
|
|
25
|
+
};
|
|
26
|
+
return (_jsx(ReactSortable, { tag: "div", className: clsx("PaSortableList", direction, className), list: sortableItems, setList: handleSetList, children: sortableItems.map((item, index) => (_jsx("div", { className: clsx("PaSortableList-item", itemClassName), children: renderItem(item.data, index) }, item.id))) }));
|
|
27
|
+
}
|
package/dist/Spinner.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import "../styles/SplitButton.css";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
import { type AnchorElProps, type AsyncButtonElProps, type ButtonElProps } from "./Button.js";
|
|
4
|
+
export type SplitButtonProps = SplitButtonElProps | SplitAsyncButtonElProps | SplitAnchorElProps;
|
|
5
|
+
export interface SplitButtonElProps extends SplitButtonBaseProps, Omit<ButtonElProps, "className"> {
|
|
6
|
+
}
|
|
7
|
+
export interface SplitAsyncButtonElProps extends SplitButtonBaseProps, Omit<AsyncButtonElProps, "className"> {
|
|
8
|
+
}
|
|
9
|
+
export interface SplitAnchorElProps extends SplitButtonBaseProps, Omit<AnchorElProps, "className"> {
|
|
10
|
+
}
|
|
11
|
+
interface SplitButtonBaseProps {
|
|
12
|
+
items: SplitButtonItem[];
|
|
13
|
+
className?: string;
|
|
14
|
+
position?: "auto" | "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
|
|
15
|
+
}
|
|
16
|
+
export interface SplitButtonItem {
|
|
17
|
+
label: string;
|
|
18
|
+
icon?: ReactNode;
|
|
19
|
+
/** can be async */
|
|
20
|
+
command: () => unknown;
|
|
21
|
+
danger?: boolean;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare function SplitButton(props: SplitButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/SplitButton.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { ChevronDown } from "lucide-react";
|
|
5
|
+
import { useEffect, useRef } from "react";
|
|
6
|
+
import { Button, } from "./Button.js";
|
|
7
|
+
import { computePopupPosition, setupPopoverPositioning } from "./popup-positioning.js";
|
|
8
|
+
export function SplitButton(props) {
|
|
9
|
+
const { items, className, position, ...buttonProps } = props;
|
|
10
|
+
const containerRef = useRef(null);
|
|
11
|
+
const menuRef = useRef(null);
|
|
12
|
+
const menuId = useRef(`pa-splitbtn-menu-${Math.random().toString(36).substring(2, 9)}`);
|
|
13
|
+
const severity = props.severity ?? "primary";
|
|
14
|
+
const disabled = props.disabled;
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const menu = menuRef.current;
|
|
17
|
+
const container = containerRef.current;
|
|
18
|
+
if (!menu || !container)
|
|
19
|
+
return;
|
|
20
|
+
return setupPopoverPositioning(menu, () => computePopupPosition(container, menu, position ?? "auto", "corner"));
|
|
21
|
+
}, [position]);
|
|
22
|
+
const handleItemClick = async (item) => {
|
|
23
|
+
try {
|
|
24
|
+
await item.command();
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (props.as === "async" && props.onError) {
|
|
28
|
+
props.onError(error);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
console.error("Error executing SplitButton item command:", error);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
menuRef.current?.hidePopover();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
return (_jsxs("div", { ref: containerRef, className: clsx("PaSplitBtn", severity, disabled && "disabled", className), children: [_jsx(Button, { ...buttonProps, className: "PaSplitBtn-main" }), _jsx("button", { type: "button", className: "PaSplitBtn-toggle", popoverTarget: menuId.current, popoverTargetAction: "toggle", "aria-haspopup": "menu", children: _jsx(ChevronDown, { className: "PaSplitBtn-toggleIcon" }) }), _jsx("div", { ref: menuRef, id: menuId.current, className: "PaSplitBtn-menu", role: "menu", popover: "auto", children: items.map((item) => (_jsxs("button", { type: "button", className: clsx("PaSplitBtn-menuItem", item.danger && "danger", item.disabled && "disabled"), onClick: () => void handleItemClick(item), role: "menuitem", disabled: item.disabled, children: [item.icon && _jsx("span", { className: "PaSplitBtn-menuIcon", children: item.icon }), item.label] }, item.label))) })] }));
|
|
39
|
+
}
|
package/dist/Switch.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { InputHTMLAttributes } from "react";
|
|
2
|
+
import "../styles/Switch.css";
|
|
3
|
+
export interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {
|
|
4
|
+
checked: boolean;
|
|
5
|
+
onChange: (checked: boolean) => void;
|
|
6
|
+
label?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function Switch({ checked, onChange, label, className, ...rest }: SwitchProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Switch.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import "../styles/Switch.css";
|
|
4
|
+
export function Switch({ checked, onChange, label, className, ...rest }) {
|
|
5
|
+
const handleChange = (e) => {
|
|
6
|
+
onChange(e.target.checked);
|
|
7
|
+
};
|
|
8
|
+
if (label) {
|
|
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 })] }));
|
|
10
|
+
}
|
|
11
|
+
return (_jsxs("span", { 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" }) })] }));
|
|
12
|
+
}
|
package/dist/Tabs.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import "../styles/Tabs.css";
|
|
3
|
+
export interface TabProps {
|
|
4
|
+
value: string;
|
|
5
|
+
label: string;
|
|
6
|
+
icon?: ReactNode;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface TabsProps {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
value: string;
|
|
13
|
+
onChange: (value: string) => void;
|
|
14
|
+
variant?: "default" | "pill" | "stretch";
|
|
15
|
+
className?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function Tabs({ children, value, onChange, variant, className }: TabsProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
/**
|
|
19
|
+
* Render-less component for tab definition.
|
|
20
|
+
* Used for configuration only - does not render anything directly.
|
|
21
|
+
*/
|
|
22
|
+
export declare function Tab(_props: TabProps): null;
|
package/dist/Tabs.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import { Children, isValidElement } from "react";
|
|
4
|
+
import "../styles/Tabs.css";
|
|
5
|
+
export function Tabs({ children, value, onChange, variant = "default", className }) {
|
|
6
|
+
// Extract tab definitions from children
|
|
7
|
+
const tabs = [];
|
|
8
|
+
Children.forEach(children, (child) => {
|
|
9
|
+
if (isValidElement(child) && child.props) {
|
|
10
|
+
tabs.push(child.props);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
return (_jsx("div", { className: clsx("PaTabs", variant, className), role: "tablist", children: tabs.map((tab) => (_jsxs("button", { type: "button", className: clsx("PaTab", value === tab.value && "active", tab.disabled && "disabled", tab.className), onClick: () => !tab.disabled && onChange(tab.value), disabled: tab.disabled, role: "tab", "aria-selected": value === tab.value, children: [tab.icon && _jsx("span", { className: "PaTab-icon", children: tab.icon }), tab.label] }, tab.value))) }));
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Render-less component for tab definition.
|
|
17
|
+
* Used for configuration only - does not render anything directly.
|
|
18
|
+
*/
|
|
19
|
+
export function Tab(_props) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "../styles/Textarea.css";
|
|
2
|
+
import type { Ref, TextareaHTMLAttributes } from "react";
|
|
3
|
+
export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
4
|
+
label?: string;
|
|
5
|
+
error?: string;
|
|
6
|
+
ref?: Ref<HTMLTextAreaElement>;
|
|
7
|
+
}
|
|
8
|
+
export declare function Textarea({ className, label, error, ref, ...props }: TextareaProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Textarea.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/Textarea.css";
|
|
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 })] }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import "../styles/ToggleButton.css";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
export interface ToggleButtonProps {
|
|
4
|
+
checked: boolean;
|
|
5
|
+
onChange: (checked: boolean) => void;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
"aria-label"?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function ToggleButton({ checked, onChange, children, className, disabled, ...rest }: ToggleButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/ToggleButton.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
export function ToggleButton({ checked, onChange, children, className, disabled, ...rest }) {
|
|
5
|
+
return (_jsx("button", { type: "button", className: clsx("PaToggleBtn", checked && "active", disabled && "disabled", className), onClick: () => !disabled && onChange(!checked), disabled: disabled, "aria-pressed": checked, ...rest, children: children }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import "../styles/ToggleGroup.css";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
export interface ToggleGroupOption {
|
|
4
|
+
value: string;
|
|
5
|
+
label: ReactNode;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface ToggleGroupProps {
|
|
9
|
+
value: string;
|
|
10
|
+
onChange: (value: string) => void;
|
|
11
|
+
options: ToggleGroupOption[];
|
|
12
|
+
className?: string;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function ToggleGroup({ value, onChange, options, className, disabled }: ToggleGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/ToggleGroup.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
export function ToggleGroup({ value, onChange, options, className, disabled }) {
|
|
5
|
+
return (_jsx("fieldset", { className: clsx("PaToggleGroup", disabled && "disabled", className), disabled: disabled, children: options.map((option) => (_jsx("button", { type: "button", className: clsx("PaToggleGroup-item", value === option.value && "active", option.disabled && "disabled"), onClick: () => !option.disabled && onChange(option.value), disabled: option.disabled, "aria-pressed": value === option.value, children: option.label }, option.value))) }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import "../styles/Tooltip.css";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
export interface TooltipProps {
|
|
4
|
+
content: string;
|
|
5
|
+
position?: "auto" | "top" | "bottom" | "left" | "right";
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
delay?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function Tooltip({ content, position, children, className, delay, }: TooltipProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/Tooltip.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../styles/Tooltip.css";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { useEffect, useRef } from "react";
|
|
5
|
+
import { computePopupPosition, setupPopoverPositioning } from "./popup-positioning.js";
|
|
6
|
+
export function Tooltip({ content, position = "auto", children, className, delay = 200, }) {
|
|
7
|
+
const triggerRef = useRef(null);
|
|
8
|
+
const tooltipRef = useRef(null);
|
|
9
|
+
const timeoutRef = useRef(undefined);
|
|
10
|
+
const showTooltip = () => {
|
|
11
|
+
timeoutRef.current = window.setTimeout(() => {
|
|
12
|
+
tooltipRef.current?.showPopover();
|
|
13
|
+
}, delay);
|
|
14
|
+
};
|
|
15
|
+
const hideTooltip = () => {
|
|
16
|
+
if (timeoutRef.current) {
|
|
17
|
+
clearTimeout(timeoutRef.current);
|
|
18
|
+
}
|
|
19
|
+
tooltipRef.current?.hidePopover();
|
|
20
|
+
};
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (!tooltipRef.current || !triggerRef.current)
|
|
23
|
+
return;
|
|
24
|
+
const triggerEl = triggerRef.current;
|
|
25
|
+
const popupEl = tooltipRef.current;
|
|
26
|
+
return setupPopoverPositioning(popupEl, () => computePopupPosition(triggerEl, popupEl, position, "cardinal"));
|
|
27
|
+
}, [position]);
|
|
28
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { ref: triggerRef, className: "PaTooltip-trigger", onMouseEnter: showTooltip, onMouseLeave: hideTooltip, onFocus: showTooltip, onBlur: hideTooltip, children: children }), _jsx("div", { ref: tooltipRef, className: clsx("PaTooltip", className), role: "tooltip", popover: "hint", children: content })] }));
|
|
29
|
+
}
|