webcoreui 1.1.0 → 1.2.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.
Files changed (45) hide show
  1. package/README.md +9 -1
  2. package/astro.d.ts +5 -0
  3. package/astro.js +2 -0
  4. package/components/BottomNavigation/BottomNavigation.astro +1 -3
  5. package/components/Breadcrumb/Breadcrumb.astro +1 -3
  6. package/components/Carousel/Carousel.astro +79 -9
  7. package/components/Carousel/Carousel.svelte +40 -9
  8. package/components/Carousel/Carousel.tsx +46 -11
  9. package/components/Carousel/carousel.ts +3 -1
  10. package/components/Copy/Copy.astro +3 -5
  11. package/components/Copy/Copy.svelte +1 -1
  12. package/components/Copy/Copy.tsx +1 -1
  13. package/components/Input/input.ts +62 -62
  14. package/components/Modal/Modal.astro +75 -75
  15. package/components/Modal/modal.ts +25 -25
  16. package/components/OTPInput/OTPInput.astro +194 -96
  17. package/components/OTPInput/OTPInput.svelte +141 -26
  18. package/components/OTPInput/OTPInput.tsx +140 -36
  19. package/components/OTPInput/otpinput.module.scss +59 -85
  20. package/components/Pagination/Pagination.astro +3 -3
  21. package/components/Pagination/Pagination.svelte +4 -4
  22. package/components/Pagination/pagination.module.scss +3 -3
  23. package/components/RangeSlider/RangeSlider.astro +270 -0
  24. package/components/RangeSlider/RangeSlider.svelte +188 -0
  25. package/components/RangeSlider/RangeSlider.tsx +205 -0
  26. package/components/RangeSlider/rangeslider.module.scss +143 -0
  27. package/components/RangeSlider/rangeslider.ts +37 -0
  28. package/components/Sidebar/Sidebar.astro +1 -3
  29. package/components/Stepper/Stepper.astro +1 -3
  30. package/index.d.ts +23 -4
  31. package/index.js +2 -0
  32. package/package.json +109 -103
  33. package/react.d.ts +5 -0
  34. package/react.js +2 -0
  35. package/scss/global/breakpoints.scss +15 -0
  36. package/scss/setup.scss +7 -1
  37. package/svelte.d.ts +5 -0
  38. package/svelte.js +2 -0
  39. package/utils/DOMUtils.ts +27 -2
  40. package/utils/bodyFreeze.ts +1 -1
  41. package/utils/context.ts +2 -2
  42. package/utils/getBreakpoint.ts +17 -0
  43. package/utils/isOneOf.ts +5 -0
  44. package/utils/modal.ts +54 -55
  45. package/utils/toast.ts +1 -1
@@ -0,0 +1,270 @@
1
+ ---
2
+ import type { RangeSliderProps } from './rangeslider'
3
+
4
+ import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.astro'
5
+ import Icon from '../Icon/Icon.astro'
6
+
7
+ import { classNames } from '../../utils/classNames'
8
+ import { interpolate } from '../../utils/interpolate'
9
+
10
+ import styles from './rangeslider.module.scss'
11
+
12
+ interface Props extends RangeSliderProps {}
13
+
14
+ const {
15
+ min = 0,
16
+ max = 100,
17
+ selectedMin,
18
+ selectedMax,
19
+ step = 1,
20
+ minGap = 5,
21
+ disabled,
22
+ color,
23
+ background,
24
+ thumb,
25
+ label,
26
+ subText,
27
+ minLabel,
28
+ maxLabel,
29
+ minIcon,
30
+ maxIcon,
31
+ interactiveLabels,
32
+ updateLabels,
33
+ className
34
+ } = Astro.props
35
+
36
+ const styleVariables = classNames([
37
+ color && `--w-range-slider-color: ${color};`,
38
+ background && `--w-range-slider-background: ${background};`,
39
+ thumb && `--w-range-slider-thumb: ${thumb};`
40
+ ])
41
+
42
+ const minLabelWidth = `${String(max).length}ch`
43
+ const labelStyle = updateLabels ? `min-width:${minLabelWidth};` : null
44
+ ---
45
+
46
+ <ConditionalWrapper condition={!!(label || subText)}>
47
+ <label slot="wrapper" class:list={[styles.label, className]}>children</label>
48
+
49
+ {label && <span>{label}</span>}
50
+
51
+ <div
52
+ class:list={[styles.container, !(label && subText) && className]}
53
+ data-id="w-range-slider"
54
+ data-gap={minGap}
55
+ data-interactive={interactiveLabels}
56
+ data-update-labels={updateLabels}
57
+ style={styleVariables}
58
+ >
59
+ <ConditionalWrapper condition={!!interactiveLabels}>
60
+ <button slot="wrapper" data-dir="left">children</button>
61
+
62
+ {minIcon && (
63
+ <Fragment>
64
+ {minIcon.startsWith('<svg')
65
+ ? <Fragment set:html={minIcon} />
66
+ : <Icon type={minIcon} size={18} />
67
+ }
68
+ </Fragment>
69
+ )}
70
+ {minLabel && (
71
+ <span data-id="w-min-label" style={labelStyle}>{minLabel}</span>
72
+ )}
73
+ </ConditionalWrapper>
74
+
75
+ <div class={styles.slider}>
76
+ <div
77
+ data-id="w-range"
78
+ data-disabled={disabled ? 'true' : undefined}
79
+ class={styles.range}
80
+ style={`
81
+ left: ${interpolate(selectedMin || min, [min, max], [0, 100])}%;
82
+ right: ${interpolate(selectedMax || max, [min, max], [100, 0])}%;
83
+ `}
84
+ />
85
+ <input
86
+ type="range"
87
+ class:list={[styles.input, styles.min]}
88
+ min={min}
89
+ max={max}
90
+ value={selectedMin || min}
91
+ step={step}
92
+ disabled={disabled}
93
+ data-min="true"
94
+ />
95
+ <input
96
+ type="range"
97
+ min={min}
98
+ max={max}
99
+ class={styles.input}
100
+ value={selectedMax || max}
101
+ step={step}
102
+ disabled={disabled}
103
+ data-max="true"
104
+ />
105
+ </div>
106
+
107
+ <ConditionalWrapper condition={!!interactiveLabels}>
108
+ <button slot="wrapper" data-dir="right">children</button>
109
+
110
+ {maxLabel && (
111
+ <span data-id="w-max-label" style={labelStyle}>{maxLabel}</span>
112
+ )}
113
+ {maxIcon && (
114
+ <Fragment>
115
+ {maxIcon.startsWith('<svg')
116
+ ? <Fragment set:html={maxIcon} />
117
+ : <Icon type={maxIcon} size={14} />
118
+ }
119
+ </Fragment>
120
+ )}
121
+ </ConditionalWrapper>
122
+ </div>
123
+
124
+ {subText && <span class="muted">{subText}</span>}
125
+ </ConditionalWrapper>
126
+
127
+ <script>
128
+ import { off, on } from '../../utils/DOMUtils'
129
+ import { dispatch } from '../../utils/event'
130
+ import { interpolate } from '../../utils/interpolate'
131
+
132
+ type RangeParams = {
133
+ range: HTMLDivElement
134
+ minValue: number
135
+ maxValue: number
136
+ min: number
137
+ max: number
138
+ }
139
+
140
+ const updateRange = ({ range, minValue, maxValue, min, max }: RangeParams) => {
141
+ range.style.left = `${interpolate(minValue, [min, max], [0, 100])}%`
142
+ range.style.right = `${interpolate(maxValue, [min, max], [100, 0])}%`
143
+ }
144
+
145
+ const updateLabels = (wrapper: HTMLDivElement, minValue: number, maxValue: number) => {
146
+ const minLabel = wrapper.querySelector('[data-id="w-min-label"]')
147
+ const maxLabel = wrapper.querySelector('[data-id="w-max-label"]')
148
+
149
+ if (minLabel instanceof HTMLElement && maxLabel instanceof HTMLElement) {
150
+ minLabel.innerText = minLabel.innerText.replace(/\d+(\.\d+)?/, String(minValue))
151
+ maxLabel.innerText = maxLabel.innerText.replace(/\d+(\.\d+)?/, String(maxValue))
152
+ }
153
+ }
154
+
155
+ const addEventListeners = () => {
156
+ on('[data-id="w-range-slider"] input', 'input', (event: Event) => {
157
+ const target = event.target
158
+
159
+ if (!(target instanceof HTMLInputElement)) {
160
+ return
161
+ }
162
+
163
+ const range = target.parentElement?.querySelector('[data-id="w-range"]')
164
+ const wrapper = target.parentElement?.parentElement
165
+ const prevInput = target.previousElementSibling
166
+ const nextInput = target.nextElementSibling
167
+
168
+ if (!(wrapper instanceof HTMLDivElement) || !(range instanceof HTMLDivElement)) {
169
+ return
170
+ }
171
+
172
+ const value = Number(target.value)
173
+ const min = Number(target.min)
174
+ const max = Number(target.max)
175
+ const step = Number(target.step)
176
+ const gap = Number(wrapper.dataset.gap)
177
+ const shouldUpdateLabels = !!wrapper.dataset.updateLabels
178
+ const prevInputValue = prevInput instanceof HTMLInputElement ? prevInput.value : 0
179
+ const nextInputValue = nextInput instanceof HTMLInputElement ? nextInput.value : 0
180
+ const minValue = target.dataset.min ? value : Number(prevInputValue)
181
+ const maxValue = target.dataset.max ? value : Number(nextInputValue)
182
+
183
+ let currentMin = minValue
184
+ let currentMax = maxValue
185
+
186
+ if (maxValue - minValue >= gap) {
187
+ if (shouldUpdateLabels) {
188
+ updateLabels(wrapper, minValue, maxValue)
189
+ }
190
+
191
+ dispatch('rangeSliderOnChange', {
192
+ min: minValue,
193
+ max: maxValue
194
+ })
195
+ } else if (target.dataset.min) {
196
+ currentMin = maxValue - Math.max(step, gap)
197
+ target.value = String(currentMin)
198
+ } else {
199
+ currentMax = minValue + Math.max(step, gap)
200
+ target.value = String(currentMax)
201
+ }
202
+
203
+ updateRange({
204
+ range,
205
+ minValue: currentMin,
206
+ maxValue: currentMax,
207
+ min,
208
+ max
209
+ })
210
+ }, true)
211
+
212
+ on('[data-id="w-range-slider"] button', 'click', (event: Event) => {
213
+ const target = event.currentTarget
214
+
215
+ if (!(target instanceof HTMLButtonElement)) {
216
+ return
217
+ }
218
+
219
+ const wrapper = target.parentElement
220
+ const range = wrapper?.querySelector('[data-id="w-range"]')
221
+ const minInput = wrapper?.querySelector('[data-min]')
222
+ const maxInput = wrapper?.querySelector('[data-max]')
223
+
224
+ if (!(wrapper instanceof HTMLDivElement)
225
+ || !(range instanceof HTMLDivElement)
226
+ || !(minInput instanceof HTMLInputElement)
227
+ || !(maxInput instanceof HTMLInputElement)
228
+ ) {
229
+ return
230
+ }
231
+
232
+ const dir = target.dataset.dir === 'left' ? -1 : 1
233
+ const step = Number(minInput.step)
234
+ const min = Number(minInput.min)
235
+ const max = Number(minInput.max)
236
+ const minValue = Number(minInput.value) + (dir * step)
237
+ const maxValue = Number(maxInput.value) + (dir * step)
238
+ const shouldUpdateLabels = !!wrapper.dataset.updateLabels
239
+
240
+ if (minValue < min || maxValue > max) {
241
+ return
242
+ }
243
+
244
+ minInput.value = String(minValue)
245
+ maxInput.value = String(maxValue)
246
+
247
+ updateRange({
248
+ range,
249
+ minValue,
250
+ maxValue,
251
+ min,
252
+ max
253
+ })
254
+
255
+ if (shouldUpdateLabels) {
256
+ updateLabels(wrapper, minValue, maxValue)
257
+ }
258
+
259
+ dispatch('rangeSliderOnChange', {
260
+ min: minValue,
261
+ max: maxValue
262
+ })
263
+ }, true)
264
+ }
265
+
266
+ off(document, 'astro:after-swap', addEventListeners)
267
+ on(document, 'astro:after-swap', addEventListeners)
268
+
269
+ addEventListeners()
270
+ </script>
@@ -0,0 +1,188 @@
1
+ <script lang="ts">
2
+ import type { SvelteRangeSliderProps } from './rangeslider'
3
+
4
+ import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.svelte'
5
+
6
+ import { classNames } from '../../utils/classNames'
7
+ import { interpolate } from '../../utils/interpolate'
8
+
9
+ import styles from './rangeslider.module.scss'
10
+
11
+ const {
12
+ min = 0,
13
+ max = 100,
14
+ selectedMin,
15
+ selectedMax,
16
+ step = 1,
17
+ minGap = 5,
18
+ disabled,
19
+ color,
20
+ background,
21
+ thumb,
22
+ label,
23
+ subText,
24
+ minLabel,
25
+ maxLabel,
26
+ minIcon,
27
+ maxIcon,
28
+ interactiveLabels,
29
+ updateLabels,
30
+ className,
31
+ onChange
32
+ }: SvelteRangeSliderProps = $props()
33
+
34
+ const styleVariables = classNames([
35
+ color && `--w-range-slider-color: ${color};`,
36
+ background && `--w-range-slider-background: ${background};`,
37
+ thumb && `--w-range-slider-thumb: ${thumb};`
38
+ ])
39
+
40
+ const minLabelWidth = `${String(max).length}ch`
41
+ const labelStyle = updateLabels ? `min-width:${minLabelWidth};` : null
42
+
43
+ let minValue = $state(selectedMin || min)
44
+ let maxValue = $state(selectedMax || max)
45
+ let dynamicMinLabel = $state(minLabel)
46
+ let dynamicMaxLabel = $state(maxLabel)
47
+
48
+ const rangeLeftPercent = $derived(interpolate((minValue || min), [min, max], [0, 100]))
49
+ const rangeRightPercent = $derived(interpolate((maxValue || max), [min, max], [100, 0]))
50
+
51
+ const updateDynamicLabels = (minValue: number, maxValue: number) => {
52
+ if (dynamicMinLabel && dynamicMaxLabel) {
53
+ dynamicMinLabel = dynamicMinLabel.replace(/\d+(\.\d+)?/, String(minValue))
54
+ dynamicMaxLabel = dynamicMaxLabel.replace(/\d+(\.\d+)?/, String(maxValue))
55
+ }
56
+ }
57
+
58
+ const handleInput = (event: Event) => {
59
+ const target = event.target
60
+
61
+ if (!(target instanceof HTMLInputElement)) {
62
+ return
63
+ }
64
+
65
+ if (maxValue - minValue >= minGap) {
66
+ if (updateLabels) {
67
+ updateDynamicLabels(minValue, maxValue)
68
+ }
69
+
70
+ onChange?.({
71
+ min: minValue,
72
+ max: maxValue
73
+ })
74
+ } else if (target.dataset.min) {
75
+ minValue = maxValue - Math.max(step, minGap)
76
+ target.value = String(minValue)
77
+ } else {
78
+ maxValue = minValue + Math.max(step, minGap)
79
+ target.value = String(maxValue)
80
+ }
81
+ }
82
+
83
+ const handleClick = (event: Event, direction: 'left' | 'right') => {
84
+ const target = event.currentTarget
85
+
86
+ if (!(target instanceof HTMLButtonElement)) {
87
+ return
88
+ }
89
+
90
+ const dir = direction === 'left' ? -1 : 1
91
+ const updatedMinValue = Number(minValue) + (dir * step)
92
+ const updatedMaxValue = Number(maxValue) + (dir * step)
93
+
94
+ if (updatedMinValue < min || updatedMaxValue > max) {
95
+ return
96
+ }
97
+
98
+ minValue = updatedMinValue
99
+ maxValue = updatedMaxValue
100
+
101
+ if (updateLabels) {
102
+ updateDynamicLabels(minValue, maxValue)
103
+ }
104
+
105
+ onChange?.({
106
+ min: minValue,
107
+ max: maxValue
108
+ })
109
+ }
110
+ </script>
111
+
112
+ <ConditionalWrapper
113
+ element="label"
114
+ condition={!!(label || subText)}
115
+ class={classNames([styles.label, className])}
116
+ >
117
+ {#if label}
118
+ <span>{label}</span>
119
+ {/if}
120
+
121
+ <div
122
+ class={classNames([styles.container, !(label && subText) && className])}
123
+ style={styleVariables}
124
+ >
125
+ <ConditionalWrapper
126
+ element="button"
127
+ condition={!!interactiveLabels}
128
+ onclick={(e: Event) => handleClick(e, 'left')}
129
+ >
130
+ {#if minIcon}
131
+ {@html minIcon}
132
+ {/if}
133
+ {#if dynamicMinLabel}
134
+ <span style={labelStyle}>{dynamicMinLabel}</span>
135
+ {/if}
136
+ </ConditionalWrapper>
137
+
138
+ <div class={styles.slider}>
139
+ <div
140
+ data-disabled={disabled ? 'true' : undefined}
141
+ class={styles.range}
142
+ style={`
143
+ left: ${rangeLeftPercent}%;
144
+ right: ${rangeRightPercent}%;
145
+ `}
146
+ ></div>
147
+ <input
148
+ type="range"
149
+ class={classNames([styles.input, styles.min])}
150
+ min={min}
151
+ max={max}
152
+ bind:value={minValue}
153
+ step={step}
154
+ disabled={disabled}
155
+ oninput={handleInput}
156
+ data-min="true"
157
+ />
158
+ <input
159
+ type="range"
160
+ min={min}
161
+ max={max}
162
+ class={styles.input}
163
+ bind:value={maxValue}
164
+ step={step}
165
+ disabled={disabled}
166
+ oninput={handleInput}
167
+ data-max="true"
168
+ />
169
+ </div>
170
+
171
+ <ConditionalWrapper
172
+ element="button"
173
+ condition={!!interactiveLabels}
174
+ onclick={(e: Event) => handleClick(e, 'right')}
175
+ >
176
+ {#if maxIcon}
177
+ {@html maxIcon}
178
+ {/if}
179
+ {#if dynamicMaxLabel}
180
+ <span style={labelStyle}>{dynamicMaxLabel}</span>
181
+ {/if}
182
+ </ConditionalWrapper>
183
+ </div>
184
+
185
+ {#if subText}
186
+ <span class="muted">{subText}</span>
187
+ {/if}
188
+ </ConditionalWrapper>
@@ -0,0 +1,205 @@
1
+ /* eslint-disable complexity */
2
+ import React, { useEffect, useRef, useState } from 'react'
3
+ import type { ReactRangeSliderProps } from './rangeslider'
4
+
5
+ import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.tsx'
6
+
7
+ import { classNames } from '../../utils/classNames'
8
+ import { interpolate } from '../../utils/interpolate'
9
+
10
+ import styles from './rangeslider.module.scss'
11
+
12
+ const RangeSlider = ({
13
+ min = 0,
14
+ max = 100,
15
+ selectedMin,
16
+ selectedMax,
17
+ step = 1,
18
+ minGap = 5,
19
+ disabled,
20
+ color,
21
+ background,
22
+ thumb,
23
+ label,
24
+ subText,
25
+ minLabel,
26
+ maxLabel,
27
+ minIcon,
28
+ maxIcon,
29
+ interactiveLabels,
30
+ updateLabels,
31
+ className,
32
+ onChange
33
+ }: ReactRangeSliderProps) => {
34
+ const [minValue, setMinValue] = useState(selectedMin || min)
35
+ const [maxValue, setMaxValue] = useState(selectedMax || max)
36
+ const [dynamicMinLabel, setDynamicMinLabel] = useState(minLabel)
37
+ const [dynamicMaxLabel, setDynamicMaxLabel] = useState(maxLabel)
38
+ const rangeLeftPercent = useRef(interpolate(minValue || min, [min, max], [0, 100]))
39
+ const rangeRightPercent = useRef(interpolate(maxValue || max, [min, max], [100, 0]))
40
+
41
+ const minLabelWidth = `${String(max).length}ch`
42
+ const labelStyle = updateLabels ? { minWidth: minLabelWidth } as React.CSSProperties : undefined
43
+
44
+ const styleVariables = {
45
+ ...(color && { '--w-range-slider-color': color }),
46
+ ...(background && { '--w-range-slider-background': background }),
47
+ ...(thumb && { '--w-range-slider-thumb': thumb })
48
+ } as React.CSSProperties
49
+
50
+ const updateDynamicLabels = (minValue: number, maxValue: number) => {
51
+ if (dynamicMinLabel && dynamicMaxLabel) {
52
+ setDynamicMinLabel(dynamicMinLabel.replace(/\d+(\.\d+)?/, String(minValue)))
53
+ setDynamicMaxLabel(dynamicMaxLabel.replace(/\d+(\.\d+)?/, String(maxValue)))
54
+ }
55
+ }
56
+
57
+ const handleInput = (event: React.FormEvent) => {
58
+ const target = event.target
59
+
60
+ if (!(target instanceof HTMLInputElement)) {
61
+ return
62
+ }
63
+
64
+ const value = Number(target.value)
65
+
66
+ let currentMin = target.dataset.min ? value : minValue
67
+ let currentMax = target.dataset.max ? value : maxValue
68
+
69
+ if (currentMax - currentMin >= minGap) {
70
+ if (updateLabels) {
71
+ updateDynamicLabels(currentMin, currentMax)
72
+ }
73
+
74
+ onChange?.({
75
+ min: currentMin,
76
+ max: currentMax
77
+ })
78
+ } else if (target.dataset.min) {
79
+ currentMin = currentMax - Math.max(step, minGap)
80
+ target.value = String(currentMin)
81
+ } else {
82
+ currentMax = currentMin + Math.max(step, minGap)
83
+ target.value = String(currentMax)
84
+ }
85
+
86
+ setMinValue(currentMin)
87
+ setMaxValue(currentMax)
88
+ }
89
+
90
+ const handleClick = (event: React.MouseEvent, direction: 'left' | 'right') => {
91
+ const target = event.currentTarget
92
+
93
+ if (!(target instanceof HTMLButtonElement)) {
94
+ return
95
+ }
96
+
97
+ const dir = direction === 'left' ? -1 : 1
98
+ const updatedMinValue = Number(minValue) + (dir * step)
99
+ const updatedMaxValue = Number(maxValue) + (dir * step)
100
+
101
+ if (updatedMinValue < min || updatedMaxValue > max) {
102
+ return
103
+ }
104
+
105
+ setMinValue(updatedMinValue)
106
+ setMaxValue(updatedMaxValue)
107
+
108
+ if (updateLabels) {
109
+ updateDynamicLabels(updatedMinValue, updatedMaxValue)
110
+ }
111
+
112
+ onChange?.({
113
+ min: updatedMinValue,
114
+ max: updatedMaxValue
115
+ })
116
+ }
117
+
118
+ useEffect(() => {
119
+ rangeLeftPercent.current = interpolate((minValue || min), [min, max], [0, 100])
120
+ rangeRightPercent.current = interpolate((maxValue || max), [min, max], [100, 0])
121
+ }, [minValue, maxValue])
122
+
123
+ return (
124
+ <ConditionalWrapper
125
+ condition={!!(label || subText)}
126
+ wrapper={children => (
127
+ <label className={classNames([styles.label, className])}>{children}</label>
128
+ )}
129
+ >
130
+ {label && <span>{label}</span>}
131
+
132
+ <div
133
+ className={classNames([styles.container, !(label && subText) && className])}
134
+ style={styleVariables}
135
+ >
136
+ <ConditionalWrapper
137
+ condition={!!interactiveLabels}
138
+ wrapper={children => (
139
+ <button onClick={(e: React.MouseEvent) => handleClick(e, 'left')}>{children}</button>
140
+ )}
141
+ >
142
+ {minIcon && (
143
+ <span
144
+ dangerouslySetInnerHTML={{ __html: minIcon }}
145
+ style={{ height: 18 }}
146
+ />
147
+ )}
148
+ {dynamicMinLabel && <span style={labelStyle}>{dynamicMinLabel}</span>}
149
+ </ConditionalWrapper>
150
+
151
+ <div className={styles.slider}>
152
+ <div
153
+ data-disabled={disabled ? 'true' : undefined}
154
+ className={styles.range}
155
+ style={{
156
+ left: `${rangeLeftPercent.current}%`,
157
+ right: `${rangeRightPercent.current}%`
158
+ }}
159
+ />
160
+ <input
161
+ type="range"
162
+ className={classNames([styles.input, styles.min])}
163
+ min={min}
164
+ max={max}
165
+ value={minValue}
166
+ step={step}
167
+ disabled={disabled}
168
+ onInput={handleInput}
169
+ data-min="true"
170
+ />
171
+ <input
172
+ type="range"
173
+ min={min}
174
+ max={max}
175
+ className={styles.input}
176
+ value={maxValue}
177
+ step={step}
178
+ disabled={disabled}
179
+ onInput={handleInput}
180
+ data-max="true"
181
+ />
182
+ </div>
183
+
184
+ <ConditionalWrapper
185
+ condition={!!interactiveLabels}
186
+ wrapper={children => (
187
+ <button onClick={(e: React.MouseEvent) => handleClick(e, 'right')}>{children}</button>
188
+ )}
189
+ >
190
+ {maxIcon && (
191
+ <span
192
+ dangerouslySetInnerHTML={{ __html: maxIcon }}
193
+ style={{ height: 18 }}
194
+ />
195
+ )}
196
+ {dynamicMaxLabel && <span style={labelStyle}>{dynamicMaxLabel}</span>}
197
+ </ConditionalWrapper>
198
+ </div>
199
+
200
+ {subText && <span className="muted">{subText}</span>}
201
+ </ConditionalWrapper>
202
+ )
203
+ }
204
+
205
+ export default RangeSlider