@fab1o978/react-ui 0.1.5 → 0.1.8

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.cjs CHANGED
@@ -607,10 +607,6 @@ var ColorPicker_module_default = {
607
607
  discWrapper: "ColorPicker_module_discWrapper",
608
608
  disc: "ColorPicker_module_disc",
609
609
  dot: "ColorPicker_module_dot",
610
- lSlider: "ColorPicker_module_lSlider",
611
- lThumb: "ColorPicker_module_lThumb",
612
- alphaSlider: "ColorPicker_module_alphaSlider",
613
- alphaThumb: "ColorPicker_module_alphaThumb",
614
610
  previewSwatch: "ColorPicker_module_previewSwatch",
615
611
  eyedropperBtn: "ColorPicker_module_eyedropperBtn",
616
612
  inputSection: "ColorPicker_module_inputSection",
@@ -626,6 +622,192 @@ var ColorPicker_module_default = {
626
622
  swatches: "ColorPicker_module_swatches",
627
623
  recentSwatch: "ColorPicker_module_recentSwatch"
628
624
  };
625
+
626
+ // src/components/SliderControl/SliderControl.module.scss
627
+ var SliderControl_module_default = {
628
+ wrapper: "SliderControl_module_wrapper",
629
+ disabled: "SliderControl_module_disabled",
630
+ icon: "SliderControl_module_icon",
631
+ trackArea: "SliderControl_module_trackArea",
632
+ groove: "SliderControl_module_groove",
633
+ rail: "SliderControl_module_rail",
634
+ fill: "SliderControl_module_fill",
635
+ thumb: "SliderControl_module_thumb",
636
+ thumbDragging: "SliderControl_module_thumbDragging",
637
+ tooltip: "SliderControl_module_tooltip",
638
+ tooltipVisible: "SliderControl_module_tooltipVisible"
639
+ };
640
+ function clamp(v, min, max) {
641
+ return Math.min(Math.max(v, min), max);
642
+ }
643
+ function snapToStep(v, min, step) {
644
+ return Math.round((v - min) / step) * step + min;
645
+ }
646
+ var SliderControl = ({
647
+ value: controlledValue,
648
+ defaultValue = 50,
649
+ min = 0,
650
+ max = 100,
651
+ step = 1,
652
+ onChange,
653
+ showTooltip = "drag",
654
+ showPercentage = false,
655
+ leftIcon,
656
+ rightIcon,
657
+ railBackground,
658
+ accent,
659
+ className,
660
+ disabled = false
661
+ }) => {
662
+ const isControlled = controlledValue !== void 0;
663
+ const [internalValue, setInternalValue] = React.useState(defaultValue);
664
+ const [isDragging, setIsDragging] = React.useState(false);
665
+ const [isFocused, setIsFocused] = React.useState(false);
666
+ const trackRef = React.useRef(null);
667
+ const thumbRef = React.useRef(null);
668
+ const value = isControlled ? controlledValue : internalValue;
669
+ const pct = (clamp(value, min, max) - min) / (max - min);
670
+ const accentVars = accent ? accentToCssVars(deriveAccent(accent), "slider") : {};
671
+ const setValue = React.useCallback(
672
+ (next) => {
673
+ const snapped = clamp(snapToStep(next, min, step), min, max);
674
+ if (!isControlled) setInternalValue(snapped);
675
+ onChange?.(snapped);
676
+ },
677
+ [isControlled, min, max, step, onChange]
678
+ );
679
+ const valueFromPointer = React.useCallback(
680
+ (e) => {
681
+ const rect = trackRef.current.getBoundingClientRect();
682
+ const ratio = clamp((e.clientX - rect.left) / rect.width, 0, 1);
683
+ return min + ratio * (max - min);
684
+ },
685
+ [min, max]
686
+ );
687
+ const handlePointerDown = React.useCallback(
688
+ (e) => {
689
+ if (disabled) return;
690
+ e.currentTarget.setPointerCapture(e.pointerId);
691
+ setIsDragging(true);
692
+ thumbRef.current?.focus();
693
+ setValue(valueFromPointer(e.nativeEvent));
694
+ },
695
+ [disabled, setValue, valueFromPointer]
696
+ );
697
+ const handlePointerMove = React.useCallback(
698
+ (e) => {
699
+ if (!isDragging || disabled) return;
700
+ setValue(valueFromPointer(e.nativeEvent));
701
+ },
702
+ [isDragging, disabled, setValue, valueFromPointer]
703
+ );
704
+ const handlePointerUp = React.useCallback(() => {
705
+ setIsDragging(false);
706
+ thumbRef.current?.blur();
707
+ }, []);
708
+ React.useEffect(() => {
709
+ const el = trackRef.current;
710
+ if (!el) return;
711
+ const onWheel = (e) => {
712
+ if (disabled) return;
713
+ e.preventDefault();
714
+ setValue(value + (e.deltaY < 0 ? step : -step));
715
+ };
716
+ el.addEventListener("wheel", onWheel, { passive: false });
717
+ return () => el.removeEventListener("wheel", onWheel);
718
+ }, [disabled, value, step, setValue]);
719
+ const handleKeyDown = React.useCallback(
720
+ (e) => {
721
+ if (disabled) return;
722
+ const map = {
723
+ ArrowRight: step,
724
+ ArrowUp: step,
725
+ ArrowLeft: -step,
726
+ ArrowDown: -step,
727
+ PageUp: step * 10,
728
+ PageDown: -step * 10
729
+ };
730
+ if (e.key === "Home") {
731
+ setValue(min);
732
+ e.preventDefault();
733
+ return;
734
+ }
735
+ if (e.key === "End") {
736
+ setValue(max);
737
+ e.preventDefault();
738
+ return;
739
+ }
740
+ if (map[e.key] !== void 0) {
741
+ setValue(value + map[e.key]);
742
+ e.preventDefault();
743
+ }
744
+ },
745
+ [disabled, step, min, max, value, setValue]
746
+ );
747
+ const tooltipVisible = showTooltip === "always" || showTooltip === "drag" && (isDragging || isFocused);
748
+ const decimals = step < 1 ? Math.ceil(-Math.log10(step)) : 0;
749
+ const displayValue = showPercentage ? `${Math.round((value - min) / (max - min) * 100)}%` : value.toFixed(decimals);
750
+ const tooltipOffset = `calc(${pct * 100}% + ${(0.5 - pct) * 20}px)`;
751
+ return /* @__PURE__ */ jsxRuntime.jsxs(
752
+ "div",
753
+ {
754
+ className: [SliderControl_module_default.wrapper, disabled ? SliderControl_module_default.disabled : "", className ?? ""].filter(Boolean).join(" "),
755
+ style: accentVars,
756
+ children: [
757
+ leftIcon !== null && leftIcon !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: SliderControl_module_default.icon, children: leftIcon }),
758
+ /* @__PURE__ */ jsxRuntime.jsxs(
759
+ "div",
760
+ {
761
+ ref: trackRef,
762
+ className: SliderControl_module_default.trackArea,
763
+ onPointerDown: handlePointerDown,
764
+ onPointerMove: handlePointerMove,
765
+ onPointerUp: handlePointerUp,
766
+ onPointerCancel: handlePointerUp,
767
+ children: [
768
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: SliderControl_module_default.groove, children: /* @__PURE__ */ jsxRuntime.jsx(
769
+ "div",
770
+ {
771
+ className: SliderControl_module_default.rail,
772
+ style: railBackground ? { background: railBackground } : void 0,
773
+ children: !railBackground && /* @__PURE__ */ jsxRuntime.jsx("div", { className: SliderControl_module_default.fill, style: { width: `${pct * 100}%` } })
774
+ }
775
+ ) }),
776
+ /* @__PURE__ */ jsxRuntime.jsx(
777
+ "div",
778
+ {
779
+ ref: thumbRef,
780
+ role: "slider",
781
+ tabIndex: disabled ? -1 : 0,
782
+ "aria-valuenow": Math.round(value),
783
+ "aria-valuemin": min,
784
+ "aria-valuemax": max,
785
+ "aria-disabled": disabled,
786
+ className: [SliderControl_module_default.thumb, isDragging ? SliderControl_module_default.thumbDragging : ""].filter(Boolean).join(" "),
787
+ style: { left: `calc(${pct * 100}% + ${(0.5 - pct) * 24}px)` },
788
+ onKeyDown: handleKeyDown,
789
+ onFocus: () => setIsFocused(true),
790
+ onBlur: () => setIsFocused(false)
791
+ }
792
+ ),
793
+ /* @__PURE__ */ jsxRuntime.jsx(
794
+ "div",
795
+ {
796
+ className: [SliderControl_module_default.tooltip, tooltipVisible ? SliderControl_module_default.tooltipVisible : ""].filter(Boolean).join(" "),
797
+ style: { left: tooltipOffset },
798
+ "aria-hidden": "true",
799
+ children: displayValue
800
+ }
801
+ )
802
+ ]
803
+ }
804
+ ),
805
+ rightIcon !== null && rightIcon !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: SliderControl_module_default.icon, children: rightIcon })
806
+ ]
807
+ }
808
+ );
809
+ };
810
+ SliderControl.displayName = "SliderControl";
629
811
  var DISC = 200;
630
812
  var CopyIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: [
631
813
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "5", y: "5", width: "7", height: "7", rx: "1.5", stroke: "currentColor", strokeWidth: "1.4" }),
@@ -795,50 +977,21 @@ var ColorPicker = ({
795
977
  },
796
978
  [updateDisc]
797
979
  );
798
- const updateL = React.useCallback(
799
- (clientX, rect) => {
800
- const nl = Math.max(0, Math.min(100, (clientX - rect.left) / rect.width * 100));
980
+ const handleLChange = React.useCallback(
981
+ (nl) => {
801
982
  setL(nl);
802
983
  notify(h, s, nl, a);
803
984
  },
804
985
  [h, s, a, notify]
805
986
  );
806
- const handleLPointerDown = React.useCallback(
807
- (e) => {
808
- e.currentTarget.setPointerCapture(e.pointerId);
809
- updateL(e.clientX, e.currentTarget.getBoundingClientRect());
810
- },
811
- [updateL]
812
- );
813
- const handleLPointerMove = React.useCallback(
814
- (e) => {
815
- if (e.buttons === 0) return;
816
- updateL(e.clientX, e.currentTarget.getBoundingClientRect());
817
- },
818
- [updateL]
819
- );
820
- const updateA = React.useCallback(
821
- (clientX, rect) => {
822
- const na = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
987
+ const handleAChange = React.useCallback(
988
+ (val) => {
989
+ const na = val / 100;
823
990
  setA(na);
824
991
  notify(h, s, l, na);
825
992
  },
826
993
  [h, s, l, notify]
827
994
  );
828
- const handleAPointerDown = React.useCallback(
829
- (e) => {
830
- e.currentTarget.setPointerCapture(e.pointerId);
831
- updateA(e.clientX, e.currentTarget.getBoundingClientRect());
832
- },
833
- [updateA]
834
- );
835
- const handleAPointerMove = React.useCallback(
836
- (e) => {
837
- if (e.buttons === 0) return;
838
- updateA(e.clientX, e.currentTarget.getBoundingClientRect());
839
- },
840
- [updateA]
841
- );
842
995
  const { r: rr, g: gg, b: bb } = hslToRgb(h, s, l);
843
996
  const luminance = (0.299 * rr + 0.587 * gg + 0.114 * bb) / 255;
844
997
  const swatchFg = luminance > 0.6 ? "rgba(0,0,0,0.5)" : "rgba(255,255,255,0.9)";
@@ -851,7 +1004,6 @@ var ColorPicker = ({
851
1004
  hsl(${h}, ${s}%, 5%),
852
1005
  hsl(${h}, ${s}%, 50%),
853
1006
  hsl(${h}, ${s}%, 95%))`;
854
- const alphaGradient = `linear-gradient(to right, transparent, ${rgbStr})`;
855
1007
  const handleEyeDropper = async () => {
856
1008
  if (!window.EyeDropper) return;
857
1009
  try {
@@ -912,35 +1064,27 @@ var ColorPicker = ({
912
1064
  )
913
1065
  ] }) }),
914
1066
  /* @__PURE__ */ jsxRuntime.jsx(
915
- "div",
1067
+ SliderControl,
916
1068
  {
917
- className: ColorPicker_module_default.lSlider,
918
- style: { backgroundImage: lGradient },
919
- onPointerDown: handleLPointerDown,
920
- onPointerMove: handleLPointerMove,
921
- children: /* @__PURE__ */ jsxRuntime.jsx(
922
- "div",
923
- {
924
- className: ColorPicker_module_default.lThumb,
925
- style: { left: `${l}%` }
926
- }
927
- )
1069
+ value: l,
1070
+ onChange: handleLChange,
1071
+ min: 0,
1072
+ max: 100,
1073
+ step: 1,
1074
+ showTooltip: "never",
1075
+ railBackground: lGradient
928
1076
  }
929
1077
  ),
930
1078
  showAlpha && /* @__PURE__ */ jsxRuntime.jsx(
931
- "div",
1079
+ SliderControl,
932
1080
  {
933
- className: ColorPicker_module_default.alphaSlider,
934
- style: { backgroundImage: alphaGradient },
935
- onPointerDown: handleAPointerDown,
936
- onPointerMove: handleAPointerMove,
937
- children: /* @__PURE__ */ jsxRuntime.jsx(
938
- "div",
939
- {
940
- className: ColorPicker_module_default.alphaThumb,
941
- style: { left: `${a * 100}%` }
942
- }
943
- )
1081
+ value: Math.round(a * 100),
1082
+ onChange: handleAChange,
1083
+ min: 0,
1084
+ max: 100,
1085
+ step: 1,
1086
+ showTooltip: "never",
1087
+ railBackground: `linear-gradient(to right, transparent, ${rgbStr}), repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%) 0 / 10px 10px`
944
1088
  }
945
1089
  ),
946
1090
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4565,6 +4709,7 @@ exports.PageBreak = PageBreak;
4565
4709
  exports.PageBreakButton = PageBreakButton;
4566
4710
  exports.RainCanvas = RainCanvas;
4567
4711
  exports.RichTextEditor = RichTextEditor;
4712
+ exports.SliderControl = SliderControl;
4568
4713
  exports.SlidingCounter = SlidingCounter;
4569
4714
  exports.Timeline = Timeline;
4570
4715
  //# sourceMappingURL=index.cjs.map