flikkui 0.1.0-beta.4 → 0.1.0-beta.6
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/components/charts/AreaChart/AreaChart.js +434 -0
- package/dist/components/charts/AreaChart/AreaChart.types.js +7 -0
- package/dist/components/charts/BarChart/BarChart.js +402 -0
- package/dist/components/charts/BarChart/BarChart.types.js +7 -0
- package/dist/components/charts/ChartContainer.js +38 -0
- package/dist/components/charts/Heatmap/Heatmap.js +153 -0
- package/dist/components/charts/Heatmap/HeatmapCell.js +100 -0
- package/dist/components/charts/Heatmap/HeatmapLegend.js +20 -0
- package/dist/components/charts/Heatmap/utils/heatmapUtils.js +174 -0
- package/dist/components/charts/LineChart/LineChart.js +396 -0
- package/dist/components/charts/LineChart/LineChart.types.js +7 -0
- package/dist/components/charts/hooks/useChartAccessibility.js +127 -0
- package/dist/components/charts/hooks/useChartTheme.js +86 -0
- package/dist/components/charts/hooks/useChartValidation.js +59 -0
- package/dist/components/charts/hooks/useTooltipPosition.js +292 -0
- package/dist/components/charts/shared/ChartAxis/XAxis.js +30 -0
- package/dist/components/charts/shared/ChartAxis/YAxis.js +97 -0
- package/dist/components/charts/shared/ChartCrosshair/ChartCrosshair.js +35 -0
- package/dist/components/charts/shared/ChartCrosshair/ChartCrosshair.theme.js +11 -0
- package/dist/components/charts/shared/ChartErrorBoundary/ChartErrorBoundary.js +66 -0
- package/dist/components/charts/shared/ChartGrid/HorizontalGrid.js +22 -0
- package/dist/components/charts/shared/ChartLegend/ChartLegend.js +30 -0
- package/dist/components/charts/shared/ChartLegend/ChartLegendContent.js +22 -0
- package/dist/components/charts/shared/ChartMarker/ChartMarker.js +25 -0
- package/dist/components/charts/shared/ChartMarker/ChartMarker.theme.js +9 -0
- package/dist/components/charts/shared/ChartText/ChartText.js +33 -0
- package/dist/components/charts/shared/ChartText/ChartText.theme.js +9 -0
- package/dist/components/charts/shared/ChartTooltip/ChartTooltip.js +62 -0
- package/dist/components/charts/theme/chart.theme.js +73 -0
- package/dist/components/charts/types/chart.types.js +29 -0
- package/dist/components/charts/utils/chart-validation.js +292 -0
- package/dist/components/charts/utils/color-utils.js +175 -0
- package/dist/components/core/Accordion/Accordion.animations.js +45 -0
- package/dist/components/core/Accordion/Accordion.js +52 -0
- package/dist/components/core/Accordion/Accordion.theme.js +8 -0
- package/dist/components/core/Accordion/AccordionContent.js +25 -0
- package/dist/components/core/Accordion/AccordionItem.js +56 -0
- package/dist/components/core/Accordion/AccordionTrigger.js +32 -0
- package/dist/components/core/Accordion/index.js +5 -0
- package/dist/components/core/Avatar/Avatar.js +94 -0
- package/dist/components/core/Avatar/Avatar.theme.js +25 -0
- package/dist/components/core/AvatarGroup/AvatarGroup.animations.js +79 -0
- package/dist/components/core/AvatarGroup/AvatarGroup.js +67 -0
- package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +23 -0
- package/dist/components/core/Badge/Badge.animations.js +109 -0
- package/dist/components/core/Badge/Badge.js +101 -0
- package/dist/components/core/Badge/Badge.theme.js +41 -0
- package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.js +8 -8
- package/dist/components/core/Button/Button.theme.js +5 -5
- package/dist/components/core/Card/Card.js +46 -0
- package/dist/components/core/Card/Card.theme.js +5 -0
- package/dist/components/core/Divider/Divider.js +21 -0
- package/dist/components/core/Divider/Divider.theme.js +19 -0
- package/dist/components/core/Pagination/Pagination.js +113 -0
- package/dist/components/core/Pagination/Pagination.theme.js +27 -0
- package/dist/components/core/Segmented/Segmented.js +69 -0
- package/dist/components/core/Segmented/Segmented.theme.js +40 -0
- package/dist/components/core/Segmented/SegmentedContext.js +8 -0
- package/dist/components/core/Segmented/SegmentedItem.js +30 -0
- package/dist/components/core/Stepper/Stepper.js +57 -0
- package/dist/components/core/Stepper/Stepper.theme.js +9 -0
- package/dist/components/core/Stepper/components/ConnectorLine.js +42 -0
- package/dist/components/core/Stepper/components/IconCircle.js +44 -0
- package/dist/components/core/Stepper/components/ProgressIndicator.js +12 -0
- package/dist/components/core/Stepper/components/StepContent.js +36 -0
- package/dist/components/core/Stepper/components/StepperItem.js +22 -0
- package/dist/components/core/Tabs/Tabs.theme.js +2 -2
- package/dist/components/core/Tooltip/Tooltip.animations.js +46 -0
- package/dist/components/core/Tooltip/Tooltip.js +85 -0
- package/dist/components/core/Tooltip/Tooltip.theme.js +11 -0
- package/dist/components/core/Tooltip/useTooltipPositioning.js +59 -0
- package/dist/components/core/Tree/Tree.animations.js +38 -0
- package/dist/components/core/Tree/Tree.js +177 -0
- package/dist/components/core/Tree/Tree.theme.js +11 -0
- package/dist/components/data-display/Table/Table.js +177 -0
- package/dist/components/data-display/Table/Table.theme.js +28 -0
- package/dist/components/data-display/Table/Table.utils.js +28 -0
- package/dist/components/data-display/Table/components/DeclarativeComponents.js +123 -0
- package/dist/components/data-display/Table/components/TableActions/TableActions.js +56 -0
- package/dist/components/data-display/Table/components/TableActions/TableActionsMenu.js +29 -0
- package/dist/components/data-display/Table/components/TableColumnManager/TableColumnManager.js +85 -0
- package/dist/components/data-display/Table/components/TableColumnManager/TableColumnManager.theme.js +21 -0
- package/dist/components/data-display/Table/components/TablePagination/TablePagination.js +51 -0
- package/dist/components/data-display/Table/components/TableSelectionHeader/TableSelectionHeader.js +29 -0
- package/dist/components/data-display/Table/components/core/TableBody.js +32 -0
- package/dist/components/data-display/Table/components/core/TableCell.js +47 -0
- package/dist/components/data-display/Table/components/core/TableHeader.js +77 -0
- package/dist/components/data-display/Table/components/core/TableRow.js +46 -0
- package/dist/components/data-display/Table/index.js +20 -0
- package/dist/components/feedback/Alert/Alert.js +36 -0
- package/dist/components/feedback/Alert/Alert.theme.js +17 -0
- package/dist/components/feedback/ChatMessage/ChatMessage.js +26 -0
- package/dist/components/feedback/ChatMessage/ChatMessage.theme.js +16 -0
- package/dist/components/feedback/Empty/Empty.js +26 -0
- package/dist/components/feedback/Empty/Empty.theme.js +13 -0
- package/dist/components/feedback/Notification/Notification.js +41 -0
- package/dist/components/feedback/Notification/Notification.theme.js +49 -0
- package/dist/components/feedback/Spinner/Spinner.theme.js +3 -3
- package/dist/components/feedback/Toast/Toast.animations.js +58 -0
- package/dist/components/feedback/Toast/Toast.js +67 -0
- package/dist/components/feedback/Toast/Toast.theme.js +18 -0
- package/dist/components/feedback/Toast/ToastProvider.js +73 -0
- package/dist/components/feedback/Toast/useToast.js +91 -0
- package/dist/components/forms/Checkbox/Checkbox.theme.js +1 -1
- package/dist/components/forms/FormLabel/FormLabel.theme.js +2 -2
- package/dist/components/forms/Input/Input.theme.js +4 -4
- package/dist/components/forms/Radio/Radio.theme.js +2 -2
- package/dist/components/forms/Select/Select.js +1 -1
- package/dist/components/forms/Select/Select.theme.js +5 -5
- package/dist/components/forms/Switch/Switch.theme.js +1 -1
- package/dist/components/forms/TimePicker/TimePicker.theme.js +19 -19
- package/dist/components/forms/forms.theme.js +8 -8
- package/dist/components/navigation/NavItem/NavItem.js +93 -0
- package/dist/components/navigation/NavItem/NavItem.theme.js +27 -0
- package/dist/components/navigation/Sidebar/Sidebar.js +28 -0
- package/dist/components/navigation/Sidebar/Sidebar.theme.js +16 -0
- package/dist/components/navigation/Sidebar/SidebarContent.js +12 -0
- package/dist/components/navigation/Sidebar/SidebarContext.js +38 -0
- package/dist/components/navigation/Sidebar/SidebarFooter.js +11 -0
- package/dist/components/navigation/Sidebar/SidebarHeader.js +22 -0
- package/dist/components/navigation/Sidebar/SidebarNav.js +11 -0
- package/dist/components/navigation/Sidebar/SidebarNavGroup.js +19 -0
- package/dist/components/navigation/Sidebar/SidebarToggle.js +26 -0
- package/dist/icons/core/TickIcon.js +3 -1
- package/dist/index.d.ts +29 -4
- package/dist/index.js +64 -4
- package/dist/node_modules/@heroicons/react/20/solid/esm/ChevronDownIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/ChevronDoubleLeftIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/ChevronDoubleRightIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/ChevronLeftIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/Cog6ToothIcon.js +32 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/DocumentIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/EllipsisVerticalIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/PlusIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/ArrowPathIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/BellIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/CheckCircleIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/ExclamationTriangleIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/InformationCircleIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/XCircleIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/XMarkIcon.js +26 -0
- package/dist/node_modules/tslib/tslib.es6.js +15 -1
- package/dist/utils/dateUtils.js +32 -0
- package/dist/utils/debounce.js +21 -0
- package/package.json +1 -1
- package/dist/styles.css +0 -2
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { __rest, __assign } from '../../../node_modules/tslib/tslib.es6.js';
|
|
2
|
+
import React__default, { useRef, useState, useEffect, useMemo } from 'react';
|
|
3
|
+
import { cn } from '../../../utils/cn.js';
|
|
4
|
+
import { debounce } from '../../../utils/debounce.js';
|
|
5
|
+
import { segmentedTheme } from './Segmented.theme.js';
|
|
6
|
+
import { SegmentedContext } from './SegmentedContext.js';
|
|
7
|
+
import { SegmentedItem } from './SegmentedItem.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Segmented component for selecting one option from a set of segments
|
|
11
|
+
* Uses compound component pattern with Segmented.Item
|
|
12
|
+
*/
|
|
13
|
+
var SegmentedComponent = React__default.forwardRef(function (_a, ref) {
|
|
14
|
+
var _b;
|
|
15
|
+
var value = _a.value, onChange = _a.onChange, _c = _a.size, size = _c === void 0 ? "md" : _c, _d = _a.disabled, disabled = _d === void 0 ? false : _d, _e = _a.block, block = _e === void 0 ? false : _e, children = _a.children, className = _a.className, slidingBackgroundClassName = _a.slidingBackgroundClassName, theme = _a.theme, props = __rest(_a, ["value", "onChange", "size", "disabled", "block", "children", "className", "slidingBackgroundClassName", "theme"]);
|
|
16
|
+
var containerRef = useRef(null);
|
|
17
|
+
var _f = useState({}), activeStyle = _f[0], setActiveStyle = _f[1];
|
|
18
|
+
var updateActiveStyle = function () {
|
|
19
|
+
if (!containerRef.current || !value)
|
|
20
|
+
return;
|
|
21
|
+
var activeButton = containerRef.current.querySelector("[data-value=\"".concat(value, "\"]"));
|
|
22
|
+
if (activeButton) {
|
|
23
|
+
var containerRect = containerRef.current.getBoundingClientRect();
|
|
24
|
+
var buttonRect = activeButton.getBoundingClientRect();
|
|
25
|
+
setActiveStyle({
|
|
26
|
+
width: buttonRect.width,
|
|
27
|
+
height: buttonRect.height,
|
|
28
|
+
transform: "translateX(".concat(buttonRect.left - containerRect.left - 2, "px)"),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
useEffect(function () {
|
|
33
|
+
updateActiveStyle();
|
|
34
|
+
}, [value]);
|
|
35
|
+
// Debounced resize handler for better performance
|
|
36
|
+
var debouncedUpdateActiveStyle = useMemo(function () { return debounce(updateActiveStyle, 100); }, [updateActiveStyle]);
|
|
37
|
+
useEffect(function () {
|
|
38
|
+
window.addEventListener('resize', debouncedUpdateActiveStyle);
|
|
39
|
+
return function () { return window.removeEventListener('resize', debouncedUpdateActiveStyle); };
|
|
40
|
+
}, [debouncedUpdateActiveStyle]);
|
|
41
|
+
var contextValue = {
|
|
42
|
+
selectedValue: value,
|
|
43
|
+
onChange: onChange,
|
|
44
|
+
size: size,
|
|
45
|
+
disabled: disabled,
|
|
46
|
+
};
|
|
47
|
+
return (React__default.createElement(SegmentedContext.Provider, { value: contextValue },
|
|
48
|
+
React__default.createElement("div", __assign({ ref: function (node) {
|
|
49
|
+
containerRef.current = node;
|
|
50
|
+
if (typeof ref === 'function') {
|
|
51
|
+
ref(node);
|
|
52
|
+
}
|
|
53
|
+
else if (ref) {
|
|
54
|
+
ref.current = node;
|
|
55
|
+
}
|
|
56
|
+
}, role: "tablist", "aria-orientation": "horizontal", className: cn((theme === null || theme === void 0 ? void 0 : theme.baseStyle) || segmentedTheme.baseStyle, ((_b = theme === null || theme === void 0 ? void 0 : theme.sizes) === null || _b === void 0 ? void 0 : _b[size]) || segmentedTheme.sizes[size], block && ((theme === null || theme === void 0 ? void 0 : theme.blockStyle) || segmentedTheme.blockStyle), disabled && ((theme === null || theme === void 0 ? void 0 : theme.disabledStyle) || segmentedTheme.disabledStyle), className // User overrides take precedence
|
|
57
|
+
), "data-size": size, "data-disabled": disabled, "data-block": block }, props),
|
|
58
|
+
value && (React__default.createElement("div", { className: cn((theme === null || theme === void 0 ? void 0 : theme.slidingBackgroundStyle) || segmentedTheme.slidingBackgroundStyle, slidingBackgroundClassName // User overrides take precedence
|
|
59
|
+
), style: activeStyle })),
|
|
60
|
+
children)));
|
|
61
|
+
});
|
|
62
|
+
// Set display name for dev tools and Storybook
|
|
63
|
+
SegmentedComponent.displayName = "Segmented";
|
|
64
|
+
// Create compound component with proper typing
|
|
65
|
+
var Segmented = Object.assign(SegmentedComponent, {
|
|
66
|
+
Item: SegmentedItem,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export { Segmented, Segmented as default };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default theme for the Segmented component
|
|
3
|
+
*/
|
|
4
|
+
var segmentedTheme = {
|
|
5
|
+
// Base styles for the segmented container
|
|
6
|
+
baseStyle: "relative flex rounded-[var(--segmented-rounded)] p-[2px] bg-neutral-100 overflow-hidden",
|
|
7
|
+
// Size variants using CSS variables
|
|
8
|
+
sizes: {
|
|
9
|
+
sm: "min-h-[var(--segmented-min-h-sm)]",
|
|
10
|
+
md: "min-h-[var(--segmented-min-h-md)]",
|
|
11
|
+
lg: "min-h-[var(--segmented-min-h-lg)]",
|
|
12
|
+
},
|
|
13
|
+
// Block style
|
|
14
|
+
blockStyle: "w-full",
|
|
15
|
+
// Disabled style
|
|
16
|
+
disabledStyle: "opacity-50 cursor-not-allowed pointer-events-none",
|
|
17
|
+
// Sliding background style with CSS variables
|
|
18
|
+
slidingBackgroundStyle: "absolute top-[2px] left-[2px] rounded-[calc(var(--segmented-rounded)-1.5px)] transition-transform duration-200 ease-out pointer-events-none z-0 bg-[var(--segmented-active-bg)] shadow-[var(--segmented-active-shadow)]",
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Default theme for the SegmentedItem component
|
|
22
|
+
*/
|
|
23
|
+
var segmentedItemTheme = {
|
|
24
|
+
// Base styles for the segmented item
|
|
25
|
+
baseStyle: "relative flex min-h-full min-w-fit flex-1 items-center justify-center transition-all duration-200 rounded-[calc(var(--segmented-rounded)-1.5px)] font-medium cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-1",
|
|
26
|
+
// Size variants using CSS variables
|
|
27
|
+
sizes: {
|
|
28
|
+
sm: "text-[length:var(--segmented-text-size-sm)] px-[var(--segmented-px-sm)]",
|
|
29
|
+
md: "text-[length:var(--segmented-text-size-md)] px-[var(--segmented-px-md)]",
|
|
30
|
+
lg: "text-[length:var(--segmented-text-size-lg)] px-[var(--segmented-px-lg)]",
|
|
31
|
+
},
|
|
32
|
+
// Selected state
|
|
33
|
+
selectedStyle: "text-neutral-900 z-10",
|
|
34
|
+
// Unselected state
|
|
35
|
+
unselectedStyle: "text-neutral-500 hover:text-neutral-800 ",
|
|
36
|
+
// Disabled state
|
|
37
|
+
disabledStyle: "opacity-50 cursor-not-allowed pointer-events-none",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { segmentedItemTheme, segmentedTheme };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { __rest, __assign } from '../../../node_modules/tslib/tslib.es6.js';
|
|
2
|
+
import React__default, { useContext } from 'react';
|
|
3
|
+
import { cn } from '../../../utils/cn.js';
|
|
4
|
+
import { segmentedItemTheme } from './Segmented.theme.js';
|
|
5
|
+
import { SegmentedContext } from './SegmentedContext.js';
|
|
6
|
+
|
|
7
|
+
var SegmentedItem = React__default.forwardRef(function (_a, ref) {
|
|
8
|
+
var value = _a.value, _b = _a.disabled, disabled = _b === void 0 ? false : _b, children = _a.children, className = _a.className, onClick = _a.onClick, props = __rest(_a, ["value", "disabled", "children", "className", "onClick"]);
|
|
9
|
+
var context = useContext(SegmentedContext);
|
|
10
|
+
if (!context) {
|
|
11
|
+
throw new Error("SegmentedItem must be used within a Segmented component");
|
|
12
|
+
}
|
|
13
|
+
var selectedValue = context.selectedValue, onChange = context.onChange, size = context.size, contextDisabled = context.disabled;
|
|
14
|
+
var isSelected = value === selectedValue;
|
|
15
|
+
var isDisabled = disabled || contextDisabled;
|
|
16
|
+
var handleClick = function (event) {
|
|
17
|
+
if (isDisabled)
|
|
18
|
+
return;
|
|
19
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(value);
|
|
20
|
+
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
21
|
+
};
|
|
22
|
+
return (React__default.createElement("button", __assign({ ref: ref, type: "button", role: "tab", "aria-selected": isSelected, disabled: isDisabled, className: cn(segmentedItemTheme.baseStyle, segmentedItemTheme.sizes[size], isSelected
|
|
23
|
+
? segmentedItemTheme.selectedStyle
|
|
24
|
+
: segmentedItemTheme.unselectedStyle, isDisabled && segmentedItemTheme.disabledStyle, className // User overrides take precedence
|
|
25
|
+
), onClick: handleClick, "data-value": value, "data-selected": isSelected, "data-disabled": isDisabled }, props), children));
|
|
26
|
+
});
|
|
27
|
+
// Set display name for dev tools and Storybook
|
|
28
|
+
SegmentedItem.displayName = "SegmentedItem";
|
|
29
|
+
|
|
30
|
+
export { SegmentedItem, SegmentedItem as default };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { __rest, __assign } from '../../../node_modules/tslib/tslib.es6.js';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { cn } from '../../../utils/cn.js';
|
|
4
|
+
import { stepperTheme } from './Stepper.theme.js';
|
|
5
|
+
import StepperItem from './components/StepperItem.js';
|
|
6
|
+
import ProgressIndicator from './components/ProgressIndicator.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Stepper component for displaying multi-step vertical progress
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <Stepper
|
|
14
|
+
* activeStep={1}
|
|
15
|
+
* steps={[
|
|
16
|
+
* { label: "Create account", completed: true },
|
|
17
|
+
* { label: "Profile information", active: true },
|
|
18
|
+
* { label: "Business information" },
|
|
19
|
+
* { label: "Theme" },
|
|
20
|
+
* { label: "Preview" }
|
|
21
|
+
* ]}
|
|
22
|
+
* />
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
var Stepper = React__default.forwardRef(function (_a, ref) {
|
|
26
|
+
var activeStep = _a.activeStep, steps = _a.steps, className = _a.className, props = __rest(_a, ["activeStep", "steps", "className"]);
|
|
27
|
+
// Helper function to determine step status
|
|
28
|
+
var getStepStatus = function (index, step) {
|
|
29
|
+
if (step.completed && (step.active || index === activeStep))
|
|
30
|
+
return 'active-complete';
|
|
31
|
+
if (step.completed)
|
|
32
|
+
return 'complete';
|
|
33
|
+
if (step.active || index === activeStep)
|
|
34
|
+
return 'current';
|
|
35
|
+
return 'upcoming';
|
|
36
|
+
};
|
|
37
|
+
return (
|
|
38
|
+
// Main navigation wrapper with ARIA label for accessibility
|
|
39
|
+
React__default.createElement("nav", __assign({ ref: ref, "aria-label": "Progress", className: cn(stepperTheme.baseStyle, className) }, props),
|
|
40
|
+
React__default.createElement("ol", { role: "list", className: "" }, steps === null || steps === void 0 ? void 0 : steps.map(function (step, stepIdx) {
|
|
41
|
+
var status = getStepStatus(stepIdx, step);
|
|
42
|
+
var isLast = stepIdx === steps.length - 1;
|
|
43
|
+
// Get the status of the next step (if there is one)
|
|
44
|
+
var nextStepStatus = !isLast
|
|
45
|
+
? getStepStatus(stepIdx + 1, steps[stepIdx + 1])
|
|
46
|
+
: undefined;
|
|
47
|
+
return (
|
|
48
|
+
// Individual step container
|
|
49
|
+
React__default.createElement("li", { key: step.label, className: cn(!isLast ? 'pb-10' : '', 'relative') },
|
|
50
|
+
React__default.createElement(StepperItem, { step: step, status: status, nextStepStatus: nextStepStatus, isLast: isLast, stepNumber: stepIdx + 1 })));
|
|
51
|
+
})),
|
|
52
|
+
React__default.createElement(ProgressIndicator, { activeStep: activeStep, totalSteps: steps.length })));
|
|
53
|
+
});
|
|
54
|
+
// Set display name for dev tools and Storybook
|
|
55
|
+
Stepper.displayName = "Stepper";
|
|
56
|
+
|
|
57
|
+
export { Stepper as default };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { cn } from '../../../../utils/cn.js';
|
|
3
|
+
import { motion } from '../../../../node_modules/framer-motion/dist/es/render/components/motion/proxy.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ConnectorLine component for displaying the vertical line between steps
|
|
7
|
+
*/
|
|
8
|
+
var ConnectorLine = function (_a) {
|
|
9
|
+
var status = _a.status, isLast = _a.isLast, nextStepStatus = _a.nextStepStatus, _b = _a.animate, animate = _b === void 0 ? false : _b, _c = _a.className, className = _c === void 0 ? "" : _c;
|
|
10
|
+
// If this is the last item, don't render a connector
|
|
11
|
+
if (isLast)
|
|
12
|
+
return null;
|
|
13
|
+
// Base styles for connector line
|
|
14
|
+
var baseStyles = "absolute top-4 left-4 -ml-px mt-0.5 h-full";
|
|
15
|
+
// Determine the connector style based on current and next step status
|
|
16
|
+
var statusStyles;
|
|
17
|
+
if (status === "complete" || status === "active-complete") {
|
|
18
|
+
if (nextStepStatus === "current") {
|
|
19
|
+
// Gradient only when connecting a completed step to the current step
|
|
20
|
+
statusStyles = "w-0.5 bg-gradient-to-b from-success-base to-primary-base";
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
// Solid green for connections between completed steps
|
|
24
|
+
statusStyles = "w-0.5 bg-success-base";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// Dashed line for incomplete steps
|
|
29
|
+
statusStyles = "border-l-2 border-dashed border-neutral-200";
|
|
30
|
+
}
|
|
31
|
+
// Only animate the connector line when it's a completed step connecting to the current step
|
|
32
|
+
var shouldAnimate = animate && (status === "complete" || status === "active-complete") && nextStepStatus === "current";
|
|
33
|
+
if (shouldAnimate) {
|
|
34
|
+
return (React__default.createElement(React__default.Fragment, null,
|
|
35
|
+
React__default.createElement("div", { "aria-hidden": "true", className: cn(baseStyles, "border-l-2 border-dashed border-neutral-200") }),
|
|
36
|
+
React__default.createElement(motion.div, { "aria-hidden": "true", className: cn(baseStyles, statusStyles, className, "origin-top"), initial: { scaleY: 0, opacity: 0 }, animate: { scaleY: 1, opacity: 1 }, transition: { duration: 0.8 } })));
|
|
37
|
+
}
|
|
38
|
+
// Non-animated connector - immediately show at full height
|
|
39
|
+
return (React__default.createElement("div", { "aria-hidden": "true", className: cn(baseStyles, statusStyles, className) }));
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { ConnectorLine as default };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React__default, { useState, useEffect } from 'react';
|
|
2
|
+
import { cn } from '../../../../utils/cn.js';
|
|
3
|
+
import '../../../../node_modules/tslib/tslib.es6.js';
|
|
4
|
+
import '../../../../icons/core/PlusIcon.js';
|
|
5
|
+
import '../../../../icons/core/MinusIcon.js';
|
|
6
|
+
import '../../../../icons/core/SearchIcon.js';
|
|
7
|
+
import '../../../../icons/core/LockIcon.js';
|
|
8
|
+
import '../../../../icons/core/DollarIcon.js';
|
|
9
|
+
import { TickIcon } from '../../../../icons/core/TickIcon.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* IconCircle component for displaying step status with consistent styling
|
|
13
|
+
*/
|
|
14
|
+
var IconCircle = function (_a) {
|
|
15
|
+
var status = _a.status, stepNumber = _a.stepNumber, _b = _a.animate, animate = _b === void 0 ? false : _b, _c = _a.className, className = _c === void 0 ? "" : _c;
|
|
16
|
+
// Track the visual status with a delay
|
|
17
|
+
var _d = useState(status), visualStatus = _d[0], setVisualStatus = _d[1];
|
|
18
|
+
// Update the visual status with a delay when the actual status changes
|
|
19
|
+
useEffect(function () {
|
|
20
|
+
if (animate && (status === "current" || status === "active-complete")) {
|
|
21
|
+
// Delay updating to "current" or "active-complete" status by 0.5 seconds
|
|
22
|
+
var timer_1 = setTimeout(function () {
|
|
23
|
+
setVisualStatus(status);
|
|
24
|
+
}, 500);
|
|
25
|
+
return function () { return clearTimeout(timer_1); };
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// For non-animated or non-current statuses, update immediately
|
|
29
|
+
setVisualStatus(status);
|
|
30
|
+
}
|
|
31
|
+
}, [status, animate]);
|
|
32
|
+
// Common base styles for all states
|
|
33
|
+
var baseStyles = "relative z-10 flex size-8 items-center justify-center rounded-full transition-all duration-300";
|
|
34
|
+
// Styles specific to each status
|
|
35
|
+
var statusStyles = {
|
|
36
|
+
complete: "bg-success-base ring-2 ring-white",
|
|
37
|
+
current: "border border-primary-base bg-white shadow-xl shadow-primary/20 ring-4 ring-primary-base/20",
|
|
38
|
+
upcoming: "border border-neutral-300 bg-white text-text-secondary/70",
|
|
39
|
+
"active-complete": "bg-success-base ring-2 ring-white shadow-xl shadow-success/20 ring-4 ring-success-base/20"
|
|
40
|
+
};
|
|
41
|
+
return (React__default.createElement("div", { className: cn(baseStyles, statusStyles[visualStatus], className) }, visualStatus === "complete" || visualStatus === "active-complete" ? (React__default.createElement(TickIcon, { size: "sm", className: "text-white", "aria-hidden": "true", strokeWidth: 3 })) : (React__default.createElement("div", { className: "font-bold text-sm ".concat(visualStatus === "current" ? "text-primary-base" : "") }, stepNumber))));
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { IconCircle as default };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
var ProgressIndicator = function (_a) {
|
|
4
|
+
var activeStep = _a.activeStep, totalSteps = _a.totalSteps;
|
|
5
|
+
return (React__default.createElement("div", { className: "text-xs text-text-placeholder font-medium mt-4" },
|
|
6
|
+
"Step ",
|
|
7
|
+
activeStep + 1,
|
|
8
|
+
" of ",
|
|
9
|
+
totalSteps));
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export { ProgressIndicator as default };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React__default, { useState, useEffect } from 'react';
|
|
2
|
+
import { cn } from '../../../../utils/cn.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* StepContent component for displaying step label and description
|
|
6
|
+
*/
|
|
7
|
+
var StepContent = function (_a) {
|
|
8
|
+
var step = _a.step, status = _a.status, _b = _a.animate, animate = _b === void 0 ? false : _b, _c = _a.className, className = _c === void 0 ? "" : _c;
|
|
9
|
+
// Track the visual status with a delay
|
|
10
|
+
var _d = useState(status), visualStatus = _d[0], setVisualStatus = _d[1];
|
|
11
|
+
// Update the visual status with a delay when the actual status changes
|
|
12
|
+
useEffect(function () {
|
|
13
|
+
if (animate && (status === "current" || status === "active-complete")) {
|
|
14
|
+
// Delay updating to "current" or "active-complete" status by 1 second to match IconCircle
|
|
15
|
+
var timer_1 = setTimeout(function () {
|
|
16
|
+
setVisualStatus(status);
|
|
17
|
+
}, 1000);
|
|
18
|
+
return function () { return clearTimeout(timer_1); };
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
// For non-animated or non-current statuses, update immediately
|
|
22
|
+
setVisualStatus(status);
|
|
23
|
+
}
|
|
24
|
+
}, [status, animate]);
|
|
25
|
+
return (React__default.createElement("div", { className: cn("ml-4 flex min-w-0 flex-col", className) },
|
|
26
|
+
React__default.createElement("div", { className: cn("text-sm font-semibold", visualStatus === "current" || visualStatus === "active-complete"
|
|
27
|
+
? "text-primary-base"
|
|
28
|
+
: visualStatus === "upcoming"
|
|
29
|
+
? "text-text-secondary"
|
|
30
|
+
: visualStatus === "complete"
|
|
31
|
+
? "text-text-primary"
|
|
32
|
+
: "") }, step.label),
|
|
33
|
+
step.description && (React__default.createElement("div", { className: "text-sm text-text-secondary" }, step.description))));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export { StepContent as default };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { cn } from '../../../../utils/cn.js';
|
|
3
|
+
import IconCircle from './IconCircle.js';
|
|
4
|
+
import ConnectorLine from './ConnectorLine.js';
|
|
5
|
+
import StepContent from './StepContent.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* StepperItem component for rendering an individual step
|
|
9
|
+
*/
|
|
10
|
+
var StepperItem = function (_a) {
|
|
11
|
+
var step = _a.step, status = _a.status, nextStepStatus = _a.nextStepStatus, isLast = _a.isLast, stepNumber = _a.stepNumber, _b = _a.className, className = _b === void 0 ? "" : _b;
|
|
12
|
+
// Content that goes inside either the <a> or <div> wrapper
|
|
13
|
+
var innerContent = (React__default.createElement(React__default.Fragment, null,
|
|
14
|
+
React__default.createElement("div", { className: "flex h-9 items-center", "aria-hidden": "true" },
|
|
15
|
+
React__default.createElement(IconCircle, { status: status, stepNumber: stepNumber, animate: status === "current" || status === "active-complete" })),
|
|
16
|
+
React__default.createElement(StepContent, { step: step, status: status, animate: status === "current" || status === "active-complete" })));
|
|
17
|
+
return (React__default.createElement(React__default.Fragment, null,
|
|
18
|
+
React__default.createElement(ConnectorLine, { status: status, isLast: isLast, nextStepStatus: nextStepStatus, animate: status === "complete" && nextStepStatus === "current" }),
|
|
19
|
+
step.href ? (React__default.createElement("a", { href: step.href, className: cn("group relative flex items-start", className), "aria-current": status === "current" ? "step" : undefined }, innerContent)) : (React__default.createElement("div", { className: cn("group relative flex items-start", className), "aria-current": status === "current" ? "step" : undefined }, innerContent))));
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export { StepperItem as default };
|
|
@@ -7,14 +7,14 @@ var tabsTheme = {
|
|
|
7
7
|
// TabsList styles
|
|
8
8
|
listStyle: "relative inline-flex items-center flex-row border-b border-border gap-2",
|
|
9
9
|
// TabsTrigger base styles with data-attribute state handling
|
|
10
|
-
triggerStyle: "relative inline-flex items-center justify-center whitespace-nowrap font-medium transition-all duration-300 cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-primary
|
|
10
|
+
triggerStyle: "relative inline-flex items-center justify-center whitespace-nowrap font-medium transition-all duration-300 cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 border-b-2 border-transparent hover:border-neutral-300 disabled:cursor-not-allowed disabled:opacity-50 text-text-muted hover:text-text-primary data-[state=active]:border-primary data-[state=active]:text-primary",
|
|
11
11
|
// TabsTrigger size variants
|
|
12
12
|
triggerSizes: {
|
|
13
13
|
sm: "px-2 py-1.5 text-sm gap-1",
|
|
14
14
|
md: "px-2 py-2 text-sm gap-2",
|
|
15
15
|
},
|
|
16
16
|
// TabsContent styles
|
|
17
|
-
contentStyle: "focus:outline-none focus-visible:ring-2 focus-visible:ring-primary
|
|
17
|
+
contentStyle: "focus:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2",
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
export { tabsTheme };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { __assign } from '../../../node_modules/tslib/tslib.es6.js';
|
|
2
|
+
|
|
3
|
+
// Define optimized spring configurations
|
|
4
|
+
var springConfig = {
|
|
5
|
+
type: "spring",
|
|
6
|
+
stiffness: 500,
|
|
7
|
+
damping: 30
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Base animation variants for the tooltip - optimized for smooth positioning
|
|
11
|
+
*/
|
|
12
|
+
var baseTooltipVariants = {
|
|
13
|
+
initial: {
|
|
14
|
+
opacity: 0,
|
|
15
|
+
transition: { duration: 0.1 }
|
|
16
|
+
},
|
|
17
|
+
animate: {
|
|
18
|
+
opacity: 1,
|
|
19
|
+
transition: __assign(__assign({}, springConfig), { duration: 0.2 })
|
|
20
|
+
},
|
|
21
|
+
exit: {
|
|
22
|
+
opacity: 0,
|
|
23
|
+
transition: { duration: 0.15, damping: 35 }
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Get animation variants based on tooltip placement
|
|
28
|
+
* @param placement - Tooltip placement (top, right, bottom, left)
|
|
29
|
+
* @returns Animation variants for the specified placement
|
|
30
|
+
*/
|
|
31
|
+
var getTooltipVariants = function (placement) {
|
|
32
|
+
switch (placement) {
|
|
33
|
+
case 'top':
|
|
34
|
+
return __assign(__assign({}, baseTooltipVariants), { initial: __assign(__assign({}, baseTooltipVariants.initial), { y: 2 }), animate: __assign(__assign({}, baseTooltipVariants.animate), { y: 0 }), exit: __assign(__assign({}, baseTooltipVariants.exit), { y: 2 }) });
|
|
35
|
+
case 'right':
|
|
36
|
+
return __assign(__assign({}, baseTooltipVariants), { initial: __assign(__assign({}, baseTooltipVariants.initial), { x: -2 }), animate: __assign(__assign({}, baseTooltipVariants.animate), { x: 0 }), exit: __assign(__assign({}, baseTooltipVariants.exit), { x: -2 }) });
|
|
37
|
+
case 'bottom':
|
|
38
|
+
return __assign(__assign({}, baseTooltipVariants), { initial: __assign(__assign({}, baseTooltipVariants.initial), { y: -2 }), animate: __assign(__assign({}, baseTooltipVariants.animate), { y: 0 }), exit: __assign(__assign({}, baseTooltipVariants.exit), { y: -2 }) });
|
|
39
|
+
case 'left':
|
|
40
|
+
return __assign(__assign({}, baseTooltipVariants), { initial: __assign(__assign({}, baseTooltipVariants.initial), { x: 2 }), animate: __assign(__assign({}, baseTooltipVariants.animate), { x: 0 }), exit: __assign(__assign({}, baseTooltipVariants.exit), { x: 2 }) });
|
|
41
|
+
default:
|
|
42
|
+
return baseTooltipVariants;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { baseTooltipVariants, getTooltipVariants };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { __assign } from '../../../node_modules/tslib/tslib.es6.js';
|
|
2
|
+
import React__default, { useState, useRef, useCallback, useEffect } from 'react';
|
|
3
|
+
import { cn } from '../../../utils/cn.js';
|
|
4
|
+
import { tooltipTheme } from './Tooltip.theme.js';
|
|
5
|
+
import { getTooltipVariants } from './Tooltip.animations.js';
|
|
6
|
+
import { useTooltipPositioning } from './useTooltipPositioning.js';
|
|
7
|
+
import { AnimatePresence } from '../../../node_modules/framer-motion/dist/es/components/AnimatePresence/index.js';
|
|
8
|
+
import { motion } from '../../../node_modules/framer-motion/dist/es/render/components/motion/proxy.js';
|
|
9
|
+
|
|
10
|
+
var Tooltip = function (_a) {
|
|
11
|
+
var content = _a.content, children = _a.children, _b = _a.placement, placement = _b === void 0 ? 'top' : _b, _c = _a.delay, delay = _c === void 0 ? 300 : _c, _d = _a.disabled, disabled = _d === void 0 ? false : _d, className = _a.className, _e = _a.maxWidth, maxWidth = _e === void 0 ? "360px" : _e, _f = _a.minWidth, minWidth = _f === void 0 ? "fit-content" : _f, _g = _a.showOnFocus, showOnFocus = _g === void 0 ? true : _g, _h = _a.wrapText, wrapText = _h === void 0 ? false : _h, id = _a.id, themeOverrides = _a.theme, ariaLabel = _a["aria-label"], _j = _a.role, role = _j === void 0 ? 'tooltip' : _j;
|
|
12
|
+
var _k = useState(false), isVisible = _k[0], setIsVisible = _k[1];
|
|
13
|
+
var tooltipRef = useRef(null);
|
|
14
|
+
var triggerRef = useRef(null);
|
|
15
|
+
var timerRef = useRef(null);
|
|
16
|
+
// Merge global theme with component-specific overrides
|
|
17
|
+
var theme = __assign(__assign({}, tooltipTheme), (themeOverrides || {}));
|
|
18
|
+
// Use custom positioning hook
|
|
19
|
+
var debouncedPositioning = useTooltipPositioning({
|
|
20
|
+
tooltipRef: tooltipRef,
|
|
21
|
+
triggerRef: triggerRef,
|
|
22
|
+
placement: placement,
|
|
23
|
+
isVisible: isVisible,
|
|
24
|
+
}).debouncedPositioning;
|
|
25
|
+
// Event handlers - simplified timer management
|
|
26
|
+
var handleShowTooltip = useCallback(function () {
|
|
27
|
+
if (disabled)
|
|
28
|
+
return;
|
|
29
|
+
if (timerRef.current) {
|
|
30
|
+
clearTimeout(timerRef.current);
|
|
31
|
+
}
|
|
32
|
+
timerRef.current = setTimeout(function () {
|
|
33
|
+
setIsVisible(true);
|
|
34
|
+
}, delay);
|
|
35
|
+
}, [disabled, delay]);
|
|
36
|
+
var handleHideTooltip = useCallback(function () {
|
|
37
|
+
if (timerRef.current) {
|
|
38
|
+
clearTimeout(timerRef.current);
|
|
39
|
+
}
|
|
40
|
+
// Immediate hide for better responsiveness
|
|
41
|
+
setIsVisible(false);
|
|
42
|
+
}, []);
|
|
43
|
+
// Clean up timeout on unmount
|
|
44
|
+
useEffect(function () {
|
|
45
|
+
return function () {
|
|
46
|
+
if (timerRef.current) {
|
|
47
|
+
clearTimeout(timerRef.current);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}, []);
|
|
51
|
+
// Handle window resize with debouncing - only when tooltip is visible
|
|
52
|
+
useEffect(function () {
|
|
53
|
+
if (isVisible) {
|
|
54
|
+
window.addEventListener('resize', debouncedPositioning);
|
|
55
|
+
return function () {
|
|
56
|
+
window.removeEventListener('resize', debouncedPositioning);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}, [isVisible, debouncedPositioning]);
|
|
60
|
+
// Keyboard handler - removed isVisible dependency to prevent re-creation
|
|
61
|
+
var handleKeyDown = useCallback(function (e) {
|
|
62
|
+
if (e.key === 'Escape') {
|
|
63
|
+
handleHideTooltip();
|
|
64
|
+
}
|
|
65
|
+
}, [handleHideTooltip]);
|
|
66
|
+
// Event handlers for trigger element - using mouse events for better predictability
|
|
67
|
+
var triggerHandlers = __assign(__assign({ onMouseEnter: handleShowTooltip, onMouseLeave: handleHideTooltip }, (showOnFocus && {
|
|
68
|
+
onFocus: handleShowTooltip,
|
|
69
|
+
onBlur: handleHideTooltip,
|
|
70
|
+
})), { onKeyDown: handleKeyDown });
|
|
71
|
+
// Computed values - simplified without unnecessary memoization
|
|
72
|
+
var textOverflowClass = wrapText ? '' : 'text-ellipsis overflow-hidden whitespace-nowrap';
|
|
73
|
+
var widthClasses = cn(minWidth === 'fit-content' ? 'w-fit' : 'min-w-fit', textOverflowClass);
|
|
74
|
+
return (React__default.createElement("div", __assign({ className: "relative inline-block", ref: triggerRef }, triggerHandlers, { tabIndex: showOnFocus ? 0 : undefined, "aria-describedby": isVisible && id ? id : undefined }),
|
|
75
|
+
children,
|
|
76
|
+
React__default.createElement(AnimatePresence, null, isVisible && (React__default.createElement(motion.div, { id: id, role: role, ref: tooltipRef, style: {
|
|
77
|
+
maxWidth: maxWidth,
|
|
78
|
+
minWidth: minWidth !== 'fit-content' ? minWidth : undefined,
|
|
79
|
+
width: 'max-content'
|
|
80
|
+
}, className: cn(theme.baseStyle, theme[placement] || '', widthClasses, className), "aria-hidden": !isVisible, "aria-label": ariaLabel, "aria-live": role === 'tooltip' ? 'polite' : undefined, variants: getTooltipVariants(placement), initial: "initial", animate: "animate", exit: "exit" }, content)))));
|
|
81
|
+
};
|
|
82
|
+
// Set display name for dev tools and Storybook
|
|
83
|
+
Tooltip.displayName = "Tooltip";
|
|
84
|
+
|
|
85
|
+
export { Tooltip as default };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
var tooltipTheme = {
|
|
2
|
+
// Base style for the tooltip
|
|
3
|
+
baseStyle: "absolute z-50 bg-background border border-border rounded-lg p-1.5 px-2 shadow-xl text-xs font-medium text-text-primary transition-opacity duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 pointer-events-none",
|
|
4
|
+
// Placement styles - flattened
|
|
5
|
+
top: "bottom-full mb-2.5 text-center",
|
|
6
|
+
right: "left-full ml-2.5 text-left",
|
|
7
|
+
bottom: "top-full mt-2.5 text-center",
|
|
8
|
+
left: "right-full mr-2.5 text-right",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export { tooltipTheme };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { useRef, useCallback, useEffect } from 'react';
|
|
2
|
+
import { debounce } from '../../../utils/debounce.js';
|
|
3
|
+
import '../../../node_modules/tslib/tslib.es6.js';
|
|
4
|
+
|
|
5
|
+
var useTooltipPositioning = function (_a) {
|
|
6
|
+
var tooltipRef = _a.tooltipRef, triggerRef = _a.triggerRef, placement = _a.placement, isVisible = _a.isVisible;
|
|
7
|
+
// Stable refs to break dependency cycles
|
|
8
|
+
var placementRef = useRef(placement);
|
|
9
|
+
var isVisibleRef = useRef(isVisible);
|
|
10
|
+
// Update refs without causing re-renders
|
|
11
|
+
placementRef.current = placement;
|
|
12
|
+
isVisibleRef.current = isVisible;
|
|
13
|
+
// Optimized positioning function - reduces getBoundingClientRect calls
|
|
14
|
+
var positionTooltip = useCallback(function () {
|
|
15
|
+
if (!tooltipRef.current || !triggerRef.current || !isVisibleRef.current)
|
|
16
|
+
return;
|
|
17
|
+
var tooltipElement = tooltipRef.current;
|
|
18
|
+
var triggerElement = triggerRef.current;
|
|
19
|
+
var currentPlacement = placementRef.current;
|
|
20
|
+
// Single getBoundingClientRect call for trigger
|
|
21
|
+
var triggerRect = triggerElement.getBoundingClientRect();
|
|
22
|
+
// Only get tooltip rect when needed for centering calculations
|
|
23
|
+
if (currentPlacement === 'top' || currentPlacement === 'bottom') {
|
|
24
|
+
var tooltipRect = tooltipElement.getBoundingClientRect();
|
|
25
|
+
var leftOffset = (triggerRect.width - tooltipRect.width) / 2;
|
|
26
|
+
tooltipElement.style.left = "".concat(leftOffset, "px");
|
|
27
|
+
}
|
|
28
|
+
else if (currentPlacement === 'left' || currentPlacement === 'right') {
|
|
29
|
+
var tooltipRect = tooltipElement.getBoundingClientRect();
|
|
30
|
+
var topOffset = (triggerRect.height - tooltipRect.height) / 2;
|
|
31
|
+
tooltipElement.style.top = "".concat(topOffset, "px");
|
|
32
|
+
}
|
|
33
|
+
}, []); // No dependencies = stable function!
|
|
34
|
+
// Stable debounced positioning - no dependency on positionTooltip
|
|
35
|
+
var debouncedPositioning = useCallback(debounce(function () {
|
|
36
|
+
if (isVisibleRef.current) {
|
|
37
|
+
positionTooltip();
|
|
38
|
+
}
|
|
39
|
+
}, 100), [] // No dependencies = stable function!
|
|
40
|
+
);
|
|
41
|
+
// Single positioning effect - only triggers when visibility changes
|
|
42
|
+
useEffect(function () {
|
|
43
|
+
if (isVisible && tooltipRef.current && triggerRef.current) {
|
|
44
|
+
// Reduced delay for better responsiveness
|
|
45
|
+
var timeoutId_1 = setTimeout(function () {
|
|
46
|
+
if (isVisibleRef.current) {
|
|
47
|
+
positionTooltip();
|
|
48
|
+
}
|
|
49
|
+
}, 10); // Reduced from 16ms to 10ms
|
|
50
|
+
return function () { return clearTimeout(timeoutId_1); };
|
|
51
|
+
}
|
|
52
|
+
}, [isVisible]); // Removed positionTooltip dependency to prevent circular re-renders
|
|
53
|
+
return {
|
|
54
|
+
positionTooltip: positionTooltip,
|
|
55
|
+
debouncedPositioning: debouncedPositioning,
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export { useTooltipPositioning };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Animation variants for expand/collapse
|
|
2
|
+
var treeNodeVariants = {
|
|
3
|
+
expanded: {
|
|
4
|
+
opacity: 1,
|
|
5
|
+
height: 'auto',
|
|
6
|
+
transition: {
|
|
7
|
+
duration: 0.2,
|
|
8
|
+
ease: 'easeOut',
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
collapsed: {
|
|
12
|
+
opacity: 0,
|
|
13
|
+
height: 0,
|
|
14
|
+
transition: {
|
|
15
|
+
duration: 0.15,
|
|
16
|
+
ease: 'easeIn',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
// Animation variants for expand icon rotation
|
|
21
|
+
var expandIconVariants = {
|
|
22
|
+
expanded: {
|
|
23
|
+
rotate: 90,
|
|
24
|
+
transition: {
|
|
25
|
+
duration: 0.2,
|
|
26
|
+
ease: 'easeOut',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
collapsed: {
|
|
30
|
+
rotate: 0,
|
|
31
|
+
transition: {
|
|
32
|
+
duration: 0.15,
|
|
33
|
+
ease: 'easeIn',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export { expandIconVariants, treeNodeVariants };
|