@marcoschwartz/lite-ui 0.27.0 → 0.27.3

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 CHANGED
@@ -3757,54 +3757,23 @@ 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 [indicatorStyle, setIndicatorStyle] = (0, import_react20.useState)({});
3762
- const options = normalizeData(data);
3760
+ const options = (0, import_react20.useMemo)(() => normalizeData(data), [data]);
3763
3761
  const [internalValue, setInternalValue] = (0, import_react20.useState)(
3764
3762
  defaultValue || options[0]?.value || ""
3765
3763
  );
3766
3764
  const isControlled = controlledValue !== void 0;
3767
3765
  const currentValue = isControlled ? controlledValue : internalValue;
3766
+ const [hasInteracted, setHasInteracted] = (0, import_react20.useState)(false);
3767
+ const activeIndex = options.findIndex((opt) => opt.value === currentValue);
3768
3768
  const handleChange = (0, import_react20.useCallback)((newValue) => {
3769
3769
  if (disabled) return;
3770
+ setHasInteracted(true);
3770
3771
  if (!isControlled) {
3771
3772
  setInternalValue(newValue);
3772
3773
  }
3773
3774
  onChange?.(newValue);
3774
3775
  }, [disabled, isControlled, onChange]);
3775
- const updateIndicator = (0, import_react20.useCallback)(() => {
3776
- if (!containerRef.current) return;
3777
- const container = containerRef.current;
3778
- const activeIndex = options.findIndex((opt) => opt.value === currentValue);
3779
- if (activeIndex === -1) return;
3780
- const buttons = container.querySelectorAll("[data-segment-button]");
3781
- const activeButton = buttons[activeIndex];
3782
- if (!activeButton) return;
3783
- const containerRect = container.getBoundingClientRect();
3784
- const buttonRect = activeButton.getBoundingClientRect();
3785
- if (orientation === "horizontal") {
3786
- setIndicatorStyle({
3787
- width: buttonRect.width,
3788
- height: "100%",
3789
- transform: `translateX(${buttonRect.left - containerRect.left}px)`,
3790
- transition: `transform ${transitionDuration}ms ease, width ${transitionDuration}ms ease`
3791
- });
3792
- } else {
3793
- setIndicatorStyle({
3794
- width: "100%",
3795
- height: buttonRect.height,
3796
- transform: `translateY(${buttonRect.top - containerRect.top}px)`,
3797
- transition: `transform ${transitionDuration}ms ease, height ${transitionDuration}ms ease`
3798
- });
3799
- }
3800
- }, [currentValue, options, orientation, transitionDuration]);
3801
- (0, import_react20.useEffect)(() => {
3802
- updateIndicator();
3803
- const handleResize = () => updateIndicator();
3804
- window.addEventListener("resize", handleResize);
3805
- return () => window.removeEventListener("resize", handleResize);
3806
- }, [updateIndicator]);
3807
- const handleKeyDown = (0, import_react20.useCallback)((e, index) => {
3776
+ const handleKeyDown = (0, import_react20.useCallback)((e) => {
3808
3777
  const enabledOptions = options.filter((opt) => !opt.disabled);
3809
3778
  const currentEnabledIndex = enabledOptions.findIndex((opt) => opt.value === currentValue);
3810
3779
  let nextIndex = -1;
@@ -3830,15 +3799,24 @@ var SegmentedControl = ({
3830
3799
  e.preventDefault();
3831
3800
  const nextOption = enabledOptions[nextIndex];
3832
3801
  handleChange(nextOption.value);
3833
- const buttons = containerRef.current?.querySelectorAll("[data-segment-button]");
3834
- const nextButton = Array.from(buttons || []).find(
3835
- (btn) => btn.getAttribute("data-value") === nextOption.value
3836
- );
3837
- nextButton?.focus();
3838
3802
  }
3839
3803
  }, [options, currentValue, orientation, handleChange]);
3840
3804
  const sizeStyles2 = sizeConfig[size];
3841
3805
  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" };
3842
3820
  const containerClasses = [
3843
3821
  "relative inline-flex p-1",
3844
3822
  "bg-[hsl(var(--muted))]",
@@ -3851,7 +3829,6 @@ var SegmentedControl = ({
3851
3829
  return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)(
3852
3830
  "div",
3853
3831
  {
3854
- ref: containerRef,
3855
3832
  role: "radiogroup",
3856
3833
  "aria-label": ariaLabel || "Segmented control",
3857
3834
  className: containerClasses,
@@ -3860,7 +3837,7 @@ var SegmentedControl = ({
3860
3837
  "div",
3861
3838
  {
3862
3839
  className: [
3863
- "absolute top-1 left-1 z-0",
3840
+ "absolute z-0",
3864
3841
  radiusStyle,
3865
3842
  colorConfig[color],
3866
3843
  "shadow-sm"
@@ -3897,7 +3874,7 @@ var SegmentedControl = ({
3897
3874
  tabIndex: isActive ? 0 : -1,
3898
3875
  className: buttonClasses,
3899
3876
  onClick: () => !isDisabled && handleChange(option.value),
3900
- onKeyDown: (e) => handleKeyDown(e, index),
3877
+ onKeyDown: handleKeyDown,
3901
3878
  children: [
3902
3879
  option.label,
3903
3880
  /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(