allaw-ui 3.8.8 → 3.9.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.
@@ -0,0 +1,18 @@
1
+ import React from "react";
2
+ export interface RangeSliderProps {
3
+ minValue: number;
4
+ maxValue: number;
5
+ step?: number;
6
+ unit?: string;
7
+ title?: string;
8
+ description?: string;
9
+ showRange?: boolean;
10
+ value?: [number, number];
11
+ defaultValue?: [number, number];
12
+ isDisabled?: boolean;
13
+ onChange?: (value: [number, number]) => void;
14
+ style?: React.CSSProperties;
15
+ className?: string;
16
+ }
17
+ declare const RangeSlider: React.FC<RangeSliderProps>;
18
+ export default RangeSlider;
@@ -0,0 +1,190 @@
1
+ import React, { useState, useEffect, useRef, useCallback } from "react";
2
+ import TinyInfo from "../../atoms/typography/TinyInfo";
3
+ import Heading from "../../atoms/typography/Heading";
4
+ import styles from "./rangeSlider.module.css";
5
+ var RangeSlider = function (_a) {
6
+ var minValue = _a.minValue, maxValue = _a.maxValue, _b = _a.step, step = _b === void 0 ? 1 : _b, _c = _a.unit, unit = _c === void 0 ? "" : _c, title = _a.title, description = _a.description, _d = _a.showRange, showRange = _d === void 0 ? false : _d, value = _a.value, _e = _a.defaultValue, defaultValue = _e === void 0 ? [minValue, maxValue] : _e, _f = _a.isDisabled, isDisabled = _f === void 0 ? false : _f, onChange = _a.onChange, style = _a.style, _g = _a.className, className = _g === void 0 ? "" : _g;
7
+ var _h = useState(value || defaultValue), internalValue = _h[0], setInternalValue = _h[1];
8
+ var _j = useState(null), isDragging = _j[0], setIsDragging = _j[1];
9
+ var _k = useState(null), focusedThumb = _k[0], setFocusedThumb = _k[1];
10
+ var _l = useState(null), ripplePosition = _l[0], setRipplePosition = _l[1];
11
+ var trackRef = useRef(null);
12
+ var thumb1Ref = useRef(null);
13
+ var thumb2Ref = useRef(null);
14
+ var isControlled = value !== undefined;
15
+ var currentValue = isControlled ? value : internalValue;
16
+ var minVal = currentValue[0], maxVal = currentValue[1];
17
+ // Clamp value between min and max
18
+ var clampValue = useCallback(function (val) {
19
+ return Math.max(minValue, Math.min(maxValue, val));
20
+ }, [minValue, maxValue]);
21
+ // Convert pixel position to value
22
+ var pixelToValue = useCallback(function (pixel) {
23
+ if (!trackRef.current)
24
+ return minValue;
25
+ var rect = trackRef.current.getBoundingClientRect();
26
+ var percentage = (pixel - rect.left) / rect.width;
27
+ var rawValue = minValue + percentage * (maxValue - minValue);
28
+ return Math.round(rawValue / step) * step;
29
+ }, [minValue, maxValue, step]);
30
+ // Convert value to percentage
31
+ var valueToPercentage = useCallback(function (val) {
32
+ return ((val - minValue) / (maxValue - minValue)) * 100;
33
+ }, [minValue, maxValue]);
34
+ // Update value
35
+ var updateValue = useCallback(function (newValue) {
36
+ var clampedValue = [
37
+ clampValue(newValue[0]),
38
+ clampValue(newValue[1]),
39
+ ];
40
+ // Ensure min <= max
41
+ if (clampedValue[0] > clampedValue[1]) {
42
+ clampedValue[0] = clampedValue[1];
43
+ }
44
+ if (!isControlled) {
45
+ setInternalValue(clampedValue);
46
+ }
47
+ onChange === null || onChange === void 0 ? void 0 : onChange(clampedValue);
48
+ }, [clampValue, isControlled, onChange]);
49
+ // Handle track click
50
+ var handleTrackClick = useCallback(function (event) {
51
+ var _a;
52
+ if (isDisabled)
53
+ return;
54
+ var clickValue = clampValue(pixelToValue(event.clientX));
55
+ var distToMin = Math.abs(clickValue - minVal);
56
+ var distToMax = Math.abs(clickValue - maxVal);
57
+ // Move closest thumb
58
+ if (distToMin <= distToMax) {
59
+ updateValue([clickValue, maxVal]);
60
+ }
61
+ else {
62
+ updateValue([minVal, clickValue]);
63
+ }
64
+ // Show ripple effect
65
+ var rect = (_a = trackRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
66
+ if (rect) {
67
+ setRipplePosition({
68
+ x: event.clientX - rect.left,
69
+ y: event.clientY - rect.top,
70
+ });
71
+ setTimeout(function () { return setRipplePosition(null); }, 600);
72
+ }
73
+ }, [isDisabled, pixelToValue, clampValue, minVal, maxVal, updateValue]);
74
+ // Handle mouse down on thumb
75
+ var handleThumbMouseDown = useCallback(function (thumbIndex, event) {
76
+ if (isDisabled)
77
+ return;
78
+ event.preventDefault();
79
+ event.stopPropagation();
80
+ setIsDragging(thumbIndex);
81
+ setFocusedThumb(thumbIndex);
82
+ }, [isDisabled]);
83
+ // Handle mouse move
84
+ useEffect(function () {
85
+ var handleMouseMove = function (event) {
86
+ if (isDragging === null || isDisabled)
87
+ return;
88
+ var newValue = clampValue(pixelToValue(event.clientX));
89
+ if (isDragging === 0) {
90
+ updateValue([newValue, maxVal]);
91
+ }
92
+ else {
93
+ updateValue([minVal, newValue]);
94
+ }
95
+ };
96
+ var handleMouseUp = function () {
97
+ setIsDragging(null);
98
+ };
99
+ if (isDragging !== null) {
100
+ document.addEventListener("mousemove", handleMouseMove);
101
+ document.addEventListener("mouseup", handleMouseUp);
102
+ }
103
+ return function () {
104
+ document.removeEventListener("mousemove", handleMouseMove);
105
+ document.removeEventListener("mouseup", handleMouseUp);
106
+ };
107
+ }, [
108
+ isDragging,
109
+ isDisabled,
110
+ clampValue,
111
+ pixelToValue,
112
+ minVal,
113
+ maxVal,
114
+ updateValue,
115
+ ]);
116
+ // Handle keyboard navigation
117
+ var handleKeyDown = useCallback(function (thumbIndex, event) {
118
+ if (isDisabled)
119
+ return;
120
+ var newValue = thumbIndex === 0 ? minVal : maxVal;
121
+ switch (event.key) {
122
+ case "ArrowLeft":
123
+ case "ArrowDown":
124
+ event.preventDefault();
125
+ newValue = clampValue(newValue - step);
126
+ break;
127
+ case "ArrowRight":
128
+ case "ArrowUp":
129
+ event.preventDefault();
130
+ newValue = clampValue(newValue + step);
131
+ break;
132
+ case "Home":
133
+ event.preventDefault();
134
+ newValue = minValue;
135
+ break;
136
+ case "End":
137
+ event.preventDefault();
138
+ newValue = maxValue;
139
+ break;
140
+ default:
141
+ return;
142
+ }
143
+ if (thumbIndex === 0) {
144
+ updateValue([newValue, maxVal]);
145
+ }
146
+ else {
147
+ updateValue([minVal, newValue]);
148
+ }
149
+ }, [
150
+ isDisabled,
151
+ minVal,
152
+ maxVal,
153
+ clampValue,
154
+ step,
155
+ minValue,
156
+ maxValue,
157
+ updateValue,
158
+ ]);
159
+ // Update internal value when controlled value changes
160
+ useEffect(function () {
161
+ if (isControlled && value) {
162
+ setInternalValue(value);
163
+ }
164
+ }, [isControlled, value]);
165
+ var leftPercentage = valueToPercentage(minVal);
166
+ var rightPercentage = valueToPercentage(maxVal);
167
+ var activeWidth = rightPercentage - leftPercentage;
168
+ return (React.createElement("div", { id: "range-slider-main", className: "".concat(styles.rangeSlider, " ").concat(className), style: style },
169
+ React.createElement("div", { id: "range-slider-header", className: "".concat(styles.titleContainer, " ").concat(styles.flexContainer) },
170
+ title && (React.createElement("div", { id: "range-slider-title", className: styles.titleWrapper },
171
+ React.createElement(Heading, { variant: "h6", color: "noir", text: title, align: "left" }))),
172
+ showRange && (React.createElement("div", { id: "range-slider-values", className: styles.rangeInfo },
173
+ React.createElement(TinyInfo, { variant: "medium14", color: "dark-grey", text: "".concat(minVal).concat(unit, " - ").concat(maxVal).concat(unit), align: "right" })))),
174
+ description && (React.createElement("div", { id: "range-slider-description", className: styles.descriptionContainer },
175
+ React.createElement(TinyInfo, { variant: "medium14", color: "mid-grey", text: description, align: "left", className: styles.description }))),
176
+ React.createElement("div", { id: "range-slider-controls", className: styles.sliderContainer },
177
+ React.createElement("div", { id: "range-slider-track", ref: trackRef, className: "".concat(styles.track, " ").concat(isDisabled ? styles.disabled : ""), onClick: handleTrackClick },
178
+ React.createElement("div", { id: "range-slider-track-inactive", className: styles.trackInactive }),
179
+ React.createElement("div", { id: "range-slider-track-active", className: styles.trackActive, style: {
180
+ left: "".concat(leftPercentage, "%"),
181
+ width: "".concat(activeWidth, "%"),
182
+ } }),
183
+ ripplePosition && (React.createElement("div", { id: "range-slider-ripple", className: styles.ripple, style: {
184
+ left: ripplePosition.x,
185
+ top: ripplePosition.y,
186
+ } })),
187
+ React.createElement("div", { id: "range-slider-thumb-min", ref: thumb1Ref, className: "".concat(styles.thumb, " ").concat(focusedThumb === 0 ? styles.focused : "", " ").concat(isDragging === 0 ? styles.active : ""), style: { left: "".concat(leftPercentage, "%") }, role: "slider", "aria-valuenow": minVal, "aria-valuemin": minValue, "aria-valuemax": maxValue, "aria-label": "Valeur minimale: ".concat(minVal).concat(unit), tabIndex: isDisabled ? -1 : 0, onMouseDown: function (e) { return handleThumbMouseDown(0, e); }, onKeyDown: function (e) { return handleKeyDown(0, e); }, onFocus: function () { return setFocusedThumb(0); }, onBlur: function () { return setFocusedThumb(null); } }),
188
+ React.createElement("div", { id: "range-slider-thumb-max", ref: thumb2Ref, className: "".concat(styles.thumb, " ").concat(focusedThumb === 1 ? styles.focused : "", " ").concat(isDragging === 1 ? styles.active : ""), style: { left: "".concat(rightPercentage, "%") }, role: "slider", "aria-valuenow": maxVal, "aria-valuemin": minValue, "aria-valuemax": maxValue, "aria-label": "Valeur maximale: ".concat(maxVal).concat(unit), tabIndex: isDisabled ? -1 : 0, onMouseDown: function (e) { return handleThumbMouseDown(1, e); }, onKeyDown: function (e) { return handleKeyDown(1, e); }, onFocus: function () { return setFocusedThumb(1); }, onBlur: function () { return setFocusedThumb(null); } })))));
189
+ };
190
+ export default RangeSlider;
@@ -0,0 +1,96 @@
1
+ declare namespace _default {
2
+ export let title: string;
3
+ export { RangeSlider as component };
4
+ export let tags: string[];
5
+ export namespace argTypes {
6
+ export namespace minValue {
7
+ namespace control {
8
+ let type: string;
9
+ }
10
+ let description: string;
11
+ }
12
+ export namespace maxValue {
13
+ export namespace control_1 {
14
+ let type_1: string;
15
+ export { type_1 as type };
16
+ }
17
+ export { control_1 as control };
18
+ let description_1: string;
19
+ export { description_1 as description };
20
+ }
21
+ export namespace step {
22
+ export namespace control_2 {
23
+ let type_2: string;
24
+ export { type_2 as type };
25
+ }
26
+ export { control_2 as control };
27
+ let description_2: string;
28
+ export { description_2 as description };
29
+ }
30
+ export namespace unit {
31
+ let control_3: string;
32
+ export { control_3 as control };
33
+ let description_3: string;
34
+ export { description_3 as description };
35
+ }
36
+ export namespace title_1 {
37
+ let control_4: string;
38
+ export { control_4 as control };
39
+ let description_4: string;
40
+ export { description_4 as description };
41
+ }
42
+ export { title_1 as title };
43
+ export namespace description_5 {
44
+ let control_5: string;
45
+ export { control_5 as control };
46
+ let description_6: string;
47
+ export { description_6 as description };
48
+ }
49
+ export { description_5 as description };
50
+ export namespace showRange {
51
+ let control_6: string;
52
+ export { control_6 as control };
53
+ let description_7: string;
54
+ export { description_7 as description };
55
+ }
56
+ export namespace defaultValue {
57
+ export namespace control_7 {
58
+ let type_3: string;
59
+ export { type_3 as type };
60
+ }
61
+ export { control_7 as control };
62
+ let description_8: string;
63
+ export { description_8 as description };
64
+ }
65
+ export namespace isDisabled {
66
+ let control_8: string;
67
+ export { control_8 as control };
68
+ let description_9: string;
69
+ export { description_9 as description };
70
+ }
71
+ export namespace onChange {
72
+ export let action: string;
73
+ let description_10: string;
74
+ export { description_10 as description };
75
+ }
76
+ }
77
+ export namespace parameters {
78
+ namespace backgrounds {
79
+ let _default: string;
80
+ export { _default as default };
81
+ export let values: {
82
+ name: string;
83
+ value: string;
84
+ }[];
85
+ }
86
+ }
87
+ }
88
+ export default _default;
89
+ export const Default: any;
90
+ export const WithUnit: any;
91
+ export const SimpleRange: any;
92
+ export const WithoutRange: any;
93
+ export const Disabled: any;
94
+ export const LargeRange: any;
95
+ export const DecimalStep: any;
96
+ import RangeSlider from "./RangeSlider";
@@ -0,0 +1,162 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import React from "react";
13
+ import { action } from "@storybook/addon-actions";
14
+ import RangeSlider from "./RangeSlider";
15
+ import "../../../styles/global.css";
16
+ export default {
17
+ title: "Components/Molecules/RangeSlider",
18
+ component: RangeSlider,
19
+ tags: ["autodocs"],
20
+ argTypes: {
21
+ minValue: {
22
+ control: { type: "number" },
23
+ description: "Valeur minimale du slider",
24
+ },
25
+ maxValue: {
26
+ control: { type: "number" },
27
+ description: "Valeur maximale du slider",
28
+ },
29
+ step: {
30
+ control: { type: "number" },
31
+ description: "Pas d'incrémentation",
32
+ },
33
+ unit: {
34
+ control: "text",
35
+ description: "Unité à afficher après les valeurs",
36
+ },
37
+ title: {
38
+ control: "text",
39
+ description: "Titre du slider",
40
+ },
41
+ description: {
42
+ control: "text",
43
+ description: "Description du slider",
44
+ },
45
+ showRange: {
46
+ control: "boolean",
47
+ description: "Affiche les valeurs min et max sous le slider",
48
+ },
49
+ defaultValue: {
50
+ control: { type: "object" },
51
+ description: "Valeur par défaut [min, max]",
52
+ },
53
+ isDisabled: {
54
+ control: "boolean",
55
+ description: "Désactive le slider",
56
+ },
57
+ onChange: {
58
+ action: "changed",
59
+ description: "Callback appelé quand la valeur change",
60
+ },
61
+ },
62
+ parameters: {
63
+ backgrounds: {
64
+ default: "light",
65
+ values: [
66
+ { name: "light", value: "#ffffff" },
67
+ { name: "grey", value: "#728ea7" },
68
+ { name: "figma", value: "#404040" },
69
+ { name: "dark", value: "#171e25" },
70
+ ],
71
+ },
72
+ },
73
+ };
74
+ var Template = function (args) { return React.createElement(RangeSlider, __assign({}, args)); };
75
+ export var Default = Template.bind({});
76
+ Default.args = {
77
+ title: "Age de vos contacts",
78
+ description: "Sélectionnez l'âge minimum et maximum des contacts à afficher",
79
+ minValue: 0,
80
+ maxValue: 120,
81
+ step: 1,
82
+ unit: "",
83
+ defaultValue: [0, 120],
84
+ showRange: true,
85
+ isDisabled: false,
86
+ onChange: action("Range changed"),
87
+ };
88
+ export var WithUnit = Template.bind({});
89
+ WithUnit.args = {
90
+ title: "Budget mensuel",
91
+ description: "Définissez votre budget minimum et maximum",
92
+ minValue: 0,
93
+ maxValue: 5000,
94
+ step: 50,
95
+ unit: "€",
96
+ defaultValue: [500, 3000],
97
+ showRange: true,
98
+ isDisabled: false,
99
+ onChange: action("Range changed"),
100
+ };
101
+ export var SimpleRange = Template.bind({});
102
+ SimpleRange.args = {
103
+ minValue: 0,
104
+ maxValue: 100,
105
+ step: 5,
106
+ unit: "%",
107
+ defaultValue: [20, 80],
108
+ showRange: true,
109
+ isDisabled: false,
110
+ onChange: action("Range changed"),
111
+ };
112
+ export var WithoutRange = Template.bind({});
113
+ WithoutRange.args = {
114
+ title: "Sélection de plage",
115
+ description: "Choisissez vos valeurs préférées",
116
+ minValue: 1,
117
+ maxValue: 10,
118
+ step: 1,
119
+ defaultValue: [3, 7],
120
+ showRange: false,
121
+ isDisabled: false,
122
+ onChange: action("Range changed"),
123
+ };
124
+ export var Disabled = Template.bind({});
125
+ Disabled.args = {
126
+ title: "Slider désactivé",
127
+ description: "Ce slider est en lecture seule",
128
+ minValue: 0,
129
+ maxValue: 100,
130
+ step: 1,
131
+ unit: "%",
132
+ defaultValue: [25, 75],
133
+ showRange: true,
134
+ isDisabled: true,
135
+ onChange: action("Range changed"),
136
+ };
137
+ export var LargeRange = Template.bind({});
138
+ LargeRange.args = {
139
+ title: "Années d'expérience",
140
+ description: "Indiquez la plage d'expérience souhaitée",
141
+ minValue: 0,
142
+ maxValue: 50,
143
+ step: 1,
144
+ unit: " ans",
145
+ defaultValue: [2, 15],
146
+ showRange: true,
147
+ isDisabled: false,
148
+ onChange: action("Range changed"),
149
+ };
150
+ export var DecimalStep = Template.bind({});
151
+ DecimalStep.args = {
152
+ title: "Note moyenne",
153
+ description: "Sélectionnez la plage de notes",
154
+ minValue: 0,
155
+ maxValue: 5,
156
+ step: 0.5,
157
+ unit: "/5",
158
+ defaultValue: [2.5, 4.5],
159
+ showRange: true,
160
+ isDisabled: false,
161
+ onChange: action("Range changed"),
162
+ };
@@ -0,0 +1,2 @@
1
+ export { default as RangeSlider } from "./RangeSlider";
2
+ export type { RangeSliderProps } from "./RangeSlider";
@@ -0,0 +1 @@
1
+ export { default as RangeSlider } from "./RangeSlider";
@@ -0,0 +1,265 @@
1
+ .rangeSlider {
2
+ width: 100%;
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: 8px;
6
+ }
7
+
8
+ .titleContainer {
9
+ display: flex;
10
+ flex-direction: row;
11
+ justify-content: space-between;
12
+ width: 100%;
13
+ }
14
+
15
+ .title {
16
+ overflow: hidden;
17
+ text-overflow: ellipsis;
18
+ white-space: nowrap;
19
+ flex: 1;
20
+ min-width: 250px;
21
+ }
22
+
23
+ .descriptionContainer {
24
+ margin-bottom: 8px;
25
+ }
26
+
27
+ .description {
28
+ line-height: 1.4;
29
+ }
30
+
31
+ .sliderContainer {
32
+ display: flex;
33
+ flex-direction: column;
34
+ gap: 8px;
35
+ padding-left: 0.82rem;
36
+ padding-right: 0.82rem;
37
+ }
38
+
39
+ .track {
40
+ position: relative;
41
+ width: 100%;
42
+ height: 44px; /* Touch target minimum */
43
+ display: flex;
44
+ align-items: center;
45
+ cursor: pointer;
46
+ padding: 20px 0; /* Padding for touch target */
47
+ }
48
+
49
+ .track.disabled {
50
+ cursor: not-allowed;
51
+ opacity: 0.5;
52
+ }
53
+
54
+ .trackInactive {
55
+ position: absolute;
56
+ width: 100%;
57
+ height: 8px;
58
+ background-color: #e6edf5; /* --grey-venom */
59
+ border-radius: 2px;
60
+ top: 50%;
61
+ transform: translateY(-50%);
62
+ border-radius: 4px;
63
+ }
64
+
65
+ .trackActive {
66
+ position: absolute;
67
+ height: 8px;
68
+ background-color: #25beeb; /* --bleu-allaw */
69
+ border-radius: 2px;
70
+ top: 50%;
71
+ transform: translateY(-50%);
72
+ transition: background-color 0.05s ease;
73
+ border-radius: 4px;
74
+ }
75
+
76
+ .thumb {
77
+ position: absolute;
78
+ width: 10px;
79
+ height: 10px;
80
+ background-color: #ffffff;
81
+ border: 2px solid #25beeb; /* --bleu-allaw */
82
+ border-radius: 50%;
83
+ cursor: grab;
84
+ transform: translate(-50%, -50%);
85
+ top: 50%;
86
+ transition: all 0.05s ease;
87
+ z-index: 2;
88
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
89
+
90
+ /* Touch target minimum */
91
+ min-width: 24px;
92
+ min-height: 24px;
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ }
97
+
98
+ .thumb::before {
99
+ content: "";
100
+ width: 2px;
101
+ height: 2px;
102
+ background-color: #ffffff;
103
+ border: 2px solid #25beeb;
104
+ border-radius: 50%;
105
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
106
+ }
107
+
108
+ .thumb:hover {
109
+ transform: translate(-50%, -50%) scale(1.1);
110
+ }
111
+
112
+ .thumb:hover::after {
113
+ content: "";
114
+ position: absolute;
115
+ width: 24px;
116
+ height: 24px;
117
+ background-color: rgba(37, 190, 235, 0.5); /* --bleu-allaw with opacity */
118
+ border-radius: 50%;
119
+ animation: rippleHover 0.3s ease-out;
120
+ z-index: -1;
121
+ }
122
+
123
+ .thumb.focused {
124
+ /* outline: 2px solid #25beeb;
125
+ outline-offset: 2px; */
126
+ border: 2px solid #25beeb;
127
+ }
128
+
129
+ .thumb.active {
130
+ cursor: grabbing;
131
+ transform: translate(-50%, -50%) scale(1.1);
132
+ }
133
+
134
+ .thumb.active::after {
135
+ content: "";
136
+ position: absolute;
137
+ width: 24px;
138
+ height: 24px;
139
+ background-color: #1fa3c9; /* --bleu-allaw full opacity */
140
+ border-radius: 50%;
141
+ animation: rippleActive 0.3s ease-out;
142
+ z-index: -1;
143
+ }
144
+
145
+ .thumb:focus-visible {
146
+ outline: 2px solid #25beeb;
147
+ outline-offset: 2px;
148
+ }
149
+
150
+ .track.disabled .thumb {
151
+ cursor: not-allowed;
152
+ border-color: #728ea7; /* --mid-grey */
153
+ }
154
+
155
+ .track.disabled .thumb::before {
156
+ border-color: #728ea7; /* --mid-grey */
157
+ }
158
+
159
+ .track.disabled .thumb:hover {
160
+ transform: translate(-50%, -50%);
161
+ }
162
+
163
+ .track.disabled .thumb:hover::after {
164
+ display: none;
165
+ }
166
+
167
+ .ripple {
168
+ position: absolute;
169
+ width: 20px;
170
+ height: 20px;
171
+ background-color: rgba(37, 190, 235, 0.5);
172
+ border-radius: 50%;
173
+ transform: translate(-50%, -50%);
174
+ animation: rippleClick 0.6s ease-out;
175
+ pointer-events: none;
176
+ z-index: 1;
177
+ }
178
+
179
+ .rangeDisplay {
180
+ margin-top: 4px;
181
+ }
182
+
183
+ /* Animations */
184
+ @keyframes rippleHover {
185
+ 0% {
186
+ transform: scale(0);
187
+ opacity: 1;
188
+ }
189
+ 100% {
190
+ transform: scale(1);
191
+ opacity: 0.5;
192
+ }
193
+ }
194
+
195
+ @keyframes rippleActive {
196
+ 0% {
197
+ transform: scale(0);
198
+ opacity: 1;
199
+ }
200
+ 100% {
201
+ transform: scale(1);
202
+ opacity: 1;
203
+ }
204
+ }
205
+
206
+ @keyframes rippleClick {
207
+ 0% {
208
+ transform: translate(-50%, -50%) scale(0);
209
+ opacity: 0.8;
210
+ }
211
+ 100% {
212
+ transform: translate(-50%, -50%) scale(1.5);
213
+ opacity: 0;
214
+ }
215
+ }
216
+
217
+ /* Responsive adjustments */
218
+ @media (max-width: 768px) {
219
+ .thumb {
220
+ min-width: 20px;
221
+ min-height: 20px;
222
+ }
223
+
224
+ .track {
225
+ height: 8px;
226
+ padding: 24px 0;
227
+ }
228
+ }
229
+
230
+ .flexContainer {
231
+ display: flex;
232
+ justify-content: space-between;
233
+ }
234
+
235
+ .rangeInfo {
236
+ margin-left: auto;
237
+ align-self: center;
238
+ }
239
+
240
+ .titleWrapper {
241
+ flex: 1;
242
+ min-width: 0;
243
+ overflow: hidden;
244
+ }
245
+
246
+ .titleWrapper h1,
247
+ .titleWrapper h2,
248
+ .titleWrapper h3,
249
+ .titleWrapper h4,
250
+ .titleWrapper h5,
251
+ .titleWrapper h6,
252
+ .titleWrapper span {
253
+ overflow: hidden;
254
+ text-overflow: ellipsis;
255
+ white-space: nowrap;
256
+ width: 100%;
257
+ display: block;
258
+ }
259
+
260
+ .rangeInfo {
261
+ flex-shrink: 0;
262
+ margin-left: 16px;
263
+ align-self: center;
264
+ white-space: nowrap;
265
+ }
package/dist/index.d.ts CHANGED
@@ -62,6 +62,8 @@ export type { DocumentCardProps } from "./components/molecules/documentCard/Docu
62
62
  export { default as EmployeeCard } from "./components/molecules/employeeCard/EmployeeCard";
63
63
  export { default as Stepper } from "./components/molecules/stepper/Stepper";
64
64
  export type { StepperProps } from "./components/molecules/stepper/Stepper";
65
+ export { default as RangeSlider } from "./components/molecules/rangeSlider/RangeSlider";
66
+ export type { RangeSliderProps } from "./components/molecules/rangeSlider/RangeSlider";
65
67
  export { default as Modal } from "./components/molecules/modal/Modal";
66
68
  export type { ModalProps } from "./components/molecules/modal/Modal";
67
69
  export { default as CheckboxForm } from "./components/molecules/checkboxForm/CheckboxForm";
package/dist/index.js CHANGED
@@ -71,6 +71,8 @@ export { default as DocumentCard } from "./components/molecules/documentCard/Doc
71
71
  export { default as EmployeeCard } from "./components/molecules/employeeCard/EmployeeCard";
72
72
  // Stepper
73
73
  export { default as Stepper } from "./components/molecules/stepper/Stepper";
74
+ // Range Slider
75
+ export { default as RangeSlider } from "./components/molecules/rangeSlider/RangeSlider";
74
76
  // Modal
75
77
  export { default as Modal } from "./components/molecules/modal/Modal";
76
78
  // CheckboxForm
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allaw-ui",
3
- "version": "3.8.8",
3
+ "version": "3.9.0",
4
4
  "description": "Composants UI pour l'application Allaw",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",