cloudmr-ux 4.8.6 → 4.8.7

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.
@@ -10,12 +10,71 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { useEffect, useState } from "react";
13
14
  import "./tk-dual-range.css";
14
15
  var clamp = function (v, lo, hi) { return Math.max(lo, Math.min(hi, v)); };
16
+ // Display REAL-space values; use scientific notation for small non-zero values
17
+ // so they don't display as "0.000". Use type="text" because type="number" can
18
+ // show "0" for very small values instead of scientific notation.
19
+ function fmt(v, precision) {
20
+ if (!Number.isFinite(v))
21
+ return "";
22
+ return v !== 0 && Math.abs(v) < 0.01
23
+ ? Number(v).toExponential(precision)
24
+ : v.toFixed(precision);
25
+ }
26
+ function parse(s) {
27
+ var n = Number(s);
28
+ return Number.isFinite(n) ? n : NaN;
29
+ }
30
+ /**
31
+ * A text input that holds a local string draft while the user is typing,
32
+ * committing only on blur or Enter. This lets the user type multi-digit and
33
+ * decimal values without mid-entry validation snapping the field.
34
+ * Shows a small red "Out of range" message when the committed value falls
35
+ * outside [lo, hi].
36
+ */
37
+ function DeferredInput(_a) {
38
+ var committed = _a.committed, onCommit = _a.onCommit, lo = _a.lo, hi = _a.hi, className = _a.className;
39
+ var _b = useState(committed), draft = _b[0], setDraft = _b[1];
40
+ var _c = useState(false), focused = _c[0], setFocused = _c[1];
41
+ var _d = useState(null), error = _d[0], setError = _d[1];
42
+ // Sync external changes into the field only when the user is not typing.
43
+ useEffect(function () {
44
+ if (!focused)
45
+ setDraft(committed);
46
+ }, [committed, focused]);
47
+ var commit = function (value) {
48
+ var n = Number(value);
49
+ if (!Number.isFinite(n)) {
50
+ setError("\"".concat(value, "\" is not a valid number"));
51
+ }
52
+ else if (n < lo || n > hi) {
53
+ setError("".concat(value.trim(), " is out of range"));
54
+ }
55
+ else {
56
+ setError(null);
57
+ }
58
+ onCommit(value);
59
+ // After commit the parent re-formats, so sync back to avoid a stale draft.
60
+ setDraft(committed);
61
+ };
62
+ return (_jsxs("div", __assign({ className: "tkdr__input-wrap" }, { children: [_jsx("input", { className: "".concat(className !== null && className !== void 0 ? className : "").concat(error ? " tkdr__num--error" : ""), type: "text", inputMode: "decimal", value: draft, onChange: function (e) { return setDraft(e.target.value); }, onFocus: function () {
63
+ setFocused(true);
64
+ setError(null);
65
+ }, onBlur: function (e) {
66
+ setFocused(false);
67
+ commit(e.target.value);
68
+ }, onKeyDown: function (e) {
69
+ if (e.key === "Enter") {
70
+ e.target.blur();
71
+ }
72
+ } }), error && _jsx("span", __assign({ className: "tkdr__error" }, { children: error }))] })));
73
+ }
15
74
  export default function TKDualRange(_a) {
16
75
  var _b;
17
76
  var _c = _a.name, name = _c === void 0 ? "Values" : _c, minDomain = _a.minDomain, maxDomain = _a.maxDomain, valueLow = _a.valueLow, valueHigh = _a.valueHigh, onChangeLow = _a.onChangeLow, onChangeHigh = _a.onChangeHigh, _d = _a.transform, transform = _d === void 0 ? function (x) { return x; } : _d, _e = _a.inverse, inverse = _e === void 0 ? function (y) { return y; } : _e, step = _a.step, _f = _a.precision, precision = _f === void 0 ? 3 : _f, _g = _a.accentColor, accentColor = _g === void 0 ? "#580f8b" : _g;
18
- // Map domain & current values into RENDER space (like TestKarts)
77
+ // Map domain & current values into RENDER space
19
78
  var tMin = transform(minDomain);
20
79
  var tMax = transform(maxDomain);
21
80
  var tLow = transform(valueLow);
@@ -23,7 +82,7 @@ export default function TKDualRange(_a) {
23
82
  var span = Math.max(1e-12, tMax - tMin);
24
83
  var pct = function (t) { return ((t - tMin) / span) * 100; };
25
84
  var s = step !== null && step !== void 0 ? step : Math.max(span * 0.001, Number.EPSILON);
26
- // Keep ends from crossing; clamp in REAL space against the other end
85
+ // Keep ends from crossing; clamp in REAL space against the other end.
27
86
  var handleLowRender = function (nextRender) {
28
87
  var nextReal = clamp(inverse(nextRender), minDomain, valueHigh);
29
88
  onChangeLow(nextReal);
@@ -32,37 +91,13 @@ export default function TKDualRange(_a) {
32
91
  var nextReal = clamp(inverse(nextRender), valueLow, maxDomain);
33
92
  onChangeHigh(nextReal);
34
93
  };
35
- // Display REAL-space values (matching the color bar); use scientific notation for
36
- // small non-zero values so they don't display as "0.000". Use type="text" because
37
- // type="number" can show "0" for very small values instead of scientific notation.
38
- var fmt = function (v) {
39
- return Number.isFinite(v)
40
- ? v !== 0 && Math.abs(v) < 0.01
41
- ? Number(v).toExponential(precision)
42
- : v.toFixed(precision)
43
- : "";
44
- };
45
- var parse = function (s) {
46
- var n = Number(s);
47
- return Number.isFinite(n) ? n : NaN;
48
- };
49
- return (_jsxs("div", __assign({ className: "tkdr" }, { children: [_jsxs("div", __assign({ className: "tkdr__row tkdr__row--ends" }, { children: [_jsxs("div", __assign({ className: "tkdr__group" }, { children: [_jsx("span", __assign({ className: "tkdr__hint" }, { children: "Min" })), _jsx("input", { className: "tkdr__num", type: "text", inputMode: "decimal", value: fmt(valueLow), onChange: function (e) {
50
- var n = parse(e.target.value);
51
- if (!Number.isFinite(n))
52
- return;
53
- onChangeLow(clamp(n, minDomain, valueHigh));
54
- }, onBlur: function (e) {
55
- var n = parse(e.target.value);
94
+ return (_jsxs("div", __assign({ className: "tkdr" }, { children: [_jsxs("div", __assign({ className: "tkdr__row tkdr__row--ends" }, { children: [_jsxs("div", __assign({ className: "tkdr__group" }, { children: [_jsx("span", __assign({ className: "tkdr__hint" }, { children: "Min" })), _jsx(DeferredInput, { className: "tkdr__num", committed: fmt(valueLow, precision), lo: minDomain, hi: valueHigh, onCommit: function (raw) {
95
+ var n = parse(raw);
56
96
  if (!Number.isFinite(n))
57
97
  return;
58
98
  onChangeLow(clamp(n, minDomain, valueHigh));
59
- } })] })), _jsxs("div", __assign({ className: "tkdr__group" }, { children: [_jsx("span", __assign({ className: "tkdr__hint" }, { children: "Max" })), _jsx("input", { className: "tkdr__num", type: "text", inputMode: "decimal", value: fmt(valueHigh), onChange: function (e) {
60
- var n = parse(e.target.value);
61
- if (!Number.isFinite(n))
62
- return;
63
- onChangeHigh(clamp(n, valueLow, maxDomain));
64
- }, onBlur: function (e) {
65
- var n = parse(e.target.value);
99
+ } })] })), _jsxs("div", __assign({ className: "tkdr__group" }, { children: [_jsx("span", __assign({ className: "tkdr__hint" }, { children: "Max" })), _jsx(DeferredInput, { className: "tkdr__num", committed: fmt(valueHigh, precision), lo: valueLow, hi: maxDomain, onCommit: function (raw) {
100
+ var n = parse(raw);
66
101
  if (!Number.isFinite(n))
67
102
  return;
68
103
  onChangeHigh(clamp(n, valueLow, maxDomain));
@@ -140,3 +140,25 @@
140
140
  font-weight: 400;
141
141
  font-family: 'Inter', 'Roboto', 'Helvetica', 'Arial', sans-serif;
142
142
  }
143
+
144
+ /* wrapper that stacks the input + error text */
145
+ .tkdr__input-wrap {
146
+ display: flex;
147
+ flex-direction: column;
148
+ align-items: flex-start;
149
+ gap: 2px;
150
+ }
151
+
152
+ /* red outline when the value is invalid */
153
+ .tkdr__num--error {
154
+ border-color: #d32f2f;
155
+ outline-color: #d32f2f;
156
+ }
157
+
158
+ /* small red validation message */
159
+ .tkdr__error {
160
+ font-size: 0.7rem;
161
+ color: #d32f2f;
162
+ line-height: 1;
163
+ white-space: nowrap;
164
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudmr-ux",
3
- "version": "4.8.6",
3
+ "version": "4.8.7",
4
4
  "author": "erosmontin@gmail.com",
5
5
  "license": "MIT",
6
6
  "repository": "erosmontin/cloudmr-ux",