webcoreui 1.2.0 → 1.3.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 (43) hide show
  1. package/README.md +11 -6
  2. package/astro.d.ts +3 -0
  3. package/astro.js +2 -0
  4. package/components/Badge/Badge.astro +2 -0
  5. package/components/Badge/Badge.svelte +2 -0
  6. package/components/Badge/Badge.tsx +2 -0
  7. package/components/Badge/badge.module.scss +26 -0
  8. package/components/Badge/badge.ts +1 -0
  9. package/components/Counter/Counter.astro +164 -0
  10. package/components/Counter/Counter.svelte +141 -0
  11. package/components/Counter/Counter.tsx +161 -0
  12. package/components/Counter/counter.module.scss +155 -0
  13. package/components/Counter/counter.ts +21 -0
  14. package/components/DataTable/DataTable.tsx +1 -1
  15. package/components/Icon/map.ts +2 -0
  16. package/components/List/List.astro +3 -0
  17. package/components/List/List.svelte +12 -9
  18. package/components/List/List.tsx +3 -0
  19. package/components/List/list.module.scss +5 -0
  20. package/components/List/list.ts +40 -39
  21. package/components/Menu/Menu.tsx +1 -1
  22. package/components/Pagination/Pagination.tsx +1 -1
  23. package/components/Pagination/pagination.module.scss +1 -0
  24. package/components/Popover/Popover.astro +28 -26
  25. package/components/Popover/Popover.svelte +2 -0
  26. package/components/Popover/Popover.tsx +2 -0
  27. package/components/Popover/popover.module.scss +6 -0
  28. package/components/Popover/popover.ts +17 -16
  29. package/components/Progress/Progress.astro +6 -2
  30. package/components/Progress/Progress.svelte +6 -2
  31. package/components/Progress/Progress.tsx +6 -2
  32. package/components/Progress/progress.module.scss +15 -0
  33. package/components/Progress/progress.ts +1 -0
  34. package/components/RangeSlider/RangeSlider.astro +5 -0
  35. package/components/RangeSlider/rangeslider.ts +1 -0
  36. package/icons/minus.svg +3 -0
  37. package/icons.d.ts +1 -0
  38. package/icons.js +1 -0
  39. package/package.json +111 -109
  40. package/react.d.ts +3 -0
  41. package/react.js +2 -0
  42. package/svelte.d.ts +3 -0
  43. package/svelte.js +2 -0
package/README.md CHANGED
@@ -64,18 +64,18 @@ Webcore can be used as a standalone project, or it can be integrated into your e
64
64
 
65
65
  Webcore components use Sass for styling. To use the component library, you must have the following packages installed:
66
66
 
67
- - [Sass](https://www.npmjs.com/package/sass) - `v1.9`
68
- - [TypeScript](https://www.npmjs.com/package/typescript) - `v5.8`
67
+ - [Sass](https://www.npmjs.com/package/sass) - `v1.94`
68
+ - [TypeScript](https://www.npmjs.com/package/typescript) - `v5.9`
69
69
 
70
70
  Depending on your project setup, you'll also need the following packages:
71
71
 
72
72
  - **For Astro projects**
73
- - [Astro](https://www.npmjs.com/package/astro) - `v5.13`
73
+ - [Astro](https://www.npmjs.com/package/astro) - `v5.16`
74
74
  - **For Svelte projects**
75
- - [Svelte](https://www.npmjs.com/package/svelte) - `v5.38`
75
+ - [Svelte](https://www.npmjs.com/package/svelte) - `v5.45`
76
76
  - **For React projects**
77
- - [React](https://www.npmjs.com/package/react) - `v19.0`
78
- - [React DOM](https://www.npmjs.com/package/react-dom) -`v19.0`
77
+ - [React](https://www.npmjs.com/package/react) - `v19.2`
78
+ - [React DOM](https://www.npmjs.com/package/react-dom) -`v19.2`
79
79
 
80
80
  ### Installation with CLI
81
81
 
@@ -167,6 +167,9 @@ html body {
167
167
  --w-collapsible-initial-height: 0;
168
168
  --w-collapsible-max-height: 100%;
169
169
 
170
+ // Counter component
171
+ --w-counter-width: 10ch;
172
+
170
173
  // Masonry component
171
174
  --w-masonry-gap: 5px;
172
175
 
@@ -287,6 +290,7 @@ import { Accordion } from 'webcoreui/react'
287
290
  - [ConditionalWrapper](https://github.com/Frontendland/webcoreui/tree/main/src/components/ConditionalWrapper)
288
291
  - [ContextMenu](https://github.com/Frontendland/webcoreui/tree/main/src/components/ContextMenu)
289
292
  - [Copy](https://github.com/Frontendland/webcoreui/tree/main/src/components/Copy)
293
+ - [Counter](https://github.com/Frontendland/webcoreui/tree/main/src/components/Counter)
290
294
  - [DataTable](https://github.com/Frontendland/webcoreui/tree/main/src/components/DataTable)
291
295
  - [Flex](https://github.com/Frontendland/webcoreui/tree/main/src/components/Flex)
292
296
  - [Footer](https://github.com/Frontendland/webcoreui/tree/main/src/components/Footer)
@@ -332,6 +336,7 @@ import { Accordion } from 'webcoreui/react'
332
336
  - [BlogCard](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/BlogCard)
333
337
  - [ComponentMap](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/ComponentMap)
334
338
  - [DeviceMockup](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/DeviceMockup)
339
+ - [Empty](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/Empty)
335
340
  - [ErrorPage](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/ErrorPage)
336
341
  - [ExpandableTable](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/ExpandableTable)
337
342
  - [FAQ](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/FAQ)
package/astro.d.ts CHANGED
@@ -14,6 +14,7 @@ import type { CollapsibleProps as WCollapsibleProps } from './components/Collaps
14
14
  import type { ConditionalWrapperProps as WConditionalWrapperProps } from './components/ConditionalWrapper/conditionalwrapper'
15
15
  import type { ContextMenuProps as WContextMenuProps } from './components/ContextMenu/contextmenu'
16
16
  import type { CopyProps as WCopyProps } from './components/Copy/copy'
17
+ import type { CounterProps as WCounterProps } from './components/Counter/counter'
17
18
  import type { DataTableProps as WDataTableProps } from './components/DataTable/datatable'
18
19
  import type { FlexProps as WFlexProps } from './components/Flex/flex'
19
20
  import type { FooterProps as WFooterProps } from './components/Footer/footer'
@@ -75,6 +76,7 @@ declare module 'webcoreui/astro' {
75
76
  export function ConditionalWrapper(_props: WConditionalWrapperProps): any
76
77
  export function ContextMenu(_props: WContextMenuProps): any
77
78
  export function Copy(_props: WCopyProps): any
79
+ export function Counter(_props: WCounterProps): any
78
80
  export function DataTable(_props: WDataTableProps): any
79
81
  export function Flex(_props: WFlexProps): any
80
82
  export function Footer(_props: WFooterProps): any
@@ -129,6 +131,7 @@ declare module 'webcoreui/astro' {
129
131
  export type ConditionalWrapperProps = WConditionalWrapperProps
130
132
  export type ContextMenuProps = WContextMenuProps
131
133
  export type CopyProps = WCopyProps
134
+ export type CounterProps = WCounterProps
132
135
  export type DataTableProps = WDataTableProps
133
136
  export type FlexProps = WFlexProps
134
137
  export type FooterProps = WFooterProps
package/astro.js CHANGED
@@ -14,6 +14,7 @@ import CollapsibleComponent from './components/Collapsible/Collapsible.astro'
14
14
  import ConditionalWrapperComponent from './components/ConditionalWrapper/ConditionalWrapper.astro'
15
15
  import ContextMenuComponent from './components/ContextMenu/ContextMenu.astro'
16
16
  import CopyComponent from './components/Copy/Copy.astro'
17
+ import CounterComponent from './components/Counter/Counter.astro'
17
18
  import DataTableComponent from './components/DataTable/DataTable.astro'
18
19
  import FlexComponent from './components/Flex/Flex.astro'
19
20
  import FooterComponent from './components/Footer/Footer.astro'
@@ -68,6 +69,7 @@ export const Collapsible = CollapsibleComponent
68
69
  export const ConditionalWrapper = ConditionalWrapperComponent
69
70
  export const ContextMenu = ContextMenuComponent
70
71
  export const Copy = CopyComponent
72
+ export const Counter = CounterComponent
71
73
  export const DataTable = DataTableComponent
72
74
  export const Flex = FlexComponent
73
75
  export const Footer = FooterComponent
@@ -10,6 +10,7 @@ const {
10
10
  hover,
11
11
  small,
12
12
  rounded,
13
+ transparent,
13
14
  className,
14
15
  ...rest
15
16
  } = Astro.props
@@ -20,6 +21,7 @@ const classes = [
20
21
  hover && styles.hover,
21
22
  small && styles.small,
22
23
  rounded && styles.round,
24
+ transparent && styles.transparent,
23
25
  className
24
26
  ]
25
27
  ---
@@ -10,6 +10,7 @@
10
10
  hover,
11
11
  small,
12
12
  rounded,
13
+ transparent,
13
14
  className,
14
15
  onClick,
15
16
  children,
@@ -22,6 +23,7 @@
22
23
  (onClick || hover) && styles.hover,
23
24
  small && styles.small,
24
25
  rounded && styles.round,
26
+ transparent && styles.transparent,
25
27
  className
26
28
  ])
27
29
  </script>
@@ -11,6 +11,7 @@ const Badge = ({
11
11
  hover,
12
12
  small,
13
13
  rounded,
14
+ transparent,
14
15
  className,
15
16
  children,
16
17
  ...rest
@@ -21,6 +22,7 @@ const Badge = ({
21
22
  (onClick || hover) && styles.hover,
22
23
  small && styles.small,
23
24
  rounded && styles.round,
25
+ transparent && styles.transparent,
24
26
  className
25
27
  ])
26
28
 
@@ -91,4 +91,30 @@
91
91
  &.round {
92
92
  @include border-radius(lg);
93
93
  }
94
+
95
+ &.transparent {
96
+ @include background(transparent);
97
+ @include typography(primary);
98
+ @include spacing(p0);
99
+
100
+ &.secondary {
101
+ @include typography(primary-20);
102
+ }
103
+
104
+ &.info {
105
+ @include typography(info);
106
+ }
107
+
108
+ &.success {
109
+ @include typography(success);
110
+ }
111
+
112
+ &.warning {
113
+ @include typography(warning);
114
+ }
115
+
116
+ &.alert {
117
+ @include typography(alert);
118
+ }
119
+ }
94
120
  }
@@ -12,6 +12,7 @@ export type BadgeProps = {
12
12
  hover?: boolean
13
13
  small?: boolean
14
14
  rounded?: boolean
15
+ transparent?: boolean
15
16
  className?: string
16
17
  [key: string]: any
17
18
  }
@@ -0,0 +1,164 @@
1
+ ---
2
+ import type { CounterProps } from './counter'
3
+
4
+ import Icon from '../Icon/Icon.astro'
5
+
6
+ import minusIcon from '../../icons/minus.svg?raw'
7
+ import plusIcon from '../../icons/plus.svg?raw'
8
+
9
+ import styles from './counter.module.scss'
10
+
11
+ interface Props extends CounterProps {}
12
+
13
+ const {
14
+ type = 'compact',
15
+ theme,
16
+ rounded,
17
+ minIcon,
18
+ maxIcon,
19
+ className,
20
+ width,
21
+ value = 0,
22
+ disabled,
23
+ ...rest
24
+ } = Astro.props
25
+
26
+ const classes = [
27
+ styles.counter,
28
+ styles[type],
29
+ theme && styles[theme],
30
+ rounded && styles.rounded,
31
+ className
32
+ ]
33
+
34
+ const subtractIcon = minIcon || minusIcon
35
+ const addIcon = maxIcon || plusIcon
36
+
37
+ const styleVariable = width
38
+ ? `--w-counter-width: ${width};`
39
+ : null
40
+ ---
41
+
42
+ <div class:list={classes} data-id="w-counter" style={styleVariable}>
43
+ <button data-id="w-counter-min" disabled={disabled}>
44
+ <Fragment>
45
+ {subtractIcon.startsWith('<svg')
46
+ ? <Fragment set:html={subtractIcon} />
47
+ : <Icon type={subtractIcon} />
48
+ }
49
+ </Fragment>
50
+ </button>
51
+ <input
52
+ type="number"
53
+ value={value}
54
+ disabled={disabled}
55
+ {...rest}
56
+ />
57
+ <button data-id="w-counter-max" disabled={disabled}>
58
+ <Fragment>
59
+ {addIcon.startsWith('<svg')
60
+ ? <Fragment set:html={addIcon} />
61
+ : <Icon type={addIcon} />
62
+ }
63
+ </Fragment>
64
+ </button>
65
+ </div>
66
+
67
+ <script>
68
+ import { off, on } from '../../utils/DOMUtils'
69
+ import { dispatch } from '../../utils/event'
70
+
71
+ const addEventListeners = () => {
72
+ const buttonSelector = '[data-id="w-counter"] button'
73
+ const inputSelector = '[data-id="w-counter"] input'
74
+ const eventName = 'counterOnChange'
75
+
76
+ let intervalId: ReturnType<typeof setTimeout>
77
+ let timeoutId: ReturnType<typeof setTimeout>
78
+ let longPressDelay = 500
79
+ let isKeyDown = false
80
+
81
+ const updateValue = (input: HTMLInputElement, min?: boolean) => {
82
+ const step = input.step ? Number(input.step) : 1
83
+ const direction = min ? -1 : 1
84
+ const newValue = Number(input.value) + (direction * step)
85
+
86
+ if ((input.min && newValue < Number(input.min)) || (input.max && newValue > Number(input.max))) {
87
+ return
88
+ }
89
+
90
+ input.value = String(newValue)
91
+
92
+ dispatch(eventName, {
93
+ name: input.name,
94
+ value: newValue
95
+ })
96
+ }
97
+
98
+ const startHold = (event: Event) => {
99
+ const target = event.currentTarget
100
+
101
+ if (target instanceof HTMLButtonElement && target.parentElement) {
102
+ const input = target.parentElement.querySelector('input') as HTMLInputElement
103
+ const min = target.dataset.id === 'w-counter-min'
104
+
105
+ updateValue(input, min)
106
+
107
+ timeoutId = setTimeout(function repeat() {
108
+ updateValue(input, min)
109
+
110
+ longPressDelay = Math.max(50, longPressDelay * 0.8)
111
+
112
+ intervalId = setTimeout(repeat, longPressDelay)
113
+ }, 500)
114
+ }
115
+ }
116
+
117
+ const stopHold = () => {
118
+ clearTimeout(timeoutId)
119
+ clearTimeout(intervalId)
120
+
121
+ isKeyDown = false
122
+ longPressDelay = 500
123
+ }
124
+
125
+ on(buttonSelector, 'mousedown', startHold, true)
126
+ on(buttonSelector, 'touchstart', startHold, true)
127
+
128
+ on(buttonSelector, 'mouseup', stopHold, true)
129
+ on(buttonSelector, 'mouseleave', stopHold, true)
130
+ on(buttonSelector, 'touchend', stopHold, true)
131
+ on(buttonSelector, 'touchcancel', stopHold, true)
132
+
133
+ on(buttonSelector, 'keydown', (event: KeyboardEvent) => {
134
+ if (event.key === 'Enter' && !isKeyDown) {
135
+ event.preventDefault()
136
+ startHold(event)
137
+
138
+ isKeyDown = true
139
+ }
140
+ }, true)
141
+
142
+ on(buttonSelector, 'keyup', (event: KeyboardEvent) => {
143
+ if (event.key === 'Enter') {
144
+ stopHold()
145
+ }
146
+ }, true)
147
+
148
+ on(inputSelector, 'input', (event: Event) => {
149
+ const target = event.target
150
+
151
+ if (target instanceof HTMLInputElement) {
152
+ dispatch(eventName, {
153
+ name: target.name,
154
+ value: Number(target.value)
155
+ })
156
+ }
157
+ }, true)
158
+ }
159
+
160
+ off(document, 'astro:after-swap', addEventListeners)
161
+ on(document, 'astro:after-swap', addEventListeners)
162
+
163
+ addEventListeners()
164
+ </script>
@@ -0,0 +1,141 @@
1
+ <script lang="ts">
2
+ import type { SvelteCounterProps } from './counter'
3
+
4
+ import { classNames } from '../../utils/classNames'
5
+
6
+ import minusIcon from '../../icons/minus.svg?raw'
7
+ import plusIcon from '../../icons/plus.svg?raw'
8
+
9
+ import styles from './counter.module.scss'
10
+
11
+ let {
12
+ type = 'compact',
13
+ theme,
14
+ rounded,
15
+ minIcon,
16
+ maxIcon,
17
+ className,
18
+ width,
19
+ value = $bindable(0),
20
+ disabled,
21
+ onChange,
22
+ step = 1,
23
+ min,
24
+ max,
25
+ ...rest
26
+ }: SvelteCounterProps = $props()
27
+
28
+ const classes = classNames([
29
+ styles.counter,
30
+ styles[type],
31
+ theme && styles[theme],
32
+ rounded && styles.rounded,
33
+ className
34
+ ])
35
+
36
+ const subtractIcon = minIcon || minusIcon
37
+ const addIcon = maxIcon || plusIcon
38
+
39
+ const styleVariable = width
40
+ ? `--w-counter-width: ${width};`
41
+ : null
42
+
43
+ let intervalId: ReturnType<typeof setTimeout>
44
+ let timeoutId: ReturnType<typeof setTimeout>
45
+ let longPressDelay = 500
46
+ let isKeyDown = false
47
+
48
+ const updateValue = (isMin?: boolean) => {
49
+ const direction = isMin ? -1 : 1
50
+ const newValue = value + (direction * step)
51
+
52
+ if ((min !== undefined && newValue < min) || (max !== undefined && newValue > max)) {
53
+ return
54
+ }
55
+
56
+ value = newValue
57
+
58
+ onChange?.(newValue)
59
+ }
60
+
61
+ const startHold = (event: Event) => {
62
+ const target = event.currentTarget
63
+
64
+ if (target instanceof HTMLButtonElement) {
65
+ const isMin = target.dataset.id === 'w-counter-min'
66
+
67
+ updateValue(isMin)
68
+
69
+ timeoutId = setTimeout(function repeat() {
70
+ updateValue(isMin)
71
+
72
+ longPressDelay = Math.max(50, longPressDelay * 0.8)
73
+ intervalId = setTimeout(repeat, longPressDelay)
74
+ }, 500)
75
+ }
76
+ }
77
+
78
+ const stopHold = () => {
79
+ clearTimeout(timeoutId)
80
+ clearTimeout(intervalId)
81
+
82
+ isKeyDown = false
83
+ longPressDelay = 500
84
+ }
85
+
86
+ const handleKeyDown = (event: KeyboardEvent) => {
87
+ if (event.key === 'Enter' && !isKeyDown) {
88
+ event.preventDefault()
89
+ startHold(event)
90
+
91
+ isKeyDown = true
92
+ }
93
+ }
94
+
95
+ const handleKeyUp = (event: KeyboardEvent) => {
96
+ if (event.key === 'Enter') {
97
+ stopHold()
98
+ }
99
+ }
100
+ </script>
101
+
102
+ <div class={classes} style={styleVariable}>
103
+ <button
104
+ data-id="w-counter-min"
105
+ disabled={disabled}
106
+ onmousedown={startHold}
107
+ ontouchstart={startHold}
108
+ onmouseup={stopHold}
109
+ onmouseleave={stopHold}
110
+ ontouchend={stopHold}
111
+ ontouchcancel={stopHold}
112
+ onkeydown={handleKeyDown}
113
+ onkeyup={handleKeyUp}
114
+ >
115
+ {@html subtractIcon}
116
+ </button>
117
+ <input
118
+ bind:value={value}
119
+ type="number"
120
+ disabled={disabled}
121
+ step={step}
122
+ min={min}
123
+ max={max}
124
+ oninput={() => onChange?.(value)}
125
+ {...rest}
126
+ />
127
+ <button
128
+ data-id="w-counter-max"
129
+ disabled={disabled}
130
+ onmousedown={startHold}
131
+ ontouchstart={startHold}
132
+ onmouseup={stopHold}
133
+ onmouseleave={stopHold}
134
+ ontouchend={stopHold}
135
+ ontouchcancel={stopHold}
136
+ onkeydown={handleKeyDown}
137
+ onkeyup={handleKeyUp}
138
+ >
139
+ {@html addIcon}
140
+ </button>
141
+ </div>
@@ -0,0 +1,161 @@
1
+ import React, { useRef, useState } from 'react'
2
+ import type { ReactCounterProps } from './counter'
3
+
4
+ import { classNames } from '../../utils/classNames'
5
+
6
+ import minusIcon from '../../icons/minus.svg?raw'
7
+ import plusIcon from '../../icons/plus.svg?raw'
8
+
9
+ import styles from './counter.module.scss'
10
+
11
+ const Counter = ({
12
+ type = 'compact',
13
+ theme,
14
+ rounded,
15
+ minIcon,
16
+ maxIcon,
17
+ className,
18
+ width,
19
+ value = 0,
20
+ disabled,
21
+ onChange,
22
+ step = 1,
23
+ min,
24
+ max,
25
+ ...rest
26
+ }: ReactCounterProps) => {
27
+ const [inputValue, setInputValue] = useState(value)
28
+ const intervalId = useRef<ReturnType<typeof setTimeout> | null>(null)
29
+ const timeoutId = useRef<ReturnType<typeof setTimeout> | null>(null)
30
+ const longPressDelay = useRef(500)
31
+ const isKeyDown = useRef(false)
32
+
33
+ const classes = classNames([
34
+ styles.counter,
35
+ styles[type],
36
+ theme && styles[theme],
37
+ rounded && styles.rounded,
38
+ className
39
+ ])
40
+
41
+ const subtractIcon = minIcon || minusIcon
42
+ const addIcon = maxIcon || plusIcon
43
+
44
+ const styleVariable = width
45
+ ? { '--w-counter-width': width } as React.CSSProperties
46
+ : undefined
47
+
48
+ const updateValue = (isMin?: boolean) => {
49
+ setInputValue((prevValue: number) => {
50
+ const direction = isMin ? -1 : 1
51
+ const newValue = prevValue + (direction * step)
52
+
53
+ if ((min !== undefined && newValue < min) || (max !== undefined && newValue > max)) {
54
+ return prevValue
55
+ }
56
+
57
+ onChange?.(newValue)
58
+ return newValue
59
+ })
60
+ }
61
+
62
+ const startHold = (event: React.MouseEvent | React.TouchEvent | React.KeyboardEvent) => {
63
+ const target = event.currentTarget
64
+
65
+ if (target instanceof HTMLButtonElement) {
66
+ const isMin = target.dataset.id === 'w-counter-min'
67
+
68
+ updateValue(isMin)
69
+
70
+ timeoutId.current = setTimeout(function repeat() {
71
+ updateValue(isMin)
72
+
73
+ longPressDelay.current = Math.max(50, longPressDelay.current * 0.8)
74
+ intervalId.current = setTimeout(repeat, longPressDelay.current)
75
+ }, 500)
76
+ }
77
+ }
78
+
79
+ const stopHold = () => {
80
+ if (timeoutId.current) {
81
+ clearTimeout(timeoutId.current)
82
+ }
83
+
84
+ if (intervalId.current) {
85
+ clearTimeout(intervalId.current)
86
+ }
87
+
88
+ isKeyDown.current = false
89
+ longPressDelay.current = 500
90
+ }
91
+
92
+ const handleKeyDown = (event: React.KeyboardEvent) => {
93
+ if (event.key === 'Enter' && !isKeyDown.current) {
94
+ event.preventDefault()
95
+ startHold(event)
96
+
97
+ isKeyDown.current = true
98
+ }
99
+ }
100
+
101
+ const handleKeyUp = (event: React.KeyboardEvent) => {
102
+ if (event.key === 'Enter') {
103
+ stopHold()
104
+ }
105
+ }
106
+
107
+ const handleInput = (event: React.FormEvent) => {
108
+ const target = event.target
109
+
110
+ if (target instanceof HTMLInputElement) {
111
+ const newValue = Number(target.value)
112
+
113
+ setInputValue(newValue)
114
+ onChange?.(newValue)
115
+ }
116
+ }
117
+
118
+ return (
119
+ <div className={classes} style={styleVariable}>
120
+ <button
121
+ data-id="w-counter-min"
122
+ disabled={disabled}
123
+ onMouseDown={startHold}
124
+ onTouchStart={startHold}
125
+ onMouseUp={stopHold}
126
+ onMouseLeave={stopHold}
127
+ onTouchEnd={stopHold}
128
+ onTouchCancel={stopHold}
129
+ onKeyDown={handleKeyDown}
130
+ onKeyUp={handleKeyUp}
131
+ dangerouslySetInnerHTML={{ __html: subtractIcon }}
132
+ />
133
+ <input
134
+ value={inputValue}
135
+ type="number"
136
+ disabled={disabled}
137
+ step={step}
138
+ min={min}
139
+ max={max}
140
+ onInput={handleInput}
141
+ {...rest}
142
+ />
143
+ <button
144
+ data-id="w-counter-max"
145
+ disabled={disabled}
146
+ onMouseDown={startHold}
147
+ onTouchStart={startHold}
148
+ onMouseUp={stopHold}
149
+ onMouseLeave={stopHold}
150
+ onTouchEnd={stopHold}
151
+ onTouchCancel={stopHold}
152
+ onKeyDown={handleKeyDown}
153
+ onKeyUp={handleKeyUp}
154
+ dangerouslySetInnerHTML={{ __html: addIcon }}
155
+ />
156
+ </div>
157
+
158
+ )
159
+ }
160
+
161
+ export default Counter