@bagelink/vue 1.15.486 → 1.15.492

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "1.15.486",
4
+ "version": "1.15.492",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
@@ -77,6 +77,15 @@ const btnLayouts: NumberLayout[] = ['horizontal', 'vertical']
77
77
 
78
78
  const TRAILING_ZEROS_RE = /\.\d*0$/
79
79
 
80
+ /** Mid-keystroke drafts that are not yet a finished number (e.g. "1.", "1.50", "-"). */
81
+ function isIncompleteDraft(value: string) {
82
+ if (!value) return false
83
+ const numeric = value.replace(/[^\d.-]/g, '')
84
+ return ['-', '.', '-.'].includes(numeric)
85
+ || numeric.endsWith('.')
86
+ || TRAILING_ZEROS_RE.test(numeric)
87
+ }
88
+
80
89
  function getPrecision() {
81
90
  return step.toString().split('.')[1]?.length || 0
82
91
  }
@@ -98,12 +107,14 @@ const canDecrement = computed(() => min === undefined || subtract(numberValue.va
98
107
  function increment() {
99
108
  if (!canIncrement.value) { return }
100
109
  numberValue.value = add(numberValue.value ?? 0, step)
110
+ formattedValue.value = formatNumber(numberValue.value)
101
111
  emit('update:modelValue', numberValue.value)
102
112
  }
103
113
 
104
114
  function decrement() {
105
115
  if (!canDecrement.value) { return }
106
116
  numberValue.value = subtract(numberValue.value ?? 0, step)
117
+ formattedValue.value = formatNumber(numberValue.value)
107
118
  emit('update:modelValue', numberValue.value)
108
119
  }
109
120
 
@@ -128,10 +139,18 @@ function formatNumber(num: number) {
128
139
  const formattedValue = ref('')
129
140
  function inputHandler() {
130
141
  const numeric = formattedValue.value.replace(/[^\d.-]/g, '')
131
- const isIncomplete = ['', '-', '.', '-.'].includes(numeric) || numeric.endsWith('.') || TRAILING_ZEROS_RE.test(numeric)
142
+ const isIncomplete = numeric === ''
143
+ || ['-', '.', '-.'].includes(numeric)
144
+ || numeric.endsWith('.')
145
+ || TRAILING_ZEROS_RE.test(numeric)
132
146
 
133
147
  if (isIncomplete) {
134
- emit('update:modelValue', numeric === '-' ? '-' : numeric)
148
+ if (numeric === '') {
149
+ numberValue.value = undefined
150
+ emit('update:modelValue', undefined)
151
+ }
152
+ // Keep the local draft ("1.", "0.10", …). Do not emit strings —
153
+ // number-only v-models coerce/clear them and wipe the decimal point.
135
154
  return
136
155
  }
137
156
 
@@ -142,18 +161,43 @@ function inputHandler() {
142
161
 
143
162
  watch(() => numberValue.value, () => {
144
163
  nextTick(() => {
145
- if (formattedValue.value.endsWith('.') || TRAILING_ZEROS_RE.test(formattedValue.value)) { return }
164
+ if (isIncompleteDraft(formattedValue.value)) { return }
146
165
  formattedValue.value = numberValue.value !== undefined ? formatNumber(numberValue.value) : ''
147
166
  })
148
167
  })
149
168
 
150
169
  watch(() => modelValue, (newVal) => {
170
+ // Parent re-rendered while the user is mid-decimal — keep the draft unless
171
+ // the parent intentionally replaced/cleared the value.
172
+ if (isIncompleteDraft(formattedValue.value)) {
173
+ if (typeof newVal === 'string' && isIncompleteDraft(newVal)) {
174
+ formattedValue.value = newVal
175
+ return
176
+ }
177
+ if (typeof newVal === 'number') {
178
+ const draftParsed = Number.parseFloat(formattedValue.value)
179
+ // Coerced echo of the same draft (e.g. "1." → 1) — keep typing.
180
+ if (!Number.isNaN(draftParsed) && draftParsed === newVal) return
181
+ numberValue.value = newVal
182
+ formattedValue.value = formatNumber(newVal)
183
+ return
184
+ }
185
+ if (newVal === undefined || newVal === null || newVal === '') {
186
+ // Empty parent while we never committed a number = normal mid-draft.
187
+ if (numberValue.value === undefined) return
188
+ // Parent cleared a previously committed value (e.g. external reset).
189
+ numberValue.value = undefined
190
+ formattedValue.value = ''
191
+ return
192
+ }
193
+ return
194
+ }
151
195
  if (newVal === undefined || newVal === null || newVal === '') {
152
196
  numberValue.value = undefined
153
197
  formattedValue.value = ''
154
198
  return
155
199
  }
156
- if (typeof newVal === 'string' && (newVal === '-' || newVal.endsWith('.'))) {
200
+ if (typeof newVal === 'string' && isIncompleteDraft(newVal)) {
157
201
  formattedValue.value = newVal
158
202
  return
159
203
  }