@plexui/ui 0.2.1 → 0.4.0
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/es/components/Field/Field.js +34 -0
- package/dist/es/components/Field/Field.js.map +1 -0
- package/dist/es/components/Field/Field.module.css +97 -0
- package/dist/es/components/Field/index.js +2 -0
- package/dist/es/components/Field/index.js.map +1 -0
- package/dist/es/components/SegmentedControl/index.js +1 -1
- package/dist/es/components/SegmentedControl/index.js.map +1 -1
- package/dist/es/components/Slider/Slider.js +68 -37
- package/dist/es/components/Slider/Slider.js.map +1 -1
- package/dist/es/components/Slider/Slider.module.css +36 -3
- package/dist/es/components/Tabs/Tabs.js +153 -0
- package/dist/es/components/Tabs/Tabs.js.map +1 -0
- package/dist/es/components/{SegmentedControl/SegmentedControl.module.css → Tabs/Tabs.module.css} +232 -98
- package/dist/es/components/Tabs/index.js +2 -0
- package/dist/es/components/Tabs/index.js.map +1 -0
- package/dist/es/styles/variables-components.css +12 -0
- package/dist/types/components/Field/Field.d.ts +58 -0
- package/dist/types/components/Field/index.d.ts +1 -0
- package/dist/types/components/SegmentedControl/index.d.ts +2 -2
- package/dist/types/components/Slider/Slider.d.ts +47 -18
- package/dist/types/components/{SegmentedControl/SegmentedControl.d.ts → Tabs/Tabs.d.ts} +30 -14
- package/dist/types/components/Tabs/index.d.ts +2 -0
- package/package.json +1 -1
- package/dist/es/components/SegmentedControl/SegmentedControl.js +0 -118
- package/dist/es/components/SegmentedControl/SegmentedControl.js.map +0 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { cloneElement, isValidElement, useId } from "react";
|
|
5
|
+
import { FieldError } from "../FieldError";
|
|
6
|
+
import s from "./Field.module.css";
|
|
7
|
+
export function Field({ label, description, errorMessage, size = "md", required = false, orientation = "vertical", id: idProp, className, children, }) {
|
|
8
|
+
const generatedId = useId();
|
|
9
|
+
const fieldId = idProp || `field-${generatedId}`;
|
|
10
|
+
const descriptionId = description ? `${fieldId}-description` : undefined;
|
|
11
|
+
const errorId = errorMessage ? `${fieldId}-error` : undefined;
|
|
12
|
+
// Build aria-describedby from description + error IDs
|
|
13
|
+
const ariaDescribedBy = [descriptionId, errorId].filter(Boolean).join(" ") || undefined;
|
|
14
|
+
const invalid = !!errorMessage;
|
|
15
|
+
// Props to inject into the child control
|
|
16
|
+
const fieldChildProps = {
|
|
17
|
+
id: fieldId,
|
|
18
|
+
"aria-describedby": ariaDescribedBy,
|
|
19
|
+
"aria-invalid": invalid || undefined,
|
|
20
|
+
};
|
|
21
|
+
// Resolve the children
|
|
22
|
+
let resolvedChildren;
|
|
23
|
+
if (typeof children === "function") {
|
|
24
|
+
resolvedChildren = children(fieldChildProps);
|
|
25
|
+
}
|
|
26
|
+
else if (isValidElement(children)) {
|
|
27
|
+
resolvedChildren = cloneElement(children, fieldChildProps);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
resolvedChildren = children;
|
|
31
|
+
}
|
|
32
|
+
return (_jsxs("div", { className: clsx(s.Field, className), "data-size": size, "data-orientation": orientation, children: [_jsxs("label", { className: s.Label, htmlFor: fieldId, children: [label, required && (_jsx("span", { className: s.RequiredIndicator, "aria-hidden": "true", children: "*" }))] }), description && (_jsx("div", { className: s.Description, id: descriptionId, children: description })), _jsx("div", { className: s.Control, children: resolvedChildren }), errorMessage && (_jsx(FieldError, { id: errorId, children: errorMessage }))] }));
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=Field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Field.js","sourceRoot":"","sources":["../../../../src/components/Field/Field.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAG3D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1C,OAAO,CAAC,MAAM,oBAAoB,CAAA;AA4DlC,MAAM,UAAU,KAAK,CAAC,EACpB,KAAK,EACL,WAAW,EACX,YAAY,EACZ,IAAI,GAAG,IAAI,EACX,QAAQ,GAAG,KAAK,EAChB,WAAW,GAAG,UAAU,EACxB,EAAE,EAAE,MAAM,EACV,SAAS,EACT,QAAQ,GACG;IACX,MAAM,WAAW,GAAG,KAAK,EAAE,CAAA;IAC3B,MAAM,OAAO,GAAG,MAAM,IAAI,SAAS,WAAW,EAAE,CAAA;IAChD,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,cAAc,CAAC,CAAC,CAAC,SAAS,CAAA;IACxE,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAA;IAE7D,sDAAsD;IACtD,MAAM,eAAe,GACnB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAA;IAEjE,MAAM,OAAO,GAAG,CAAC,CAAC,YAAY,CAAA;IAE9B,yCAAyC;IACzC,MAAM,eAAe,GAAoB;QACvC,EAAE,EAAE,OAAO;QACX,kBAAkB,EAAE,eAAe;QACnC,cAAc,EAAE,OAAO,IAAI,SAAS;KACrC,CAAA;IAED,uBAAuB;IACvB,IAAI,gBAAiC,CAAA;IACrC,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACnC,gBAAgB,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAA;IAC9C,CAAC;SAAM,IAAI,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpC,gBAAgB,GAAG,YAAY,CAC7B,QAAuD,EACvD,eAAe,CAChB,CAAA;IACH,CAAC;SAAM,CAAC;QACN,gBAAgB,GAAG,QAAQ,CAAA;IAC7B,CAAC;IAED,OAAO,CACL,eACE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,eACxB,IAAI,sBACG,WAAW,aAE7B,iBAAO,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,aACxC,KAAK,EACL,QAAQ,IAAI,CACX,eAAM,SAAS,EAAE,CAAC,CAAC,iBAAiB,iBAAc,MAAM,kBAEjD,CACR,IACK,EACP,WAAW,IAAI,CACd,cAAK,SAAS,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,EAAE,aAAa,YAC7C,WAAW,GACR,CACP,EACD,cAAK,SAAS,EAAE,CAAC,CAAC,OAAO,YAAG,gBAAgB,GAAO,EAClD,YAAY,IAAI,CACf,KAAC,UAAU,IAAC,EAAE,EAAE,OAAO,YAAG,YAAY,GAAc,CACrD,IACG,CACP,CAAA;AACH,CAAC","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { cloneElement, isValidElement, useId } from \"react\"\n\nimport type { ControlSize } from \"../../types\"\nimport { FieldError } from \"../FieldError\"\n\nimport s from \"./Field.module.css\"\n\nexport type FieldChildProps = {\n id: string\n \"aria-describedby\"?: string\n \"aria-invalid\"?: boolean\n}\n\nexport type FieldProps = {\n /**\n * Label text for the field\n */\n label: React.ReactNode\n /**\n * Helper/description text displayed below the label.\n * Automatically linked via aria-describedby.\n */\n description?: React.ReactNode\n /**\n * Error message displayed below the control.\n * When provided, the child control receives aria-invalid=\"true\".\n * Uses the existing FieldError component internally.\n */\n errorMessage?: React.ReactNode\n /**\n * Controls the font size of the label to visually match the child control's size.\n * Matches the ControlSize scale used by Input, Select, etc.\n * @default \"md\"\n */\n size?: ControlSize\n /**\n * Display a required indicator (asterisk) after the label.\n * This is purely visual — it does not add the `required` HTML attribute.\n * @default false\n */\n required?: boolean\n /**\n * Layout direction of label and control.\n * - \"vertical\": label stacked above control (default)\n * - \"horizontal\": label beside control\n * @default \"vertical\"\n */\n orientation?: \"vertical\" | \"horizontal\"\n /**\n * Allows overriding the auto-generated `id`. When provided, this becomes\n * the id set on the child control and the `htmlFor` on the label.\n */\n id?: string\n /**\n * CSS class applied to the root wrapper\n */\n className?: string\n /**\n * The form control(s) to render.\n * - If a single ReactElement, Field clones it with { id, aria-describedby, aria-invalid }.\n * - If a function (render prop), it is called with { id, \"aria-describedby\", \"aria-invalid\" }.\n */\n children: React.ReactElement | ((fieldProps: FieldChildProps) => React.ReactNode)\n}\n\nexport function Field({\n label,\n description,\n errorMessage,\n size = \"md\",\n required = false,\n orientation = \"vertical\",\n id: idProp,\n className,\n children,\n}: FieldProps) {\n const generatedId = useId()\n const fieldId = idProp || `field-${generatedId}`\n const descriptionId = description ? `${fieldId}-description` : undefined\n const errorId = errorMessage ? `${fieldId}-error` : undefined\n\n // Build aria-describedby from description + error IDs\n const ariaDescribedBy =\n [descriptionId, errorId].filter(Boolean).join(\" \") || undefined\n\n const invalid = !!errorMessage\n\n // Props to inject into the child control\n const fieldChildProps: FieldChildProps = {\n id: fieldId,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-invalid\": invalid || undefined,\n }\n\n // Resolve the children\n let resolvedChildren: React.ReactNode\n if (typeof children === \"function\") {\n resolvedChildren = children(fieldChildProps)\n } else if (isValidElement(children)) {\n resolvedChildren = cloneElement(\n children as React.ReactElement<Record<string, unknown>>,\n fieldChildProps,\n )\n } else {\n resolvedChildren = children\n }\n\n return (\n <div\n className={clsx(s.Field, className)}\n data-size={size}\n data-orientation={orientation}\n >\n <label className={s.Label} htmlFor={fieldId}>\n {label}\n {required && (\n <span className={s.RequiredIndicator} aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n {description && (\n <div className={s.Description} id={descriptionId}>\n {description}\n </div>\n )}\n <div className={s.Control}>{resolvedChildren}</div>\n {errorMessage && (\n <FieldError id={errorId}>{errorMessage}</FieldError>\n )}\n </div>\n )\n}\n"]}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
@layer components {.Field {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: var(--field-gap);
|
|
5
|
+
|
|
6
|
+
/* Override FieldError margins since Field controls spacing via gap */
|
|
7
|
+
--field-error-margin-top: 0;
|
|
8
|
+
--field-error-margin-bottom: 0;
|
|
9
|
+
--field-error-padding-inline: 0;
|
|
10
|
+
}/* =============================================
|
|
11
|
+
Orientation
|
|
12
|
+
============================================= */.Field:where([data-orientation="horizontal"]) {
|
|
13
|
+
flex-direction: row;
|
|
14
|
+
align-items: flex-start;
|
|
15
|
+
}.Field:where([data-orientation="horizontal"]) .Label {
|
|
16
|
+
flex-shrink: 0;
|
|
17
|
+
padding-top: var(--field-label-horizontal-offset);
|
|
18
|
+
min-width: var(--field-label-horizontal-min-width, 120px);
|
|
19
|
+
}.Field:where([data-orientation="horizontal"]) .Control {
|
|
20
|
+
flex: 1;
|
|
21
|
+
min-width: 0;
|
|
22
|
+
}/* =============================================
|
|
23
|
+
Sizes
|
|
24
|
+
============================================= */.Field:where([data-size="3xs"]),
|
|
25
|
+
.Field:where([data-size="2xs"]) {
|
|
26
|
+
--field-gap: calc(var(--spacing) * 1.5);
|
|
27
|
+
--field-label-font-size: var(--font-text-xs-size);
|
|
28
|
+
--field-label-line-height: var(--font-text-xs-line-height);
|
|
29
|
+
--field-description-font-size: var(--font-text-xs-size);
|
|
30
|
+
--field-description-line-height: var(--font-text-xs-line-height);
|
|
31
|
+
--field-label-horizontal-offset: 0.25rem;
|
|
32
|
+
}.Field:where([data-size="xs"]),
|
|
33
|
+
.Field:where([data-size="sm"]) {
|
|
34
|
+
--field-gap: calc(var(--spacing) * 1.5);
|
|
35
|
+
--field-label-font-size: var(--font-text-xs-size);
|
|
36
|
+
--field-label-line-height: var(--font-text-xs-line-height);
|
|
37
|
+
--field-description-font-size: var(--font-text-xs-size);
|
|
38
|
+
--field-description-line-height: var(--font-text-xs-line-height);
|
|
39
|
+
--field-label-horizontal-offset: 0.375rem;
|
|
40
|
+
}.Field:where([data-size="md"]) {
|
|
41
|
+
--field-gap: calc(var(--spacing) * 2);
|
|
42
|
+
--field-label-font-size: var(--font-text-sm-size);
|
|
43
|
+
--field-label-line-height: var(--font-text-sm-line-height);
|
|
44
|
+
--field-description-font-size: var(--font-text-xs-size);
|
|
45
|
+
--field-description-line-height: var(--font-text-xs-line-height);
|
|
46
|
+
--field-description-margin-top: calc(-1 * calc(var(--spacing) * 1));
|
|
47
|
+
--field-label-horizontal-offset: 0.5rem;
|
|
48
|
+
}.Field:where([data-size="lg"]),
|
|
49
|
+
.Field:where([data-size="xl"]) {
|
|
50
|
+
--field-gap: calc(var(--spacing) * 2);
|
|
51
|
+
--field-label-font-size: var(--font-text-sm-size);
|
|
52
|
+
--field-label-line-height: var(--font-text-sm-line-height);
|
|
53
|
+
--field-description-font-size: var(--font-text-xs-size);
|
|
54
|
+
--field-description-line-height: var(--font-text-xs-line-height);
|
|
55
|
+
--field-description-margin-top: calc(-1 * calc(var(--spacing) * 1));
|
|
56
|
+
--field-label-horizontal-offset: 0.625rem;
|
|
57
|
+
}.Field:where([data-size="2xl"]),
|
|
58
|
+
.Field:where([data-size="3xl"]) {
|
|
59
|
+
--field-gap: calc(var(--spacing) * 2.5);
|
|
60
|
+
--field-label-font-size: var(--font-text-md-size);
|
|
61
|
+
--field-label-line-height: var(--font-text-md-line-height);
|
|
62
|
+
--field-description-font-size: var(--font-text-sm-size);
|
|
63
|
+
--field-description-line-height: var(--font-text-sm-line-height);
|
|
64
|
+
--field-description-margin-top: calc(-1 * calc(var(--spacing) * 1));
|
|
65
|
+
--field-label-horizontal-offset: 0.875rem;
|
|
66
|
+
}/* =============================================
|
|
67
|
+
Label
|
|
68
|
+
============================================= */.Label {
|
|
69
|
+
display: inline-flex;
|
|
70
|
+
align-items: baseline;
|
|
71
|
+
gap: calc(var(--spacing) * 0.5);
|
|
72
|
+
color: var(--color-text);
|
|
73
|
+
font-size: var(--field-label-font-size);
|
|
74
|
+
line-height: var(--field-label-line-height);
|
|
75
|
+
font-weight: var(--font-weight-semibold);
|
|
76
|
+
cursor: default;
|
|
77
|
+
-webkit-user-select: none;
|
|
78
|
+
-moz-user-select: none;
|
|
79
|
+
user-select: none;
|
|
80
|
+
}/* =============================================
|
|
81
|
+
Required Indicator
|
|
82
|
+
============================================= */.RequiredIndicator {
|
|
83
|
+
color: var(--field-error-color);
|
|
84
|
+
font-weight: var(--font-weight-normal);
|
|
85
|
+
}/* =============================================
|
|
86
|
+
Description
|
|
87
|
+
============================================= */.Description {
|
|
88
|
+
color: var(--color-text-secondary);
|
|
89
|
+
font-size: var(--field-description-font-size);
|
|
90
|
+
line-height: var(--field-description-line-height);
|
|
91
|
+
margin-top: var(--field-description-margin-top, calc(-1 * calc(var(--spacing) * 0.5)));
|
|
92
|
+
}/* =============================================
|
|
93
|
+
Control
|
|
94
|
+
============================================= */.Control {
|
|
95
|
+
/* Container for the child form control */
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/Field/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAyC,MAAM,SAAS,CAAA","sourcesContent":["export { Field, type FieldProps, type FieldChildProps } from \"./Field\"\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { SegmentedControl } from "
|
|
1
|
+
export { Tabs as SegmentedControl } from "../Tabs";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/SegmentedControl/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/SegmentedControl/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,gBAAgB,EAAE,MAAM,SAAS,CAAA","sourcesContent":["export { Tabs as SegmentedControl } from \"../Tabs\"\nexport type {\n TabsBadgeProp as SegmentedControlBadgeProp,\n TabProps as SegmentedControlOptionProps,\n TabsProps as SegmentedControlProps,\n SizeVariant,\n} from \"../Tabs\"\n"]}
|
|
@@ -16,15 +16,20 @@ import { Reload } from "../Icon";
|
|
|
16
16
|
import { Tooltip } from "../Tooltip";
|
|
17
17
|
import s from "./Slider.module.css";
|
|
18
18
|
export const Slider = memo((props) => {
|
|
19
|
-
const { className, onChange, min, max, step, disabled, value,
|
|
19
|
+
const { className, onChange, min, max, step, disabled, value, onBlur, onFocus, unit, prefixUnit, label, marks: propMarks = [], trackColor, rangeColor, orientation = "horizontal", ref: forwardedRef, } = props;
|
|
20
|
+
const isRange = props.range === true;
|
|
21
|
+
const isVertical = orientation === "vertical";
|
|
20
22
|
const id = useId();
|
|
21
23
|
const precision = useMemo(() => String(step).split(".")[1]?.length ?? 0, [step]);
|
|
22
|
-
|
|
24
|
+
// Single-mode state for editable input
|
|
25
|
+
const singleValue = isRange ? 0 : value;
|
|
26
|
+
const [inputValue, setInputValue] = useState(isRange ? "" : String(value.toFixed(precision)));
|
|
23
27
|
const setInputValueNumber = useCallback((nextValue) => {
|
|
24
28
|
setInputValue(nextValue.toFixed(precision));
|
|
25
29
|
}, [precision]);
|
|
26
30
|
// prevents input from jumping around while the user is typing
|
|
27
|
-
const
|
|
31
|
+
const singleOnChange = isRange ? undefined : onChange;
|
|
32
|
+
const debouncedOnChange = useDebounceCallback(singleOnChange ?? (() => { }), 250);
|
|
28
33
|
const [pointerDown, setPointerDown] = useState(false);
|
|
29
34
|
const isMounted = useIsMounted();
|
|
30
35
|
// Used to position the input over the thumb
|
|
@@ -33,24 +38,22 @@ export const Slider = memo((props) => {
|
|
|
33
38
|
// The input width is based on the number of characters in the input / font size
|
|
34
39
|
const inputWidth = Math.max(inputValue.length, 1) * (isTabletAndUp ? 7.8 : 9.5);
|
|
35
40
|
// Calculate animation duration based on the distance the thumb needs to move
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
const percent = (value - min) / (max - min);
|
|
41
|
+
// Skip custom animation for range mode — let Radix handle it
|
|
42
|
+
const percent = isRange ? 0 : (value - min) / (max - min);
|
|
39
43
|
const previousPercent = usePrevious(percent);
|
|
40
|
-
const animationDurationMS = !isMounted || pointerDown
|
|
44
|
+
const animationDurationMS = isRange || !isMounted || pointerDown
|
|
45
|
+
? 0
|
|
46
|
+
: Math.max(Math.abs(percent - previousPercent) * 300, 100);
|
|
41
47
|
// We assume that the width of the thumb does not change from render to render
|
|
42
|
-
// so we can avoid the overhead of watching it with a resize observer.
|
|
43
48
|
const thumbRef = useRef(null);
|
|
44
|
-
//
|
|
45
|
-
// We are sorting so we can make assumptions about which marks have the ability to collide with each other.
|
|
49
|
+
// Sort marks for collision detection
|
|
46
50
|
const marks = useMemo(() => [...propMarks].sort((a, b) => a.value - b.value),
|
|
47
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
51
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
48
52
|
[propMarks.length]);
|
|
49
|
-
//
|
|
53
|
+
// Validate marks
|
|
50
54
|
useEffect(() => {
|
|
51
|
-
if (!marks)
|
|
55
|
+
if (!marks)
|
|
52
56
|
return;
|
|
53
|
-
}
|
|
54
57
|
const markValues = new Set();
|
|
55
58
|
for (const mark of marks) {
|
|
56
59
|
if (mark.value < min || mark.value > max) {
|
|
@@ -62,57 +65,63 @@ export const Slider = memo((props) => {
|
|
|
62
65
|
markValues.add(mark.value);
|
|
63
66
|
}
|
|
64
67
|
}, [marks, max, min]);
|
|
65
|
-
// Update
|
|
68
|
+
// Update value if out of bounds (single mode only)
|
|
66
69
|
const latestValue = useLatestValue(value);
|
|
67
70
|
const latestOnChange = useLatestValue(onChange);
|
|
68
71
|
useEffect(() => {
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
if (isRange)
|
|
73
|
+
return;
|
|
74
|
+
const v = latestValue.current;
|
|
75
|
+
const clamped = clamp(v, min, max);
|
|
76
|
+
if (clamped !== v) {
|
|
77
|
+
;
|
|
71
78
|
latestOnChange.current(clamped);
|
|
72
79
|
setInputValueNumber(clamped);
|
|
73
80
|
}
|
|
74
|
-
}, [max, min, latestValue, latestOnChange, setInputValueNumber]);
|
|
81
|
+
}, [max, min, latestValue, latestOnChange, setInputValueNumber, isRange]);
|
|
75
82
|
useEffect(() => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// the actual value.
|
|
83
|
+
if (isRange)
|
|
84
|
+
return;
|
|
79
85
|
if (inputRef.current !== document.activeElement) {
|
|
80
86
|
setInputValueNumber(value);
|
|
81
87
|
}
|
|
82
|
-
}, [value, setInputValueNumber]);
|
|
88
|
+
}, [value, setInputValueNumber, isRange]);
|
|
89
|
+
// Single-mode keyboard handler
|
|
83
90
|
const handleKeyDown = (evt) => {
|
|
84
|
-
|
|
91
|
+
if (isRange || !singleOnChange)
|
|
92
|
+
return;
|
|
85
93
|
if (evt.key === "Home") {
|
|
86
94
|
evt.preventDefault();
|
|
87
|
-
|
|
95
|
+
singleOnChange(min);
|
|
88
96
|
setInputValueNumber(min);
|
|
89
97
|
}
|
|
90
98
|
if (evt.key === "End") {
|
|
91
99
|
evt.preventDefault();
|
|
92
|
-
|
|
100
|
+
singleOnChange(max);
|
|
93
101
|
setInputValueNumber(max);
|
|
94
102
|
}
|
|
95
103
|
if (evt.key === "ArrowUp") {
|
|
96
104
|
evt.preventDefault();
|
|
97
105
|
const multiplier = evt.shiftKey ? 10 : 1;
|
|
98
|
-
const next = clamp(
|
|
99
|
-
|
|
106
|
+
const next = clamp(singleValue + step * multiplier, min, max);
|
|
107
|
+
singleOnChange(next);
|
|
100
108
|
setInputValueNumber(next);
|
|
101
109
|
}
|
|
102
110
|
if (evt.key === "ArrowDown") {
|
|
103
111
|
evt.preventDefault();
|
|
104
112
|
const multiplier = evt.shiftKey ? 10 : 1;
|
|
105
|
-
const next = clamp(
|
|
106
|
-
|
|
113
|
+
const next = clamp(singleValue - step * multiplier, min, max);
|
|
114
|
+
singleOnChange(next);
|
|
107
115
|
setInputValueNumber(next);
|
|
108
116
|
}
|
|
109
|
-
// Other keyboard actions not tied to normal slider behavior
|
|
110
117
|
if (evt.key === "Enter" || evt.key === "Escape") {
|
|
111
118
|
evt.preventDefault();
|
|
112
119
|
evt.currentTarget.blur();
|
|
113
120
|
}
|
|
114
121
|
};
|
|
115
122
|
const handleInputChange = (evt) => {
|
|
123
|
+
if (isRange || !singleOnChange)
|
|
124
|
+
return;
|
|
116
125
|
const nextValue = evt.currentTarget.value.replace(/[^\d.]/, "").trim();
|
|
117
126
|
let parsed = parseFloat(nextValue || "0");
|
|
118
127
|
parsed = clamp(parsed, min, max);
|
|
@@ -123,30 +132,52 @@ export const Slider = memo((props) => {
|
|
|
123
132
|
setInputValue(nextValue);
|
|
124
133
|
};
|
|
125
134
|
const handleInputBlur = (evt) => {
|
|
135
|
+
if (isRange || !singleOnChange)
|
|
136
|
+
return;
|
|
126
137
|
let parsed = parseFloat(evt.target.value.trim()) || 0;
|
|
127
|
-
// If floats are not allowed (based on `step` value) coerce to whole number
|
|
128
138
|
if (step >= 1) {
|
|
129
139
|
parsed = Math.floor(parsed);
|
|
130
140
|
}
|
|
131
141
|
else {
|
|
132
142
|
parsed = round(parsed, precision);
|
|
133
143
|
}
|
|
134
|
-
// Make sure the final value is within the min/max range (and emit a change if necessary)
|
|
135
144
|
parsed = clamp(parsed, min, max);
|
|
136
|
-
if (parsed !==
|
|
137
|
-
|
|
145
|
+
if (parsed !== singleValue) {
|
|
146
|
+
singleOnChange(parsed);
|
|
138
147
|
}
|
|
139
148
|
setInputValueNumber(parsed);
|
|
140
149
|
onBlur?.(evt);
|
|
141
150
|
};
|
|
142
|
-
|
|
151
|
+
// Radix value/onChange wiring
|
|
152
|
+
const radixValue = isRange ? value : [value];
|
|
153
|
+
const handleValueChange = isRange
|
|
154
|
+
? (values) => onChange(values)
|
|
155
|
+
: (values) => onChange(values[0]);
|
|
156
|
+
// Single-mode props
|
|
157
|
+
const resetValue = !isRange ? props.resetValue : undefined;
|
|
158
|
+
const resetTooltip = !isRange
|
|
159
|
+
? props.resetTooltip ?? "Reset to default"
|
|
160
|
+
: undefined;
|
|
161
|
+
// Range-mode props
|
|
162
|
+
const minStepsBetweenThumbs = isRange
|
|
163
|
+
? props.minStepsBetweenThumbs
|
|
164
|
+
: undefined;
|
|
165
|
+
// Show marks only in horizontal orientation
|
|
166
|
+
const showMarks = marks.length > 0 && !isVertical;
|
|
167
|
+
// Format range display text
|
|
168
|
+
const rangeDisplayText = isRange
|
|
169
|
+
? value
|
|
170
|
+
.map((v) => `${prefixUnit ?? ""}${v.toFixed(precision)}${unit ?? ""}`)
|
|
171
|
+
.join(" – ")
|
|
172
|
+
: "";
|
|
173
|
+
return (_jsxs("div", { className: clsx(s.SliderWrap, className), "data-orientation": orientation, children: [label && (_jsxs("div", { className: s.SliderLabel, children: [_jsx("label", { htmlFor: id, className: "flex-1", children: label }), !isRange && resetValue !== undefined && (_jsx(Tooltip, { content: resetTooltip, compact: true, children: _jsx(Button, { size: "2xs", variant: "ghost", color: "secondary", className: s.Reset, "data-hide": disabled || (resetValue === singleValue && !pointerDown), onClick: () => singleOnChange(resetValue), children: _jsx(Reload, {}) }) })), isRange ? (_jsx("span", { className: s.RangeDisplay, children: rangeDisplayText })) : (_jsxs("div", { className: s.SliderValue, onClick: () => inputRef.current?.focus(), children: [prefixUnit && _jsx("span", { className: s.ValueUnit, children: prefixUnit }), _jsx("input", { id: id, className: s.ValueInput, ref: inputRef, style: { width: `${Math.ceil(inputWidth)}px` }, onKeyDown: handleKeyDown, value: inputValue, type: "text", onClick: (e) => e.stopPropagation(), onBlur: handleInputBlur, onFocus: (e) => {
|
|
143
174
|
e.currentTarget.setSelectionRange(0, e.currentTarget.value.length);
|
|
144
175
|
onFocus?.(e);
|
|
145
|
-
}, onChange: handleInputChange, disabled: disabled }), unit && _jsx("span", { className: s.ValueUnit, children: unit })] })] }), _jsxs("div", { className: s.SliderContainer, children: [_jsxs(RadixSlider.Root, { ref: forwardedRef, className: s.Slider, onValueChange:
|
|
176
|
+
}, onChange: handleInputChange, disabled: disabled }), unit && _jsx("span", { className: s.ValueUnit, children: unit })] }))] })), _jsxs("div", { className: s.SliderContainer, children: [_jsxs(RadixSlider.Root, { ref: forwardedRef, className: s.Slider, onValueChange: handleValueChange, min: min, max: max, step: step, disabled: disabled, value: radixValue, orientation: orientation, minStepsBetweenThumbs: minStepsBetweenThumbs, onBlur: onBlur, onFocus: onFocus, onPointerDown: () => setPointerDown(true), onPointerUp: () => setPointerDown(false), style: toCssVariables({
|
|
146
177
|
"slider-duration": `${animationDurationMS}ms`,
|
|
147
178
|
"slider-track-color": trackColor,
|
|
148
179
|
"slider-range-color": rangeColor,
|
|
149
|
-
}), children: [_jsx(RadixSlider.Track, { className: s.Track, children: _jsx(RadixSlider.Range, { className: s.Range }) }), _jsx(RadixSlider.Thumb, { className: s.Thumb, ref: thumbRef })] }),
|
|
180
|
+
}), children: [_jsx(RadixSlider.Track, { className: s.Track, children: _jsx(RadixSlider.Range, { className: s.Range }) }), isRange ? (value.map((_, i) => (_jsx(RadixSlider.Thumb, { className: s.Thumb }, i)))) : (_jsx(RadixSlider.Thumb, { className: s.Thumb, ref: thumbRef }))] }), showMarks && _jsx(SliderMarks, { marks: marks, thumbRef: thumbRef, min: min, max: max })] })] }));
|
|
150
181
|
});
|
|
151
182
|
// The minimum difference we enforce between marks, in pixels
|
|
152
183
|
const MINIMUM_MARK_SPACING_PX = 16;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Slider.js","sourceRoot":"","sources":["../../../../src/components/Slider/Slider.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport clamp from \"lodash/clamp\"\nimport round from \"lodash/round\"\nimport { Slider as RadixSlider } from \"radix-ui\"\nimport {\n type ChangeEventHandler,\n type ElementRef,\n type FocusEventHandler,\n type KeyboardEventHandler,\n memo,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\"\nimport { useDebounceCallback, useResizeObserver } from \"usehooks-ts\"\nimport { useBreakpoint } from \"../../hooks/useBreakpoints\"\nimport { useIsMounted } from \"../../hooks/useIsMounted\"\nimport { useLatestValue } from \"../../hooks/useLatestValue\"\nimport { usePrevious } from \"../../hooks/usePrevious\"\nimport { toCssVariables } from \"../../lib/helpers\"\nimport { Button } from \"../Button\"\nimport { Reload } from \"../Icon\"\nimport { Tooltip } from \"../Tooltip\"\nimport s from \"./Slider.module.css\"\n\nexport type SliderMark = {\n value: number\n label: string\n}\n\nexport type SliderProps = {\n /**\n * The current value of the slider\n */\n value: number\n /**\n * The minimum value the slider can have\n */\n min: number\n /**\n * The maximum value the slider can have\n */\n max: number\n /**\n * The step increment between slider values\n */\n step: number\n /**\n * Value that will be offered as a \"reset to default\" option\n */\n resetValue?: number\n /**\n * String that will be displayed in the tooltip\n * @default Reset to default\n */\n resetTooltip?: string\n /**\n * Unit to display next to the slider value (e.g., ms, px)\n */\n unit?: string\n /**\n * Unit to display to the right of the slider value (e.g., $)\n */\n prefixUnit?: string\n /**\n * Optional label for the slider, which can be a string or React node.\n */\n label?: ReactNode\n /**\n * List of marks to display below the slider track\n */\n marks?: SliderMark[]\n /**\n * Color of the slider track\n */\n trackColor?: string\n /**\n * Color of the slider progress along the track\n */\n rangeColor?: string\n className?: string\n disabled?: boolean\n /**\n * Callback function invoked when the slider value changes.\n *\n * @param value - The new value of the slider.\n */\n onChange: (value: number) => void\n onBlur?: FocusEventHandler<HTMLInputElement>\n onFocus?: FocusEventHandler<HTMLInputElement>\n ref?: React.Ref<ElementRef<typeof RadixSlider.Root> | null>\n}\n\nexport const Slider = memo((props: SliderProps) => {\n const {\n className,\n onChange,\n min,\n max,\n step,\n disabled,\n value,\n resetValue,\n resetTooltip = \"Reset to default\",\n onBlur,\n onFocus,\n unit,\n prefixUnit,\n label,\n marks: propMarks = [],\n trackColor,\n rangeColor,\n ref: forwardedRef,\n } = props\n const id = useId()\n const precision = useMemo(() => String(step).split(\".\")[1]?.length ?? 0, [step])\n const [inputValue, setInputValue] = useState<string>(String(value.toFixed(precision)))\n const setInputValueNumber = useCallback(\n (nextValue: number) => {\n setInputValue(nextValue.toFixed(precision))\n },\n [precision],\n )\n\n // prevents input from jumping around while the user is typing\n const debouncedOnChange = useDebounceCallback(onChange, 250)\n const [pointerDown, setPointerDown] = useState(false)\n const isMounted = useIsMounted()\n\n // Used to position the input over the thumb\n const isTabletAndUp = useBreakpoint(\"md\")\n const inputRef = useRef<HTMLInputElement>(null)\n\n // The input width is based on the number of characters in the input / font size\n const inputWidth = Math.max(inputValue.length, 1) * (isTabletAndUp ? 7.8 : 9.5)\n\n // Calculate animation duration based on the distance the thumb needs to move\n // If the pointer is down, it means the user is dragging the thumb and we want\n // to disable the animation to make the thumb move in sync with the pointer.\n const percent = (value - min) / (max - min)\n const previousPercent = usePrevious(percent)\n const animationDurationMS =\n !isMounted || pointerDown ? 0 : Math.max(Math.abs(percent - previousPercent) * 300, 100)\n\n // We assume that the width of the thumb does not change from render to render\n // so we can avoid the overhead of watching it with a resize observer.\n const thumbRef = useRef<HTMLDivElement>(null)\n\n // It should be exceedingly uncommon to change marks dynamically, and they are unlikely to be a stable array reference from consumers.\n // We are sorting so we can make assumptions about which marks have the ability to collide with each other.\n const marks = useMemo<SliderMark[]>(\n () => [...propMarks].sort((a, b) => a.value - b.value),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Intentionally limiting when this stable value changes to length of marks\n [propMarks.length],\n )\n\n // We make assumptions about marks in order to efficiently position them\n useEffect(() => {\n if (!marks) {\n return\n }\n\n const markValues = new Set<number>()\n\n for (const mark of marks) {\n if (mark.value < min || mark.value > max) {\n throw new Error(`Slider mark value ${mark.value} is out of bounds [${min}, ${max}]`)\n }\n if (markValues.has(mark.value)) {\n throw new Error(\"Slider marks must have unique values\")\n }\n markValues.add(mark.value)\n }\n }, [marks, max, min])\n\n // Update the value if it is out of bounds due to min/max changes\n const latestValue = useLatestValue(value)\n const latestOnChange = useLatestValue(onChange)\n useEffect(() => {\n const clamped = clamp(latestValue.current, min, max)\n if (clamped !== latestValue.current) {\n latestOnChange.current(clamped)\n setInputValueNumber(clamped)\n }\n }, [max, min, latestValue, latestOnChange, setInputValueNumber])\n\n useEffect(() => {\n // If the input is focused then the change came from this input we\n // wait until after they blur before updating the input value to be\n // the actual value.\n if (inputRef.current !== document.activeElement) {\n setInputValueNumber(value)\n }\n }, [value, setInputValueNumber])\n\n const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = (evt) => {\n // https://www.w3.org/WAI/ARIA/apg/patterns/slider-multithumb/\n if (evt.key === \"Home\") {\n evt.preventDefault()\n onChange(min)\n setInputValueNumber(min)\n }\n if (evt.key === \"End\") {\n evt.preventDefault()\n onChange(max)\n setInputValueNumber(max)\n }\n if (evt.key === \"ArrowUp\") {\n evt.preventDefault()\n const multiplier = evt.shiftKey ? 10 : 1\n const next = clamp(value + step * multiplier, min, max)\n onChange(next)\n setInputValueNumber(next)\n }\n if (evt.key === \"ArrowDown\") {\n evt.preventDefault()\n const multiplier = evt.shiftKey ? 10 : 1\n const next = clamp(value - step * multiplier, min, max)\n onChange(next)\n setInputValueNumber(next)\n }\n\n // Other keyboard actions not tied to normal slider behavior\n if (evt.key === \"Enter\" || evt.key === \"Escape\") {\n evt.preventDefault()\n evt.currentTarget.blur()\n }\n }\n\n const handleInputChange: ChangeEventHandler<HTMLInputElement> = (evt) => {\n const nextValue = evt.currentTarget.value.replace(/[^\\d.]/, \"\").trim()\n let parsed = parseFloat(nextValue || \"0\")\n parsed = clamp(parsed, min, max)\n if (step >= 1) {\n parsed = Math.floor(parsed)\n }\n debouncedOnChange(parsed)\n setInputValue(nextValue)\n }\n\n const handleInputBlur: FocusEventHandler<HTMLInputElement> = (evt) => {\n let parsed = parseFloat(evt.target.value.trim()) || 0\n // If floats are not allowed (based on `step` value) coerce to whole number\n if (step >= 1) {\n parsed = Math.floor(parsed)\n } else {\n parsed = round(parsed, precision)\n }\n // Make sure the final value is within the min/max range (and emit a change if necessary)\n parsed = clamp(parsed, min, max)\n if (parsed !== value) {\n onChange(parsed)\n }\n setInputValueNumber(parsed)\n onBlur?.(evt)\n }\n\n return (\n <div className={clsx(s.SliderWrap, className)}>\n <div className={s.SliderLabel}>\n <label htmlFor={id} className=\"flex-1\">\n {label}\n </label>\n {resetValue !== undefined && (\n <Tooltip content={resetTooltip} compact>\n <Button\n size=\"2xs\"\n variant=\"ghost\"\n color=\"secondary\"\n className={s.Reset}\n data-hide={disabled || (resetValue === value && !pointerDown)}\n onClick={() => onChange(resetValue)}\n >\n <Reload />\n </Button>\n </Tooltip>\n )}\n <div className={s.SliderValue} onClick={() => inputRef.current?.focus()}>\n {prefixUnit && <span className={s.ValueUnit}>{prefixUnit}</span>}\n <input\n id={id}\n className={s.ValueInput}\n ref={inputRef}\n style={{ width: `${Math.ceil(inputWidth)}px` }}\n onKeyDown={handleKeyDown}\n value={inputValue}\n type=\"text\"\n onClick={(e) => e.stopPropagation()}\n onBlur={handleInputBlur}\n onFocus={(e) => {\n e.currentTarget.setSelectionRange(0, e.currentTarget.value.length)\n onFocus?.(e)\n }}\n onChange={handleInputChange}\n disabled={disabled}\n />\n {unit && <span className={s.ValueUnit}>{unit}</span>}\n </div>\n </div>\n <div className={s.SliderContainer}>\n <RadixSlider.Root\n ref={forwardedRef}\n className={s.Slider}\n onValueChange={(values) => onChange(values[0])}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n value={[value]}\n onBlur={onBlur}\n onFocus={onFocus}\n onPointerDown={() => setPointerDown(true)}\n onPointerUp={() => setPointerDown(false)}\n style={toCssVariables({\n \"slider-duration\": `${animationDurationMS}ms`,\n \"slider-track-color\": trackColor,\n \"slider-range-color\": rangeColor,\n })}\n >\n <RadixSlider.Track className={s.Track}>\n <RadixSlider.Range className={s.Range} />\n </RadixSlider.Track>\n <RadixSlider.Thumb className={s.Thumb} ref={thumbRef} />\n </RadixSlider.Root>\n {marks && <SliderMarks marks={marks} thumbRef={thumbRef} min={min} max={max} />}\n </div>\n </div>\n )\n})\n\ntype MarksProps = {\n marks: SliderMark[]\n thumbRef: React.RefObject<HTMLDivElement | null>\n min: number\n max: number\n}\n\n// The minimum difference we enforce between marks, in pixels\nconst MINIMUM_MARK_SPACING_PX = 16\n\nconst SliderMarks = memo(({ marks, thumbRef, min, max }: MarksProps) => {\n // We seperate the container and measure divs so that our resize observer\n // does not fire when we adjust the height of the marks container.\n const marksContainerRef = useRef<HTMLDivElement>(null)\n const measureRef = useRef<HTMLDivElement>(null)\n\n // We measure the width of the slider within this component so that sliders\n // without marks do not pay a performance penalty.\n // @ts-expect-error(2322) -- bug in types: https://github.com/juliencrn/usehooks-ts/issues/663\n const { width: sliderWidth } = useResizeObserver({ ref: measureRef })\n\n useLayoutEffect(() => {\n // Impossible\n if (!thumbRef.current || !marksContainerRef.current) {\n return\n }\n\n const markElements = Array.from(\n marksContainerRef.current.querySelectorAll(\"[data-mark]\"),\n ) as HTMLDivElement[]\n\n const thumbHalfWidth = thumbRef.current.getBoundingClientRect().width / 2\n\n // Wipe all styles so we can accurately determine the positions of the marks\n markElements.forEach((markEl) => {\n markEl.style.width = \"\"\n markEl.style.display = \"\"\n })\n\n const positionMarks = () => {\n if (!sliderWidth) {\n return\n }\n\n markElements.forEach((markEl, index) => {\n const markValue = marks[index].value\n const valuePercent = (markValue - min) / (max - min)\n const markWidth = markEl.getBoundingClientRect().width\n const markHalfWidth = markWidth / 2\n\n // Radix smoothes the width of the thumb over the entire track so\n // that the thumb is always within bounds. We need to duplicate\n // this smoothing so that the marks match the observed breakpoints.\n const smoothedThumb = thumbHalfWidth - valuePercent * (thumbHalfWidth / 0.5)\n\n // Calculate where we would naively put the mark based on the value\n const naiveLeftOffset = valuePercent * sliderWidth\n\n // Add the thumb smoothing, and account for the width of the mark itself\n let left = naiveLeftOffset + smoothedThumb - markHalfWidth\n\n // Clamp to the left and right bounds of the container\n left = Math.max(0, Math.min(left, sliderWidth - markWidth))\n\n markEl.style.left = `${left}px`\n })\n }\n\n const marksHaveCollisions = () => {\n for (let i = 0; i < markElements.length - 1; i++) {\n const currentRect = markElements[i].getBoundingClientRect()\n const nextRect = markElements[i + 1].getBoundingClientRect()\n\n if (currentRect.right + MINIMUM_MARK_SPACING_PX > nextRect.left) {\n return true\n }\n }\n return false\n }\n\n positionMarks()\n\n // If we have collisions, try to wrap the content\n if (marksHaveCollisions()) {\n markElements.forEach((markEl) => {\n markEl.style.width = \"min-content\"\n })\n\n positionMarks()\n\n // Hide all marks if we still have collisions\n if (marksHaveCollisions()) {\n markElements.forEach((markEl) => {\n markEl.style.display = \"none\"\n })\n }\n }\n\n const tallestHeight = Math.max(\n ...markElements.map((markEl) => markEl.getBoundingClientRect().height),\n )\n\n // Give our container a height so that we allocate space on the page\n // for the marks and push down other content when we have to wrap\n marksContainerRef.current.style.height = tallestHeight > 0 ? `${tallestHeight}px` : \"\"\n }, [marks, thumbRef, marksContainerRef, min, max, sliderWidth])\n\n return (\n <div className={s.MarksContainer} ref={marksContainerRef}>\n <div ref={measureRef}>\n {marks.map((mark) => (\n <div key={mark.value} className={s.Mark} data-mark>\n <span className={s.MarkLabel}>{mark.label}</span>\n </div>\n ))}\n </div>\n </div>\n )\n})\n"]}
|
|
1
|
+
{"version":3,"file":"Slider.js","sourceRoot":"","sources":["../../../../src/components/Slider/Slider.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport clamp from \"lodash/clamp\"\nimport round from \"lodash/round\"\nimport { Slider as RadixSlider } from \"radix-ui\"\nimport {\n type ChangeEventHandler,\n type ElementRef,\n type FocusEventHandler,\n type KeyboardEventHandler,\n memo,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\"\nimport { useDebounceCallback, useResizeObserver } from \"usehooks-ts\"\nimport { useBreakpoint } from \"../../hooks/useBreakpoints\"\nimport { useIsMounted } from \"../../hooks/useIsMounted\"\nimport { useLatestValue } from \"../../hooks/useLatestValue\"\nimport { usePrevious } from \"../../hooks/usePrevious\"\nimport { toCssVariables } from \"../../lib/helpers\"\nimport { Button } from \"../Button\"\nimport { Reload } from \"../Icon\"\nimport { Tooltip } from \"../Tooltip\"\nimport s from \"./Slider.module.css\"\n\nexport type SliderMark = {\n value: number\n label: string\n}\n\ntype SliderBaseProps = {\n /**\n * The minimum value the slider can have\n */\n min: number\n /**\n * The maximum value the slider can have\n */\n max: number\n /**\n * The step increment between slider values\n */\n step: number\n /**\n * Unit to display next to the slider value (e.g., ms, px)\n */\n unit?: string\n /**\n * Unit to display to the right of the slider value (e.g., $)\n */\n prefixUnit?: string\n /**\n * Optional label for the slider, which can be a string or React node.\n */\n label?: ReactNode\n /**\n * List of marks to display below the slider track\n */\n marks?: SliderMark[]\n /**\n * Color of the slider track\n */\n trackColor?: string\n /**\n * Color of the slider progress along the track\n */\n rangeColor?: string\n className?: string\n disabled?: boolean\n /**\n * Orientation of the slider\n * @default \"horizontal\"\n */\n orientation?: \"horizontal\" | \"vertical\"\n onBlur?: FocusEventHandler<HTMLInputElement>\n onFocus?: FocusEventHandler<HTMLInputElement>\n ref?: React.Ref<ElementRef<typeof RadixSlider.Root> | null>\n}\n\ntype SingleSliderProps = SliderBaseProps & {\n /**\n * When false or omitted, the slider has a single thumb\n */\n range?: false\n /**\n * The current value of the slider\n */\n value: number\n /**\n * Callback function invoked when the slider value changes.\n */\n onChange: (value: number) => void\n /**\n * Value that will be offered as a \"reset to default\" option\n */\n resetValue?: number\n /**\n * String that will be displayed in the tooltip\n * @default Reset to default\n */\n resetTooltip?: string\n}\n\ntype RangeSliderProps = SliderBaseProps & {\n /**\n * When true, the slider supports multiple thumbs\n */\n range: true\n /**\n * Array of values, one per thumb\n */\n value: number[]\n /**\n * Callback function invoked when slider values change.\n */\n onChange: (value: number[]) => void\n /**\n * Minimum number of steps between thumbs\n */\n minStepsBetweenThumbs?: number\n}\n\nexport type SliderProps = SingleSliderProps | RangeSliderProps\n\nexport const Slider = memo((props: SliderProps) => {\n const {\n className,\n onChange,\n min,\n max,\n step,\n disabled,\n value,\n onBlur,\n onFocus,\n unit,\n prefixUnit,\n label,\n marks: propMarks = [],\n trackColor,\n rangeColor,\n orientation = \"horizontal\",\n ref: forwardedRef,\n } = props\n\n const isRange = props.range === true\n const isVertical = orientation === \"vertical\"\n\n const id = useId()\n const precision = useMemo(() => String(step).split(\".\")[1]?.length ?? 0, [step])\n\n // Single-mode state for editable input\n const singleValue = isRange ? 0 : (value as number)\n const [inputValue, setInputValue] = useState<string>(\n isRange ? \"\" : String((value as number).toFixed(precision)),\n )\n const setInputValueNumber = useCallback(\n (nextValue: number) => {\n setInputValue(nextValue.toFixed(precision))\n },\n [precision],\n )\n\n // prevents input from jumping around while the user is typing\n const singleOnChange = isRange ? undefined : (onChange as (v: number) => void)\n const debouncedOnChange = useDebounceCallback(singleOnChange ?? (() => {}), 250)\n const [pointerDown, setPointerDown] = useState(false)\n const isMounted = useIsMounted()\n\n // Used to position the input over the thumb\n const isTabletAndUp = useBreakpoint(\"md\")\n const inputRef = useRef<HTMLInputElement>(null)\n\n // The input width is based on the number of characters in the input / font size\n const inputWidth = Math.max(inputValue.length, 1) * (isTabletAndUp ? 7.8 : 9.5)\n\n // Calculate animation duration based on the distance the thumb needs to move\n // Skip custom animation for range mode — let Radix handle it\n const percent = isRange ? 0 : ((value as number) - min) / (max - min)\n const previousPercent = usePrevious(percent)\n const animationDurationMS =\n isRange || !isMounted || pointerDown\n ? 0\n : Math.max(Math.abs(percent - previousPercent) * 300, 100)\n\n // We assume that the width of the thumb does not change from render to render\n const thumbRef = useRef<HTMLDivElement>(null)\n\n // Sort marks for collision detection\n const marks = useMemo<SliderMark[]>(\n () => [...propMarks].sort((a, b) => a.value - b.value),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [propMarks.length],\n )\n\n // Validate marks\n useEffect(() => {\n if (!marks) return\n const markValues = new Set<number>()\n for (const mark of marks) {\n if (mark.value < min || mark.value > max) {\n throw new Error(`Slider mark value ${mark.value} is out of bounds [${min}, ${max}]`)\n }\n if (markValues.has(mark.value)) {\n throw new Error(\"Slider marks must have unique values\")\n }\n markValues.add(mark.value)\n }\n }, [marks, max, min])\n\n // Update value if out of bounds (single mode only)\n const latestValue = useLatestValue(value)\n const latestOnChange = useLatestValue(onChange)\n useEffect(() => {\n if (isRange) return\n const v = latestValue.current as number\n const clamped = clamp(v, min, max)\n if (clamped !== v) {\n ;(latestOnChange.current as (v: number) => void)(clamped)\n setInputValueNumber(clamped)\n }\n }, [max, min, latestValue, latestOnChange, setInputValueNumber, isRange])\n\n useEffect(() => {\n if (isRange) return\n if (inputRef.current !== document.activeElement) {\n setInputValueNumber(value as number)\n }\n }, [value, setInputValueNumber, isRange])\n\n // Single-mode keyboard handler\n const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = (evt) => {\n if (isRange || !singleOnChange) return\n if (evt.key === \"Home\") {\n evt.preventDefault()\n singleOnChange(min)\n setInputValueNumber(min)\n }\n if (evt.key === \"End\") {\n evt.preventDefault()\n singleOnChange(max)\n setInputValueNumber(max)\n }\n if (evt.key === \"ArrowUp\") {\n evt.preventDefault()\n const multiplier = evt.shiftKey ? 10 : 1\n const next = clamp(singleValue + step * multiplier, min, max)\n singleOnChange(next)\n setInputValueNumber(next)\n }\n if (evt.key === \"ArrowDown\") {\n evt.preventDefault()\n const multiplier = evt.shiftKey ? 10 : 1\n const next = clamp(singleValue - step * multiplier, min, max)\n singleOnChange(next)\n setInputValueNumber(next)\n }\n if (evt.key === \"Enter\" || evt.key === \"Escape\") {\n evt.preventDefault()\n evt.currentTarget.blur()\n }\n }\n\n const handleInputChange: ChangeEventHandler<HTMLInputElement> = (evt) => {\n if (isRange || !singleOnChange) return\n const nextValue = evt.currentTarget.value.replace(/[^\\d.]/, \"\").trim()\n let parsed = parseFloat(nextValue || \"0\")\n parsed = clamp(parsed, min, max)\n if (step >= 1) {\n parsed = Math.floor(parsed)\n }\n debouncedOnChange(parsed)\n setInputValue(nextValue)\n }\n\n const handleInputBlur: FocusEventHandler<HTMLInputElement> = (evt) => {\n if (isRange || !singleOnChange) return\n let parsed = parseFloat(evt.target.value.trim()) || 0\n if (step >= 1) {\n parsed = Math.floor(parsed)\n } else {\n parsed = round(parsed, precision)\n }\n parsed = clamp(parsed, min, max)\n if (parsed !== singleValue) {\n singleOnChange(parsed)\n }\n setInputValueNumber(parsed)\n onBlur?.(evt)\n }\n\n // Radix value/onChange wiring\n const radixValue = isRange ? (value as number[]) : [value as number]\n const handleValueChange = isRange\n ? (values: number[]) => (onChange as (v: number[]) => void)(values)\n : (values: number[]) => (onChange as (v: number) => void)(values[0])\n\n // Single-mode props\n const resetValue = !isRange ? (props as SingleSliderProps).resetValue : undefined\n const resetTooltip = !isRange\n ? (props as SingleSliderProps).resetTooltip ?? \"Reset to default\"\n : undefined\n\n // Range-mode props\n const minStepsBetweenThumbs = isRange\n ? (props as RangeSliderProps).minStepsBetweenThumbs\n : undefined\n\n // Show marks only in horizontal orientation\n const showMarks = marks.length > 0 && !isVertical\n\n // Format range display text\n const rangeDisplayText = isRange\n ? (value as number[])\n .map((v) => `${prefixUnit ?? \"\"}${v.toFixed(precision)}${unit ?? \"\"}`)\n .join(\" – \")\n : \"\"\n\n return (\n <div\n className={clsx(s.SliderWrap, className)}\n data-orientation={orientation}\n >\n {label && (\n <div className={s.SliderLabel}>\n <label htmlFor={id} className=\"flex-1\">\n {label}\n </label>\n {!isRange && resetValue !== undefined && (\n <Tooltip content={resetTooltip!} compact>\n <Button\n size=\"2xs\"\n variant=\"ghost\"\n color=\"secondary\"\n className={s.Reset}\n data-hide={disabled || (resetValue === singleValue && !pointerDown)}\n onClick={() => singleOnChange!(resetValue)}\n >\n <Reload />\n </Button>\n </Tooltip>\n )}\n {isRange ? (\n <span className={s.RangeDisplay}>{rangeDisplayText}</span>\n ) : (\n <div className={s.SliderValue} onClick={() => inputRef.current?.focus()}>\n {prefixUnit && <span className={s.ValueUnit}>{prefixUnit}</span>}\n <input\n id={id}\n className={s.ValueInput}\n ref={inputRef}\n style={{ width: `${Math.ceil(inputWidth)}px` }}\n onKeyDown={handleKeyDown}\n value={inputValue}\n type=\"text\"\n onClick={(e) => e.stopPropagation()}\n onBlur={handleInputBlur}\n onFocus={(e) => {\n e.currentTarget.setSelectionRange(0, e.currentTarget.value.length)\n onFocus?.(e)\n }}\n onChange={handleInputChange}\n disabled={disabled}\n />\n {unit && <span className={s.ValueUnit}>{unit}</span>}\n </div>\n )}\n </div>\n )}\n <div className={s.SliderContainer}>\n <RadixSlider.Root\n ref={forwardedRef}\n className={s.Slider}\n onValueChange={handleValueChange}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n value={radixValue}\n orientation={orientation}\n minStepsBetweenThumbs={minStepsBetweenThumbs}\n onBlur={onBlur}\n onFocus={onFocus}\n onPointerDown={() => setPointerDown(true)}\n onPointerUp={() => setPointerDown(false)}\n style={toCssVariables({\n \"slider-duration\": `${animationDurationMS}ms`,\n \"slider-track-color\": trackColor,\n \"slider-range-color\": rangeColor,\n })}\n >\n <RadixSlider.Track className={s.Track}>\n <RadixSlider.Range className={s.Range} />\n </RadixSlider.Track>\n {isRange ? (\n (value as number[]).map((_, i) => (\n <RadixSlider.Thumb key={i} className={s.Thumb} />\n ))\n ) : (\n <RadixSlider.Thumb className={s.Thumb} ref={thumbRef} />\n )}\n </RadixSlider.Root>\n {showMarks && <SliderMarks marks={marks} thumbRef={thumbRef} min={min} max={max} />}\n </div>\n </div>\n )\n})\n\ntype MarksProps = {\n marks: SliderMark[]\n thumbRef: React.RefObject<HTMLDivElement | null>\n min: number\n max: number\n}\n\n// The minimum difference we enforce between marks, in pixels\nconst MINIMUM_MARK_SPACING_PX = 16\n\nconst SliderMarks = memo(({ marks, thumbRef, min, max }: MarksProps) => {\n // We seperate the container and measure divs so that our resize observer\n // does not fire when we adjust the height of the marks container.\n const marksContainerRef = useRef<HTMLDivElement>(null)\n const measureRef = useRef<HTMLDivElement>(null)\n\n // We measure the width of the slider within this component so that sliders\n // without marks do not pay a performance penalty.\n // @ts-expect-error(2322) -- bug in types: https://github.com/juliencrn/usehooks-ts/issues/663\n const { width: sliderWidth } = useResizeObserver({ ref: measureRef })\n\n useLayoutEffect(() => {\n // Impossible\n if (!thumbRef.current || !marksContainerRef.current) {\n return\n }\n\n const markElements = Array.from(\n marksContainerRef.current.querySelectorAll(\"[data-mark]\"),\n ) as HTMLDivElement[]\n\n const thumbHalfWidth = thumbRef.current.getBoundingClientRect().width / 2\n\n // Wipe all styles so we can accurately determine the positions of the marks\n markElements.forEach((markEl) => {\n markEl.style.width = \"\"\n markEl.style.display = \"\"\n })\n\n const positionMarks = () => {\n if (!sliderWidth) {\n return\n }\n\n markElements.forEach((markEl, index) => {\n const markValue = marks[index].value\n const valuePercent = (markValue - min) / (max - min)\n const markWidth = markEl.getBoundingClientRect().width\n const markHalfWidth = markWidth / 2\n\n // Radix smoothes the width of the thumb over the entire track so\n // that the thumb is always within bounds. We need to duplicate\n // this smoothing so that the marks match the observed breakpoints.\n const smoothedThumb = thumbHalfWidth - valuePercent * (thumbHalfWidth / 0.5)\n\n // Calculate where we would naively put the mark based on the value\n const naiveLeftOffset = valuePercent * sliderWidth\n\n // Add the thumb smoothing, and account for the width of the mark itself\n let left = naiveLeftOffset + smoothedThumb - markHalfWidth\n\n // Clamp to the left and right bounds of the container\n left = Math.max(0, Math.min(left, sliderWidth - markWidth))\n\n markEl.style.left = `${left}px`\n })\n }\n\n const marksHaveCollisions = () => {\n for (let i = 0; i < markElements.length - 1; i++) {\n const currentRect = markElements[i].getBoundingClientRect()\n const nextRect = markElements[i + 1].getBoundingClientRect()\n\n if (currentRect.right + MINIMUM_MARK_SPACING_PX > nextRect.left) {\n return true\n }\n }\n return false\n }\n\n positionMarks()\n\n // If we have collisions, try to wrap the content\n if (marksHaveCollisions()) {\n markElements.forEach((markEl) => {\n markEl.style.width = \"min-content\"\n })\n\n positionMarks()\n\n // Hide all marks if we still have collisions\n if (marksHaveCollisions()) {\n markElements.forEach((markEl) => {\n markEl.style.display = \"none\"\n })\n }\n }\n\n const tallestHeight = Math.max(\n ...markElements.map((markEl) => markEl.getBoundingClientRect().height),\n )\n\n // Give our container a height so that we allocate space on the page\n // for the marks and push down other content when we have to wrap\n marksContainerRef.current.style.height = tallestHeight > 0 ? `${tallestHeight}px` : \"\"\n }, [marks, thumbRef, marksContainerRef, min, max, sliderWidth])\n\n return (\n <div className={s.MarksContainer} ref={marksContainerRef}>\n <div ref={measureRef}>\n {marks.map((mark) => (\n <div key={mark.value} className={s.Mark} data-mark>\n <span className={s.MarkLabel}>{mark.label}</span>\n </div>\n ))}\n </div>\n </div>\n )\n})\n"]}
|
|
@@ -20,10 +20,36 @@
|
|
|
20
20
|
user-select: none;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
/*
|
|
24
|
-
.Slider
|
|
23
|
+
/* Animate thumb position for single-mode programmatic changes */
|
|
24
|
+
.Slider .Thumb {
|
|
25
25
|
transition: left var(--slider-duration) var(--cubic-move);
|
|
26
|
-
}
|
|
26
|
+
}/* =============================================
|
|
27
|
+
Vertical orientation
|
|
28
|
+
============================================= */.SliderWrap[data-orientation="vertical"] {
|
|
29
|
+
display: inline-flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
align-items: center;
|
|
32
|
+
height: var(--slider-vertical-height, 200px);
|
|
33
|
+
}.SliderWrap[data-orientation="vertical"] .SliderLabel {
|
|
34
|
+
margin-bottom: 8px;
|
|
35
|
+
}.SliderWrap[data-orientation="vertical"] .SliderContainer {
|
|
36
|
+
height: 100%;
|
|
37
|
+
width: auto;
|
|
38
|
+
}.SliderWrap[data-orientation="vertical"] .Slider {
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
width: auto;
|
|
41
|
+
height: 100%;
|
|
42
|
+
padding-bottom: 0;
|
|
43
|
+
padding-right: 6px;
|
|
44
|
+
}.SliderWrap[data-orientation="vertical"] .Track {
|
|
45
|
+
width: 4px;
|
|
46
|
+
height: 100%;
|
|
47
|
+
}.SliderWrap[data-orientation="vertical"] .Range {
|
|
48
|
+
width: 100%;
|
|
49
|
+
height: auto;
|
|
50
|
+
}.SliderWrap[data-orientation="vertical"] .Thumb {
|
|
51
|
+
transition: none;
|
|
52
|
+
}.Track {
|
|
27
53
|
position: relative;
|
|
28
54
|
flex-grow: 1;
|
|
29
55
|
width: 100%;
|
|
@@ -166,5 +192,12 @@
|
|
|
166
192
|
overflow-wrap: break-word;
|
|
167
193
|
text-align: center;
|
|
168
194
|
word-wrap: break-word;
|
|
195
|
+
}/* =============================================
|
|
196
|
+
Range display (read-only value for range mode)
|
|
197
|
+
============================================= */.RangeDisplay {
|
|
198
|
+
color: var(--color-text);
|
|
199
|
+
font-size: 13px;
|
|
200
|
+
font-variant-numeric: tabular-nums;
|
|
201
|
+
white-space: nowrap;
|
|
169
202
|
}
|
|
170
203
|
}
|