@paroicms/react-ui 0.4.4 → 0.5.0

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 (130) hide show
  1. package/dist/Accordion.d.ts +10 -0
  2. package/dist/{PuAccordion.jsx → Accordion.js} +5 -8
  3. package/dist/Alert.d.ts +10 -0
  4. package/dist/Alert.js +7 -0
  5. package/dist/Badge.d.ts +8 -0
  6. package/dist/Badge.js +6 -0
  7. package/dist/Breadcrumb.d.ts +14 -0
  8. package/dist/Breadcrumb.js +10 -0
  9. package/dist/Button.d.ts +36 -0
  10. package/dist/Button.js +74 -0
  11. package/dist/Card.d.ts +10 -0
  12. package/dist/Card.js +7 -0
  13. package/dist/Checkbox.d.ts +9 -0
  14. package/dist/Checkbox.js +12 -0
  15. package/dist/Chip.d.ts +8 -0
  16. package/dist/Chip.js +7 -0
  17. package/dist/Column.d.ts +14 -0
  18. package/dist/Column.js +7 -0
  19. package/dist/DataTable.d.ts +30 -0
  20. package/dist/DataTable.js +26 -0
  21. package/dist/DateInput.d.ts +9 -0
  22. package/dist/DateInput.js +7 -0
  23. package/dist/Dialog.d.ts +13 -0
  24. package/dist/Dialog.js +55 -0
  25. package/dist/Inplace.d.ts +12 -0
  26. package/dist/Inplace.js +16 -0
  27. package/dist/InputNumber.d.ts +10 -0
  28. package/dist/InputNumber.js +19 -0
  29. package/dist/InputText.d.ts +14 -0
  30. package/dist/InputText.js +11 -0
  31. package/dist/MenuItem.d.ts +8 -0
  32. package/dist/MenuItem.js +18 -0
  33. package/dist/MultiSelect.d.ts +17 -0
  34. package/dist/MultiSelect.js +50 -0
  35. package/dist/Panel.d.ts +11 -0
  36. package/dist/Panel.js +9 -0
  37. package/dist/PasswordInput.d.ts +8 -0
  38. package/dist/PasswordInput.js +10 -0
  39. package/dist/PopupMenu.d.ts +20 -0
  40. package/dist/{PuPopupMenu.jsx → PopupMenu.js} +45 -36
  41. package/dist/RadioButton.d.ts +9 -0
  42. package/dist/RadioButton.js +12 -0
  43. package/dist/Select.d.ts +18 -0
  44. package/dist/Select.js +11 -0
  45. package/dist/SideMenu.d.ts +5 -0
  46. package/dist/SideMenu.js +13 -0
  47. package/dist/SortableList.d.ts +19 -0
  48. package/dist/SortableList.js +27 -0
  49. package/dist/Spinner.d.ts +2 -0
  50. package/dist/Spinner.js +5 -0
  51. package/dist/SplitButton.d.ts +24 -0
  52. package/dist/SplitButton.js +42 -0
  53. package/dist/Switch.d.ts +9 -0
  54. package/dist/Switch.js +12 -0
  55. package/dist/Tabs.d.ts +22 -0
  56. package/dist/Tabs.js +21 -0
  57. package/dist/Textarea.d.ts +8 -0
  58. package/dist/Textarea.js +7 -0
  59. package/dist/ToggleButton.d.ts +11 -0
  60. package/dist/ToggleButton.js +6 -0
  61. package/dist/ToggleGroup.d.ts +15 -0
  62. package/dist/ToggleGroup.js +6 -0
  63. package/dist/Tooltip.d.ts +10 -0
  64. package/dist/Tooltip.js +50 -0
  65. package/dist/Tree.d.ts +22 -0
  66. package/dist/Tree.js +43 -0
  67. package/dist/alert-stack.d.ts +18 -0
  68. package/dist/alert-stack.js +72 -0
  69. package/dist/index.d.ts +36 -10
  70. package/dist/index.js +45 -10
  71. package/dist/paroi-ui-lib-types.d.ts +4 -4
  72. package/dist/react-ui-provider.d.ts +15 -0
  73. package/dist/react-ui-provider.js +22 -0
  74. package/package.json +16 -2
  75. package/styles/Accordion.css +46 -0
  76. package/styles/Alert.css +76 -0
  77. package/styles/Badge.css +59 -0
  78. package/styles/Breadcrumb.css +57 -0
  79. package/styles/Button.css +167 -0
  80. package/styles/Card.css +28 -0
  81. package/styles/Checkbox.css +61 -0
  82. package/styles/Chip.css +35 -0
  83. package/styles/DataTable.css +176 -0
  84. package/styles/DateInput.css +59 -0
  85. package/styles/Dialog.css +77 -0
  86. package/styles/Inplace.css +44 -0
  87. package/styles/InputNumber.css +60 -0
  88. package/styles/InputText.css +99 -0
  89. package/styles/MenuItem.css +169 -0
  90. package/styles/MultiSelect.css +158 -0
  91. package/styles/Panel.css +40 -0
  92. package/styles/PasswordInput.css +80 -0
  93. package/styles/PopupMenu.css +37 -0
  94. package/styles/RadioButton.css +60 -0
  95. package/styles/Select.css +72 -0
  96. package/styles/SideMenu.css +7 -0
  97. package/styles/SortableList.css +32 -0
  98. package/styles/Spinner.css +30 -0
  99. package/styles/SplitButton.css +143 -0
  100. package/styles/Switch.css +60 -0
  101. package/styles/Tabs.css +94 -0
  102. package/styles/Textarea.css +66 -0
  103. package/styles/ToggleButton.css +36 -0
  104. package/styles/ToggleGroup.css +55 -0
  105. package/styles/Tooltip.css +34 -0
  106. package/styles/Tree.css +161 -0
  107. package/styles/theme/base.css +40 -0
  108. package/styles/theme/common.css +410 -0
  109. package/styles/theme/index.css +15 -0
  110. package/styles/theme/margins.css +119 -0
  111. package/styles/theme/reset.css +119 -0
  112. package/styles/theme/tokens.css +226 -0
  113. package/dist/PuAccordion.d.ts +0 -9
  114. package/dist/PuButton.d.ts +0 -14
  115. package/dist/PuButton.jsx +0 -15
  116. package/dist/PuCheckbox.d.ts +0 -8
  117. package/dist/PuCheckbox.jsx +0 -13
  118. package/dist/PuInput.d.ts +0 -10
  119. package/dist/PuInput.jsx +0 -13
  120. package/dist/PuMenuItem.d.ts +0 -7
  121. package/dist/PuMenuItem.jsx +0 -33
  122. package/dist/PuPopupMenu.d.ts +0 -14
  123. package/dist/PuSelect.d.ts +0 -17
  124. package/dist/PuSelect.jsx +0 -24
  125. package/dist/PuSideMenu.d.ts +0 -4
  126. package/dist/PuSideMenu.jsx +0 -15
  127. package/dist/PuSpinner.d.ts +0 -1
  128. package/dist/PuSpinner.jsx +0 -3
  129. package/dist/svg-icons.d.ts +0 -5
  130. package/dist/svg-icons.jsx +0 -30
@@ -0,0 +1,50 @@
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, 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 });
8
+ const triggerRef = useRef(null);
9
+ const tooltipRef = useRef(null);
10
+ const timeoutRef = useRef(undefined);
11
+ const showTooltip = () => {
12
+ timeoutRef.current = window.setTimeout(() => {
13
+ setVisible(true);
14
+ }, delay);
15
+ };
16
+ const hideTooltip = () => {
17
+ if (timeoutRef.current) {
18
+ clearTimeout(timeoutRef.current);
19
+ }
20
+ setVisible(false);
21
+ };
22
+ useEffect(() => {
23
+ if (!visible || !triggerRef.current)
24
+ 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 }))] }));
50
+ }
package/dist/Tree.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { type ReactNode } from "react";
2
+ import "../styles/Tree.css";
3
+ export interface TreeNode {
4
+ key: string;
5
+ label: ReactNode;
6
+ children?: TreeNode[];
7
+ data?: unknown;
8
+ selectable?: boolean;
9
+ icon?: ReactNode;
10
+ className?: string;
11
+ }
12
+ export interface TreeProps {
13
+ value: TreeNode[];
14
+ selectionMode?: "single" | "checkbox";
15
+ selection?: Record<string, boolean>;
16
+ onSelectionChange?: (selection: Record<string, boolean>) => void;
17
+ expandedKeys?: Record<string, boolean>;
18
+ onExpandedKeysChange?: (keys: Record<string, boolean>) => void;
19
+ nodeTemplate?: (node: TreeNode) => ReactNode;
20
+ className?: string;
21
+ }
22
+ export declare function Tree({ value, selectionMode, selection, onSelectionChange, expandedKeys, onExpandedKeysChange, nodeTemplate, className, }: TreeProps): import("react/jsx-runtime").JSX.Element;
package/dist/Tree.js ADDED
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { clsx } from "clsx";
3
+ import { ChevronDown, ChevronRight } from "lucide-react";
4
+ import { useCallback } from "react";
5
+ import "../styles/Tree.css";
6
+ export function Tree({ value, selectionMode, selection = {}, onSelectionChange, expandedKeys = {}, onExpandedKeysChange, nodeTemplate, className, }) {
7
+ const toggleExpand = useCallback((key) => {
8
+ if (onExpandedKeysChange) {
9
+ const newKeys = { ...expandedKeys };
10
+ if (newKeys[key]) {
11
+ delete newKeys[key];
12
+ }
13
+ else {
14
+ newKeys[key] = true;
15
+ }
16
+ onExpandedKeysChange(newKeys);
17
+ }
18
+ }, [expandedKeys, onExpandedKeysChange]);
19
+ const toggleSelect = useCallback((key, node) => {
20
+ if (!onSelectionChange || node.selectable === false)
21
+ return;
22
+ if (selectionMode === "single") {
23
+ onSelectionChange({ [key]: true });
24
+ }
25
+ else if (selectionMode === "checkbox") {
26
+ const newSelection = { ...selection };
27
+ if (newSelection[key]) {
28
+ delete newSelection[key];
29
+ }
30
+ else {
31
+ newSelection[key] = true;
32
+ }
33
+ onSelectionChange(newSelection);
34
+ }
35
+ }, [selection, selectionMode, onSelectionChange]);
36
+ return (_jsx("div", { className: clsx("PaTree", className), children: _jsx("ul", { className: "PaTree-root", children: value.map((node) => (_jsx(TreeNodeItem, { node: node, expandedKeys: expandedKeys, selection: selection, selectionMode: selectionMode, onToggleExpand: toggleExpand, onToggleSelect: toggleSelect, nodeTemplate: nodeTemplate }, node.key))) }) }));
37
+ }
38
+ function TreeNodeItem({ node, expandedKeys, selection, selectionMode, onToggleExpand, onToggleSelect, nodeTemplate, }) {
39
+ const hasChildren = node.children && node.children.length > 0;
40
+ const isExpanded = expandedKeys[node.key];
41
+ const isSelected = selection[node.key];
42
+ return (_jsxs("li", { className: clsx("PaTree-node", node.className), children: [_jsxs("div", { className: clsx("PaTree-nodeContent", isSelected && "selected"), children: [hasChildren ? (_jsx("button", { type: "button", className: "PaTree-toggle", onClick: () => onToggleExpand(node.key), "aria-label": isExpanded ? "Collapse" : "Expand", children: isExpanded ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronRight, { size: 14 }) })) : (_jsx("span", { className: "PaTree-togglePlaceholder" })), selectionMode === "checkbox" && (_jsx("input", { type: "checkbox", className: "PaTree-checkbox", checked: isSelected, onChange: () => onToggleSelect(node.key, node), disabled: node.selectable === false })), selectionMode === "single" && node.selectable !== false ? (_jsxs("button", { type: "button", className: clsx("PaTree-labelWrapper", "selectable"), onClick: () => onToggleSelect(node.key, node), children: [node.icon && _jsx("span", { className: "PaTree-icon", children: node.icon }), nodeTemplate ? nodeTemplate(node) : _jsx("span", { className: "PaTree-label", children: node.label })] })) : (_jsxs("div", { className: "PaTree-labelWrapper", children: [node.icon && _jsx("span", { className: "PaTree-icon", children: node.icon }), nodeTemplate ? nodeTemplate(node) : _jsx("span", { className: "PaTree-label", children: node.label })] }))] }), hasChildren && isExpanded && (_jsx("ul", { className: "PaTree-children", children: node.children?.map((child) => (_jsx(TreeNodeItem, { node: child, expandedKeys: expandedKeys, selection: selection, selectionMode: selectionMode, onToggleExpand: onToggleExpand, onToggleSelect: onToggleSelect, nodeTemplate: nodeTemplate }, child.key))) }))] }));
43
+ }
@@ -0,0 +1,18 @@
1
+ import type { ReactNode, Ref } from "react";
2
+ export type AlertSeverity = "info" | "success" | "warning" | "error";
3
+ export interface ShowAlertOptions {
4
+ severity?: AlertSeverity;
5
+ autoDismiss?: boolean;
6
+ }
7
+ export interface AlertStackHandle {
8
+ showAlert: (message: string, options?: ShowAlertOptions) => void;
9
+ showError: (error: unknown) => void;
10
+ }
11
+ interface AlertStackProviderProps {
12
+ children: ReactNode;
13
+ ref?: Ref<AlertStackHandle>;
14
+ }
15
+ export declare function AlertStackProvider({ children, ref }: AlertStackProviderProps): import("react/jsx-runtime").JSX.Element;
16
+ export declare function useAlertStack(): AlertStackHandle;
17
+ export declare function AlertStack(): import("react/jsx-runtime").JSX.Element | null;
18
+ export {};
@@ -0,0 +1,72 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { messageOf } from "@paroicms/public-anywhere-lib";
3
+ import { createContext, useCallback, useContext, useEffect, useImperativeHandle, useReducer, useRef, } from "react";
4
+ import { Alert } from "./Alert.js";
5
+ import { useReactUIConfig } from "./react-ui-provider.js";
6
+ const AlertStackContext = createContext(undefined);
7
+ export function AlertStackProvider({ children, ref }) {
8
+ const { logger } = useReactUIConfig();
9
+ const queue = useRef([]);
10
+ const idSeq = useRef(0);
11
+ const [renderCount, forceRender] = useReducer((x) => x + 1, 0);
12
+ const showAlert = useCallback((message, options) => {
13
+ const alert = {
14
+ id: ++idSeq.current,
15
+ message,
16
+ severity: options?.severity ?? "info",
17
+ autoDismiss: options?.autoDismiss ?? false,
18
+ };
19
+ queue.current.push(alert);
20
+ forceRender();
21
+ }, []);
22
+ const dismissCurrent = useCallback(() => {
23
+ queue.current.shift();
24
+ forceRender();
25
+ }, []);
26
+ const showError = useCallback((error) => {
27
+ logger.error("AlertStack caught error:", error);
28
+ showAlert(messageOf(error), { severity: "error" });
29
+ }, [showAlert]);
30
+ useImperativeHandle(ref, () => ({ showAlert, showError }), [showAlert, showError]);
31
+ const contextValue = {
32
+ showAlert,
33
+ queue: queue.current,
34
+ dismissCurrent,
35
+ };
36
+ // renderCount is used to ensure context value updates trigger re-renders
37
+ void renderCount;
38
+ return _jsx(AlertStackContext.Provider, { value: contextValue, children: children });
39
+ }
40
+ export function useAlertStack() {
41
+ const context = useContext(AlertStackContext);
42
+ if (!context) {
43
+ throw new Error("useAlertStack must be used within an AlertStackProvider");
44
+ }
45
+ const showError = useCallback((error) => {
46
+ context.showAlert(messageOf(error), { severity: "error" });
47
+ }, [context.showAlert]);
48
+ return { showAlert: context.showAlert, showError };
49
+ }
50
+ export function AlertStack() {
51
+ const context = useContext(AlertStackContext);
52
+ const config = useReactUIConfig();
53
+ if (!context) {
54
+ throw new Error("AlertStack must be used within an AlertStackProvider");
55
+ }
56
+ const { queue, dismissCurrent } = context;
57
+ const currentAlert = queue[0];
58
+ useEffect(() => {
59
+ if (!currentAlert?.autoDismiss)
60
+ return;
61
+ const timer = setTimeout(dismissCurrent, config.autoDismissAlertDurationMs);
62
+ return () => clearTimeout(timer);
63
+ }, [
64
+ currentAlert?.id,
65
+ currentAlert?.autoDismiss,
66
+ config.autoDismissAlertDurationMs,
67
+ dismissCurrent,
68
+ ]);
69
+ if (!currentAlert)
70
+ return null;
71
+ return (_jsx(Alert, { severity: currentAlert.severity, onClose: dismissCurrent, children: currentAlert.message }));
72
+ }
package/dist/index.d.ts CHANGED
@@ -1,11 +1,37 @@
1
- import "../styles/index.scss";
2
- export * from "./PuAccordion.jsx";
3
- export * from "./PuButton.jsx";
4
- export * from "./PuCheckbox.jsx";
5
- export * from "./PuInput.jsx";
6
- export * from "./PuMenuItem.jsx";
7
- export * from "./PuPopupMenu.jsx";
8
- export * from "./PuSelect.jsx";
9
- export * from "./PuSideMenu.jsx";
10
- export * from "./PuSpinner.jsx";
1
+ import "../styles/theme/index.css";
2
+ export * from "./Checkbox.js";
3
+ export * from "./DateInput.js";
4
+ export * from "./InputNumber.js";
5
+ export * from "./InputText.js";
6
+ export * from "./MultiSelect.js";
7
+ export * from "./PasswordInput.js";
8
+ export * from "./RadioButton.js";
9
+ export * from "./Select.js";
10
+ export * from "./Switch.js";
11
+ export * from "./Textarea.js";
12
+ export * from "./ToggleGroup.js";
13
+ export * from "./Button.js";
14
+ export * from "./SplitButton.js";
15
+ export * from "./ToggleButton.js";
16
+ export * from "./Alert.js";
17
+ export * from "./Badge.js";
18
+ export * from "./Card.js";
19
+ export * from "./Chip.js";
20
+ export * from "./Column.js";
21
+ export * from "./DataTable.js";
22
+ export * from "./Breadcrumb.js";
23
+ export * from "./MenuItem.js";
24
+ export * from "./PopupMenu.js";
25
+ export * from "./SideMenu.js";
26
+ export * from "./Tabs.js";
27
+ export * from "./Dialog.js";
28
+ export * from "./Spinner.js";
29
+ export * from "./Tooltip.js";
30
+ export * from "./Accordion.js";
31
+ export * from "./Inplace.js";
32
+ export * from "./Panel.js";
33
+ export * from "./Tree.js";
34
+ export * from "./SortableList.js";
35
+ export * from "./alert-stack.js";
36
+ export * from "./react-ui-provider.js";
11
37
  export type * from "./paroi-ui-lib-types.js";
package/dist/index.js CHANGED
@@ -1,10 +1,45 @@
1
- import "../styles/index.scss";
2
- export * from "./PuAccordion.jsx";
3
- export * from "./PuButton.jsx";
4
- export * from "./PuCheckbox.jsx";
5
- export * from "./PuInput.jsx";
6
- export * from "./PuMenuItem.jsx";
7
- export * from "./PuPopupMenu.jsx";
8
- export * from "./PuSelect.jsx";
9
- export * from "./PuSideMenu.jsx";
10
- export * from "./PuSpinner.jsx";
1
+ import "../styles/theme/index.css";
2
+ // Form Controls
3
+ export * from "./Checkbox.js";
4
+ export * from "./DateInput.js";
5
+ export * from "./InputNumber.js";
6
+ export * from "./InputText.js";
7
+ export * from "./MultiSelect.js";
8
+ export * from "./PasswordInput.js";
9
+ export * from "./RadioButton.js";
10
+ export * from "./Select.js";
11
+ export * from "./Switch.js";
12
+ export * from "./Textarea.js";
13
+ export * from "./ToggleGroup.js";
14
+ // Buttons
15
+ export * from "./Button.js";
16
+ export * from "./SplitButton.js";
17
+ export * from "./ToggleButton.js";
18
+ // Data Display
19
+ export * from "./Alert.js";
20
+ export * from "./Badge.js";
21
+ export * from "./Card.js";
22
+ export * from "./Chip.js";
23
+ export * from "./Column.js";
24
+ export * from "./DataTable.js";
25
+ // Navigation
26
+ export * from "./Breadcrumb.js";
27
+ export * from "./MenuItem.js";
28
+ export * from "./PopupMenu.js";
29
+ export * from "./SideMenu.js";
30
+ export * from "./Tabs.js";
31
+ // Overlays & Feedback
32
+ export * from "./Dialog.js";
33
+ export * from "./Spinner.js";
34
+ export * from "./Tooltip.js";
35
+ // Layout
36
+ export * from "./Accordion.js";
37
+ export * from "./Inplace.js";
38
+ export * from "./Panel.js";
39
+ // Tree
40
+ export * from "./Tree.js";
41
+ // Drag & Drop
42
+ export * from "./SortableList.js";
43
+ // Providers
44
+ export * from "./alert-stack.js";
45
+ export * from "./react-ui-provider.js";
@@ -1,5 +1,5 @@
1
1
  import type { CSSProperties, ReactNode } from "react";
2
- export interface PuMenuOption {
2
+ export interface MenuOption {
3
3
  /**
4
4
  * Unique identifier of the menuitem.
5
5
  */
@@ -32,14 +32,14 @@ export interface PuMenuOption {
32
32
  * Callback to execute when item is clicked.
33
33
  */
34
34
  command?(): void;
35
- popupMenu?: PuMenuNode[];
35
+ popupMenu?: MenuNode[];
36
36
  active?: boolean;
37
37
  }
38
- export interface PuMenuNode extends PuMenuOption {
38
+ export interface MenuNode extends MenuOption {
39
39
  /**
40
40
  * An array of child menu items.
41
41
  */
42
- subMenu?: PuMenuNode[];
42
+ subMenu?: MenuNode[];
43
43
  /**
44
44
  * Initial visibility of submenu.
45
45
  */
@@ -0,0 +1,15 @@
1
+ import type { ReactNode } from "react";
2
+ export interface ReactUIConfig {
3
+ autoDismissAlertDurationMs?: number;
4
+ autoDismissInsideFeedbackDurationMs?: number;
5
+ logger?: {
6
+ error: (...messages: unknown[]) => void;
7
+ };
8
+ }
9
+ interface ReactUIProviderProps {
10
+ config?: ReactUIConfig;
11
+ children: ReactNode;
12
+ }
13
+ export declare function ReactUIProvider({ config, children }: ReactUIProviderProps): import("react/jsx-runtime").JSX.Element;
14
+ export declare function useReactUIConfig(): Required<ReactUIConfig>;
15
+ export {};
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from "react";
3
+ const ReactUIContext = createContext(undefined);
4
+ const defaultConfig = {
5
+ autoDismissAlertDurationMs: 5000,
6
+ autoDismissInsideFeedbackDurationMs: 2000,
7
+ logger: {
8
+ error: console.error,
9
+ },
10
+ };
11
+ export function ReactUIProvider({ config, children }) {
12
+ return _jsx(ReactUIContext.Provider, { value: config, children: children });
13
+ }
14
+ export function useReactUIConfig() {
15
+ const config = useContext(ReactUIContext);
16
+ return {
17
+ autoDismissAlertDurationMs: config?.autoDismissAlertDurationMs ?? defaultConfig.autoDismissAlertDurationMs,
18
+ autoDismissInsideFeedbackDurationMs: config?.autoDismissInsideFeedbackDurationMs ??
19
+ defaultConfig.autoDismissInsideFeedbackDurationMs,
20
+ logger: config?.logger ?? defaultConfig.logger,
21
+ };
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paroicms/react-ui",
3
- "version": "0.4.4",
3
+ "version": "0.5.0",
4
4
  "description": "React UI toolkit for ParoiCMS.",
5
5
  "keywords": [
6
6
  "paroicms",
@@ -19,19 +19,33 @@
19
19
  "main": "dist/index.js",
20
20
  "typings": "dist/index.d.ts",
21
21
  "scripts": {
22
+ "tsc": "tsc",
22
23
  "build": "tsc",
23
24
  "clear": "rimraf dist/*",
24
25
  "dev": "tsc --watch --preserveWatchOutput"
25
26
  },
27
+ "dependencies": {
28
+ "@paroicms/public-anywhere-lib": "0.41.0",
29
+ "clsx": "~2.1.1",
30
+ "lucide-react": "~0.562.0",
31
+ "react-sortablejs": "~6.1.4",
32
+ "sortablejs": "~1.15.6"
33
+ },
34
+ "peerDependencies": {
35
+ "react": ">=18.0.0",
36
+ "react-dom": ">=18.0.0"
37
+ },
26
38
  "devDependencies": {
27
39
  "@types/react": "~19.2.7",
28
40
  "@types/react-dom": "~19.2.3",
41
+ "@types/sortablejs": "^1.15.8",
29
42
  "react": "~19.2.0",
30
43
  "react-dom": "~19.2.0",
31
44
  "rimraf": "~6.1.2",
32
45
  "typescript": "~5.9.3"
33
46
  },
34
47
  "files": [
35
- "dist"
48
+ "dist",
49
+ "styles"
36
50
  ]
37
51
  }
@@ -0,0 +1,46 @@
1
+ /* ========================================
2
+ Accordion / Collapsible
3
+ ======================================== */
4
+ .PaAccordion-content {
5
+ padding-left: 20px;
6
+ transition: max-height 200ms ease-out;
7
+
8
+ &.transition {
9
+ overflow: hidden;
10
+ }
11
+
12
+ &.hide {
13
+ display: none;
14
+ }
15
+ }
16
+
17
+ .PaAccordion-header {
18
+ display: flex;
19
+ gap: var(--space-3);
20
+ align-items: center;
21
+ justify-content: space-between;
22
+ padding: var(--space-4) var(--space-5);
23
+ cursor: pointer;
24
+ background: var(--color-bg-subtle);
25
+ transition: background-color var(--transition);
26
+
27
+ /* &:hover {
28
+ background: var(--color-bg-section);
29
+ } */
30
+ }
31
+
32
+ .PaAccordion-title {
33
+ font-size: var(--text-base);
34
+ font-weight: var(--font-medium);
35
+ color: var(--color-text);
36
+ }
37
+
38
+ .PaAccordion-chevron {
39
+ flex-shrink: 0;
40
+ color: var(--color-text-light);
41
+ transition: transform var(--transition);
42
+
43
+ .PaAccordion.open & {
44
+ transform: rotate(180deg);
45
+ }
46
+ }
@@ -0,0 +1,76 @@
1
+ /* ========================================
2
+ Alert / Notice Box
3
+ ======================================== */
4
+ .PaAlert {
5
+ position: relative;
6
+ padding: var(--space-4) var(--space-5);
7
+ border-left: 4px solid;
8
+ border-radius: var(--radius);
9
+
10
+ &.dismissible {
11
+ padding-right: var(--space-10);
12
+ }
13
+
14
+ &.info {
15
+ background: var(--color-info-light);
16
+ border-color: var(--color-info);
17
+ }
18
+
19
+ &.primary {
20
+ background: var(--color-primary-light);
21
+ border-color: var(--color-primary);
22
+ }
23
+
24
+ &.success {
25
+ background: var(--color-success-light);
26
+ border-color: var(--color-success);
27
+ }
28
+
29
+ &.warning {
30
+ background: var(--color-yellow-light);
31
+ border-color: var(--color-yellow);
32
+ }
33
+
34
+ &.error {
35
+ background: var(--color-danger-light);
36
+ border-color: var(--color-danger);
37
+ }
38
+ }
39
+
40
+ .PaAlert-closeBtn {
41
+ position: absolute;
42
+ top: var(--space-3);
43
+ right: var(--space-3);
44
+ display: flex;
45
+ align-items: center;
46
+ justify-content: center;
47
+ padding: var(--space-1);
48
+ color: var(--color-text-muted);
49
+ cursor: pointer;
50
+ background: transparent;
51
+ border: none;
52
+ border-radius: var(--radius-sm);
53
+ transition:
54
+ color 0.15s,
55
+ background-color 0.15s;
56
+
57
+ &:hover {
58
+ color: var(--color-text);
59
+ background: rgb(0 0 0 / 10%);
60
+ }
61
+ }
62
+
63
+ .PaAlert-title {
64
+ margin-bottom: var(--space-2);
65
+ font-size: var(--text-sm);
66
+ font-weight: var(--font-semibold);
67
+ color: var(--color-text);
68
+ text-transform: uppercase;
69
+ letter-spacing: 0.025em;
70
+ }
71
+
72
+ .PaAlert-content {
73
+ font-size: var(--text-sm);
74
+ line-height: 1.7;
75
+ color: var(--color-text);
76
+ }
@@ -0,0 +1,59 @@
1
+ /* ========================================
2
+ Badges / Pills
3
+ ======================================== */
4
+ .PaBadge {
5
+ display: inline-flex;
6
+ gap: var(--space-1);
7
+ align-items: center;
8
+ padding: var(--space-1) var(--space-2);
9
+ font-size: var(--text-xs);
10
+ font-weight: var(--font-medium);
11
+ border-radius: var(--radius-full);
12
+
13
+ &.default {
14
+ color: var(--color-text-muted);
15
+ background: var(--color-bg-subtle);
16
+ border: 1px solid var(--color-border);
17
+ }
18
+
19
+ &.primary {
20
+ color: var(--color-primary-dark);
21
+ background: var(--color-primary-light);
22
+ }
23
+
24
+ &.accent {
25
+ color: var(--color-accent-dark);
26
+ background: var(--color-accent-light);
27
+ }
28
+
29
+ &.success {
30
+ color: var(--color-success-dark);
31
+ background: var(--color-success-light);
32
+ }
33
+
34
+ &.warning {
35
+ color: var(--color-yellow-dark);
36
+ background: var(--color-yellow-light);
37
+ }
38
+
39
+ &.danger {
40
+ color: var(--color-danger-dark);
41
+ background: var(--color-danger-light);
42
+ }
43
+
44
+ &.info {
45
+ color: var(--color-primary-dark);
46
+ background: var(--color-primary-subtle);
47
+ }
48
+
49
+ &.secondary {
50
+ color: var(--color-text-light);
51
+ background: var(--color-bg-muted);
52
+ border: 1px solid var(--color-border-light);
53
+ }
54
+
55
+ &.contrast {
56
+ color: var(--color-text-inverse);
57
+ background: var(--color-text);
58
+ }
59
+ }
@@ -0,0 +1,57 @@
1
+ /* ========================================
2
+ Breadcrumb
3
+ ======================================== */
4
+ .PaBreadcrumb {
5
+ display: flex;
6
+ flex-wrap: wrap;
7
+ gap: var(--space-1);
8
+ align-items: center;
9
+ }
10
+
11
+ .PaBreadcrumb-item {
12
+ display: flex;
13
+ gap: var(--space-1);
14
+ align-items: center;
15
+ }
16
+
17
+ .PaBreadcrumb-link {
18
+ max-width: 150px;
19
+ overflow: hidden;
20
+ text-overflow: ellipsis;
21
+ font-size: var(--text-sm);
22
+ color: var(--color-text-muted);
23
+ white-space: nowrap;
24
+ }
25
+
26
+ .PaBreadcrumb-link:is(a, button) {
27
+ cursor: pointer;
28
+ transition: color var(--transition);
29
+
30
+ &:hover {
31
+ color: var(--color-primary);
32
+ }
33
+ }
34
+
35
+ .PaBreadcrumb-separator {
36
+ display: flex;
37
+ align-items: center;
38
+ height: 100%;
39
+ padding: 0 var(--space-1);
40
+ font-size: var(--text-xs);
41
+ color: var(--color-text-light);
42
+
43
+ svg {
44
+ width: 16px;
45
+ height: 16px;
46
+ }
47
+ }
48
+
49
+ .PaBreadcrumb-current {
50
+ max-width: 200px;
51
+ overflow: hidden;
52
+ text-overflow: ellipsis;
53
+ font-size: var(--text-sm);
54
+ font-weight: var(--font-medium);
55
+ color: var(--color-text);
56
+ white-space: nowrap;
57
+ }