@popovandrii/ui-elements 0.0.1
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/LICENSE +9 -0
- package/README.md +29 -0
- package/dist/SpinBox.d.ts +11 -0
- package/dist/SpinBox.js +195 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.es.js +102 -0
- package/dist/index.js +2 -0
- package/dist/index.umd.js +1 -0
- package/dist/style.css +1 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
Copyright 2025 Andrii Popov autoxarkov@gmail.com
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# UI elements
|
|
2
|
+
|
|
3
|
+
TypeScript-based NPM plugin.
|
|
4
|
+
The plugin includes interface elements with specific properties.
|
|
5
|
+
Currently implemented:
|
|
6
|
+
- Spin-Box This is a field with two buttons. Provides increment and decrement of numbers
|
|
7
|
+
|
|
8
|
+
# Information for Developers
|
|
9
|
+
```sh
|
|
10
|
+
git clone git@gitlab.com:AndreyPopov/ui-elements.git && cd ui-elements
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
docker compose up -d --build
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
docker compose exec vite-dev sh
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
$ npm install
|
|
23
|
+
$ npm run build # Compile the project into the ./dist folder.
|
|
24
|
+
$ npm run dev # Work on the project
|
|
25
|
+
$ npm run lint
|
|
26
|
+
$ npm run format
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The './playground' folder for viewing in a browser
|
package/dist/SpinBox.js
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
var _SpinBox_instances, _SpinBox_state, _SpinBox_event;
|
|
7
|
+
export class SpinBox {
|
|
8
|
+
constructor(selectors = {}) {
|
|
9
|
+
_SpinBox_instances.add(this);
|
|
10
|
+
Object.defineProperty(this, "selectors", {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
writable: true,
|
|
14
|
+
value: void 0
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(this, "spinBoxes", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: void 0
|
|
21
|
+
});
|
|
22
|
+
_SpinBox_state.set(this, (inputNumber, down, up, min = 0, max = 0) => {
|
|
23
|
+
if (inputNumber == min || inputNumber < min) {
|
|
24
|
+
down.classList.add(this.selectors.disabledBtn);
|
|
25
|
+
down.disabled = true;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
down.classList.remove(this.selectors.disabledBtn);
|
|
29
|
+
down.disabled = false;
|
|
30
|
+
}
|
|
31
|
+
if (inputNumber == max || inputNumber > max) {
|
|
32
|
+
up.classList.add(this.selectors.disabledBtn);
|
|
33
|
+
up.disabled = true;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
up.classList.remove(this.selectors.disabledBtn);
|
|
37
|
+
up.disabled = false;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
const defaultSelectors = {
|
|
41
|
+
main: "spin-box",
|
|
42
|
+
disabledBtn: "disabled",
|
|
43
|
+
};
|
|
44
|
+
this.selectors = { ...defaultSelectors, ...selectors };
|
|
45
|
+
this.spinBoxes = document.querySelectorAll(`.${this.selectors.main}`);
|
|
46
|
+
__classPrivateFieldGet(this, _SpinBox_instances, "m", _SpinBox_event).call(this);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
_SpinBox_state = new WeakMap(), _SpinBox_instances = new WeakSet(), _SpinBox_event = function _SpinBox_event() {
|
|
50
|
+
this.spinBoxes.forEach((e) => {
|
|
51
|
+
const btnDown = e.firstElementChild;
|
|
52
|
+
const input = e.querySelector("input");
|
|
53
|
+
const btnUp = e.lastElementChild;
|
|
54
|
+
const step = Number(e.dataset.step);
|
|
55
|
+
const min = Number(e.dataset.min);
|
|
56
|
+
const max = Number(e.dataset.max);
|
|
57
|
+
const updateAria = (val) => {
|
|
58
|
+
input.setAttribute("aria-valuenow", String(val));
|
|
59
|
+
input.setAttribute("aria-valuetext", `${val} items`);
|
|
60
|
+
};
|
|
61
|
+
if (Number(input.value) <= min)
|
|
62
|
+
input.value = min.toFixed(step);
|
|
63
|
+
if (Number(input.value) >= max)
|
|
64
|
+
input.value = max.toFixed(step);
|
|
65
|
+
if (min)
|
|
66
|
+
input.setAttribute("aria-valuemin", min.toFixed(step));
|
|
67
|
+
if (max)
|
|
68
|
+
input.setAttribute("aria-valuemax", max.toFixed(step));
|
|
69
|
+
__classPrivateFieldGet(this, _SpinBox_state, "f").call(this, Number(input.value), btnDown, btnUp, min, max);
|
|
70
|
+
updateAria(min);
|
|
71
|
+
let timerId = null;
|
|
72
|
+
const increment = (speed = 1) => {
|
|
73
|
+
input.value = String(Math.abs(Number(input.value)));
|
|
74
|
+
let val = parseFloat(input.value) || 0;
|
|
75
|
+
val = val + (1 * speed) / Math.pow(10, step);
|
|
76
|
+
if (val > max)
|
|
77
|
+
val = max;
|
|
78
|
+
input.value = val.toFixed(step);
|
|
79
|
+
__classPrivateFieldGet(this, _SpinBox_state, "f").call(this, Number(input.value), btnDown, btnUp, min, max);
|
|
80
|
+
updateAria(val);
|
|
81
|
+
};
|
|
82
|
+
const decrement = (speed = 1) => {
|
|
83
|
+
input.value = String(Math.abs(Number(input.value)));
|
|
84
|
+
let val = parseFloat(input.value) || 0;
|
|
85
|
+
val = val - (1 * speed) / Math.pow(10, step);
|
|
86
|
+
if (val < min)
|
|
87
|
+
val = min;
|
|
88
|
+
input.value = val.toFixed(step);
|
|
89
|
+
__classPrivateFieldGet(this, _SpinBox_state, "f").call(this, Number(input.value), btnDown, btnUp, min, max);
|
|
90
|
+
updateAria(val);
|
|
91
|
+
};
|
|
92
|
+
const startTimer = (action, ms = 150) => {
|
|
93
|
+
if (timerId !== null)
|
|
94
|
+
return;
|
|
95
|
+
timerId = window.setInterval(action, ms);
|
|
96
|
+
};
|
|
97
|
+
const stopTimer = () => {
|
|
98
|
+
if (timerId !== null) {
|
|
99
|
+
clearInterval(timerId);
|
|
100
|
+
timerId = null;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
// hold
|
|
104
|
+
btnUp.addEventListener("mousedown", (e) => {
|
|
105
|
+
const speed = e.shiftKey ? 3 : 1;
|
|
106
|
+
startTimer(() => increment(speed));
|
|
107
|
+
});
|
|
108
|
+
btnUp.addEventListener("touchstart", () => startTimer(increment));
|
|
109
|
+
// lost
|
|
110
|
+
["mouseup", "mouseleave", "mouseout", "touchend", "touchcancel"].forEach((event) => {
|
|
111
|
+
btnUp.addEventListener(event, stopTimer);
|
|
112
|
+
});
|
|
113
|
+
// once click
|
|
114
|
+
btnUp.addEventListener("click", (e) => {
|
|
115
|
+
const speed = e.shiftKey ? 3 : 1;
|
|
116
|
+
// block when holding
|
|
117
|
+
if (timerId === null)
|
|
118
|
+
increment(speed);
|
|
119
|
+
});
|
|
120
|
+
btnDown.addEventListener("click", (e) => {
|
|
121
|
+
const speed = e.shiftKey ? 3 : 1;
|
|
122
|
+
if (timerId === null)
|
|
123
|
+
decrement(speed);
|
|
124
|
+
});
|
|
125
|
+
btnDown.addEventListener("mousedown", (e) => {
|
|
126
|
+
const speed = e.shiftKey ? 3 : 1;
|
|
127
|
+
startTimer(() => decrement(speed), 100);
|
|
128
|
+
});
|
|
129
|
+
btnDown.addEventListener("touchstart", () => startTimer(decrement, 100));
|
|
130
|
+
["mouseup", "mouseleave", "mouseout", "touchend", "touchcancel"].forEach((event) => {
|
|
131
|
+
btnDown.addEventListener(event, stopTimer);
|
|
132
|
+
});
|
|
133
|
+
input.addEventListener("keydown", (e) => {
|
|
134
|
+
const key = e.key;
|
|
135
|
+
const speed = e.shiftKey ? 3 : 1;
|
|
136
|
+
const allowedKeys = [
|
|
137
|
+
"Backspace",
|
|
138
|
+
"Delete",
|
|
139
|
+
"ArrowLeft",
|
|
140
|
+
"ArrowRight",
|
|
141
|
+
"Tab",
|
|
142
|
+
"Enter",
|
|
143
|
+
"Home",
|
|
144
|
+
"End",
|
|
145
|
+
];
|
|
146
|
+
if (allowedKeys.includes(key) ||
|
|
147
|
+
((e.ctrlKey || e.metaKey) &&
|
|
148
|
+
["a", "c", "v", "x"].includes(key.toLowerCase()))) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (["e", "+", "-"].includes(key)) {
|
|
152
|
+
e.preventDefault();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (key === "ArrowUp" || key === "ArrowDown") {
|
|
156
|
+
e.preventDefault();
|
|
157
|
+
const val = parseFloat(input.value) || 0;
|
|
158
|
+
const stepSize = (1 * speed) / Math.pow(10, step);
|
|
159
|
+
let newVal = key === "ArrowUp" ? val + stepSize : val - stepSize;
|
|
160
|
+
if (newVal < min)
|
|
161
|
+
newVal = min;
|
|
162
|
+
input.value = newVal.toFixed(step);
|
|
163
|
+
if (Number(input.value) < min)
|
|
164
|
+
input.value = min.toFixed(step);
|
|
165
|
+
if (Number(input.value) > max)
|
|
166
|
+
input.value = max.toFixed(step);
|
|
167
|
+
__classPrivateFieldGet(this, _SpinBox_state, "f").call(this, Number(input.value), btnDown, btnUp, min, max);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const normalizedKey = key === "," ? "." : key;
|
|
171
|
+
const isNumeric = /^[0-9]$/.test(normalizedKey);
|
|
172
|
+
const isDot = normalizedKey === ".";
|
|
173
|
+
const alreadyHasDot = input.value.includes(".");
|
|
174
|
+
if ((step === 0 && !isNumeric) ||
|
|
175
|
+
(step > 0 && !(isNumeric || isDot)) ||
|
|
176
|
+
(isDot && alreadyHasDot)) {
|
|
177
|
+
e.preventDefault();
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
input.addEventListener("keyup", () => {
|
|
181
|
+
if (Number(input.value) < min)
|
|
182
|
+
input.value = min.toFixed(step);
|
|
183
|
+
if (Number(input.value) > max)
|
|
184
|
+
input.value = max.toFixed(step);
|
|
185
|
+
__classPrivateFieldGet(this, _SpinBox_state, "f").call(this, Number(input.value), btnDown, btnUp, min, max);
|
|
186
|
+
});
|
|
187
|
+
input.addEventListener("change", () => {
|
|
188
|
+
if (Number(input.value) < min)
|
|
189
|
+
input.value = min.toFixed(step);
|
|
190
|
+
if (Number(input.value) > max)
|
|
191
|
+
input.value = max.toFixed(step);
|
|
192
|
+
__classPrivateFieldGet(this, _SpinBox_state, "f").call(this, Number(input.value), btnDown, btnUp, min, max);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
};
|
package/dist/index.d.ts
ADDED
package/dist/index.es.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
var C = Object.defineProperty;
|
|
2
|
+
var K = (r) => {
|
|
3
|
+
throw TypeError(r);
|
|
4
|
+
};
|
|
5
|
+
var I = (r, t, a) => t in r ? C(r, t, { enumerable: !0, configurable: !0, writable: !0, value: a }) : r[t] = a;
|
|
6
|
+
var E = (r, t, a) => I(r, typeof t != "symbol" ? t + "" : t, a), D = (r, t, a) => t.has(r) || K("Cannot " + a);
|
|
7
|
+
var v = (r, t, a) => (D(r, t, "read from private field"), a ? a.call(r) : t.get(r)), w = (r, t, a) => t.has(r) ? K("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(r) : t.set(r, a);
|
|
8
|
+
var S = (r, t, a) => (D(r, t, "access private method"), a);
|
|
9
|
+
var d, f, k;
|
|
10
|
+
class $ {
|
|
11
|
+
constructor(t = {}) {
|
|
12
|
+
w(this, f);
|
|
13
|
+
E(this, "selectors");
|
|
14
|
+
E(this, "spinBoxes");
|
|
15
|
+
w(this, d, (t, a, e, u = 0, l = 0) => {
|
|
16
|
+
t == u || t < u ? (a.classList.add(this.selectors.disabledBtn), a.disabled = !0) : (a.classList.remove(this.selectors.disabledBtn), a.disabled = !1), t == l || t > l ? (e.classList.add(this.selectors.disabledBtn), e.disabled = !0) : (e.classList.remove(this.selectors.disabledBtn), e.disabled = !1);
|
|
17
|
+
});
|
|
18
|
+
const a = {
|
|
19
|
+
main: "spin-box",
|
|
20
|
+
disabledBtn: "disabled"
|
|
21
|
+
};
|
|
22
|
+
this.selectors = { ...a, ...t }, this.spinBoxes = document.querySelectorAll(
|
|
23
|
+
`.${this.selectors.main}`
|
|
24
|
+
), S(this, f, k).call(this);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
d = new WeakMap(), f = new WeakSet(), k = function() {
|
|
28
|
+
this.spinBoxes.forEach((t) => {
|
|
29
|
+
const a = t.firstElementChild, e = t.querySelector("input"), u = t.lastElementChild, l = Number(t.dataset.step), n = Number(t.dataset.min), o = Number(t.dataset.max), h = (i) => {
|
|
30
|
+
e.setAttribute("aria-valuenow", String(i)), e.setAttribute("aria-valuetext", `${i} items`);
|
|
31
|
+
};
|
|
32
|
+
Number(e.value) <= n && (e.value = n.toFixed(l)), Number(e.value) >= o && (e.value = o.toFixed(l)), n && e.setAttribute("aria-valuemin", n.toFixed(l)), o && e.setAttribute("aria-valuemax", o.toFixed(l)), v(this, d).call(this, Number(e.value), a, u, n, o), h(n);
|
|
33
|
+
let c = null;
|
|
34
|
+
const b = (i = 1) => {
|
|
35
|
+
e.value = String(Math.abs(Number(e.value)));
|
|
36
|
+
let s = parseFloat(e.value) || 0;
|
|
37
|
+
s = s + 1 * i / Math.pow(10, l), s > o && (s = o), e.value = s.toFixed(l), v(this, d).call(this, Number(e.value), a, u, n, o), h(s);
|
|
38
|
+
}, p = (i = 1) => {
|
|
39
|
+
e.value = String(Math.abs(Number(e.value)));
|
|
40
|
+
let s = parseFloat(e.value) || 0;
|
|
41
|
+
s = s - 1 * i / Math.pow(10, l), s < n && (s = n), e.value = s.toFixed(l), v(this, d).call(this, Number(e.value), a, u, n, o), h(s);
|
|
42
|
+
}, m = (i, s = 150) => {
|
|
43
|
+
c === null && (c = window.setInterval(i, s));
|
|
44
|
+
}, y = () => {
|
|
45
|
+
c !== null && (clearInterval(c), c = null);
|
|
46
|
+
};
|
|
47
|
+
u.addEventListener("mousedown", (i) => {
|
|
48
|
+
const s = i.shiftKey ? 3 : 1;
|
|
49
|
+
m(() => b(s));
|
|
50
|
+
}), u.addEventListener("touchstart", () => m(b)), ["mouseup", "mouseleave", "mouseout", "touchend", "touchcancel"].forEach(
|
|
51
|
+
(i) => {
|
|
52
|
+
u.addEventListener(i, y);
|
|
53
|
+
}
|
|
54
|
+
), u.addEventListener("click", (i) => {
|
|
55
|
+
const s = i.shiftKey ? 3 : 1;
|
|
56
|
+
c === null && b(s);
|
|
57
|
+
}), a.addEventListener("click", (i) => {
|
|
58
|
+
const s = i.shiftKey ? 3 : 1;
|
|
59
|
+
c === null && p(s);
|
|
60
|
+
}), a.addEventListener("mousedown", (i) => {
|
|
61
|
+
const s = i.shiftKey ? 3 : 1;
|
|
62
|
+
m(() => p(s), 100);
|
|
63
|
+
}), a.addEventListener("touchstart", () => m(p, 100)), ["mouseup", "mouseleave", "mouseout", "touchend", "touchcancel"].forEach(
|
|
64
|
+
(i) => {
|
|
65
|
+
a.addEventListener(i, y);
|
|
66
|
+
}
|
|
67
|
+
), e.addEventListener("keydown", (i) => {
|
|
68
|
+
const s = i.key, g = i.shiftKey ? 3 : 1;
|
|
69
|
+
if ([
|
|
70
|
+
"Backspace",
|
|
71
|
+
"Delete",
|
|
72
|
+
"ArrowLeft",
|
|
73
|
+
"ArrowRight",
|
|
74
|
+
"Tab",
|
|
75
|
+
"Enter",
|
|
76
|
+
"Home",
|
|
77
|
+
"End"
|
|
78
|
+
].includes(s) || (i.ctrlKey || i.metaKey) && ["a", "c", "v", "x"].includes(s.toLowerCase()))
|
|
79
|
+
return;
|
|
80
|
+
if (["e", "+", "-"].includes(s)) {
|
|
81
|
+
i.preventDefault();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (s === "ArrowUp" || s === "ArrowDown") {
|
|
85
|
+
i.preventDefault();
|
|
86
|
+
const A = parseFloat(e.value) || 0, B = 1 * g / Math.pow(10, l);
|
|
87
|
+
let x = s === "ArrowUp" ? A + B : A - B;
|
|
88
|
+
x < n && (x = n), e.value = x.toFixed(l), Number(e.value) < n && (e.value = n.toFixed(l)), Number(e.value) > o && (e.value = o.toFixed(l)), v(this, d).call(this, Number(e.value), a, u, n, o);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const L = s === "," ? "." : s, N = /^[0-9]$/.test(L), F = L === ".", M = e.value.includes(".");
|
|
92
|
+
(l === 0 && !N || l > 0 && !(N || F) || F && M) && i.preventDefault();
|
|
93
|
+
}), e.addEventListener("keyup", () => {
|
|
94
|
+
Number(e.value) < n && (e.value = n.toFixed(l)), Number(e.value) > o && (e.value = o.toFixed(l)), v(this, d).call(this, Number(e.value), a, u, n, o);
|
|
95
|
+
}), e.addEventListener("change", () => {
|
|
96
|
+
Number(e.value) < n && (e.value = n.toFixed(l)), Number(e.value) > o && (e.value = o.toFixed(l)), v(this, d).call(this, Number(e.value), a, u, n, o);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
export {
|
|
101
|
+
$ as SpinBox
|
|
102
|
+
};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(i,a){typeof exports=="object"&&typeof module<"u"?a(exports):typeof define=="function"&&define.amd?define(["exports"],a):(i=typeof globalThis<"u"?globalThis:i||self,a(i["Ui Elements"]={}))})(this,function(i){"use strict";var U=Object.defineProperty;var K=i=>{throw TypeError(i)};var C=(i,a,l)=>a in i?U(i,a,{enumerable:!0,configurable:!0,writable:!0,value:l}):i[a]=l;var E=(i,a,l)=>C(i,typeof a!="symbol"?a+"":a,l),D=(i,a,l)=>a.has(i)||K("Cannot "+l);var f=(i,a,l)=>(D(i,a,"read from private field"),l?l.call(i):a.get(i)),w=(i,a,l)=>a.has(i)?K("Cannot add the same private member more than once"):a instanceof WeakSet?a.add(i):a.set(i,l);var g=(i,a,l)=>(D(i,a,"access private method"),l);var l,m,k;class a{constructor(d={}){w(this,m);E(this,"selectors");E(this,"spinBoxes");w(this,l,(d,r,e,c=0,n=0)=>{d==c||d<c?(r.classList.add(this.selectors.disabledBtn),r.disabled=!0):(r.classList.remove(this.selectors.disabledBtn),r.disabled=!1),d==n||d>n?(e.classList.add(this.selectors.disabledBtn),e.disabled=!0):(e.classList.remove(this.selectors.disabledBtn),e.disabled=!1)});const r={main:"spin-box",disabledBtn:"disabled"};this.selectors={...r,...d},this.spinBoxes=document.querySelectorAll(`.${this.selectors.main}`),g(this,m,k).call(this)}}l=new WeakMap,m=new WeakSet,k=function(){this.spinBoxes.forEach(d=>{const r=d.firstElementChild,e=d.querySelector("input"),c=d.lastElementChild,n=Number(d.dataset.step),o=Number(d.dataset.min),u=Number(d.dataset.max),b=s=>{e.setAttribute("aria-valuenow",String(s)),e.setAttribute("aria-valuetext",`${s} items`)};Number(e.value)<=o&&(e.value=o.toFixed(n)),Number(e.value)>=u&&(e.value=u.toFixed(n)),o&&e.setAttribute("aria-valuemin",o.toFixed(n)),u&&e.setAttribute("aria-valuemax",u.toFixed(n)),f(this,l).call(this,Number(e.value),r,c,o,u),b(o);let v=null;const p=(s=1)=>{e.value=String(Math.abs(Number(e.value)));let t=parseFloat(e.value)||0;t=t+1*s/Math.pow(10,n),t>u&&(t=u),e.value=t.toFixed(n),f(this,l).call(this,Number(e.value),r,c,o,u),b(t)},x=(s=1)=>{e.value=String(Math.abs(Number(e.value)));let t=parseFloat(e.value)||0;t=t-1*s/Math.pow(10,n),t<o&&(t=o),e.value=t.toFixed(n),f(this,l).call(this,Number(e.value),r,c,o,u),b(t)},h=(s,t=150)=>{v===null&&(v=window.setInterval(s,t))},L=()=>{v!==null&&(clearInterval(v),v=null)};c.addEventListener("mousedown",s=>{const t=s.shiftKey?3:1;h(()=>p(t))}),c.addEventListener("touchstart",()=>h(p)),["mouseup","mouseleave","mouseout","touchend","touchcancel"].forEach(s=>{c.addEventListener(s,L)}),c.addEventListener("click",s=>{const t=s.shiftKey?3:1;v===null&&p(t)}),r.addEventListener("click",s=>{const t=s.shiftKey?3:1;v===null&&x(t)}),r.addEventListener("mousedown",s=>{const t=s.shiftKey?3:1;h(()=>x(t),100)}),r.addEventListener("touchstart",()=>h(x,100)),["mouseup","mouseleave","mouseout","touchend","touchcancel"].forEach(s=>{r.addEventListener(s,L)}),e.addEventListener("keydown",s=>{const t=s.key,M=s.shiftKey?3:1;if(["Backspace","Delete","ArrowLeft","ArrowRight","Tab","Enter","Home","End"].includes(t)||(s.ctrlKey||s.metaKey)&&["a","c","v","x"].includes(t.toLowerCase()))return;if(["e","+","-"].includes(t)){s.preventDefault();return}if(t==="ArrowUp"||t==="ArrowDown"){s.preventDefault();const B=parseFloat(e.value)||0,S=1*M/Math.pow(10,n);let y=t==="ArrowUp"?B+S:B-S;y<o&&(y=o),e.value=y.toFixed(n),Number(e.value)<o&&(e.value=o.toFixed(n)),Number(e.value)>u&&(e.value=u.toFixed(n)),f(this,l).call(this,Number(e.value),r,c,o,u);return}const N=t===","?".":t,F=/^[0-9]$/.test(N),A=N===".",T=e.value.includes(".");(n===0&&!F||n>0&&!(F||A)||A&&T)&&s.preventDefault()}),e.addEventListener("keyup",()=>{Number(e.value)<o&&(e.value=o.toFixed(n)),Number(e.value)>u&&(e.value=u.toFixed(n)),f(this,l).call(this,Number(e.value),r,c,o,u)}),e.addEventListener("change",()=>{Number(e.value)<o&&(e.value=o.toFixed(n)),Number(e.value)>u&&(e.value=u.toFixed(n)),f(this,l).call(this,Number(e.value),r,c,o,u)})})},i.SpinBox=a,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})});
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.spin-box{position:relative;display:grid;grid-template-columns:min-content 1fr min-content;align-items:center;width:13rem;height:2.5rem;-webkit-user-select:none;user-select:none;border:1px solid var(--c-g-500);border-radius:.5rem;background-color:var(--c-g-500)}.spin-box>input{border:none;height:100%;outline:none;font-weight:700;font-size:1.5rem;text-align:center;background-color:var(--c-g-50);color:var(--c-g-700);width:100%;min-width:3rem;padding:0}.spin-box>input:focus{background-color:var(--c-g-50);color:var(--c-g-950)}.spin-box__txt{font-weight:400}.spin-box>button{color:var(--c-g-900);display:flex;align-items:center;justify-content:center;border:none;height:100%;background-color:var(--c-g-300);cursor:pointer;font-size:2rem;width:3rem}.spin-box>button:hover{background-color:var(--c-g-500);color:var(--c-g-50)}.spin-box>.disabled{background-color:var(--c-g-100);color:var(--c-g-300);pointer-events:none}.spin-box>button:first-child{border-right:1px solid var(--c-g-500);border-radius:.5rem 0 0 .5rem}.spin-box button:last-child{border-left:1px solid var(--c-g-500);border-radius:0 .5rem .5rem 0}.spin-box.radius-none{border-radius:0}.spin-box.radius-none>button{border-radius:0}.spin-box.sm{height:2rem;width:10rem}.spin-box.sm>input,.spin-box.sm>button{font-size:1rem}.spin-box.sm>button{width:2rem}.spin-box.lg{height:3.5rem;width:16rem}.spin-box.lg>input,.spin-box.lg>button{font-size:2rem}.spin-box.lg>button{width:3.5rem}.spin-box.danger{background-color:var(--c-d-500);border-color:var(--c-d-500)}.spin-box.danger>input{background-color:var(--c-d-50);color:var(--c-d-700)}.spin-box.danger>input:focus{background-color:var(--c-d-50);color:var(--c-d-950)}.spin-box.danger>button{color:var(--c-d-500);background-color:var(--c-d-300);border-color:var(--c-d-500)}.spin-box.danger>button:hover{color:var(--c-d-300);background-color:var(--c-d-500)}.spin-box.danger>.disabled{background-color:var(--c-d-100);color:var(--c-d-300)}.spin-box.info{background-color:var(--c-i-500);border-color:var(--c-i-500)}.spin-box.info>input{background-color:var(--c-i-50);color:var(--c-i-700)}.spin-box.info>input:focus{background-color:var(--c-i-50);color:var(--c-i-950)}.spin-box.info>button{color:var(--c-i-500);background-color:var(--c-i-300);border-color:var(--c-i-500)}.spin-box.info>button:hover{color:var(--c-i-300);background-color:var(--c-i-500)}.spin-box.info>.disabled{background-color:var(--c-i-100);color:var(--c-i-300)}.spin-box.primary{background-color:var(--c-p-500);border-color:var(--c-p-500)}.spin-box.primary>input{background-color:var(--c-p-50);color:var(--c-p-700)}.spin-box.primary>input:focus{background-color:var(--c-p-50);color:var(--c-p-950)}.spin-box.primary>button{color:var(--c-p-500);background-color:var(--c-p-300);border-color:var(--c-p-500)}.spin-box.primary>button:hover{color:var(--c-p-300);background-color:var(--c-p-500)}.spin-box.primary>.disabled{background-color:var(--c-p-100);color:var(--c-p-300)}.spin-box.success{background-color:var(--c-s-500);border-color:var(--c-s-500)}.spin-box.success>input{background-color:var(--c-s-50);color:var(--c-s-700)}.spin-box.success>input:focus{background-color:var(--c-s-50);color:var(--c-s-950)}.spin-box.success>button{color:var(--c-s-500);background-color:var(--c-s-300);border-color:var(--c-s-500)}.spin-box.success>button:hover{color:var(--c-s-300);background-color:var(--c-s-500)}.spin-box.success>.disabled{background-color:var(--c-s-100);color:var(--c-s-300)}.spin-box.warning{background-color:var(--c-w-500);border-color:var(--c-w-500)}.spin-box.warning>input{background-color:var(--c-w-50);color:var(--c-w-700)}.spin-box.warning>input:focus{background-color:var(--c-w-50);color:var(--c-w-950)}.spin-box.warning>button{color:var(--c-w-500);background-color:var(--c-w-300);border-color:var(--c-w-500)}.spin-box.warning>button:hover{color:var(--c-w-300);background-color:var(--c-w-500)}.spin-box.warning>.disabled{background-color:var(--c-w-100);color:var(--c-w-300)}:root{--g-50: hsl(0, 0%, 95%);--g-100: hsl(0, 0%, 90%);--g-300: hsl(0, 0%, 70%);--g-500: hsl(0, 0%, 50%);--g-700: hsl(0, 0%, 30%);--g-900: hsl(0, 0%, 10%);--g-950: hsl(0, 0%, 5%);--d-50: hsl(354, 76%, 95%);--d-100: hsl(354, 76%, 90%);--d-300: hsl(354, 76%, 70%);--d-500: hsl(354, 76%, 50%);--d-700: hsl(354, 76%, 30%);--d-900: hsl(354, 76%, 10%);--d-950: hsl(354, 76%, 5%);--i-50: hsl(190, 90%, 95%);--i-100: hsl(190, 90%, 90%);--i-300: hsl(190, 90%, 70%);--i-500: hsl(190, 90%, 50%);--i-700: hsl(190, 90%, 30%);--i-900: hsl(190, 90%, 10%);--i-950: hsl(190, 90%, 5%);--p-50: hsl(216, 98%, 95%);--p-100: hsl(216, 98%, 90%);--p-300: hsl(216, 98%, 70%);--p-500: hsl(216, 98%, 50%);--p-700: hsl(216, 98%, 30%);--p-900: hsl(216, 98%, 10%);--p-950: hsl(216, 98%, 5%);--s-50: hsl(152, 81%, 95%);--s-100: hsl(152, 81%, 90%);--s-300: hsl(152, 81%, 70%);--s-500: hsl(152, 81%, 50%);--s-700: hsl(152, 81%, 30%);--s-900: hsl(152, 81%, 10%);--s-950: hsl(152, 81%, 5%);--w-50: hsl(45, 100%, 95%);--w-100: hsl(45, 100%, 90%);--w-300: hsl(45, 100%, 70%);--w-500: hsl(45, 100%, 50%);--w-700: hsl(45, 100%, 30%);--w-900: hsl(45, 100%, 10%);--w-950: hsl(45, 100%, 5%);--c-d-50: var(--d-50);--c-d-100: var(--d-100);--c-d-300: var(--d-300);--c-d-500: var(--d-500);--c-d-700: var(--d-700);--c-d-900: var(--d-900);--c-d-950: var(--d-950);--c-i-50: var(--i-50);--c-i-100: var(--i-100);--c-i-300: var(--i-300);--c-i-500: var(--i-500);--c-i-700: var(--i-700);--c-i-900: var(--i-900);--c-i-950: var(--i-950);--c-p-50: var(--p-50);--c-p-100: var(--p-100);--c-p-300: var(--p-300);--c-p-500: var(--p-500);--c-p-700: var(--p-700);--c-p-900: var(--p-900);--c-p-950: var(--p-950);--c-s-50: var(--s-50);--c-s-100: var(--s-100);--c-s-300: var(--s-300);--c-s-500: var(--s-500);--c-s-700: var(--s-700);--c-s-900: var(--s-900);--c-s-950: var(--s-950);--c-g-50: var(--g-50);--c-g-100: var(--g-100);--c-g-300: var(--g-300);--c-g-500: var(--g-500);--c-g-700: var(--g-700);--c-g-900: var(--g-900);--c-g-950: var(--g-950);--c-w-50: var(--w-50);--c-w-100: var(--w-100);--c-w-300: var(--w-300);--c-w-500: var(--w-500);--c-w-700: var(--w-700);--c-w-900: var(--w-900);--c-w-950: var(--w-950)}[data-theme=dark]{--c-d-50: var(--d-950);--c-d-100: var(--d-900);--c-d-300: var(--d-700);--c-d-500: var(--d-500);--c-d-700: var(--d-300);--c-d-900: var(--d-100);--c-d-950: var(--d-50);--c-i-50: var(--i-950);--c-i-100: var(--i-900);--c-i-300: var(--i-700);--c-i-500: var(--i-500);--c-i-700: var(--i-300);--c-i-900: var(--i-100);--c-i-950: var(--i-50);--c-p-50: var(--p-950);--c-p-100: var(--p-900);--c-p-300: var(--p-700);--c-p-500: var(--p-500);--c-p-700: var(--p-300);--c-p-900: var(--p-100);--c-p-950: var(--p-50);--c-s-50: var(--s-950);--c-s-100: var(--s-900);--c-s-300: var(--s-700);--c-s-500: var(--s-500);--c-s-700: var(--s-300);--c-s-900: var(--s-100);--c-s-950: var(--s-50);--c-g-50: var(--g-950);--c-g-100: var(--g-900);--c-g-300: var(--g-700);--c-g-500: var(--g-500);--c-g-700: var(--g-300);--c-g-900: var(--g-100);--c-g-950: var(--g-50);--c-w-50: var(--w-950);--c-w-100: var(--w-900);--c-w-300: var(--w-700);--c-w-500: var(--w-500);--c-w-700: var(--w-300);--c-w-900: var(--w-100);--c-w-950: var(--w-50)}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": "Andrii Popov",
|
|
3
|
+
"name": "@popovandrii/ui-elements",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"spinbox",
|
|
8
|
+
"input",
|
|
9
|
+
"ui",
|
|
10
|
+
"theme"
|
|
11
|
+
],
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://gitlab.com/AndreyPopov/ui-elements"
|
|
15
|
+
},
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"import": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"scripts": {
|
|
29
|
+
"dev": "vite --config playground/vite.config.js",
|
|
30
|
+
"build": "vite build && tsc",
|
|
31
|
+
"preview": "vite preview",
|
|
32
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
33
|
+
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,scss,md}\""
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"sass": "^1.89.2",
|
|
37
|
+
"typescript": "~5.8.3",
|
|
38
|
+
"vite": "^6.3.5",
|
|
39
|
+
"eslint": "^9.27.0",
|
|
40
|
+
"eslint-config-prettier": "^10.1.5",
|
|
41
|
+
"eslint-plugin-prettier": "^5.4.0",
|
|
42
|
+
"prettier": "^3.5.3",
|
|
43
|
+
"@typescript-eslint/eslint-plugin": "^8.8.0",
|
|
44
|
+
"@typescript-eslint/parser": "^8.8.0"
|
|
45
|
+
}
|
|
46
|
+
}
|