@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.
Files changed (50) hide show
  1. package/dist/Button.js +7 -1
  2. package/dist/Checkbox.d.ts +4 -3
  3. package/dist/Checkbox.js +5 -7
  4. package/dist/DateInput.d.ts +5 -3
  5. package/dist/DateInput.js +7 -4
  6. package/dist/Dialog.d.ts +4 -2
  7. package/dist/Dialog.js +30 -27
  8. package/dist/InputNumber.d.ts +2 -2
  9. package/dist/InputNumber.js +5 -5
  10. package/dist/InputText.d.ts +3 -4
  11. package/dist/InputText.js +7 -6
  12. package/dist/MultiSelect.d.ts +3 -2
  13. package/dist/MultiSelect.js +27 -24
  14. package/dist/PasswordInput.d.ts +5 -3
  15. package/dist/PasswordInput.js +7 -4
  16. package/dist/PopupMenu.d.ts +3 -4
  17. package/dist/PopupMenu.js +13 -51
  18. package/dist/RadioButton.d.ts +4 -4
  19. package/dist/RadioButton.js +5 -5
  20. package/dist/Select.d.ts +3 -4
  21. package/dist/Select.js +5 -5
  22. package/dist/SplitButton.d.ts +1 -0
  23. package/dist/SplitButton.js +12 -15
  24. package/dist/Switch.d.ts +2 -2
  25. package/dist/Switch.js +1 -1
  26. package/dist/Textarea.d.ts +5 -3
  27. package/dist/Textarea.js +7 -4
  28. package/dist/Tooltip.d.ts +1 -1
  29. package/dist/Tooltip.js +11 -32
  30. package/dist/alert-stack.d.ts +3 -1
  31. package/dist/alert-stack.js +2 -2
  32. package/dist/popup-positioning.d.ts +10 -0
  33. package/dist/popup-positioning.js +160 -0
  34. package/package.json +6 -6
  35. package/styles/Alert.css +1 -0
  36. package/styles/Checkbox.css +7 -6
  37. package/styles/DateInput.css +2 -25
  38. package/styles/Dialog.css +35 -22
  39. package/styles/InputNumber.css +2 -25
  40. package/styles/InputText.css +16 -31
  41. package/styles/MultiSelect.css +8 -23
  42. package/styles/PasswordInput.css +7 -18
  43. package/styles/RadioButton.css +6 -5
  44. package/styles/Select.css +12 -27
  45. package/styles/SplitButton.css +2 -8
  46. package/styles/Textarea.css +1 -24
  47. package/styles/Tooltip.css +4 -18
  48. package/styles/Tree.css +4 -3
  49. package/styles/theme/field.css +29 -0
  50. package/styles/theme/index.css +1 -0
@@ -2,26 +2,23 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import "../styles/SplitButton.css";
3
3
  import { clsx } from "clsx";
4
4
  import { ChevronDown } from "lucide-react";
5
- import { useEffect, useRef, useState } from "react";
5
+ import { useEffect, useRef } from "react";
6
6
  import { Button, } from "./Button.js";
7
+ import { computePopupPosition, setupPopoverPositioning } from "./popup-positioning.js";
7
8
  export function SplitButton(props) {
8
- const { items, className, ...buttonProps } = props;
9
- const [open, setOpen] = useState(false);
9
+ const { items, className, position, ...buttonProps } = props;
10
10
  const containerRef = useRef(null);
11
+ const menuRef = useRef(null);
12
+ const menuId = useRef(`pa-splitbtn-menu-${Math.random().toString(36).substring(2, 9)}`);
11
13
  const severity = props.severity ?? "primary";
12
14
  const disabled = props.disabled;
13
- // Close dropdown when clicking outside
14
15
  useEffect(() => {
15
- if (!open)
16
+ const menu = menuRef.current;
17
+ const container = containerRef.current;
18
+ if (!menu || !container)
16
19
  return;
17
- const handleClickOutside = (e) => {
18
- if (containerRef.current && !containerRef.current.contains(e.target)) {
19
- setOpen(false);
20
- }
21
- };
22
- document.addEventListener("mousedown", handleClickOutside);
23
- return () => document.removeEventListener("mousedown", handleClickOutside);
24
- }, [open]);
20
+ return setupPopoverPositioning(menu, () => computePopupPosition(container, menu, position ?? "auto", "corner"));
21
+ }, [position]);
25
22
  const handleItemClick = async (item) => {
26
23
  try {
27
24
  await item.command();
@@ -35,8 +32,8 @@ export function SplitButton(props) {
35
32
  }
36
33
  }
37
34
  finally {
38
- setOpen(false);
35
+ menuRef.current?.hidePopover();
39
36
  }
40
37
  };
41
- return (_jsxs("div", { ref: containerRef, className: clsx("PaSplitBtn", severity, open && "open", disabled && "disabled", className), children: [_jsx(Button, { ...buttonProps, className: "PaSplitBtn-main" }), _jsx("button", { type: "button", className: "PaSplitBtn-toggle", onClick: () => setOpen(!open), "aria-haspopup": "menu", "aria-expanded": open, children: _jsx(ChevronDown, { className: "PaSplitBtn-toggleIcon" }) }), open && (_jsx("div", { className: "PaSplitBtn-menu", role: "menu", 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))) }))] }));
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))) })] }));
42
39
  }
package/dist/Switch.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import type { InputHTMLAttributes } from "react";
1
+ import type { ChangeEvent, InputHTMLAttributes } from "react";
2
2
  import "../styles/Switch.css";
3
3
  export interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {
4
4
  checked: boolean;
5
- onChange: (checked: boolean) => void;
5
+ onChange?: (checked: boolean, ev: ChangeEvent<HTMLInputElement>) => void;
6
6
  label?: string;
7
7
  className?: string;
8
8
  }
package/dist/Switch.js CHANGED
@@ -3,7 +3,7 @@ import { clsx } from "clsx";
3
3
  import "../styles/Switch.css";
4
4
  export function Switch({ checked, onChange, label, className, ...rest }) {
5
5
  const handleChange = (e) => {
6
- onChange(e.target.checked);
6
+ onChange?.(e.target.checked, e);
7
7
  };
8
8
  if (label) {
9
9
  return (_jsxs("label", { className: clsx("PaSwitch", className), children: [_jsx("input", { className: "PaSwitch-input", type: "checkbox", checked: checked, onChange: handleChange, ...rest }), _jsx("span", { className: "PaSwitch-track", children: _jsx("span", { className: "PaSwitch-thumb" }) }), _jsx("span", { className: "PaSwitch-label", children: label })] }));
@@ -1,8 +1,10 @@
1
1
  import "../styles/Textarea.css";
2
- import type { Ref, TextareaHTMLAttributes } from "react";
3
- export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
2
+ import type { ChangeEvent, Ref, TextareaHTMLAttributes } from "react";
3
+ export interface TextareaProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange"> {
4
+ value?: string;
5
+ onChange?: (value: string, ev: ChangeEvent<HTMLTextAreaElement>) => void;
4
6
  label?: string;
5
7
  error?: string;
6
8
  ref?: Ref<HTMLTextAreaElement>;
7
9
  }
8
- export declare function Textarea({ className, label, error, ref, ...props }: TextareaProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function Textarea({ className, label, error, value, onChange, ref, ...props }: TextareaProps): import("react/jsx-runtime").JSX.Element;
package/dist/Textarea.js CHANGED
@@ -1,7 +1,10 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import "../styles/Textarea.css";
3
3
  import { clsx } from "clsx";
4
- export function Textarea({ className, label, error, ref, ...props }) {
5
- const textareaElement = (_jsx("textarea", { ref: ref, className: clsx("PaTextarea-field", error && "error"), ...props }));
6
- return (_jsxs("span", { className: clsx("PaTextarea", className), children: [label ? (_jsxs("label", { className: "PaTextarea-wrapper", children: [_jsx("span", { className: "PaTextarea-label", children: label }), textareaElement] })) : (textareaElement), error && _jsx("span", { className: "PaTextarea-error", children: error })] }));
4
+ export function Textarea({ className, label, error, value, onChange, ref, ...props }) {
5
+ const handleChange = (e) => {
6
+ onChange?.(e.target.value, e);
7
+ };
8
+ const textareaElement = (_jsx("textarea", { ref: ref, className: clsx("PaTextarea", error && "error", !label && className), value: value, onChange: handleChange, ...props }));
9
+ return (_jsxs(_Fragment, { children: [label ? (_jsxs("label", { className: clsx("PaField", error && "error", className), children: [_jsx("span", { className: "PaField-label", children: label }), textareaElement] })) : (textareaElement), error && _jsx("span", { className: "PaFieldError", children: error })] }));
7
10
  }
package/dist/Tooltip.d.ts CHANGED
@@ -2,7 +2,7 @@ import "../styles/Tooltip.css";
2
2
  import { type ReactNode } from "react";
3
3
  export interface TooltipProps {
4
4
  content: string;
5
- position?: "top" | "bottom" | "left" | "right";
5
+ position?: "auto" | "top" | "bottom" | "left" | "right";
6
6
  children: ReactNode;
7
7
  className?: string;
8
8
  delay?: number;
package/dist/Tooltip.js CHANGED
@@ -1,50 +1,29 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import "../styles/Tooltip.css";
3
3
  import { clsx } from "clsx";
4
- import { useEffect, useRef, useState } from "react";
5
- export function Tooltip({ content, position = "top", children, className, delay = 200, }) {
6
- const [visible, setVisible] = useState(false);
7
- const [coords, setCoords] = useState({ top: 0, left: 0 });
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, }) {
8
7
  const triggerRef = useRef(null);
9
8
  const tooltipRef = useRef(null);
10
9
  const timeoutRef = useRef(undefined);
11
10
  const showTooltip = () => {
12
11
  timeoutRef.current = window.setTimeout(() => {
13
- setVisible(true);
12
+ tooltipRef.current?.showPopover();
14
13
  }, delay);
15
14
  };
16
15
  const hideTooltip = () => {
17
16
  if (timeoutRef.current) {
18
17
  clearTimeout(timeoutRef.current);
19
18
  }
20
- setVisible(false);
19
+ tooltipRef.current?.hidePopover();
21
20
  };
22
21
  useEffect(() => {
23
- if (!visible || !triggerRef.current)
22
+ if (!tooltipRef.current || !triggerRef.current)
24
23
  return;
25
- const trigger = triggerRef.current;
26
- const rect = trigger.getBoundingClientRect();
27
- let top = 0;
28
- let left = 0;
29
- switch (position) {
30
- case "top":
31
- top = rect.top - 8;
32
- left = rect.left + rect.width / 2;
33
- break;
34
- case "bottom":
35
- top = rect.bottom + 8;
36
- left = rect.left + rect.width / 2;
37
- break;
38
- case "left":
39
- top = rect.top + rect.height / 2;
40
- left = rect.left - 8;
41
- break;
42
- case "right":
43
- top = rect.top + rect.height / 2;
44
- left = rect.right + 8;
45
- break;
46
- }
47
- setCoords({ top, left });
48
- }, [visible, position]);
49
- return (_jsxs(_Fragment, { children: [_jsx("div", { ref: triggerRef, className: "PaTooltip-trigger", onMouseEnter: showTooltip, onMouseLeave: hideTooltip, onFocus: showTooltip, onBlur: hideTooltip, children: children }), visible && (_jsx("div", { ref: tooltipRef, className: clsx("PaTooltip", position, className), style: { top: coords.top, left: coords.left }, role: "tooltip", children: content }))] }));
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 })] }));
50
29
  }
@@ -14,5 +14,7 @@ interface AlertStackProviderProps {
14
14
  }
15
15
  export declare function AlertStackProvider({ children, ref }: AlertStackProviderProps): import("react/jsx-runtime").JSX.Element;
16
16
  export declare function useAlertStack(): AlertStackHandle;
17
- export declare function AlertStack(): import("react/jsx-runtime").JSX.Element | null;
17
+ export declare function AlertStack(props?: {
18
+ className?: string;
19
+ }): import("react/jsx-runtime").JSX.Element | null;
18
20
  export {};
@@ -47,7 +47,7 @@ export function useAlertStack() {
47
47
  }, [context.showAlert]);
48
48
  return { showAlert: context.showAlert, showError };
49
49
  }
50
- export function AlertStack() {
50
+ export function AlertStack(props) {
51
51
  const context = useContext(AlertStackContext);
52
52
  const config = useReactUIConfig();
53
53
  if (!context) {
@@ -68,5 +68,5 @@ export function AlertStack() {
68
68
  ]);
69
69
  if (!currentAlert)
70
70
  return null;
71
- return (_jsx(Alert, { severity: currentAlert.severity, onClose: dismissCurrent, children: currentAlert.message }));
71
+ return (_jsx(Alert, { className: props?.className, severity: currentAlert.severity, onClose: dismissCurrent, children: currentAlert.message }));
72
72
  }
@@ -0,0 +1,10 @@
1
+ export type CornerPosition = "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
2
+ export type VerticalPosition = "top" | "bottom";
3
+ export type CardinalPosition = "top" | "bottom" | "left" | "right";
4
+ export interface PositionResult {
5
+ top: number;
6
+ left: number;
7
+ position: string;
8
+ }
9
+ export declare function setupPopoverPositioning(popupEl: HTMLElement, getPosition: () => PositionResult): () => void;
10
+ export declare function computePopupPosition(triggerEl: HTMLElement, popupEl: HTMLElement, preferredPosition: string, mode: "corner" | "vertical" | "cardinal"): PositionResult;
@@ -0,0 +1,160 @@
1
+ export function setupPopoverPositioning(popupEl, getPosition) {
2
+ const handleToggle = (e) => {
3
+ const newState = e.newState;
4
+ if (newState === "open") {
5
+ const position = getPosition();
6
+ popupEl.style.position = "absolute";
7
+ popupEl.style.top = `${position.top}px`;
8
+ popupEl.style.left = `${position.left}px`;
9
+ }
10
+ };
11
+ popupEl.addEventListener("toggle", handleToggle);
12
+ return () => popupEl.removeEventListener("toggle", handleToggle);
13
+ }
14
+ export function computePopupPosition(triggerEl, popupEl, preferredPosition, mode) {
15
+ const triggerRect = triggerEl.getBoundingClientRect();
16
+ const popupWidth = popupEl.offsetWidth;
17
+ const popupHeight = popupEl.offsetHeight;
18
+ const bounds = getConstrainingBounds(triggerEl);
19
+ let result;
20
+ switch (mode) {
21
+ case "corner":
22
+ result = computeCornerPosition(triggerRect, popupWidth, popupHeight, bounds, preferredPosition);
23
+ break;
24
+ case "vertical":
25
+ result = computeVerticalPosition(triggerRect, popupWidth, popupHeight, bounds, preferredPosition);
26
+ break;
27
+ case "cardinal":
28
+ result = computeCardinalPosition(triggerRect, popupWidth, popupHeight, bounds, preferredPosition);
29
+ break;
30
+ }
31
+ return {
32
+ position: result.position,
33
+ top: result.top + window.scrollY,
34
+ left: result.left + window.scrollX,
35
+ };
36
+ }
37
+ function getConstrainingBounds(triggerEl) {
38
+ const dialog = triggerEl.closest("dialog");
39
+ if (dialog) {
40
+ const rect = dialog.getBoundingClientRect();
41
+ return {
42
+ top: rect.top,
43
+ left: rect.left,
44
+ right: rect.right,
45
+ bottom: rect.bottom,
46
+ };
47
+ }
48
+ return {
49
+ top: 0,
50
+ left: 0,
51
+ right: window.innerWidth,
52
+ bottom: window.innerHeight,
53
+ };
54
+ }
55
+ function computeCornerPosition(triggerRect, popupWidth, popupHeight, bounds, preferredPosition) {
56
+ const spaceTop = triggerRect.top - bounds.top;
57
+ const spaceBottom = bounds.bottom - triggerRect.bottom;
58
+ const spaceLeft = triggerRect.left - bounds.left;
59
+ const spaceRight = bounds.right - triggerRect.right;
60
+ let position;
61
+ if (preferredPosition !== "auto") {
62
+ position = preferredPosition;
63
+ }
64
+ else {
65
+ // Pick corner with most space, prefer bottom-right > bottom-left > top-right > top-left
66
+ const canBottom = spaceBottom >= popupHeight;
67
+ const canTop = spaceTop >= popupHeight;
68
+ const canRight = spaceRight + triggerRect.width >= popupWidth;
69
+ const canLeft = spaceLeft + triggerRect.width >= popupWidth;
70
+ if (canBottom && canRight) {
71
+ position = "bottomRight";
72
+ }
73
+ else if (canBottom && canLeft) {
74
+ position = "bottomLeft";
75
+ }
76
+ else if (canTop && canRight) {
77
+ position = "topRight";
78
+ }
79
+ else if (canTop && canLeft) {
80
+ position = "topLeft";
81
+ }
82
+ else {
83
+ // Fallback: choose based on available space
84
+ const vertical = spaceBottom >= spaceTop ? "bottom" : "top";
85
+ const horizontal = spaceRight >= spaceLeft ? "Right" : "Left";
86
+ position = `${vertical}${horizontal}`;
87
+ }
88
+ }
89
+ let top;
90
+ let left;
91
+ if (position.startsWith("bottom")) {
92
+ top = triggerRect.bottom;
93
+ }
94
+ else {
95
+ top = triggerRect.top - popupHeight;
96
+ }
97
+ if (position.endsWith("Right")) {
98
+ left = triggerRect.left;
99
+ }
100
+ else {
101
+ left = triggerRect.right - popupWidth;
102
+ }
103
+ return { position, top, left };
104
+ }
105
+ function computeVerticalPosition(triggerRect, _popupWidth, popupHeight, bounds, preferredPosition) {
106
+ const spaceTop = triggerRect.top - bounds.top;
107
+ const spaceBottom = bounds.bottom - triggerRect.bottom;
108
+ let position;
109
+ if (preferredPosition !== "auto") {
110
+ position = preferredPosition;
111
+ }
112
+ else {
113
+ position = spaceBottom >= popupHeight || spaceBottom >= spaceTop ? "bottom" : "top";
114
+ }
115
+ const top = position === "bottom" ? triggerRect.bottom : triggerRect.top - popupHeight;
116
+ const left = triggerRect.left;
117
+ return { position, top, left };
118
+ }
119
+ function computeCardinalPosition(triggerRect, popupWidth, popupHeight, bounds, preferredPosition) {
120
+ const spaceTop = triggerRect.top - bounds.top;
121
+ const spaceBottom = bounds.bottom - triggerRect.bottom;
122
+ const spaceLeft = triggerRect.left - bounds.left;
123
+ const spaceRight = bounds.right - triggerRect.right;
124
+ let position;
125
+ if (preferredPosition !== "auto") {
126
+ position = preferredPosition;
127
+ }
128
+ else {
129
+ // Pick direction with most space
130
+ const spaces = [
131
+ { dir: "bottom", space: spaceBottom },
132
+ { dir: "right", space: spaceRight },
133
+ { dir: "top", space: spaceTop },
134
+ { dir: "left", space: spaceLeft },
135
+ ];
136
+ spaces.sort((a, b) => b.space - a.space);
137
+ position = spaces[0].dir;
138
+ }
139
+ let top;
140
+ let left;
141
+ switch (position) {
142
+ case "top":
143
+ top = triggerRect.top - popupHeight;
144
+ left = triggerRect.left + (triggerRect.width - popupWidth) / 2;
145
+ break;
146
+ case "bottom":
147
+ top = triggerRect.bottom;
148
+ left = triggerRect.left + (triggerRect.width - popupWidth) / 2;
149
+ break;
150
+ case "left":
151
+ top = triggerRect.top + (triggerRect.height - popupHeight) / 2;
152
+ left = triggerRect.left - popupWidth;
153
+ break;
154
+ case "right":
155
+ top = triggerRect.top + (triggerRect.height - popupHeight) / 2;
156
+ left = triggerRect.right;
157
+ break;
158
+ }
159
+ return { position, top, left };
160
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paroicms/react-ui",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "React UI toolkit for ParoiCMS.",
5
5
  "keywords": [
6
6
  "paroicms",
@@ -25,7 +25,7 @@
25
25
  "dev": "tsc --watch --preserveWatchOutput"
26
26
  },
27
27
  "dependencies": {
28
- "@paroicms/public-anywhere-lib": "0.41.0",
28
+ "@paroicms/public-anywhere-lib": "0.41.1",
29
29
  "clsx": "~2.1.1",
30
30
  "lucide-react": "~0.562.0",
31
31
  "react-sortablejs": "~6.1.4",
@@ -36,11 +36,11 @@
36
36
  "react-dom": ">=18.0.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@types/react": "~19.2.7",
39
+ "@types/react": "~19.2.8",
40
40
  "@types/react-dom": "~19.2.3",
41
- "@types/sortablejs": "^1.15.8",
42
- "react": "~19.2.0",
43
- "react-dom": "~19.2.0",
41
+ "@types/sortablejs": "^1.15.9",
42
+ "react": "~19.2.3",
43
+ "react-dom": "~19.2.3",
44
44
  "rimraf": "~6.1.2",
45
45
  "typescript": "~5.9.3"
46
46
  },
package/styles/Alert.css CHANGED
@@ -4,6 +4,7 @@
4
4
  .PaAlert {
5
5
  position: relative;
6
6
  padding: var(--space-4) var(--space-5);
7
+ margin: var(--space-4) 0;
7
8
  border-left: 4px solid;
8
9
  border-radius: var(--radius);
9
10
 
@@ -1,7 +1,7 @@
1
1
  /* ========================================
2
2
  Checkbox Component
3
3
  ======================================== */
4
- .PaCheckbox {
4
+ .PaCheckboxField {
5
5
  display: inline-flex;
6
6
  gap: var(--space-2);
7
7
  align-items: center;
@@ -9,7 +9,7 @@
9
9
  user-select: none;
10
10
  }
11
11
 
12
- .PaCheckbox-input {
12
+ .PaCheckboxInput {
13
13
  display: flex;
14
14
  flex-shrink: 0;
15
15
  align-items: center;
@@ -24,7 +24,7 @@
24
24
  border-radius: var(--radius-sm);
25
25
  transition: all var(--transition);
26
26
 
27
- &:hover {
27
+ &:hover:not(:disabled) {
28
28
  border-color: var(--color-primary);
29
29
  }
30
30
 
@@ -55,7 +55,8 @@
55
55
  }
56
56
  }
57
57
 
58
- .PaCheckbox-label {
59
- font-size: var(--text-sm);
60
- color: var(--color-text);
58
+ .PaCheckboxGroup {
59
+ display: flex;
60
+ flex-wrap: wrap;
61
+ gap: var(--space-3);
61
62
  }
@@ -1,25 +1,7 @@
1
1
  /* ========================================
2
2
  DateInput Component
3
3
  ======================================== */
4
- .PaDateInput {
5
- display: flex;
6
- flex-direction: column;
7
- gap: var(--space-2);
8
- }
9
-
10
- .PaDateInput-wrapper {
11
- display: flex;
12
- flex-direction: column;
13
- gap: var(--space-2);
14
- }
15
-
16
- .PaDateInput-label {
17
- font-size: var(--text-sm);
18
- font-weight: var(--font-medium);
19
- color: var(--color-text);
20
- }
21
-
22
- .PaDateInput-field {
4
+ .PaDateTimeInput {
23
5
  padding: var(--space-2) var(--space-3);
24
6
  font-family: inherit;
25
7
  font-size: var(--text-base);
@@ -32,7 +14,7 @@
32
14
  border-color var(--transition),
33
15
  box-shadow var(--transition);
34
16
 
35
- &:hover {
17
+ &:hover:not(:disabled) {
36
18
  border-color: var(--color-primary);
37
19
  }
38
20
 
@@ -52,8 +34,3 @@
52
34
  border-color: var(--color-danger);
53
35
  }
54
36
  }
55
-
56
- .PaDateInput-error {
57
- font-size: var(--text-xs);
58
- color: var(--color-danger);
59
- }
package/styles/Dialog.css CHANGED
@@ -1,32 +1,43 @@
1
1
  /* ========================================
2
2
  Dialog Component
3
3
  ======================================== */
4
- .PaDialog-overlay {
5
- position: fixed;
6
- inset: 0;
7
- z-index: var(--z-modal);
8
- display: flex;
9
- align-items: center;
10
- justify-content: center;
11
- }
12
-
13
- .PaDialog-backdrop {
14
- position: absolute;
15
- inset: 0;
16
- background: rgba(0, 0, 0, 0.5);
17
- }
18
-
19
4
  .PaDialog {
20
- position: relative;
21
- z-index: 1;
22
- display: flex;
23
- flex-direction: column;
24
- min-width: 320px;
25
5
  max-width: 90vw;
26
- max-height: 90vh;
6
+ padding: 0;
27
7
  background: var(--color-bg-elevated);
8
+ border: none;
28
9
  border-radius: var(--radius-lg);
29
10
  box-shadow: var(--shadow-lg);
11
+
12
+ &[open] {
13
+ display: flex;
14
+ flex-direction: column;
15
+ }
16
+
17
+ &:modal {
18
+ max-height: 90vh;
19
+ margin: auto;
20
+ }
21
+
22
+ &::backdrop {
23
+ background: rgba(0, 0, 0, 0.5);
24
+ }
25
+
26
+ /* Size variants */
27
+ &.sizeSm {
28
+ width: 480px;
29
+ max-width: 100%;
30
+ }
31
+
32
+ &.sizeMd {
33
+ width: 640px;
34
+ max-width: 100%;
35
+ }
36
+
37
+ &.sizeLg {
38
+ width: 800px;
39
+ max-width: 100%;
40
+ }
30
41
  }
31
42
 
32
43
  .PaDialog-header {
@@ -34,7 +45,7 @@
34
45
  gap: var(--space-4);
35
46
  align-items: center;
36
47
  justify-content: space-between;
37
- padding: var(--space-4) var(--space-5);
48
+ padding: var(--space-3) var(--space-5);
38
49
  border-bottom: 1px solid var(--color-border-light);
39
50
  }
40
51
 
@@ -48,6 +59,8 @@
48
59
  display: flex;
49
60
  align-items: center;
50
61
  justify-content: center;
62
+ width: 40px;
63
+ height: 40px;
51
64
  padding: var(--space-1);
52
65
  color: var(--color-text-muted);
53
66
  cursor: pointer;
@@ -1,25 +1,7 @@
1
1
  /* ========================================
2
2
  InputNumber Component
3
3
  ======================================== */
4
- .PaInputNumber {
5
- display: flex;
6
- flex-direction: column;
7
- gap: var(--space-2);
8
- }
9
-
10
- .PaInputNumber-wrapper {
11
- display: flex;
12
- flex-direction: column;
13
- gap: var(--space-2);
14
- }
15
-
16
- .PaInputNumber-label {
17
- font-size: var(--text-sm);
18
- font-weight: var(--font-medium);
19
- color: var(--color-text);
20
- }
21
-
22
- .PaInputNumber-field {
4
+ .PaNumberInput {
23
5
  width: 100%;
24
6
  padding: var(--space-2) var(--space-3);
25
7
  font-family: inherit;
@@ -33,7 +15,7 @@
33
15
  border-color var(--transition),
34
16
  box-shadow var(--transition);
35
17
 
36
- &:hover {
18
+ &:hover:not(:disabled) {
37
19
  border-color: var(--color-primary);
38
20
  }
39
21
 
@@ -53,8 +35,3 @@
53
35
  border-color: var(--color-danger);
54
36
  }
55
37
  }
56
-
57
- .PaInputNumber-error {
58
- font-size: var(--text-xs);
59
- color: var(--color-danger);
60
- }