@marcoschwartz/lite-ui 0.27.3 → 0.27.4
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/index.js +60 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +103 -63
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3757,17 +3757,64 @@ var SegmentedControl = ({
|
|
|
3757
3757
|
}) => {
|
|
3758
3758
|
const groupId = (0, import_react20.useId)();
|
|
3759
3759
|
const groupName = name || `segmented-control-${groupId}`;
|
|
3760
|
+
const containerRef = (0, import_react20.useRef)(null);
|
|
3761
|
+
const indicatorRef = (0, import_react20.useRef)(null);
|
|
3760
3762
|
const options = (0, import_react20.useMemo)(() => normalizeData(data), [data]);
|
|
3761
3763
|
const [internalValue, setInternalValue] = (0, import_react20.useState)(
|
|
3762
3764
|
defaultValue || options[0]?.value || ""
|
|
3763
3765
|
);
|
|
3764
3766
|
const isControlled = controlledValue !== void 0;
|
|
3765
3767
|
const currentValue = isControlled ? controlledValue : internalValue;
|
|
3766
|
-
const [
|
|
3768
|
+
const [initialized, setInitialized] = (0, import_react20.useState)(false);
|
|
3767
3769
|
const activeIndex = options.findIndex((opt) => opt.value === currentValue);
|
|
3770
|
+
const updateIndicator = (0, import_react20.useCallback)((animate = true) => {
|
|
3771
|
+
if (!containerRef.current || !indicatorRef.current) return;
|
|
3772
|
+
const container = containerRef.current;
|
|
3773
|
+
const indicator = indicatorRef.current;
|
|
3774
|
+
if (activeIndex === -1) {
|
|
3775
|
+
indicator.style.display = "none";
|
|
3776
|
+
return;
|
|
3777
|
+
}
|
|
3778
|
+
const buttons = container.querySelectorAll("[data-segment-button]");
|
|
3779
|
+
const activeButton = buttons[activeIndex];
|
|
3780
|
+
if (!activeButton) return;
|
|
3781
|
+
const containerRect = container.getBoundingClientRect();
|
|
3782
|
+
const buttonRect = activeButton.getBoundingClientRect();
|
|
3783
|
+
if (!animate) {
|
|
3784
|
+
indicator.style.transitionDuration = "0ms";
|
|
3785
|
+
} else {
|
|
3786
|
+
indicator.style.transitionDuration = `${transitionDuration}ms`;
|
|
3787
|
+
}
|
|
3788
|
+
indicator.style.display = "block";
|
|
3789
|
+
if (orientation === "horizontal") {
|
|
3790
|
+
indicator.style.width = `${buttonRect.width}px`;
|
|
3791
|
+
indicator.style.height = `calc(100% - 8px)`;
|
|
3792
|
+
indicator.style.transform = `translateX(${buttonRect.left - containerRect.left - 4}px)`;
|
|
3793
|
+
} else {
|
|
3794
|
+
indicator.style.width = `calc(100% - 8px)`;
|
|
3795
|
+
indicator.style.height = `${buttonRect.height}px`;
|
|
3796
|
+
indicator.style.transform = `translateY(${buttonRect.top - containerRect.top - 4}px)`;
|
|
3797
|
+
}
|
|
3798
|
+
}, [activeIndex, orientation, transitionDuration]);
|
|
3799
|
+
(0, import_react20.useEffect)(() => {
|
|
3800
|
+
const timer = setTimeout(() => {
|
|
3801
|
+
updateIndicator(false);
|
|
3802
|
+
setInitialized(true);
|
|
3803
|
+
}, 20);
|
|
3804
|
+
return () => clearTimeout(timer);
|
|
3805
|
+
}, []);
|
|
3806
|
+
(0, import_react20.useEffect)(() => {
|
|
3807
|
+
if (initialized) {
|
|
3808
|
+
updateIndicator(true);
|
|
3809
|
+
}
|
|
3810
|
+
}, [currentValue, initialized, updateIndicator]);
|
|
3811
|
+
(0, import_react20.useEffect)(() => {
|
|
3812
|
+
const handleResize = () => updateIndicator(false);
|
|
3813
|
+
window.addEventListener("resize", handleResize);
|
|
3814
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
3815
|
+
}, [updateIndicator]);
|
|
3768
3816
|
const handleChange = (0, import_react20.useCallback)((newValue) => {
|
|
3769
3817
|
if (disabled) return;
|
|
3770
|
-
setHasInteracted(true);
|
|
3771
3818
|
if (!isControlled) {
|
|
3772
3819
|
setInternalValue(newValue);
|
|
3773
3820
|
}
|
|
@@ -3803,20 +3850,6 @@ var SegmentedControl = ({
|
|
|
3803
3850
|
}, [options, currentValue, orientation, handleChange]);
|
|
3804
3851
|
const sizeStyles2 = sizeConfig[size];
|
|
3805
3852
|
const radiusStyle = radiusConfig[radius];
|
|
3806
|
-
const totalOptions = options.length;
|
|
3807
|
-
const indicatorStyle = activeIndex >= 0 ? orientation === "horizontal" ? {
|
|
3808
|
-
width: `calc(${100 / totalOptions}% - ${totalOptions > 1 ? 0 : 0}px)`,
|
|
3809
|
-
height: "calc(100% - 8px)",
|
|
3810
|
-
left: `calc(${activeIndex / totalOptions * 100}% + 4px)`,
|
|
3811
|
-
top: "4px",
|
|
3812
|
-
transition: hasInteracted ? `left ${transitionDuration}ms ease, width ${transitionDuration}ms ease` : "none"
|
|
3813
|
-
} : {
|
|
3814
|
-
width: "calc(100% - 8px)",
|
|
3815
|
-
height: `calc(${100 / totalOptions}% - ${totalOptions > 1 ? 0 : 0}px)`,
|
|
3816
|
-
left: "4px",
|
|
3817
|
-
top: `calc(${activeIndex / totalOptions * 100}% + 4px)`,
|
|
3818
|
-
transition: hasInteracted ? `top ${transitionDuration}ms ease, height ${transitionDuration}ms ease` : "none"
|
|
3819
|
-
} : { display: "none" };
|
|
3820
3853
|
const containerClasses = [
|
|
3821
3854
|
"relative inline-flex p-1",
|
|
3822
3855
|
"bg-[hsl(var(--muted))]",
|
|
@@ -3829,6 +3862,7 @@ var SegmentedControl = ({
|
|
|
3829
3862
|
return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)(
|
|
3830
3863
|
"div",
|
|
3831
3864
|
{
|
|
3865
|
+
ref: containerRef,
|
|
3832
3866
|
role: "radiogroup",
|
|
3833
3867
|
"aria-label": ariaLabel || "Segmented control",
|
|
3834
3868
|
className: containerClasses,
|
|
@@ -3836,17 +3870,23 @@ var SegmentedControl = ({
|
|
|
3836
3870
|
/* @__PURE__ */ (0, import_jsx_runtime99.jsx)(
|
|
3837
3871
|
"div",
|
|
3838
3872
|
{
|
|
3873
|
+
ref: indicatorRef,
|
|
3839
3874
|
className: [
|
|
3840
|
-
"absolute z-0",
|
|
3875
|
+
"absolute z-0 top-1 left-1",
|
|
3841
3876
|
radiusStyle,
|
|
3842
3877
|
colorConfig[color],
|
|
3843
|
-
"shadow-sm"
|
|
3878
|
+
"shadow-sm",
|
|
3879
|
+
"transition-transform",
|
|
3880
|
+
initialized ? "opacity-100" : "opacity-0"
|
|
3844
3881
|
].join(" "),
|
|
3845
|
-
style:
|
|
3882
|
+
style: {
|
|
3883
|
+
transitionProperty: "transform, width, height, opacity",
|
|
3884
|
+
transitionTimingFunction: "ease"
|
|
3885
|
+
},
|
|
3846
3886
|
"aria-hidden": "true"
|
|
3847
3887
|
}
|
|
3848
3888
|
),
|
|
3849
|
-
options.map((option
|
|
3889
|
+
options.map((option) => {
|
|
3850
3890
|
const isActive = option.value === currentValue;
|
|
3851
3891
|
const isDisabled = disabled || option.disabled;
|
|
3852
3892
|
const buttonClasses = [
|