@bagelink/vue 1.15.209 → 1.15.211

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.209",
4
+ "version": "1.15.211",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
@@ -128,9 +128,14 @@ const computedItemHeight = computed(() => `${itemHeight.value}px`)
128
128
 
129
129
  watch(
130
130
  () => loading.value,
131
- (newLoadingVal, oldLoadingVal) => {
131
+ async (newLoadingVal, oldLoadingVal) => {
132
132
  if (newLoadingVal === oldLoadingVal) { return }
133
- if (!newLoadingVal) { registerLastItemObserver() }
133
+ if (!newLoadingVal) {
134
+ registerLastItemObserver()
135
+ scrollTo(0)
136
+ await nextTick()
137
+ scrollTo(0)
138
+ }
134
139
  },
135
140
  { immediate: true }
136
141
  )
@@ -141,9 +146,14 @@ watch(
141
146
  )
142
147
 
143
148
  watch(
144
- () => computedData.value,
145
- (newData, oldData) => {
146
- if (newData.length === oldData.length || props.onLastItemVisible !== undefined) { return }
149
+ () => computedData.value.length,
150
+ async (newLen, oldLen) => {
151
+ // Infinite-scroll appends: keep position. First load (0 → n) still resets.
152
+ const isAppend = props.onLastItemVisible !== undefined && (oldLen ?? 0) > 0
153
+ if (newLen === oldLen || isAppend) return
154
+
155
+ scrollTo(0)
156
+ await nextTick()
147
157
  scrollTo(0)
148
158
  }
149
159
  )
@@ -171,7 +181,7 @@ const headerFontSize = computed(() => {
171
181
  <template>
172
182
  <div class="table-list-wrap h-100p" v-bind="containerProps" :class="{ overflowHiddenLoading: showLoading }">
173
183
  <Loading v-if="showLoading" class="h100p" />
174
- <div v-bind="wrapperProps" :class="{ 'pointer-events-none': showLoading }">
184
+ <div v-if="!isEmpty" v-bind="wrapperProps" :class="{ 'pointer-events-none': showLoading }">
175
185
  <table class="infinite-wrapper" :class="{ selecting: computedSelectedItems.length }">
176
186
  <thead class="row first-row">
177
187
  <th v-if="isSortable" class="col-drag" />
@@ -218,16 +228,16 @@ const headerFontSize = computed(() => {
218
228
  <tr v-if="props.onLastItemVisible !== undefined" ref="lastItemEl" style="height: 1px;" />
219
229
  </tbody>
220
230
  </table>
221
- <!-- Built-in empty state (overridable via the #empty slot) -->
222
- <slot v-if="isEmpty" name="empty">
223
- <EmptyState
224
- :icon="props.emptyIcon ?? 'inbox'"
225
- :title="props.emptyTitle ?? 'No results'"
226
- :description="props.emptyDescription"
227
- compact
228
- />
229
- </slot>
230
231
  </div>
232
+ <!-- Outside the virtualized wrapper so EmptyState doesn't inflate scroll height -->
233
+ <slot v-if="isEmpty" name="empty">
234
+ <EmptyState
235
+ :icon="props.emptyIcon ?? 'inbox'"
236
+ :title="props.emptyTitle ?? 'No results'"
237
+ :description="props.emptyDescription"
238
+ compact
239
+ />
240
+ </slot>
231
241
  </div>
232
242
  </template>
233
243
 
@@ -254,6 +264,9 @@ cursor: grab;
254
264
 
255
265
  .table-list-wrap {
256
266
  min-height: 150px;
267
+ /* Prevent browser scroll anchoring from pushing content to the bottom
268
+ when rows mount and the virtual list height jumps. */
269
+ overflow-anchor: none;
257
270
  }
258
271
 
259
272
  .selected {
@@ -26,6 +26,16 @@ const SLOT_VALUE_COMPONENTS = new Set(['div', 'span', 'p'])
26
26
 
27
27
  const SRC_VALUE_COMPONENTS = new Set(['img', 'iframe'])
28
28
 
29
+ /** Display components that take content via `value` (not `modelValue`). */
30
+ const VALUE_PROP_NAMES = new Set(['BglBadge', 'Badge', 'BglPill', 'Pill'])
31
+
32
+ function usesValueProp(Component: unknown): boolean {
33
+ if (!Component || typeof Component === 'string') return false
34
+ const name = (Component as { name?: string, __name?: string }).name
35
+ ?? (Component as { __name?: string }).__name
36
+ return !!name && VALUE_PROP_NAMES.has(name)
37
+ }
38
+
29
39
  export interface UseSchemaFieldOptions<T, SFP extends Path<T>> {
30
40
  mode?: 'form' | 'preview' | 'table'
31
41
  getFormData?: () => T
@@ -217,6 +227,9 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
217
227
  // Slot components don't need a value prop
218
228
  } else if (isSrcValueComponent) {
219
229
  props.src = transformedValue
230
+ } else if (usesValueProp(Component)) {
231
+ // Badge etc. read `value`, not modelValue — empty outline pills otherwise
232
+ props.value = transformedValue != null ? String(transformedValue) : transformedValue
220
233
  } else {
221
234
  props.modelValue = transformedValue
222
235
  }