@r2digisolutions/components 0.8.10 → 0.8.12

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.
@@ -34,10 +34,6 @@
34
34
 
35
35
  let text = $state(String(value));
36
36
 
37
- $effect(() => {
38
- text = String(value);
39
- });
40
-
41
37
  const canDec = $derived(!disabled && (min === undefined || value > min));
42
38
  const canInc = $derived(!disabled && (max === undefined || value < max));
43
39
 
@@ -52,15 +48,38 @@
52
48
  return next;
53
49
  }
54
50
 
51
+ /** Avoid float noise like `30.31000000000005` when stepping by 0.01. */
52
+ function decimalsForStep(s: number): number {
53
+ const str = String(s);
54
+ const dot = str.indexOf('.');
55
+ return dot === -1 ? 0 : str.length - dot - 1;
56
+ }
57
+
58
+ function roundToStep(n: number): number {
59
+ const decimals = decimalsForStep(step);
60
+ if (decimals <= 0) return Math.round(n);
61
+ const factor = 10 ** decimals;
62
+ return Math.round((n + Number.EPSILON) * factor) / factor;
63
+ }
64
+
65
+ function formatValue(n: number): string {
66
+ const decimals = decimalsForStep(step);
67
+ return decimals > 0 ? n.toFixed(decimals) : String(n);
68
+ }
69
+
70
+ $effect(() => {
71
+ text = formatValue(value);
72
+ });
73
+
55
74
  function commit(raw: string) {
56
75
  const parsed = Number(raw);
57
76
  if (Number.isNaN(parsed)) {
58
- text = String(value);
77
+ text = formatValue(value);
59
78
  return;
60
79
  }
61
- const next = clamp(parsed);
80
+ const next = clamp(roundToStep(parsed));
62
81
  value = next;
63
- text = String(next);
82
+ text = formatValue(next);
64
83
  onchange?.(next);
65
84
  }
66
85
 
@@ -68,9 +87,9 @@
68
87
  if (disabled) return;
69
88
  if (dir < 0 && !canDec) return;
70
89
  if (dir > 0 && !canInc) return;
71
- const next = clamp(value + dir * step);
90
+ const next = clamp(roundToStep(value + dir * step));
72
91
  value = next;
73
- text = String(next);
92
+ text = formatValue(next);
74
93
  onchange?.(next);
75
94
  }
76
95
  </script>
@@ -105,13 +105,15 @@
105
105
  'group relative flex w-full min-w-0 items-center gap-2.5 text-left transition-colors',
106
106
  padY[size],
107
107
  padX,
108
+ // selected must replace surface-elevated — same utility family, otherwise dark tint never wins
108
109
  variant === 'card' &&
109
- 'overflow-hidden rounded-xl border border-border bg-surface-elevated',
110
+ (selected
111
+ ? 'overflow-hidden rounded-xl border border-brand-400/50 bg-brand-50 ring-1 ring-brand-500/20 dark:border-brand-400/45 dark:bg-brand-500/15 dark:ring-brand-400/25'
112
+ : 'overflow-hidden rounded-xl border border-border bg-surface-elevated'),
110
113
  variant === 'plain' && 'rounded-lg',
111
114
  selected &&
112
- (variant === 'card'
113
- ? 'border-brand-500/40 bg-brand-50/50 ring-1 ring-brand-500/15 dark:bg-brand-950/25'
114
- : 'bg-brand-50 dark:bg-brand-950/40'),
115
+ variant !== 'card' &&
116
+ 'bg-brand-50 dark:bg-brand-500/15',
115
117
  clickable &&
116
118
  !disabled &&
117
119
  'cursor-pointer hover:bg-surface-overlay/70 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500/30',
@@ -122,6 +124,7 @@
122
124
  variant === 'card' &&
123
125
  clickable &&
124
126
  !disabled &&
127
+ !selected &&
125
128
  'hover:border-border-strong',
126
129
  disabled && 'cursor-not-allowed opacity-50',
127
130
  className
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@r2digisolutions/components",
3
- "version": "0.8.10",
3
+ "version": "0.8.12",
4
4
  "private": false,
5
5
  "description": "R2DigiSolutions Svelte 5 component library — Atomic Design, Tailwind 4, Light/Dark mode",
6
6
  "license": "MIT",