@innertia-solutions/nuxt-theme-spark 0.1.73 → 0.1.74

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.
@@ -137,138 +137,111 @@ defineExpose({ getSelectedRows, reload, clearCache, exportTable, tableRef })
137
137
 
138
138
  <template>
139
139
  <div class="relative" ref="containerRef">
140
- <div :class="previewRow && previewEnabled ? 'flex items-stretch gap-3' : ''">
141
140
 
142
- <!-- Card -->
143
- <div
144
- class="relative bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-2xl shadow-sm overflow-hidden"
145
- :style="previewRow && previewEnabled ? { width: currentRatio + '%', minWidth: 0, flexShrink: 0 } : {}"
146
- >
147
- <!-- Toolbar -->
148
- <div class="flex flex-wrap items-center gap-3 px-4 py-3 border-b border-slate-200 dark:border-slate-700">
149
- <!-- Search -->
150
- <div v-if="showSearch" class="flex-1 min-w-48">
151
- <Forms.Input
152
- v-model="search"
153
- type="search"
154
- :placeholder="searchPlaceholder"
155
- :icon-left="IconSearch"
156
- />
157
- </div>
141
+ <!-- Card único -->
142
+ <div class="bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-2xl shadow-sm overflow-hidden">
158
143
 
159
- <!-- Filter toggle -->
160
- <button
161
- v-if="showFilters && hasFilterableColumns"
162
- type="button"
163
- @click="showFilterPanel = !showFilterPanel"
164
- :class="[
165
- 'py-1.5 px-3 inline-flex items-center gap-2 text-sm font-medium rounded-lg border transition-colors',
166
- showFilterPanel || activeFilterCount > 0
167
- ? 'border-blue-500 bg-blue-50 text-blue-700 dark:bg-blue-900/20 dark:border-blue-500 dark:text-blue-300'
168
- : 'border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-700'
169
- ]"
170
- >
171
- <IconAdjustmentsHorizontal class="size-4" stroke="1.5" />
172
- Filtros
173
- <span
174
- v-if="activeFilterCount > 0"
175
- class="inline-flex items-center justify-center size-5 rounded-full bg-blue-600 text-white text-xs font-bold"
176
- >{{ activeFilterCount }}</span>
177
- </button>
178
-
179
- <slot name="actions" />
180
-
181
- <!-- Column visibility toggle -->
182
- <button
183
- type="button"
184
- @click="showColumnPanel = !showColumnPanel"
185
- :class="[
186
- 'py-1.5 px-3 inline-flex items-center gap-2 text-sm font-medium rounded-lg border transition-colors',
187
- showColumnPanel
188
- ? 'border-blue-500 bg-blue-50 text-blue-700 dark:bg-blue-900/20 dark:border-blue-500 dark:text-blue-300'
189
- : 'border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-700'
190
- ]"
191
- >
192
- <IconLayoutColumns class="size-4" />
193
- Columnas
194
- </button>
195
-
196
- <!-- Export -->
197
- <TableExportable
198
- v-if="showExport"
199
- :table-ref="tableRef"
200
- :name="name"
201
- :columns="columns"
202
- />
144
+ <!-- Toolbar -->
145
+ <div class="flex flex-wrap items-center gap-3 px-4 py-3 border-b border-slate-200 dark:border-slate-700">
146
+ <div v-if="showSearch" class="flex-1 min-w-48">
147
+ <Forms.Input v-model="search" type="search" :placeholder="searchPlaceholder" :icon-left="IconSearch" />
203
148
  </div>
204
149
 
205
- <!-- Filter panel -->
206
- <Transition
207
- enter-active-class="transition ease-out duration-150"
208
- enter-from-class="opacity-0 -translate-y-2"
209
- enter-to-class="opacity-100 translate-y-0"
210
- leave-active-class="transition ease-in duration-100"
211
- leave-from-class="opacity-100 translate-y-0"
212
- leave-to-class="opacity-0 -translate-y-2"
150
+ <button
151
+ v-if="showFilters && hasFilterableColumns"
152
+ type="button"
153
+ @click="showFilterPanel = !showFilterPanel"
154
+ :class="[
155
+ 'py-1.5 px-3 inline-flex items-center gap-2 text-sm font-medium rounded-lg border transition-colors',
156
+ showFilterPanel || activeFilterCount > 0
157
+ ? 'border-blue-500 bg-blue-50 text-blue-700 dark:bg-blue-900/20 dark:border-blue-500 dark:text-blue-300'
158
+ : 'border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-700'
159
+ ]"
213
160
  >
214
- <div
215
- v-if="showFilterPanel && hasFilterableColumns"
216
- class="px-4 py-3 border-b border-slate-200 dark:border-slate-700 bg-slate-50 dark:bg-slate-900/50"
217
- >
218
- <TableFilter v-model="activeFilters" :columns="filtersConfig" />
219
- </div>
220
- </Transition>
221
-
222
- <!-- Table -->
223
- <Table
224
- ref="tableRef"
225
- :endpoint="endpoint"
226
- :columns="columns"
227
- :name="name"
228
- :params="mergedParams"
229
- :search="search"
230
- :checkable="checkable"
231
- :cached="cached"
232
- :show-reload-button="showReloadButton"
233
- :click-row-to-open="clickRowToOpen"
234
- :preview-row-id="previewRow?.id ?? null"
235
- :preview-mode="!!previewEnabled"
236
- @row-click="handleRowClick"
237
- @loaded="emit('loaded', $event)"
161
+ <IconAdjustmentsHorizontal class="size-4" stroke="1.5" />
162
+ Filtros
163
+ <span v-if="activeFilterCount > 0" class="inline-flex items-center justify-center size-5 rounded-full bg-blue-600 text-white text-xs font-bold">{{ activeFilterCount }}</span>
164
+ </button>
165
+
166
+ <slot name="actions" />
167
+
168
+ <button
169
+ type="button"
170
+ @click="showColumnPanel = !showColumnPanel"
171
+ :class="[
172
+ 'py-1.5 px-3 inline-flex items-center gap-2 text-sm font-medium rounded-lg border transition-colors',
173
+ showColumnPanel
174
+ ? 'border-blue-500 bg-blue-50 text-blue-700 dark:bg-blue-900/20 dark:border-blue-500 dark:text-blue-300'
175
+ : 'border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-700'
176
+ ]"
238
177
  >
239
- <template v-for="(_, name) in $slots" #[name]="slotProps">
240
- <slot :name="name" v-bind="slotProps ?? {}" />
241
- </template>
242
- </Table>
243
- </div>
178
+ <IconLayoutColumns class="size-4" />
179
+ Columnas
180
+ </button>
244
181
 
245
- <!-- Resize handle -->
246
- <div
247
- v-if="previewRow && previewEnabled"
248
- class="w-3 flex items-center justify-center cursor-col-resize shrink-0 group"
249
- @mousedown="startResize"
250
- >
251
- <div class="w-px h-12 bg-slate-200 dark:bg-slate-600 rounded-full group-hover:bg-indigo-400 dark:group-hover:bg-indigo-500 transition-colors" />
182
+ <TableExportable v-if="showExport" :table-ref="tableRef" :name="name" :columns="columns" />
252
183
  </div>
253
184
 
254
- <!-- Preview panel -->
185
+ <!-- Filter panel -->
255
186
  <Transition
256
- enter-active-class="transition ease-out duration-300"
257
- enter-from-class="opacity-0 translate-x-4"
258
- enter-to-class="opacity-100 translate-x-0"
259
- leave-active-class="transition ease-in duration-200"
260
- leave-from-class="opacity-100 translate-x-0"
261
- leave-to-class="opacity-0 translate-x-4"
187
+ enter-active-class="transition ease-out duration-150"
188
+ enter-from-class="opacity-0 -translate-y-2"
189
+ enter-to-class="opacity-100 translate-y-0"
190
+ leave-active-class="transition ease-in duration-100"
191
+ leave-from-class="opacity-100 translate-y-0"
192
+ leave-to-class="opacity-0 -translate-y-2"
262
193
  >
194
+ <div v-if="showFilterPanel && hasFilterableColumns" class="px-4 py-3 border-b border-slate-200 dark:border-slate-700 bg-slate-50 dark:bg-slate-900/50">
195
+ <TableFilter v-model="activeFilters" :columns="filtersConfig" />
196
+ </div>
197
+ </Transition>
198
+
199
+ <!-- Contenido: tabla + preview en flex -->
200
+ <div :class="previewRow && previewEnabled ? 'flex items-stretch' : ''">
201
+
202
+ <!-- Tabla -->
263
203
  <div
264
- v-if="previewRow && previewEnabled"
265
- class="bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-2xl shadow-sm overflow-hidden flex flex-col"
266
- :style="{ width: (100 - currentRatio) + '%', minWidth: 0, flexShrink: 0 }"
204
+ :style="previewRow && previewEnabled ? { width: currentRatio + '%', flexShrink: 0, minWidth: 0 } : {}"
267
205
  >
268
- <slot name="preview" :row="previewRow" :close="closePreview" />
206
+ <Table
207
+ ref="tableRef"
208
+ :endpoint="endpoint"
209
+ :columns="columns"
210
+ :name="name"
211
+ :params="mergedParams"
212
+ :search="search"
213
+ :checkable="checkable"
214
+ :cached="cached"
215
+ :show-reload-button="showReloadButton"
216
+ :click-row-to-open="clickRowToOpen"
217
+ :preview-row-id="previewRow?.id ?? null"
218
+ :preview-mode="!!previewEnabled"
219
+ @row-click="handleRowClick"
220
+ @loaded="emit('loaded', $event)"
221
+ >
222
+ <template v-for="(_, name) in $slots" #[name]="slotProps">
223
+ <slot :name="name" v-bind="slotProps ?? {}" />
224
+ </template>
225
+ </Table>
269
226
  </div>
270
- </Transition>
271
227
 
228
+ <!-- Divider + preview -->
229
+ <template v-if="previewRow && previewEnabled">
230
+ <!-- Resize handle -->
231
+ <div
232
+ class="w-1 shrink-0 cursor-col-resize bg-slate-100 dark:bg-slate-700/60 hover:bg-indigo-300 dark:hover:bg-indigo-600 transition-colors"
233
+ @mousedown="startResize"
234
+ />
235
+ <!-- Preview -->
236
+ <div
237
+ class="flex flex-col overflow-y-auto border-l border-slate-200 dark:border-slate-700"
238
+ :style="{ width: (100 - currentRatio) + '%', flexShrink: 0, minWidth: 0 }"
239
+ >
240
+ <slot name="preview" :row="previewRow" :close="closePreview" />
241
+ </div>
242
+ </template>
243
+
244
+ </div>
272
245
  </div>
273
246
 
274
247
  <!-- Column panel — outside overflow-hidden so never clipped -->
@@ -318,13 +318,11 @@ const measureText = (text, font) => {
318
318
 
319
319
  const autoSizeColumn = (header) => {
320
320
  const colId = header.column.id
321
- const pad = 32 // px-4 on each side
321
+ const pad = 32
322
322
 
323
- // Measure header label
324
323
  const label = header.column.columnDef.meta?.label ?? header.id
325
- let max = measureText(label, '500 12px ui-sans-serif,system-ui,sans-serif') + pad + 20 // +20 for sort icon
324
+ let max = measureText(label, '500 12px ui-sans-serif,system-ui,sans-serif') + pad + 20
326
325
 
327
- // Measure all visible data cells
328
326
  if (tableBodyRef.value) {
329
327
  tableBodyRef.value.querySelectorAll(`td[data-col-id="${colId}"]`).forEach(td => {
330
328
  const w = measureText(td.textContent?.trim(), '14px ui-sans-serif,system-ui,sans-serif') + pad
@@ -332,7 +330,7 @@ const autoSizeColumn = (header) => {
332
330
  })
333
331
  }
334
332
 
335
- header.column.setSize(Math.ceil(max))
333
+ table.setColumnSizing(prev => ({ ...prev, [colId]: Math.ceil(max) }))
336
334
  }
337
335
 
338
336
  const onHeaderDragStart = (colId) => { draggedHeaderId = colId }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@innertia-solutions/nuxt-theme-spark",
3
- "version": "0.1.73",
3
+ "version": "0.1.74",
4
4
  "description": "Innertia Solutions — Spark theme: backoffice, landing and mobile components and layouts",
5
5
  "keywords": [
6
6
  "nuxt",