@fab1o978/react-ui 0.1.5 → 0.1.7

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,190 @@ 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
+ leftIcon,
655
+ rightIcon,
656
+ railBackground,
657
+ accent,
658
+ className,
659
+ disabled = false
660
+ }) => {
661
+ const isControlled = controlledValue !== void 0;
662
+ const [internalValue, setInternalValue] = React.useState(defaultValue);
663
+ const [isDragging, setIsDragging] = React.useState(false);
664
+ const [isFocused, setIsFocused] = React.useState(false);
665
+ const trackRef = React.useRef(null);
666
+ const thumbRef = React.useRef(null);
667
+ const value = isControlled ? controlledValue : internalValue;
668
+ const pct = (clamp(value, min, max) - min) / (max - min);
669
+ const accentVars = accent ? accentToCssVars(deriveAccent(accent), "slider") : {};
670
+ const setValue = React.useCallback(
671
+ (next) => {
672
+ const snapped = clamp(snapToStep(next, min, step), min, max);
673
+ if (!isControlled) setInternalValue(snapped);
674
+ onChange?.(snapped);
675
+ },
676
+ [isControlled, min, max, step, onChange]
677
+ );
678
+ const valueFromPointer = React.useCallback(
679
+ (e) => {
680
+ const rect = trackRef.current.getBoundingClientRect();
681
+ const ratio = clamp((e.clientX - rect.left) / rect.width, 0, 1);
682
+ return min + ratio * (max - min);
683
+ },
684
+ [min, max]
685
+ );
686
+ const handlePointerDown = React.useCallback(
687
+ (e) => {
688
+ if (disabled) return;
689
+ e.currentTarget.setPointerCapture(e.pointerId);
690
+ setIsDragging(true);
691
+ thumbRef.current?.focus();
692
+ setValue(valueFromPointer(e.nativeEvent));
693
+ },
694
+ [disabled, setValue, valueFromPointer]
695
+ );
696
+ const handlePointerMove = React.useCallback(
697
+ (e) => {
698
+ if (!isDragging || disabled) return;
699
+ setValue(valueFromPointer(e.nativeEvent));
700
+ },
701
+ [isDragging, disabled, setValue, valueFromPointer]
702
+ );
703
+ const handlePointerUp = React.useCallback(() => {
704
+ setIsDragging(false);
705
+ thumbRef.current?.blur();
706
+ }, []);
707
+ React.useEffect(() => {
708
+ const el = trackRef.current;
709
+ if (!el) return;
710
+ const onWheel = (e) => {
711
+ if (disabled) return;
712
+ e.preventDefault();
713
+ setValue(value + (e.deltaY < 0 ? step : -step));
714
+ };
715
+ el.addEventListener("wheel", onWheel, { passive: false });
716
+ return () => el.removeEventListener("wheel", onWheel);
717
+ }, [disabled, value, step, setValue]);
718
+ const handleKeyDown = React.useCallback(
719
+ (e) => {
720
+ if (disabled) return;
721
+ const map = {
722
+ ArrowRight: step,
723
+ ArrowUp: step,
724
+ ArrowLeft: -step,
725
+ ArrowDown: -step,
726
+ PageUp: step * 10,
727
+ PageDown: -step * 10
728
+ };
729
+ if (e.key === "Home") {
730
+ setValue(min);
731
+ e.preventDefault();
732
+ return;
733
+ }
734
+ if (e.key === "End") {
735
+ setValue(max);
736
+ e.preventDefault();
737
+ return;
738
+ }
739
+ if (map[e.key] !== void 0) {
740
+ setValue(value + map[e.key]);
741
+ e.preventDefault();
742
+ }
743
+ },
744
+ [disabled, step, min, max, value, setValue]
745
+ );
746
+ const tooltipVisible = showTooltip === "always" || showTooltip === "drag" && (isDragging || isFocused);
747
+ const displayValue = `${Math.round(value)}%`;
748
+ const tooltipOffset = `calc(${pct * 100}% + ${(0.5 - pct) * 20}px)`;
749
+ return /* @__PURE__ */ jsxRuntime.jsxs(
750
+ "div",
751
+ {
752
+ className: [SliderControl_module_default.wrapper, disabled ? SliderControl_module_default.disabled : "", className ?? ""].filter(Boolean).join(" "),
753
+ style: accentVars,
754
+ children: [
755
+ leftIcon !== null && leftIcon !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: SliderControl_module_default.icon, children: leftIcon }),
756
+ /* @__PURE__ */ jsxRuntime.jsxs(
757
+ "div",
758
+ {
759
+ ref: trackRef,
760
+ className: SliderControl_module_default.trackArea,
761
+ onPointerDown: handlePointerDown,
762
+ onPointerMove: handlePointerMove,
763
+ onPointerUp: handlePointerUp,
764
+ onPointerCancel: handlePointerUp,
765
+ children: [
766
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: SliderControl_module_default.groove, children: /* @__PURE__ */ jsxRuntime.jsx(
767
+ "div",
768
+ {
769
+ className: SliderControl_module_default.rail,
770
+ style: railBackground ? { background: railBackground } : void 0,
771
+ children: !railBackground && /* @__PURE__ */ jsxRuntime.jsx("div", { className: SliderControl_module_default.fill, style: { width: `${pct * 100}%` } })
772
+ }
773
+ ) }),
774
+ /* @__PURE__ */ jsxRuntime.jsx(
775
+ "div",
776
+ {
777
+ ref: thumbRef,
778
+ role: "slider",
779
+ tabIndex: disabled ? -1 : 0,
780
+ "aria-valuenow": Math.round(value),
781
+ "aria-valuemin": min,
782
+ "aria-valuemax": max,
783
+ "aria-disabled": disabled,
784
+ className: [SliderControl_module_default.thumb, isDragging ? SliderControl_module_default.thumbDragging : ""].filter(Boolean).join(" "),
785
+ style: { left: `calc(${pct * 100}% + ${(0.5 - pct) * 24}px)` },
786
+ onKeyDown: handleKeyDown,
787
+ onFocus: () => setIsFocused(true),
788
+ onBlur: () => setIsFocused(false)
789
+ }
790
+ ),
791
+ /* @__PURE__ */ jsxRuntime.jsx(
792
+ "div",
793
+ {
794
+ className: [SliderControl_module_default.tooltip, tooltipVisible ? SliderControl_module_default.tooltipVisible : ""].filter(Boolean).join(" "),
795
+ style: { left: tooltipOffset },
796
+ "aria-hidden": "true",
797
+ children: displayValue
798
+ }
799
+ )
800
+ ]
801
+ }
802
+ ),
803
+ rightIcon !== null && rightIcon !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: SliderControl_module_default.icon, children: rightIcon })
804
+ ]
805
+ }
806
+ );
807
+ };
808
+ SliderControl.displayName = "SliderControl";
629
809
  var DISC = 200;
630
810
  var CopyIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: [
631
811
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "5", y: "5", width: "7", height: "7", rx: "1.5", stroke: "currentColor", strokeWidth: "1.4" }),
@@ -795,50 +975,21 @@ var ColorPicker = ({
795
975
  },
796
976
  [updateDisc]
797
977
  );
798
- const updateL = React.useCallback(
799
- (clientX, rect) => {
800
- const nl = Math.max(0, Math.min(100, (clientX - rect.left) / rect.width * 100));
978
+ const handleLChange = React.useCallback(
979
+ (nl) => {
801
980
  setL(nl);
802
981
  notify(h, s, nl, a);
803
982
  },
804
983
  [h, s, a, notify]
805
984
  );
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));
985
+ const handleAChange = React.useCallback(
986
+ (val) => {
987
+ const na = val / 100;
823
988
  setA(na);
824
989
  notify(h, s, l, na);
825
990
  },
826
991
  [h, s, l, notify]
827
992
  );
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
993
  const { r: rr, g: gg, b: bb } = hslToRgb(h, s, l);
843
994
  const luminance = (0.299 * rr + 0.587 * gg + 0.114 * bb) / 255;
844
995
  const swatchFg = luminance > 0.6 ? "rgba(0,0,0,0.5)" : "rgba(255,255,255,0.9)";
@@ -851,7 +1002,6 @@ var ColorPicker = ({
851
1002
  hsl(${h}, ${s}%, 5%),
852
1003
  hsl(${h}, ${s}%, 50%),
853
1004
  hsl(${h}, ${s}%, 95%))`;
854
- const alphaGradient = `linear-gradient(to right, transparent, ${rgbStr})`;
855
1005
  const handleEyeDropper = async () => {
856
1006
  if (!window.EyeDropper) return;
857
1007
  try {
@@ -912,35 +1062,27 @@ var ColorPicker = ({
912
1062
  )
913
1063
  ] }) }),
914
1064
  /* @__PURE__ */ jsxRuntime.jsx(
915
- "div",
1065
+ SliderControl,
916
1066
  {
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
- )
1067
+ value: l,
1068
+ onChange: handleLChange,
1069
+ min: 0,
1070
+ max: 100,
1071
+ step: 1,
1072
+ showTooltip: "never",
1073
+ railBackground: lGradient
928
1074
  }
929
1075
  ),
930
1076
  showAlpha && /* @__PURE__ */ jsxRuntime.jsx(
931
- "div",
1077
+ SliderControl,
932
1078
  {
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
- )
1079
+ value: Math.round(a * 100),
1080
+ onChange: handleAChange,
1081
+ min: 0,
1082
+ max: 100,
1083
+ step: 1,
1084
+ showTooltip: "never",
1085
+ railBackground: `linear-gradient(to right, transparent, ${rgbStr}), repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%) 0 / 10px 10px`
944
1086
  }
945
1087
  ),
946
1088
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4565,6 +4707,7 @@ exports.PageBreak = PageBreak;
4565
4707
  exports.PageBreakButton = PageBreakButton;
4566
4708
  exports.RainCanvas = RainCanvas;
4567
4709
  exports.RichTextEditor = RichTextEditor;
4710
+ exports.SliderControl = SliderControl;
4568
4711
  exports.SlidingCounter = SlidingCounter;
4569
4712
  exports.Timeline = Timeline;
4570
4713
  //# sourceMappingURL=index.cjs.map