@innertia-solutions/nuxt-theme-spark 0.1.77 → 0.1.79

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.
@@ -48,6 +48,9 @@ const previewRow = ref(null)
48
48
  const currentRatio = ref(props.splitRatio)
49
49
  const containerRef = ref(null)
50
50
  const previewEnabled = ref(false)
51
+ const paginationHeight = ref(0)
52
+
53
+ const previewCacheKey = computed(() => `table-preview-${props.name}`)
51
54
 
52
55
  const closePreview = () => { previewRow.value = null }
53
56
 
@@ -59,6 +62,35 @@ const handleRowClick = (row) => {
59
62
  }
60
63
  }
61
64
 
65
+ // Persist preview row in session cache when table cache is enabled
66
+ watch(previewRow, (row) => {
67
+ if (!props.cached) return
68
+ if (row) sessionStorage.setItem(previewCacheKey.value, JSON.stringify(row))
69
+ else sessionStorage.removeItem(previewCacheKey.value)
70
+ })
71
+
72
+ // When data reloads, update previewRow with fresh data from response
73
+ const handleLoaded = (res) => {
74
+ emit('loaded', res)
75
+ if (previewRow.value && Array.isArray(res?.data)) {
76
+ const fresh = res.data.find(r => r.id === previewRow.value.id)
77
+ if (fresh) previewRow.value = fresh
78
+ }
79
+ }
80
+
81
+ // Track pagination bar height so the overlay never covers it
82
+ let paginationObserver = null
83
+ watch(() => tableRef.value?.paginationBarRef, (el) => {
84
+ paginationObserver?.disconnect()
85
+ paginationObserver = null
86
+ if (!el) return
87
+ paginationHeight.value = el.offsetHeight
88
+ paginationObserver = new ResizeObserver(() => {
89
+ paginationHeight.value = el.offsetHeight
90
+ })
91
+ paginationObserver.observe(el)
92
+ }, { flush: 'post' })
93
+
62
94
  const startResize = (e) => {
63
95
  e.preventDefault()
64
96
  const onMove = (ev) => {
@@ -79,8 +111,18 @@ const onEsc = (e) => { if (e.key === 'Escape' && previewRow.value) closePreview(
79
111
  onMounted(() => {
80
112
  previewEnabled.value = !!slots.preview
81
113
  window.addEventListener('keydown', onEsc)
114
+ // Restore preview from session cache
115
+ if (props.cached && previewEnabled.value) {
116
+ try {
117
+ const raw = sessionStorage.getItem(previewCacheKey.value)
118
+ if (raw) previewRow.value = JSON.parse(raw)
119
+ } catch {}
120
+ }
121
+ })
122
+ onBeforeUnmount(() => {
123
+ window.removeEventListener('keydown', onEsc)
124
+ paginationObserver?.disconnect()
82
125
  })
83
- onBeforeUnmount(() => window.removeEventListener('keydown', onEsc))
84
126
 
85
127
  // ─── Column panel ─────────────────────────────────────────────────────────────
86
128
  const showColumnPanel = ref(false)
@@ -208,37 +250,34 @@ defineExpose({ getSelectedRows, reload, clearCache, exportTable, tableRef })
208
250
  <TableExportable v-if="showExport" :table-ref="tableRef" :name="name" :columns="columns" />
209
251
  </div>
210
252
 
211
- <!-- Contenido: tabla + preview en flex -->
212
- <div :class="previewEnabled ? 'flex items-stretch overflow-hidden' : ''">
253
+ <!-- Contenido: tabla siempre full width + preview overlay -->
254
+ <div class="relative">
213
255
 
214
256
  <!-- Tabla -->
215
- <div
216
- class="min-w-0 transition-[width] duration-200 ease-out"
217
- :style="previewEnabled ? { width: (previewRow ? currentRatio : 100) + '%', flexShrink: 0 } : {}"
257
+ <Table
258
+ ref="tableRef"
259
+ :endpoint="endpoint"
260
+ :columns="columns"
261
+ :name="name"
262
+ :params="mergedParams"
263
+ :search="search"
264
+ :checkable="checkable"
265
+ :cached="cached"
266
+ :show-reload-button="showReloadButton"
267
+ :click-row-to-open="clickRowToOpen"
268
+ :preview-row-id="previewRow?.id ?? null"
269
+ :preview-mode="!!previewEnabled"
270
+ @row-click="handleRowClick"
271
+ @loaded="handleLoaded"
272
+ @page-change="closePreview"
273
+ @per-page-change="closePreview"
218
274
  >
219
- <Table
220
- ref="tableRef"
221
- :endpoint="endpoint"
222
- :columns="columns"
223
- :name="name"
224
- :params="mergedParams"
225
- :search="search"
226
- :checkable="checkable"
227
- :cached="cached"
228
- :show-reload-button="showReloadButton"
229
- :click-row-to-open="clickRowToOpen"
230
- :preview-row-id="previewRow?.id ?? null"
231
- :preview-mode="!!previewEnabled"
232
- @row-click="handleRowClick"
233
- @loaded="emit('loaded', $event)"
234
- >
235
- <template v-for="(_, name) in $slots" #[name]="slotProps">
236
- <slot :name="name" v-bind="slotProps ?? {}" />
237
- </template>
238
- </Table>
239
- </div>
275
+ <template v-for="(_, name) in $slots" #[name]="slotProps">
276
+ <slot :name="name" v-bind="slotProps ?? {}" />
277
+ </template>
278
+ </Table>
240
279
 
241
- <!-- Divider + preview con animación slide -->
280
+ <!-- Preview panel overlay slides in from right, tapa la tabla -->
242
281
  <Transition
243
282
  enter-active-class="transition ease-out duration-200"
244
283
  enter-from-class="opacity-0 translate-x-6"
@@ -249,8 +288,8 @@ defineExpose({ getSelectedRows, reload, clearCache, exportTable, tableRef })
249
288
  >
250
289
  <div
251
290
  v-if="previewRow && previewEnabled"
252
- class="flex items-stretch shrink-0 min-w-0"
253
- :style="{ width: (100 - currentRatio) + '%' }"
291
+ class="absolute top-0 right-0 z-10 flex bg-white dark:bg-slate-800 border-l border-slate-200 dark:border-slate-700 shadow-xl"
292
+ :style="{ width: (100 - currentRatio) + '%', bottom: paginationHeight + 'px' }"
254
293
  >
255
294
  <!-- Resize handle -->
256
295
  <div
@@ -258,7 +297,7 @@ defineExpose({ getSelectedRows, reload, clearCache, exportTable, tableRef })
258
297
  @mousedown="startResize"
259
298
  />
260
299
  <!-- Preview -->
261
- <div class="flex flex-col overflow-y-auto border-l border-slate-200 dark:border-slate-700 flex-1">
300
+ <div class="flex flex-col overflow-y-auto flex-1">
262
301
  <slot name="preview" :row="previewRow" :close="closePreview" />
263
302
  </div>
264
303
  </div>
@@ -24,7 +24,7 @@ const props = defineProps({
24
24
  previewMode: { type: Boolean, default: false },
25
25
  })
26
26
 
27
- const emit = defineEmits(['update:search', 'row-click', 'loaded'])
27
+ const emit = defineEmits(['update:search', 'row-click', 'loaded', 'page-change', 'per-page-change'])
28
28
  const instance = getCurrentInstance()
29
29
 
30
30
  // ─── API / toast ─────────────────────────────────────────────────────────────
@@ -39,6 +39,7 @@ const isDataFromCache = ref(false)
39
39
  const lastDataLength = ref(-1)
40
40
  const lastRowHeight = ref(48)
41
41
  const tableBodyRef = ref(null)
42
+ const paginationBarRef = ref(null)
42
43
  const skeletonRows = computed(() => {
43
44
  const count = lastDataLength.value < 0 ? pagination.value.pageSize : lastDataLength.value
44
45
  return Array.from({ length: count })
@@ -261,6 +262,13 @@ watch(tableData, (newData) => {
261
262
  }, { flush: 'post' })
262
263
 
263
264
  watch(pagination, () => { if (!isRestoring.value) scheduleFetch(0) }, { deep: true })
265
+
266
+ watch(() => pagination.value.pageIndex, (val, old) => {
267
+ if (!isRestoring.value && val !== old) emit('page-change', val)
268
+ })
269
+ watch(() => pagination.value.pageSize, (val, old) => {
270
+ if (!isRestoring.value && val !== old) emit('per-page-change', val)
271
+ })
264
272
  watch(sorting, () => { if (!isRestoring.value) scheduleFetch(0) }, { deep: true })
265
273
  watch(columnFilters, () => { if (!isRestoring.value) scheduleFetch(300) }, { deep: true })
266
274
 
@@ -463,6 +471,7 @@ defineExpose({
463
471
  setColumnOrder,
464
472
  isDataFromCache,
465
473
  cached: computed(() => props.cached),
474
+ paginationBarRef,
466
475
  })
467
476
  </script>
468
477
 
@@ -757,7 +766,7 @@ defineExpose({
757
766
  </div>
758
767
 
759
768
  <!-- Pagination & controls bar -->
760
- <div class="flex flex-col sm:flex-row items-center justify-between gap-y-4 sm:gap-y-0 px-4 py-3 border-t border-slate-200 dark:border-slate-700">
769
+ <div ref="paginationBarRef" class="flex flex-col sm:flex-row items-center justify-between gap-y-4 sm:gap-y-0 px-4 py-3 border-t border-slate-200 dark:border-slate-700">
761
770
  <!-- Left: reload, total, cache, columns button -->
762
771
  <div class="flex items-center gap-x-4 flex-wrap gap-y-2">
763
772
  <!-- Reload button -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@innertia-solutions/nuxt-theme-spark",
3
- "version": "0.1.77",
3
+ "version": "0.1.79",
4
4
  "description": "Innertia Solutions — Spark theme: backoffice, landing and mobile components and layouts",
5
5
  "keywords": [
6
6
  "nuxt",