@smallwebco/tinypivot-vue 1.0.20 → 1.0.21
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tinypivot-vue.umd.cjs","sources":["../../core/dist/utils/index.js","../../core/dist/pivot/index.js","../../core/dist/license/index.js","../../core/dist/export/index.js","../src/composables/useExcelGrid.ts","../src/composables/useLicense.ts","../src/composables/usePivotTable.ts","../src/composables/useGridFeatures.ts","../src/components/ColumnFilter.vue","../src/components/PivotConfig.vue","../src/components/PivotSkeleton.vue","../src/components/DataGrid.vue"],"sourcesContent":["/**\n * Detect column data type from values\n */\nexport function detectColumnType(values) {\n const nonNullValues = values.filter(v => v !== null && v !== undefined && v !== '');\n if (nonNullValues.length === 0)\n return 'string';\n const sample = nonNullValues.slice(0, 100);\n let numberCount = 0;\n let dateCount = 0;\n let booleanCount = 0;\n for (const val of sample) {\n if (typeof val === 'boolean') {\n booleanCount++;\n }\n else if (typeof val === 'number' || (!Number.isNaN(Number(val)) && val !== '')) {\n numberCount++;\n }\n else if (val instanceof Date || !Number.isNaN(Date.parse(String(val)))) {\n dateCount++;\n }\n }\n const threshold = sample.length * 0.8;\n if (booleanCount >= threshold)\n return 'boolean';\n if (numberCount >= threshold)\n return 'number';\n if (dateCount >= threshold)\n return 'date';\n return 'string';\n}\n/**\n * Detect field type from sample data (for pivot)\n */\nexport function detectFieldType(data, field) {\n const values = data.map(row => row[field]).filter(v => v !== null && v !== undefined && v !== '');\n const sample = values.slice(0, 100);\n let numberCount = 0;\n const uniqueSet = new Set();\n for (const val of sample) {\n uniqueSet.add(String(val));\n if (typeof val === 'number' || (!Number.isNaN(Number(val)) && val !== '')) {\n numberCount++;\n }\n }\n const isNumeric = numberCount >= sample.length * 0.8;\n return {\n field,\n type: isNumeric ? 'number' : 'string',\n uniqueCount: uniqueSet.size,\n isNumeric,\n };\n}\n/**\n * Get unique values for a column (for Excel-style filter dropdown)\n */\nexport function getColumnUniqueValues(data, columnKey, maxValues = 500) {\n const values = [];\n let nullCount = 0;\n for (const row of data) {\n const value = row[columnKey];\n if (value === null || value === undefined || value === '') {\n nullCount++;\n }\n else {\n values.push(value);\n }\n }\n // Get unique values\n const uniqueSet = new Set();\n for (const val of values) {\n uniqueSet.add(String(val));\n if (uniqueSet.size >= maxValues)\n break;\n }\n const uniqueValues = Array.from(uniqueSet).sort((a, b) => {\n // Natural sort for numbers\n const numA = Number.parseFloat(a);\n const numB = Number.parseFloat(b);\n if (!Number.isNaN(numA) && !Number.isNaN(numB)) {\n return numA - numB;\n }\n return a.localeCompare(b);\n });\n return {\n uniqueValues,\n totalCount: data.length,\n nullCount,\n type: detectColumnType(values),\n };\n}\n/**\n * Format cell value for display\n */\nexport function formatCellValue(value, type) {\n if (value === null || value === undefined)\n return '';\n if (value === '')\n return '';\n switch (type) {\n case 'number': {\n const num = typeof value === 'number' ? value : Number.parseFloat(String(value));\n if (Number.isNaN(num))\n return String(value);\n // Format with commas for large numbers\n if (Math.abs(num) >= 1000) {\n return num.toLocaleString('en-US', { maximumFractionDigits: 2 });\n }\n return num.toLocaleString('en-US', { maximumFractionDigits: 4 });\n }\n case 'date': {\n const date = value instanceof Date ? value : new Date(String(value));\n if (Number.isNaN(date.getTime()))\n return String(value);\n return date.toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n }\n case 'boolean':\n return value ? 'Yes' : 'No';\n default:\n return String(value);\n }\n}\n/**\n * Format number for display with appropriate precision\n */\nexport function formatNumber(value, options) {\n if (value === null)\n return '-';\n const maxDigits = options?.maximumFractionDigits ?? (Math.abs(value) >= 1000 ? 2 : 4);\n return value.toLocaleString('en-US', { maximumFractionDigits: maxDigits });\n}\n/**\n * Create a composite key from field values (for pivot grouping)\n */\nexport function makeKey(row, fields) {\n return fields.map(f => String(row[f] ?? '(blank)')).join('|||');\n}\n/**\n * Parse composite key back to values\n */\nexport function parseKey(key) {\n return key.split('|||');\n}\n/**\n * Natural sort comparator\n */\nexport function naturalSort(a, b) {\n const numA = Number.parseFloat(a);\n const numB = Number.parseFloat(b);\n if (!Number.isNaN(numA) && !Number.isNaN(numB)) {\n return numA - numB;\n }\n return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });\n}\n/**\n * Debounce function\n */\nexport function debounce(fn, delay) {\n let timeoutId = null;\n return (...args) => {\n if (timeoutId)\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => fn(...args), delay);\n };\n}\n/**\n * Clamp a number between min and max\n */\nexport function clamp(value, min, max) {\n return Math.max(min, Math.min(max, value));\n}\n//# sourceMappingURL=index.js.map","import { detectFieldType, makeKey, parseKey } from '../utils';\n/**\n * Aggregate values based on function type\n */\nexport function aggregate(values, fn) {\n if (values.length === 0)\n return null;\n switch (fn) {\n case 'sum':\n return values.reduce((a, b) => a + b, 0);\n case 'count':\n return values.length;\n case 'avg':\n return values.reduce((a, b) => a + b, 0) / values.length;\n case 'min':\n return Math.min(...values);\n case 'max':\n return Math.max(...values);\n case 'countDistinct':\n return new Set(values).size;\n default:\n return values.reduce((a, b) => a + b, 0);\n }\n}\n/**\n * Format aggregated value for display\n */\nexport function formatAggregatedValue(value, fn) {\n if (value === null)\n return '-';\n if (fn === 'count' || fn === 'countDistinct') {\n return Math.round(value).toLocaleString();\n }\n if (Math.abs(value) >= 1000) {\n return value.toLocaleString('en-US', { maximumFractionDigits: 2 });\n }\n return value.toLocaleString('en-US', { maximumFractionDigits: 4 });\n}\n/**\n * Get aggregation function display label\n */\nexport function getAggregationLabel(fn) {\n const labels = {\n sum: 'Sum',\n count: 'Count',\n avg: 'Average',\n min: 'Min',\n max: 'Max',\n countDistinct: 'Count Distinct',\n };\n return labels[fn];\n}\n/**\n * Get aggregation function symbol\n */\nexport function getAggregationSymbol(fn) {\n const symbols = {\n sum: 'Σ',\n count: '#',\n avg: 'x̄',\n min: '↓',\n max: '↑',\n countDistinct: '◇',\n };\n return symbols[fn];\n}\n/**\n * Aggregation options for UI\n */\nexport const AGGREGATION_OPTIONS = [\n { value: 'sum', label: 'Sum', symbol: 'Σ' },\n { value: 'count', label: 'Count', symbol: '#' },\n { value: 'avg', label: 'Avg', symbol: 'x̄' },\n { value: 'min', label: 'Min', symbol: '↓' },\n { value: 'max', label: 'Max', symbol: '↑' },\n { value: 'countDistinct', label: 'Unique', symbol: '◇' },\n];\n/**\n * Compute available fields from data\n */\nexport function computeAvailableFields(data) {\n if (data.length === 0)\n return [];\n const keys = Object.keys(data[0]);\n return keys.map(field => detectFieldType(data, field));\n}\n/**\n * Get unassigned fields (not in row, column, or value fields)\n */\nexport function getUnassignedFields(availableFields, rowFields, columnFields, valueFields) {\n const assigned = new Set([\n ...rowFields,\n ...columnFields,\n ...valueFields.map(v => v.field),\n ]);\n return availableFields.filter(f => !assigned.has(f.field));\n}\n/**\n * Check if pivot is configured\n */\nexport function isPivotConfigured(config) {\n return (config.rowFields.length > 0 || config.columnFields.length > 0) && config.valueFields.length > 0;\n}\n/**\n * Build pivot result from data and config\n */\nexport function computePivotResult(data, config) {\n const { rowFields, columnFields, valueFields, showRowTotals, showColumnTotals } = config;\n if (!isPivotConfigured(config))\n return null;\n if (data.length === 0)\n return null;\n // Collect unique row and column keys\n const rowKeySet = new Set();\n const colKeySet = new Set();\n // Group data by row and column keys\n const dataMap = new Map();\n for (const row of data) {\n const rowKey = rowFields.length > 0 ? makeKey(row, rowFields) : '__all__';\n const colKey = columnFields.length > 0 ? makeKey(row, columnFields) : '__all__';\n rowKeySet.add(rowKey);\n colKeySet.add(colKey);\n if (!dataMap.has(rowKey)) {\n dataMap.set(rowKey, new Map());\n }\n const colMap = dataMap.get(rowKey);\n if (!colMap.has(colKey)) {\n colMap.set(colKey, valueFields.map(() => []));\n }\n const valueArrays = colMap.get(colKey);\n // Collect values for each value field\n for (let i = 0; i < valueFields.length; i++) {\n const vf = valueFields[i];\n const val = row[vf.field];\n if (val !== null && val !== undefined && val !== '') {\n const num = typeof val === 'number' ? val : Number.parseFloat(String(val));\n if (!Number.isNaN(num)) {\n valueArrays[i].push(num);\n }\n else if (vf.aggregation === 'count' || vf.aggregation === 'countDistinct') {\n valueArrays[i].push(1);\n }\n }\n }\n }\n // Sort keys\n const rowKeys = Array.from(rowKeySet).sort();\n const colKeys = Array.from(colKeySet).sort();\n // Build column headers\n const headers = [];\n if (columnFields.length > 0) {\n for (let level = 0; level < columnFields.length; level++) {\n const headerRow = [];\n for (const colKey of colKeys) {\n const parts = parseKey(colKey);\n headerRow.push(parts[level] || '');\n }\n headers.push(headerRow);\n }\n }\n // If multiple value fields, add value field labels as last header row\n if (valueFields.length > 1 || headers.length === 0) {\n const valueLabels = [];\n for (const colKey of colKeys) {\n for (const vf of valueFields) {\n valueLabels.push(`${vf.label || vf.field} (${getAggregationLabel(vf.aggregation)})`);\n }\n }\n if (colKeys.length === 1 && colKeys[0] === '__all__') {\n headers.push(valueFields.map(vf => `${vf.label || vf.field} (${getAggregationLabel(vf.aggregation)})`));\n }\n else {\n headers.push(valueLabels);\n }\n }\n // Build row headers\n const rowHeaders = rowKeys.map(key => {\n if (key === '__all__')\n return ['Total'];\n return parseKey(key);\n });\n // Build data matrix\n const pivotData = [];\n const rowTotals = [];\n const columnTotalsMap = new Map();\n for (const rowKey of rowKeys) {\n const rowData = [];\n const rowTotalValues = valueFields.map(() => []);\n let colIndex = 0;\n for (const colKey of colKeys) {\n const colMap = dataMap.get(rowKey);\n const valueArrays = colMap?.get(colKey) || valueFields.map(() => []);\n for (let i = 0; i < valueFields.length; i++) {\n const vf = valueFields[i];\n const values = valueArrays[i];\n const aggValue = aggregate(values, vf.aggregation);\n rowData.push({\n value: aggValue,\n count: values.length,\n formattedValue: formatAggregatedValue(aggValue, vf.aggregation),\n });\n rowTotalValues[i].push(...values);\n if (!columnTotalsMap.has(colIndex)) {\n columnTotalsMap.set(colIndex, valueFields.map(() => []));\n }\n columnTotalsMap.get(colIndex)[i].push(...values);\n colIndex++;\n }\n }\n pivotData.push(rowData);\n if (showRowTotals && colKeys.length > 1) {\n const totalCell = {\n value: null,\n count: 0,\n formattedValue: '-',\n };\n if (valueFields.length > 0) {\n const vf = valueFields[0];\n const allValues = rowTotalValues[0];\n const aggValue = aggregate(allValues, vf.aggregation);\n totalCell.value = aggValue;\n totalCell.count = allValues.length;\n totalCell.formattedValue = formatAggregatedValue(aggValue, vf.aggregation);\n }\n rowTotals.push(totalCell);\n }\n }\n // Calculate column totals\n const columnTotals = [];\n if (showColumnTotals && rowKeys.length > 1) {\n for (let colIdx = 0; colIdx < colKeys.length * valueFields.length; colIdx++) {\n const valueIdx = colIdx % valueFields.length;\n const vf = valueFields[valueIdx];\n const allColValues = [];\n for (const rowKey of rowKeys) {\n const colMap = dataMap.get(rowKey);\n const colKey = colKeys[Math.floor(colIdx / valueFields.length)];\n const valueArrays = colMap?.get(colKey) || valueFields.map(() => []);\n allColValues.push(...valueArrays[valueIdx]);\n }\n const aggValue = aggregate(allColValues, vf.aggregation);\n columnTotals.push({\n value: aggValue,\n count: allColValues.length,\n formattedValue: formatAggregatedValue(aggValue, vf.aggregation),\n });\n }\n }\n // Grand total\n const grandTotal = { value: null, count: 0, formattedValue: '-' };\n if (showRowTotals && showColumnTotals && valueFields.length > 0) {\n const vf = valueFields[0];\n const allValues = [];\n for (const row of data) {\n const val = row[vf.field];\n if (val !== null && val !== undefined && val !== '') {\n const num = typeof val === 'number' ? val : Number.parseFloat(String(val));\n if (!Number.isNaN(num)) {\n allValues.push(num);\n }\n else if (vf.aggregation === 'count' || vf.aggregation === 'countDistinct') {\n allValues.push(1);\n }\n }\n }\n const aggValue = aggregate(allValues, vf.aggregation);\n grandTotal.value = aggValue;\n grandTotal.count = allValues.length;\n grandTotal.formattedValue = formatAggregatedValue(aggValue, vf.aggregation);\n }\n return {\n headers,\n rowHeaders,\n data: pivotData,\n rowTotals,\n columnTotals,\n grandTotal,\n };\n}\n// Storage helpers for pivot config persistence\nconst STORAGE_KEY_PREFIX = 'vpg-pivot-';\n/**\n * Generate a storage key based on column names\n */\nexport function generateStorageKey(columns) {\n const sorted = [...columns].sort();\n const hash = sorted.join('|').substring(0, 100);\n return `${STORAGE_KEY_PREFIX}${hash}`;\n}\n/**\n * Save pivot config to sessionStorage\n */\nexport function savePivotConfig(key, config) {\n try {\n sessionStorage.setItem(key, JSON.stringify(config));\n }\n catch {\n // Ignore storage errors\n }\n}\n/**\n * Load pivot config from sessionStorage\n */\nexport function loadPivotConfig(key) {\n try {\n const stored = sessionStorage.getItem(key);\n if (stored) {\n return JSON.parse(stored);\n }\n }\n catch {\n // Ignore parse errors\n }\n return null;\n}\n/**\n * Check if config fields exist in available fields\n */\nexport function isConfigValidForFields(config, availableFieldNames) {\n const available = new Set(availableFieldNames);\n const allConfiguredFields = [\n ...config.rowFields,\n ...config.columnFields,\n ...config.valueFields.map(v => v.field),\n ];\n return allConfiguredFields.every(f => available.has(f));\n}\n//# sourceMappingURL=index.js.map","const FREE_LICENSE = {\n type: 'free',\n isValid: true,\n features: {\n pivot: false,\n advancedAggregations: false,\n percentageMode: false,\n sessionPersistence: false,\n noWatermark: false,\n },\n};\nconst INVALID_LICENSE = {\n type: 'free',\n isValid: false,\n features: {\n pivot: false,\n advancedAggregations: false,\n percentageMode: false,\n sessionPersistence: false,\n noWatermark: false,\n },\n};\nconst DEMO_LICENSE = {\n type: 'free',\n isValid: true,\n features: {\n pivot: true,\n advancedAggregations: true,\n percentageMode: true,\n sessionPersistence: true,\n noWatermark: false, // Still show watermark in demo\n },\n};\n/**\n * HMAC-SHA256 based license signature verification\n * Must match the server-side generation algorithm\n */\nasync function verifySignature(typeCode, signature, expiry) {\n // The secret must be configured before license validation can work\n const secret = globalThis.__TP_LICENSE_SECRET__;\n if (!secret) {\n console.warn('[TinyPivot] License secret not configured. Call configureLicenseSecret() first.');\n return false;\n }\n const payload = `TP-${typeCode}-${expiry}`;\n try {\n const encoder = new TextEncoder();\n const keyData = encoder.encode(secret);\n const msgData = encoder.encode(payload);\n const cryptoKey = await crypto.subtle.importKey('raw', keyData, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);\n const sig = await crypto.subtle.sign('HMAC', cryptoKey, msgData);\n const sigArray = Array.from(new Uint8Array(sig));\n const expectedSig = sigArray\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n .slice(0, 12)\n .toUpperCase();\n return signature === expectedSig;\n }\n catch {\n // Fallback for environments without crypto.subtle (SSR, older browsers)\n return false;\n }\n}\n/**\n * Validate a license key and extract info\n */\nexport async function validateLicenseKey(key) {\n // Free tier - no key needed\n if (!key || key === '') {\n return FREE_LICENSE;\n }\n // License key format: TP-{TYPE}-{SIGNATURE}-{EXPIRY}\n // Example: TP-PRO1-A1B2C3D4E5F6-20251231\n const parts = key.split('-');\n if (parts.length !== 4 || parts[0] !== 'TP') {\n return INVALID_LICENSE;\n }\n const typeCode = parts[1];\n const signature = parts[2];\n const expiryStr = parts[3];\n // Verify cryptographic signature\n const isValidSignature = await verifySignature(typeCode, signature, expiryStr);\n if (!isValidSignature) {\n return INVALID_LICENSE;\n }\n // Parse expiry date\n const year = Number.parseInt(expiryStr.slice(0, 4));\n const month = Number.parseInt(expiryStr.slice(4, 6)) - 1;\n const day = Number.parseInt(expiryStr.slice(6, 8));\n const expiresAt = new Date(year, month, day);\n if (expiresAt < new Date()) {\n return { ...INVALID_LICENSE, expiresAt };\n }\n // Determine license type\n let type = 'free';\n if (typeCode === 'PRO1')\n type = 'pro-single';\n else if (typeCode === 'PROU')\n type = 'pro-unlimited';\n else if (typeCode === 'PROT')\n type = 'pro-team';\n return {\n type,\n isValid: true,\n expiresAt,\n features: {\n pivot: type !== 'free',\n advancedAggregations: type !== 'free',\n percentageMode: type !== 'free',\n sessionPersistence: type !== 'free',\n noWatermark: type !== 'free',\n },\n };\n}\n/**\n * Configure the license secret (for SSR/build-time injection)\n */\nexport function configureLicenseSecret(secret) {\n globalThis.__TP_LICENSE_SECRET__ = secret;\n}\n// Hardcoded SHA-256 hash of the demo secret\nconst DEMO_SECRET_HASH = 'A48AA0618518D3E62F31FCFCA2DD2B86E7FE0863E2F90756FB0A960AE7A51583';\n/**\n * Hash a string using SHA-256 (async for Web Crypto API)\n */\nasync function hashSecret(secret) {\n try {\n const encoder = new TextEncoder();\n const data = encoder.encode(secret);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('').toUpperCase();\n }\n catch {\n return '';\n }\n}\n/**\n * Validate demo secret and return demo license info if valid\n * Returns null if secret is invalid\n */\nexport async function getDemoLicenseInfo(secret) {\n if (!secret) {\n return null;\n }\n const hash = await hashSecret(secret);\n if (hash !== DEMO_SECRET_HASH) {\n return null;\n }\n return DEMO_LICENSE;\n}\n/**\n * Get free license info\n */\nexport function getFreeLicenseInfo() {\n return FREE_LICENSE;\n}\n/**\n * Check if license allows pivot feature\n */\nexport function canUsePivot(info) {\n return info.features.pivot;\n}\n/**\n * Check if license is pro (any tier)\n */\nexport function isPro(info) {\n return info.isValid && info.type !== 'free';\n}\n/**\n * Check if watermark should be shown\n */\nexport function shouldShowWatermark(info, isDemo) {\n return isDemo || !info.features.noWatermark;\n}\n/**\n * Log pro requirement warning\n */\nexport function logProRequired(feature) {\n console.warn(`[TinyPivot] \"${feature}\" requires a Pro license. ` +\n `Visit https://tiny-pivot.com/#pricing to upgrade.`);\n}\n//# sourceMappingURL=index.js.map","/**\n * Escape CSV value\n */\nfunction escapeCSV(value, delimiter = ',') {\n if (value === null || value === undefined)\n return '';\n const str = String(value);\n if (str.includes(delimiter) || str.includes('\"') || str.includes('\\n')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n}\n/**\n * CSV Export functionality\n */\nexport function exportToCSV(data, columns, options = {}) {\n const { filename = 'export.csv', includeHeaders = true, delimiter = ',' } = options;\n const rows = [];\n if (includeHeaders) {\n rows.push(columns.map(col => escapeCSV(col, delimiter)).join(delimiter));\n }\n for (const row of data) {\n const values = columns.map(col => escapeCSV(row[col], delimiter));\n rows.push(values.join(delimiter));\n }\n const csvContent = rows.join('\\n');\n downloadFile(csvContent, filename, 'text/csv;charset=utf-8;');\n}\n/**\n * Export pivot table to CSV\n */\nexport function exportPivotToCSV(pivotData, rowFields, _columnFields, valueFields, options = {}) {\n const { filename = 'pivot-export.csv', delimiter = ',' } = options;\n const rows = [];\n const { headers, rowHeaders, data, rowTotals, columnTotals, grandTotal, showRowTotals, showColumnTotals } = pivotData;\n // Calculate number of row header columns\n const rowHeaderColCount = rowFields.length || 1;\n // Build column headers\n if (headers.length > 0) {\n // Multi-level column headers\n for (let level = 0; level < headers.length; level++) {\n const headerRow = [];\n // Empty cells for row field columns\n for (let i = 0; i < rowHeaderColCount; i++) {\n headerRow.push(level === headers.length - 1 ? escapeCSV(rowFields[i] || '', delimiter) : '');\n }\n // Column header values\n for (const val of headers[level]) {\n headerRow.push(escapeCSV(val, delimiter));\n }\n // Row totals header\n if (showRowTotals && rowTotals && rowTotals.length > 0) {\n if (level === headers.length - 1) {\n for (const vf of valueFields) {\n headerRow.push(escapeCSV(`Total (${vf.aggregation})`, delimiter));\n }\n }\n else {\n for (let i = 0; i < valueFields.length; i++) {\n headerRow.push('');\n }\n }\n }\n rows.push(headerRow.join(delimiter));\n }\n }\n else {\n // Simple header with value fields only\n const headerRow = [];\n for (let i = 0; i < rowHeaderColCount; i++) {\n headerRow.push(escapeCSV(rowFields[i] || '', delimiter));\n }\n for (const vf of valueFields) {\n headerRow.push(escapeCSV(`${vf.field} (${vf.aggregation})`, delimiter));\n }\n if (showRowTotals && rowTotals && rowTotals.length > 0) {\n headerRow.push(escapeCSV('Total', delimiter));\n }\n rows.push(headerRow.join(delimiter));\n }\n // Build data rows\n for (let rowIdx = 0; rowIdx < rowHeaders.length; rowIdx++) {\n const csvRow = [];\n // Row headers\n const rowHeader = rowHeaders[rowIdx] || [];\n for (let i = 0; i < rowHeaderColCount; i++) {\n csvRow.push(escapeCSV(rowHeader[i] || '', delimiter));\n }\n // Data cells\n const rowData = data[rowIdx] || [];\n for (const cell of rowData) {\n csvRow.push(escapeCSV(cell?.formattedValue || '', delimiter));\n }\n // Row total\n if (showRowTotals && rowTotals && rowTotals[rowIdx]) {\n csvRow.push(escapeCSV(rowTotals[rowIdx].formattedValue || '', delimiter));\n }\n rows.push(csvRow.join(delimiter));\n }\n // Column totals row\n if (showColumnTotals && columnTotals && columnTotals.length > 0) {\n const totalsRow = [];\n // Label for totals row\n totalsRow.push(escapeCSV('Total', delimiter));\n for (let i = 1; i < rowHeaderColCount; i++) {\n totalsRow.push('');\n }\n // Column total values\n for (const cell of columnTotals) {\n totalsRow.push(escapeCSV(cell?.formattedValue || '', delimiter));\n }\n // Grand total\n if (showRowTotals && grandTotal) {\n totalsRow.push(escapeCSV(grandTotal.formattedValue || '', delimiter));\n }\n rows.push(totalsRow.join(delimiter));\n }\n const csvContent = rows.join('\\n');\n downloadFile(csvContent, filename, 'text/csv;charset=utf-8;');\n}\n/**\n * Download file helper\n */\nfunction downloadFile(content, filename, mimeType) {\n const blob = new Blob([content], { type: mimeType });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n link.style.display = 'none';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n}\n/**\n * Copy text to clipboard\n */\nexport function copyToClipboard(text, onSuccess, onError) {\n navigator.clipboard.writeText(text).then(onSuccess).catch(onError);\n}\n/**\n * Format selected cells for clipboard (tab-separated)\n */\nexport function formatSelectionForClipboard(rows, columns, selectionBounds) {\n const { minRow, maxRow, minCol, maxCol } = selectionBounds;\n const lines = [];\n for (let r = minRow; r <= maxRow; r++) {\n const row = rows[r];\n if (!row)\n continue;\n const values = [];\n for (let c = minCol; c <= maxCol; c++) {\n const colId = columns[c];\n if (!colId)\n continue;\n const value = row[colId];\n values.push(value === null || value === undefined ? '' : String(value));\n }\n lines.push(values.join('\\t'));\n }\n return lines.join('\\n');\n}\n//# sourceMappingURL=index.js.map","/**\n * Excel-like Grid Composable for Vue\n * Provides Excel-like filtering, sorting, and data manipulation functionality\n */\nimport type { ColumnDef, ColumnFiltersState, FilterFn, SortingState, VisibilityState } from '@tanstack/vue-table'\nimport {\n getCoreRowModel,\n getFilteredRowModel,\n getSortedRowModel,\n useVueTable,\n} from '@tanstack/vue-table'\nimport { type Ref, computed, ref, watch } from 'vue'\nimport type { ColumnStats } from '@smallwebco/tinypivot-core'\nimport { getColumnUniqueValues, formatCellValue } from '@smallwebco/tinypivot-core'\n\n// Re-export for convenience\nexport { getColumnUniqueValues, formatCellValue }\n\nexport interface ExcelGridOptions<T> {\n data: Ref<T[]>\n columns?: string[]\n enableSorting?: boolean\n enableFiltering?: boolean\n pageSize?: number\n}\n\n/**\n * Multi-value filter function for Excel-style filtering\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst multiSelectFilter: FilterFn<any> = (row, columnId, filterValue) => {\n if (!filterValue || !Array.isArray(filterValue) || filterValue.length === 0) {\n return true\n }\n\n const cellValue = row.getValue(columnId)\n const cellString = cellValue === null || cellValue === undefined || cellValue === ''\n ? '(blank)'\n : String(cellValue)\n\n return filterValue.includes(cellString)\n}\n\n/**\n * Create Excel-like grid composable\n */\nexport function useExcelGrid<T extends Record<string, unknown>>(options: ExcelGridOptions<T>) {\n const { data, enableSorting = true, enableFiltering = true } = options\n\n // State\n const sorting = ref<SortingState>([])\n const columnFilters = ref<ColumnFiltersState>([])\n const columnVisibility = ref<VisibilityState>({})\n const globalFilter = ref('')\n\n // Column statistics cache\n const columnStatsCache = ref<Record<string, ColumnStats>>({})\n\n // Compute columns from data\n const columnKeys = computed(() => {\n if (data.value.length === 0) return []\n return Object.keys(data.value[0] as Record<string, unknown>)\n })\n\n // Get column stats (memoized)\n function getColumnStats(columnKey: string): ColumnStats {\n const cacheKey = `${columnKey}-${data.value.length}`\n if (!columnStatsCache.value[cacheKey]) {\n columnStatsCache.value[cacheKey] = getColumnUniqueValues(data.value, columnKey)\n }\n return columnStatsCache.value[cacheKey]\n }\n\n // Clear stats cache when data changes\n function clearStatsCache() {\n columnStatsCache.value = {}\n }\n\n // Create column definitions dynamically\n const columnDefs = computed<ColumnDef<T, unknown>[]>(() => {\n return columnKeys.value.map(key => {\n const stats = getColumnStats(key)\n\n return {\n id: key,\n accessorKey: key,\n header: key,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n cell: (info: any) => formatCellValue(info.getValue(), stats.type),\n filterFn: multiSelectFilter,\n meta: {\n type: stats.type,\n uniqueCount: stats.uniqueValues.length,\n },\n } as ColumnDef<T, unknown>\n })\n })\n\n // Create table instance\n const table = useVueTable({\n get data() { return data.value },\n get columns() { return columnDefs.value },\n state: {\n get sorting() { return sorting.value },\n get columnFilters() { return columnFilters.value },\n get columnVisibility() { return columnVisibility.value },\n get globalFilter() { return globalFilter.value },\n },\n onSortingChange: updater => {\n sorting.value = typeof updater === 'function' ? updater(sorting.value) : updater\n },\n onColumnFiltersChange: updater => {\n columnFilters.value = typeof updater === 'function' ? updater(columnFilters.value) : updater\n },\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: enableSorting ? getSortedRowModel() : undefined,\n getFilteredRowModel: enableFiltering ? getFilteredRowModel() : undefined,\n filterFns: {\n multiSelect: multiSelectFilter,\n },\n enableSorting,\n enableFilters: enableFiltering,\n })\n\n // Computed properties\n const filteredRowCount = computed(() => table.getFilteredRowModel().rows.length)\n const totalRowCount = computed(() => data.value.length)\n\n // Active filters\n const activeFilters = computed(() => {\n return columnFilters.value.map(f => ({\n column: f.id,\n values: f.value as string[],\n }))\n })\n\n // Check if column has active filter\n function hasActiveFilter(columnId: string): boolean {\n const column = table.getColumn(columnId)\n if (!column) return false\n const filterValue = column.getFilterValue()\n return filterValue !== undefined && Array.isArray(filterValue) && filterValue.length > 0\n }\n\n // Set column filter\n function setColumnFilter(columnId: string, values: string[]) {\n const column = table.getColumn(columnId)\n if (column) {\n column.setFilterValue(values.length === 0 ? undefined : values)\n // Force sync columnFilters ref with table state\n columnFilters.value = table.getState().columnFilters\n }\n }\n\n // Clear all filters\n function clearAllFilters() {\n table.resetColumnFilters()\n globalFilter.value = ''\n // Force sync columnFilters ref with table state\n columnFilters.value = []\n }\n\n // Get filter values for a specific column\n function getColumnFilterValues(columnId: string): string[] {\n const column = table.getColumn(columnId)\n if (!column) return []\n const filterValue = column.getFilterValue()\n return Array.isArray(filterValue) ? filterValue : []\n }\n\n // Toggle column sort\n function toggleSort(columnId: string) {\n const current = sorting.value.find(s => s.id === columnId)\n if (!current) {\n sorting.value = [{ id: columnId, desc: false }]\n } else if (!current.desc) {\n sorting.value = [{ id: columnId, desc: true }]\n } else {\n sorting.value = []\n }\n }\n\n // Get sort direction for column\n function getSortDirection(columnId: string): 'asc' | 'desc' | null {\n const sort = sorting.value.find(s => s.id === columnId)\n if (!sort) return null\n return sort.desc ? 'desc' : 'asc'\n }\n\n // Watch data changes to clear cache\n watch(data, () => {\n clearStatsCache()\n })\n\n return {\n // Table instance\n table,\n\n // State\n sorting,\n columnFilters,\n columnVisibility,\n globalFilter,\n columnKeys,\n\n // Computed\n filteredRowCount,\n totalRowCount,\n activeFilters,\n\n // Methods\n getColumnStats,\n clearStatsCache,\n hasActiveFilter,\n setColumnFilter,\n getColumnFilterValues,\n clearAllFilters,\n toggleSort,\n getSortDirection,\n }\n}\n\n","/**\n * License Management Composable for Vue\n * Wraps core license logic with Vue reactivity\n */\nimport { computed, ref } from 'vue'\nimport type { LicenseInfo } from '@smallwebco/tinypivot-core'\nimport {\n validateLicenseKey,\n configureLicenseSecret as coreConfigureLicenseSecret,\n getDemoLicenseInfo,\n getFreeLicenseInfo,\n canUsePivot as coreCanUsePivot,\n isPro as coreIsPro,\n shouldShowWatermark as coreShouldShowWatermark,\n logProRequired,\n} from '@smallwebco/tinypivot-core'\n\n// License state\nconst licenseKey = ref<string | null>(null)\nconst demoMode = ref(false)\nconst licenseInfo = ref<LicenseInfo>(getFreeLicenseInfo())\n\n// Cached validation result\nlet validationPromise: Promise<LicenseInfo> | null = null\n\n/**\n * Set the license key for the library\n * Returns a promise that resolves when validation is complete\n */\nexport async function setLicenseKey(key: string): Promise<void> {\n licenseKey.value = key\n\n // Start validation\n validationPromise = validateLicenseKey(key)\n licenseInfo.value = await validationPromise\n validationPromise = null\n\n if (!licenseInfo.value.isValid) {\n console.warn('[TinyPivot] Invalid or expired license key. Running in free mode.')\n } else if (licenseInfo.value.type !== 'free') {\n console.info(`[TinyPivot] Pro license activated (${licenseInfo.value.type})`)\n }\n}\n\n/**\n * Enable demo mode - unlocks all features for evaluation\n * Requires the correct demo secret\n * Shows \"Demo Mode\" watermark\n */\nexport async function enableDemoMode(secret: string): Promise<boolean> {\n const demoLicense = await getDemoLicenseInfo(secret)\n if (!demoLicense) {\n console.warn('[TinyPivot] Demo mode activation failed - invalid secret')\n return false\n }\n demoMode.value = true\n licenseInfo.value = demoLicense\n console.info('[TinyPivot] Demo mode enabled - all Pro features unlocked for evaluation')\n return true\n}\n\n/**\n * Configure the license secret\n */\nexport function configureLicenseSecret(secret: string): void {\n coreConfigureLicenseSecret(secret)\n}\n\n/**\n * Composable for accessing license information\n */\nexport function useLicense() {\n const isDemo = computed(() => demoMode.value)\n\n const isPro = computed(() => demoMode.value || coreIsPro(licenseInfo.value))\n\n const canUsePivot = computed(() => demoMode.value || coreCanUsePivot(licenseInfo.value))\n\n const canUseAdvancedAggregations = computed(\n () => demoMode.value || licenseInfo.value.features.advancedAggregations\n )\n\n const canUsePercentageMode = computed(\n () => demoMode.value || licenseInfo.value.features.percentageMode\n )\n\n const showWatermark = computed(() => coreShouldShowWatermark(licenseInfo.value, demoMode.value))\n\n function requirePro(feature: string): boolean {\n if (!isPro.value) {\n logProRequired(feature)\n return false\n }\n return true\n }\n\n return {\n licenseInfo: computed(() => licenseInfo.value),\n isDemo,\n isPro,\n canUsePivot,\n canUseAdvancedAggregations,\n canUsePercentageMode,\n showWatermark,\n requirePro,\n }\n}\n\n","/**\n * Pivot Table Composable for Vue\n * Wraps core pivot logic with Vue reactivity\n */\nimport { type Ref, computed, ref, watch } from 'vue'\nimport type { AggregationFunction, FieldStats, PivotConfig, PivotValueField } from '@smallwebco/tinypivot-core'\nimport {\n computeAvailableFields,\n getUnassignedFields,\n isPivotConfigured,\n computePivotResult,\n generateStorageKey,\n savePivotConfig,\n loadPivotConfig,\n isConfigValidForFields,\n getAggregationLabel,\n} from '@smallwebco/tinypivot-core'\nimport { useLicense } from './useLicense'\n\n// Re-export for convenience\nexport { getAggregationLabel }\n\n/**\n * Main pivot table composable\n */\nexport function usePivotTable(data: Ref<Record<string, unknown>[]>) {\n const { canUsePivot, requirePro } = useLicense()\n\n // Configuration state\n const rowFields = ref<string[]>([])\n const columnFields = ref<string[]>([])\n const valueFields = ref<PivotValueField[]>([])\n const showRowTotals = ref(true)\n const showColumnTotals = ref(true)\n\n // Track current storage key\n const currentStorageKey = ref<string | null>(null)\n\n // Compute available fields from data\n const availableFields = computed((): FieldStats[] => {\n return computeAvailableFields(data.value)\n })\n\n // Get fields that haven't been assigned yet\n const unassignedFields = computed(() => {\n return getUnassignedFields(\n availableFields.value,\n rowFields.value,\n columnFields.value,\n valueFields.value\n )\n })\n\n // Check if pivot is configured\n const isConfigured = computed(() => {\n return isPivotConfigured({\n rowFields: rowFields.value,\n columnFields: columnFields.value,\n valueFields: valueFields.value,\n showRowTotals: showRowTotals.value,\n showColumnTotals: showColumnTotals.value,\n })\n })\n\n // Build pivot result\n const pivotResult = computed(() => {\n if (!isConfigured.value) return null\n\n // Check license for pivot feature\n if (!canUsePivot.value) return null\n\n return computePivotResult(data.value, {\n rowFields: rowFields.value,\n columnFields: columnFields.value,\n valueFields: valueFields.value,\n showRowTotals: showRowTotals.value,\n showColumnTotals: showColumnTotals.value,\n })\n })\n\n // Actions with license checks\n function addRowField(field: string) {\n if (!requirePro('Pivot Table - Row Fields')) return\n if (!rowFields.value.includes(field)) {\n rowFields.value = [...rowFields.value, field]\n }\n }\n\n function removeRowField(field: string) {\n rowFields.value = rowFields.value.filter(f => f !== field)\n }\n\n function addColumnField(field: string) {\n if (!requirePro('Pivot Table - Column Fields')) return\n if (!columnFields.value.includes(field)) {\n columnFields.value = [...columnFields.value, field]\n }\n }\n\n function removeColumnField(field: string) {\n columnFields.value = columnFields.value.filter(f => f !== field)\n }\n\n function addValueField(field: string, aggregation: AggregationFunction = 'sum') {\n if (!requirePro('Pivot Table - Value Fields')) return\n if (valueFields.value.some(v => v.field === field && v.aggregation === aggregation)) {\n return\n }\n valueFields.value = [...valueFields.value, { field, aggregation }]\n }\n\n function removeValueField(field: string, aggregation?: AggregationFunction) {\n if (aggregation) {\n valueFields.value = valueFields.value.filter(\n v => !(v.field === field && v.aggregation === aggregation)\n )\n } else {\n valueFields.value = valueFields.value.filter(v => v.field !== field)\n }\n }\n\n function updateValueFieldAggregation(\n field: string,\n oldAgg: AggregationFunction,\n newAgg: AggregationFunction\n ) {\n valueFields.value = valueFields.value.map(v => {\n if (v.field === field && v.aggregation === oldAgg) {\n return { ...v, aggregation: newAgg }\n }\n return v\n })\n }\n\n function clearConfig() {\n rowFields.value = []\n columnFields.value = []\n valueFields.value = []\n }\n\n function moveField(\n from: { area: 'row' | 'column' | 'value'; index: number },\n to: { area: 'row' | 'column' | 'value'; index: number }\n ) {\n if (from.area === to.area) {\n if (from.area === 'row') {\n const items = [...rowFields.value]\n const [removed] = items.splice(from.index, 1)\n items.splice(to.index, 0, removed)\n rowFields.value = items\n } else if (from.area === 'column') {\n const items = [...columnFields.value]\n const [removed] = items.splice(from.index, 1)\n items.splice(to.index, 0, removed)\n columnFields.value = items\n }\n }\n }\n\n function autoSuggestConfig() {\n if (!requirePro('Pivot Table - Auto Suggest')) return\n if (availableFields.value.length === 0) return\n\n const categoricalFields = availableFields.value.filter(f => !f.isNumeric && f.uniqueCount < 50)\n const numericFields = availableFields.value.filter(f => f.isNumeric)\n\n if (categoricalFields.length > 0 && numericFields.length > 0) {\n rowFields.value = [categoricalFields[0].field]\n valueFields.value = [{ field: numericFields[0].field, aggregation: 'sum' }]\n }\n }\n\n // Watch data to restore or validate config\n watch(\n data,\n newData => {\n if (newData.length === 0) return\n\n const newKeys = Object.keys(newData[0])\n const storageKey = generateStorageKey(newKeys)\n\n if (storageKey !== currentStorageKey.value) {\n currentStorageKey.value = storageKey\n\n const savedConfig = loadPivotConfig(storageKey)\n if (savedConfig && isConfigValidForFields(savedConfig, newKeys)) {\n rowFields.value = savedConfig.rowFields\n columnFields.value = savedConfig.columnFields\n valueFields.value = savedConfig.valueFields\n showRowTotals.value = savedConfig.showRowTotals\n showColumnTotals.value = savedConfig.showColumnTotals\n } else {\n const currentConfig: PivotConfig = {\n rowFields: rowFields.value,\n columnFields: columnFields.value,\n valueFields: valueFields.value,\n showRowTotals: showRowTotals.value,\n showColumnTotals: showColumnTotals.value,\n }\n if (!isConfigValidForFields(currentConfig, newKeys)) {\n clearConfig()\n }\n }\n } else {\n const currentConfig: PivotConfig = {\n rowFields: rowFields.value,\n columnFields: columnFields.value,\n valueFields: valueFields.value,\n showRowTotals: showRowTotals.value,\n showColumnTotals: showColumnTotals.value,\n }\n if (!isConfigValidForFields(currentConfig, newKeys)) {\n clearConfig()\n }\n }\n },\n { immediate: true }\n )\n\n // Watch config changes and save to sessionStorage\n watch(\n [rowFields, columnFields, valueFields, showRowTotals, showColumnTotals],\n () => {\n if (!currentStorageKey.value) return\n\n const config: PivotConfig = {\n rowFields: rowFields.value,\n columnFields: columnFields.value,\n valueFields: valueFields.value,\n showRowTotals: showRowTotals.value,\n showColumnTotals: showColumnTotals.value,\n }\n savePivotConfig(currentStorageKey.value, config)\n },\n { deep: true }\n )\n\n return {\n // State\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n\n // Computed\n availableFields,\n unassignedFields,\n isConfigured,\n pivotResult,\n\n // Actions\n addRowField,\n removeRowField,\n addColumnField,\n removeColumnField,\n addValueField,\n removeValueField,\n updateValueFieldAggregation,\n clearConfig,\n moveField,\n autoSuggestConfig,\n }\n}\n\n","/**\n * Grid Features Composable for Vue\n * Provides CSV export, clipboard, pagination, and other utility features\n */\nimport { computed, ref, type Ref } from 'vue'\nimport type { PaginationOptions, SelectionBounds, PivotValueField } from '@smallwebco/tinypivot-core'\nimport {\n exportToCSV as coreExportToCSV,\n exportPivotToCSV as coreExportPivotToCSV,\n copyToClipboard as coreCopyToClipboard,\n formatSelectionForClipboard as coreFormatSelection,\n} from '@smallwebco/tinypivot-core'\nimport type { PivotExportData, ExportOptions } from '@smallwebco/tinypivot-core'\n\n// Re-export core functions\nexport {\n exportToCSV,\n exportPivotToCSV,\n copyToClipboard,\n formatSelectionForClipboard,\n}\n\n/**\n * CSV Export functionality wrapper\n */\nfunction exportToCSV<T extends Record<string, unknown>>(\n data: T[],\n columns: string[],\n options?: ExportOptions\n): void {\n coreExportToCSV(data, columns, options)\n}\n\n/**\n * Pivot CSV export wrapper\n */\nfunction exportPivotToCSV(\n pivotData: PivotExportData,\n rowFields: string[],\n columnFields: string[],\n valueFields: PivotValueField[],\n options?: ExportOptions\n): void {\n coreExportPivotToCSV(pivotData, rowFields, columnFields, valueFields, options)\n}\n\n/**\n * Copy to clipboard wrapper\n */\nfunction copyToClipboard(\n text: string,\n onSuccess?: () => void,\n onError?: (err: Error) => void\n): void {\n coreCopyToClipboard(text, onSuccess, onError)\n}\n\n/**\n * Format selection for clipboard wrapper\n */\nfunction formatSelectionForClipboard<T extends Record<string, unknown>>(\n rows: T[],\n columns: string[],\n selectionBounds: SelectionBounds\n): string {\n return coreFormatSelection(rows, columns, selectionBounds)\n}\n\n/**\n * Pagination composable\n */\nexport function usePagination<T>(data: Ref<T[]>, options: PaginationOptions = {}) {\n const pageSize = ref(options.pageSize ?? 50)\n const currentPage = ref(options.currentPage ?? 1)\n\n const totalPages = computed(() =>\n Math.max(1, Math.ceil(data.value.length / pageSize.value))\n )\n\n const paginatedData = computed(() => {\n const start = (currentPage.value - 1) * pageSize.value\n const end = start + pageSize.value\n return data.value.slice(start, end)\n })\n\n const startIndex = computed(() => (currentPage.value - 1) * pageSize.value + 1)\n const endIndex = computed(() =>\n Math.min(currentPage.value * pageSize.value, data.value.length)\n )\n\n function goToPage(page: number) {\n currentPage.value = Math.max(1, Math.min(page, totalPages.value))\n }\n\n function nextPage() {\n if (currentPage.value < totalPages.value) {\n currentPage.value++\n }\n }\n\n function prevPage() {\n if (currentPage.value > 1) {\n currentPage.value--\n }\n }\n\n function firstPage() {\n currentPage.value = 1\n }\n\n function lastPage() {\n currentPage.value = totalPages.value\n }\n\n function setPageSize(size: number) {\n pageSize.value = size\n currentPage.value = 1\n }\n\n return {\n pageSize,\n currentPage,\n totalPages,\n paginatedData,\n startIndex,\n endIndex,\n goToPage,\n nextPage,\n prevPage,\n firstPage,\n lastPage,\n setPageSize,\n }\n}\n\n/**\n * Global search/filter composable\n */\nexport function useGlobalSearch<T extends Record<string, unknown>>(\n data: Ref<T[]>,\n columns: Ref<string[]>\n) {\n const searchTerm = ref('')\n const caseSensitive = ref(false)\n\n const filteredData = computed(() => {\n if (!searchTerm.value.trim()) {\n return data.value\n }\n\n const term = caseSensitive.value\n ? searchTerm.value.trim()\n : searchTerm.value.trim().toLowerCase()\n\n return data.value.filter(row => {\n for (const col of columns.value) {\n const value = row[col]\n if (value === null || value === undefined) continue\n\n const strValue = caseSensitive.value ? String(value) : String(value).toLowerCase()\n\n if (strValue.includes(term)) {\n return true\n }\n }\n return false\n })\n })\n\n function clearSearch() {\n searchTerm.value = ''\n }\n\n return {\n searchTerm,\n caseSensitive,\n filteredData,\n clearSearch,\n }\n}\n\n/**\n * Row selection composable\n */\nexport function useRowSelection<T>(data: Ref<T[]>) {\n const selectedRowIndices = ref<Set<number>>(new Set())\n\n const selectedRows = computed(() => {\n return Array.from(selectedRowIndices.value)\n .sort((a, b) => a - b)\n .map(idx => data.value[idx])\n .filter(Boolean)\n })\n\n const allSelected = computed(() => {\n return data.value.length > 0 && selectedRowIndices.value.size === data.value.length\n })\n\n const someSelected = computed(() => {\n return selectedRowIndices.value.size > 0 && selectedRowIndices.value.size < data.value.length\n })\n\n function toggleRow(index: number) {\n if (selectedRowIndices.value.has(index)) {\n selectedRowIndices.value.delete(index)\n } else {\n selectedRowIndices.value.add(index)\n }\n selectedRowIndices.value = new Set(selectedRowIndices.value)\n }\n\n function selectRow(index: number) {\n selectedRowIndices.value.add(index)\n selectedRowIndices.value = new Set(selectedRowIndices.value)\n }\n\n function deselectRow(index: number) {\n selectedRowIndices.value.delete(index)\n selectedRowIndices.value = new Set(selectedRowIndices.value)\n }\n\n function selectAll() {\n selectedRowIndices.value = new Set(data.value.map((_, idx) => idx))\n }\n\n function deselectAll() {\n selectedRowIndices.value = new Set()\n }\n\n function toggleAll() {\n if (allSelected.value) {\n deselectAll()\n } else {\n selectAll()\n }\n }\n\n function isSelected(index: number): boolean {\n return selectedRowIndices.value.has(index)\n }\n\n function selectRange(startIndex: number, endIndex: number) {\n const min = Math.min(startIndex, endIndex)\n const max = Math.max(startIndex, endIndex)\n for (let i = min; i <= max; i++) {\n selectedRowIndices.value.add(i)\n }\n selectedRowIndices.value = new Set(selectedRowIndices.value)\n }\n\n return {\n selectedRowIndices,\n selectedRows,\n allSelected,\n someSelected,\n toggleRow,\n selectRow,\n deselectRow,\n selectAll,\n deselectAll,\n toggleAll,\n isSelected,\n selectRange,\n }\n}\n\n/**\n * Column resizing composable\n */\nexport function useColumnResize(\n initialWidths: Ref<Record<string, number>>,\n minWidth = 60,\n maxWidth = 600\n) {\n const columnWidths = ref<Record<string, number>>({ ...initialWidths.value })\n const isResizing = ref(false)\n const resizingColumn = ref<string | null>(null)\n\n function startResize(columnId: string, event: MouseEvent) {\n isResizing.value = true\n resizingColumn.value = columnId\n const startX = event.clientX\n const startWidth = columnWidths.value[columnId] || 150\n\n const handleMouseMove = (e: MouseEvent) => {\n const diff = e.clientX - startX\n const newWidth = Math.max(minWidth, Math.min(maxWidth, startWidth + diff))\n columnWidths.value = {\n ...columnWidths.value,\n [columnId]: newWidth,\n }\n }\n\n const handleMouseUp = () => {\n isResizing.value = false\n resizingColumn.value = null\n document.removeEventListener('mousemove', handleMouseMove)\n document.removeEventListener('mouseup', handleMouseUp)\n }\n\n document.addEventListener('mousemove', handleMouseMove)\n document.addEventListener('mouseup', handleMouseUp)\n }\n\n function resetColumnWidth(columnId: string) {\n if (initialWidths.value[columnId]) {\n columnWidths.value = {\n ...columnWidths.value,\n [columnId]: initialWidths.value[columnId],\n }\n }\n }\n\n function resetAllWidths() {\n columnWidths.value = { ...initialWidths.value }\n }\n\n return {\n columnWidths,\n isResizing,\n resizingColumn,\n startResize,\n resetColumnWidth,\n resetAllWidths,\n }\n}\n\n","<script setup lang=\"ts\">\n/**\n * Column Filter Dropdown Component\n * Shows unique values with checkboxes, search, and sort controls\n */\nimport { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'\nimport type { ColumnStats } from '@smallwebco/tinypivot-core'\n\nconst props = defineProps<{\n columnId: string\n columnName: string\n stats: ColumnStats\n selectedValues: string[]\n sortDirection: 'asc' | 'desc' | null\n}>()\n\nconst emit = defineEmits<{\n filter: [values: string[]]\n sort: [direction: 'asc' | 'desc' | null]\n close: []\n}>()\n\n// Local state\nconst searchQuery = ref('')\nconst dropdownRef = ref<HTMLDivElement>()\nconst searchInputRef = ref<HTMLInputElement>()\n\n// Get all possible values including blank\nconst allPossibleValues = computed(() => {\n const values = [...props.stats.uniqueValues]\n if (props.stats.nullCount > 0) {\n values.unshift('(blank)')\n }\n return values\n})\n\n// Initialize with selected values\nconst localSelected = ref<Set<string>>(new Set(props.selectedValues))\n\n// Include blank option if there are null values\nconst hasBlankValues = computed(() => props.stats.nullCount > 0)\n\n// Filtered unique values based on search\nconst filteredValues = computed(() => {\n const values = props.stats.uniqueValues\n if (!searchQuery.value)\n return values\n\n const query = searchQuery.value.toLowerCase()\n return values.filter(v => v.toLowerCase().includes(query))\n})\n\n// All values including blank\nconst allValues = computed(() => {\n const values = [...filteredValues.value]\n if (hasBlankValues.value && (!searchQuery.value || '(blank)'.includes(searchQuery.value.toLowerCase()))) {\n values.unshift('(blank)')\n }\n return values\n})\n\n// Check states\nconst isAllSelected = computed(() => {\n return allValues.value.every(v => localSelected.value.has(v))\n})\n\nconst isNoneSelected = computed(() => {\n return localSelected.value.size === 0\n})\n\n// Toggle single value\nfunction toggleValue(value: string) {\n if (localSelected.value.has(value)) {\n localSelected.value.delete(value)\n }\n else {\n localSelected.value.add(value)\n }\n localSelected.value = new Set(localSelected.value)\n}\n\n// Select all visible\nfunction selectAll() {\n for (const value of allValues.value) {\n localSelected.value.add(value)\n }\n localSelected.value = new Set(localSelected.value)\n}\n\n// Clear all\nfunction clearAll() {\n localSelected.value.clear()\n localSelected.value = new Set(localSelected.value)\n}\n\n// Apply filter\nfunction applyFilter() {\n if (localSelected.value.size === 0) {\n emit('filter', [])\n }\n else {\n emit('filter', Array.from(localSelected.value))\n }\n emit('close')\n}\n\n// Sort handlers\nfunction sortAscending() {\n emit('sort', props.sortDirection === 'asc' ? null : 'asc')\n}\n\nfunction sortDescending() {\n emit('sort', props.sortDirection === 'desc' ? null : 'desc')\n}\n\n// Clear filter only\nfunction clearFilter() {\n localSelected.value.clear()\n localSelected.value = new Set(localSelected.value)\n emit('filter', [])\n emit('close')\n}\n\n// Click outside handler\nfunction handleClickOutside(event: MouseEvent) {\n if (dropdownRef.value && !dropdownRef.value.contains(event.target as Node)) {\n emit('close')\n }\n}\n\n// Keyboard handling\nfunction handleKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape') {\n emit('close')\n }\n else if (event.key === 'Enter' && event.ctrlKey) {\n applyFilter()\n }\n}\n\n// Focus search on mount\nonMounted(() => {\n nextTick(() => {\n searchInputRef.value?.focus()\n })\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleKeydown)\n})\n\nonUnmounted(() => {\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleKeydown)\n})\n\n// Sync with props\nwatch(() => props.selectedValues, (newValues) => {\n localSelected.value = new Set(newValues)\n}, { immediate: true })\n</script>\n\n<template>\n <div ref=\"dropdownRef\" class=\"vpg-filter-dropdown\">\n <!-- Header -->\n <div class=\"vpg-filter-header\">\n <span class=\"vpg-filter-title\">{{ columnName }}</span>\n <span class=\"vpg-filter-count\">\n {{ stats.uniqueValues.length.toLocaleString() }} unique\n </span>\n </div>\n\n <!-- Sort Controls -->\n <div class=\"vpg-sort-controls\">\n <button\n class=\"vpg-sort-btn\"\n :class=\"{ active: sortDirection === 'asc' }\"\n title=\"Sort A to Z\"\n @click=\"sortAscending\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12\" />\n </svg>\n <span>A→Z</span>\n </button>\n <button\n class=\"vpg-sort-btn\"\n :class=\"{ active: sortDirection === 'desc' }\"\n title=\"Sort Z to A\"\n @click=\"sortDescending\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4\" />\n </svg>\n <span>Z→A</span>\n </button>\n </div>\n\n <div class=\"vpg-divider\" />\n\n <!-- Search -->\n <div class=\"vpg-search-container\">\n <svg class=\"vpg-search-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n <input\n ref=\"searchInputRef\"\n v-model=\"searchQuery\"\n type=\"text\"\n placeholder=\"Search values...\"\n class=\"vpg-search-input\"\n >\n <button v-if=\"searchQuery\" class=\"vpg-clear-search\" @click=\"searchQuery = ''\">\n ×\n </button>\n </div>\n\n <!-- Select All / Clear All -->\n <div class=\"vpg-bulk-actions\">\n <button class=\"vpg-bulk-btn\" @click=\"selectAll\">\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n Select All\n </button>\n <button class=\"vpg-bulk-btn\" @click=\"clearAll\">\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n Clear All\n </button>\n </div>\n\n <!-- Values List -->\n <div class=\"vpg-values-list\">\n <label\n v-for=\"value in allValues\"\n :key=\"value\"\n class=\"vpg-value-item\"\n :class=\"{ selected: localSelected.has(value) }\"\n >\n <input\n type=\"checkbox\"\n :checked=\"localSelected.has(value)\"\n class=\"vpg-value-checkbox\"\n @change=\"toggleValue(value)\"\n >\n <span class=\"vpg-value-text\" :class=\"{ 'vpg-blank': value === '(blank)' }\">\n {{ value }}\n </span>\n </label>\n\n <div v-if=\"allValues.length === 0\" class=\"vpg-no-results\">\n No matching values\n </div>\n </div>\n\n <!-- Footer -->\n <div class=\"vpg-filter-footer\">\n <button class=\"vpg-btn-clear\" @click=\"clearFilter\">\n Clear Filter\n </button>\n <button class=\"vpg-btn-apply\" @click=\"applyFilter\">\n Apply\n </button>\n </div>\n </div>\n</template>\n\n<style scoped>\n.vpg-filter-dropdown {\n position: absolute;\n z-index: 50;\n background: white;\n border-radius: 0.375rem;\n box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n border: 1px solid #e2e8f0;\n min-width: 220px;\n max-width: 280px;\n top: 100%;\n left: 0;\n margin-top: 2px;\n max-height: calc(100vh - 100px);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.vpg-filter-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.625rem;\n background: #f8fafc;\n border-bottom: 1px solid #e2e8f0;\n border-radius: 0.375rem 0.375rem 0 0;\n}\n\n.vpg-filter-title {\n font-size: 0.75rem;\n font-weight: 600;\n color: #1e293b;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.vpg-filter-count {\n font-size: 0.625rem;\n color: #64748b;\n}\n\n.vpg-sort-controls {\n display: flex;\n gap: 0.25rem;\n padding: 0.5rem;\n background: #f8fafc;\n}\n\n.vpg-sort-btn {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.25rem 0.5rem;\n font-size: 0.6875rem;\n font-weight: 500;\n border-radius: 0.25rem;\n color: #475569;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-sort-btn:hover {\n background: #e2e8f0;\n}\n\n.vpg-sort-btn.active {\n background: #e0e7ff;\n color: #4338ca;\n}\n\n.vpg-icon-sm {\n width: 0.75rem;\n height: 0.75rem;\n}\n\n.vpg-divider {\n height: 1px;\n background: #e2e8f0;\n}\n\n.vpg-search-container {\n position: relative;\n padding: 0.375rem 0.5rem;\n}\n\n.vpg-search-icon {\n position: absolute;\n left: 0.875rem;\n top: 50%;\n transform: translateY(-50%);\n width: 0.875rem;\n height: 0.875rem;\n color: #94a3b8;\n}\n\n.vpg-search-input {\n width: 100%;\n padding: 0.25rem 1.5rem 0.25rem 1.75rem;\n font-size: 0.75rem;\n border: 1px solid #cbd5e1;\n border-radius: 0.25rem;\n outline: none;\n}\n\n.vpg-search-input:focus {\n border-color: #6366f1;\n box-shadow: 0 0 0 1px #6366f1;\n}\n\n.vpg-clear-search {\n position: absolute;\n right: 0.875rem;\n top: 50%;\n transform: translateY(-50%);\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #94a3b8;\n font-size: 0.875rem;\n line-height: 1;\n background: transparent;\n border: none;\n cursor: pointer;\n}\n\n.vpg-clear-search:hover {\n color: #475569;\n}\n\n.vpg-bulk-actions {\n display: flex;\n gap: 0.375rem;\n padding: 0.25rem 0.5rem;\n border-bottom: 1px solid #f1f5f9;\n}\n\n.vpg-bulk-btn {\n display: flex;\n align-items: center;\n gap: 0.125rem;\n padding: 0.125rem 0.375rem;\n font-size: 0.625rem;\n font-weight: 500;\n color: #475569;\n background: transparent;\n border: none;\n border-radius: 0.25rem;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-bulk-btn:hover {\n color: #4f46e5;\n background: #eef2ff;\n}\n\n.vpg-values-list {\n max-height: 200px;\n overflow-y: auto;\n padding: 0.125rem 0.25rem;\n flex: 1;\n min-height: 0;\n}\n\n.vpg-value-item {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.375rem;\n border-radius: 0.25rem;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.vpg-value-item:hover {\n background: #f1f5f9;\n}\n\n.vpg-value-item.selected {\n background: #eef2ff;\n}\n\n.vpg-value-checkbox {\n width: 0.875rem;\n height: 0.875rem;\n accent-color: #4f46e5;\n border-radius: 0.25rem;\n}\n\n.vpg-value-text {\n font-size: 0.75rem;\n color: #334155;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n}\n\n.vpg-value-text.vpg-blank {\n font-style: italic;\n color: #94a3b8;\n}\n\n.vpg-no-results {\n text-align: center;\n padding: 0.75rem;\n font-size: 0.75rem;\n color: #94a3b8;\n}\n\n.vpg-filter-footer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0.5rem 0.625rem;\n background: #f8fafc;\n border-top: 1px solid #e2e8f0;\n border-radius: 0 0 0.375rem 0.375rem;\n}\n\n.vpg-btn-clear {\n padding: 0.25rem 0.5rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: #475569;\n background: transparent;\n border: none;\n border-radius: 0.25rem;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-btn-clear:hover {\n background: #e2e8f0;\n color: #1e293b;\n}\n\n.vpg-btn-apply {\n padding: 0.25rem 0.75rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: white;\n background: #4f46e5;\n border: none;\n border-radius: 0.25rem;\n cursor: pointer;\n transition: all 0.15s;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-btn-apply:hover {\n background: #4338ca;\n}\n</style>\n\n","<script setup lang=\"ts\">\n/**\n * Pivot Table Configuration Panel\n * Draggable fields with aggregation selection\n */\nimport { computed, ref } from 'vue'\nimport type { AggregationFunction, PivotValueField } from '@smallwebco/tinypivot-core'\nimport { useLicense } from '../composables/useLicense'\n\ninterface FieldStats {\n field: string\n type: 'string' | 'number' | 'date' | 'boolean' | 'mixed'\n uniqueCount: number\n isNumeric: boolean\n}\n\nconst props = defineProps<{\n availableFields: FieldStats[]\n rowFields: string[]\n columnFields: string[]\n valueFields: PivotValueField[]\n showRowTotals: boolean\n showColumnTotals: boolean\n}>()\n\nconst emit = defineEmits<{\n (e: 'update:showRowTotals', value: boolean): void\n (e: 'update:showColumnTotals', value: boolean): void\n (e: 'clearConfig'): void\n (e: 'autoSuggest'): void\n (e: 'dragStart', field: string, event: DragEvent): void\n (e: 'dragEnd'): void\n (e: 'updateAggregation', field: string, oldAgg: AggregationFunction, newAgg: AggregationFunction): void\n (e: 'addRowField', field: string): void\n (e: 'removeRowField', field: string): void\n (e: 'addColumnField', field: string): void\n (e: 'removeColumnField', field: string): void\n (e: 'addValueField', field: string, aggregation: AggregationFunction): void\n (e: 'removeValueField', field: string, aggregation: AggregationFunction): void\n}>()\n\nconst { isPro, showWatermark } = useLicense()\n\n// Aggregation options\nconst aggregationOptions: { value: AggregationFunction, label: string, symbol: string }[] = [\n { value: 'sum', label: 'Sum', symbol: 'Σ' },\n { value: 'count', label: 'Count', symbol: '#' },\n { value: 'avg', label: 'Avg', symbol: 'x̄' },\n { value: 'min', label: 'Min', symbol: '↓' },\n { value: 'max', label: 'Max', symbol: '↑' },\n { value: 'countDistinct', label: 'Unique', symbol: '◇' },\n]\n\nfunction getAggSymbol(agg: AggregationFunction): string {\n return aggregationOptions.find(a => a.value === agg)?.symbol || 'Σ'\n}\n\nfunction getAggLabel(agg: AggregationFunction): string {\n return aggregationOptions.find(a => a.value === agg)?.label || 'Sum'\n}\n\n// Assigned fields\nconst assignedFields = computed(() => {\n const rowSet = new Set(props.rowFields)\n const colSet = new Set(props.columnFields)\n const valueMap = new Map(props.valueFields.map(v => [v.field, v]))\n\n return props.availableFields\n .filter(f => rowSet.has(f.field) || colSet.has(f.field) || valueMap.has(f.field))\n .map(f => ({\n ...f,\n assignedTo: rowSet.has(f.field)\n ? 'row' as const\n : colSet.has(f.field)\n ? 'column' as const\n : 'value' as const,\n valueConfig: valueMap.get(f.field),\n }))\n})\n\n// Unassigned fields\nconst unassignedFields = computed(() => {\n const rowSet = new Set(props.rowFields)\n const colSet = new Set(props.columnFields)\n const valSet = new Set(props.valueFields.map(v => v.field))\n\n return props.availableFields.filter(f =>\n !rowSet.has(f.field) && !colSet.has(f.field) && !valSet.has(f.field),\n )\n})\n\nconst assignedCount = computed(() => assignedFields.value.length)\n\n// Field search\nconst fieldSearch = ref('')\nconst filteredUnassignedFields = computed(() => {\n if (!fieldSearch.value.trim())\n return unassignedFields.value\n const search = fieldSearch.value.toLowerCase().trim()\n return unassignedFields.value.filter(f => f.field.toLowerCase().includes(search))\n})\n\n// Field type icons\nfunction getFieldIcon(type: FieldStats['type']): string {\n switch (type) {\n case 'number': return '#'\n case 'date': return '📅'\n case 'boolean': return '✓'\n default: return 'Aa'\n }\n}\n\nfunction handleDragStart(field: string, event: DragEvent) {\n event.dataTransfer?.setData('text/plain', field)\n event.dataTransfer!.effectAllowed = 'move'\n emit('dragStart', field, event)\n}\n\nfunction handleDragEnd() {\n emit('dragEnd')\n}\n\nfunction handleAggregationChange(field: string, currentAgg: AggregationFunction, newAgg: AggregationFunction) {\n emit('updateAggregation', field, currentAgg, newAgg)\n}\n\nfunction toggleRowColumn(field: string, currentAssignment: 'row' | 'column') {\n if (currentAssignment === 'row') {\n emit('removeRowField', field)\n emit('addColumnField', field)\n }\n else {\n emit('removeColumnField', field)\n emit('addRowField', field)\n }\n}\n\nfunction removeField(field: string, assignedTo: 'row' | 'column' | 'value', valueConfig?: PivotValueField) {\n if (assignedTo === 'row') {\n emit('removeRowField', field)\n }\n else if (assignedTo === 'column') {\n emit('removeColumnField', field)\n }\n else if (valueConfig) {\n emit('removeValueField', field, valueConfig.aggregation)\n }\n}\n</script>\n\n<template>\n <div class=\"vpg-pivot-config\">\n <!-- Header -->\n <div class=\"vpg-config-header\">\n <h3 class=\"vpg-config-title\">\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 10h16M4 14h16M4 18h16\" />\n </svg>\n Fields\n </h3>\n <div class=\"vpg-header-actions\">\n <button\n v-if=\"assignedCount > 0\"\n class=\"vpg-action-btn vpg-clear-btn\"\n title=\"Clear all\"\n @click=\"emit('clearConfig')\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Assigned Fields -->\n <div v-if=\"assignedCount > 0\" class=\"vpg-assigned-section\">\n <div class=\"vpg-section-label\">Active</div>\n <div class=\"vpg-assigned-list\">\n <div\n v-for=\"field in assignedFields\"\n :key=\"field.field\"\n class=\"vpg-assigned-item\"\n :class=\"[`vpg-type-${field.assignedTo}`]\"\n :title=\"field.field\"\n draggable=\"true\"\n @dragstart=\"handleDragStart(field.field, $event)\"\n @dragend=\"handleDragEnd\"\n >\n <div class=\"vpg-item-main\">\n <span class=\"vpg-item-badge\" :class=\"field.assignedTo\">\n {{ field.assignedTo === 'row' ? 'R' : field.assignedTo === 'column' ? 'C' : getAggSymbol(field.valueConfig?.aggregation || 'sum') }}\n </span>\n <span class=\"vpg-item-name\">{{ field.field }}</span>\n </div>\n\n <div class=\"vpg-item-actions\">\n <button\n v-if=\"field.assignedTo === 'row' || field.assignedTo === 'column'\"\n class=\"vpg-toggle-btn\"\n :title=\"field.assignedTo === 'row' ? 'Move to Columns' : 'Move to Rows'\"\n @click.stop=\"toggleRowColumn(field.field, field.assignedTo)\"\n >\n <svg class=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4\" />\n </svg>\n </button>\n\n <select\n v-if=\"field.assignedTo === 'value' && field.valueConfig\"\n class=\"vpg-agg-select\"\n :value=\"field.valueConfig.aggregation\"\n @change=\"handleAggregationChange(field.field, field.valueConfig!.aggregation, ($event.target as HTMLSelectElement).value as AggregationFunction)\"\n @click.stop\n >\n <option v-for=\"agg in aggregationOptions\" :key=\"agg.value\" :value=\"agg.value\">\n {{ agg.symbol }} {{ agg.label }}\n </option>\n </select>\n\n <button\n class=\"vpg-remove-btn\"\n title=\"Remove\"\n @click.stop=\"removeField(field.field, field.assignedTo, field.valueConfig)\"\n >\n ×\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Unassigned Fields -->\n <div class=\"vpg-unassigned-section\">\n <div class=\"vpg-section-header\">\n <div class=\"vpg-section-label\">\n Available <span class=\"vpg-count\">{{ unassignedFields.length }}</span>\n </div>\n </div>\n\n <!-- Field Search -->\n <div class=\"vpg-field-search\">\n <svg class=\"vpg-search-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n <input\n v-model=\"fieldSearch\"\n type=\"text\"\n placeholder=\"Search fields...\"\n class=\"vpg-search-input\"\n >\n <button v-if=\"fieldSearch\" class=\"vpg-clear-search\" @click=\"fieldSearch = ''\">\n <svg class=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n <div class=\"vpg-field-list\">\n <div\n v-for=\"field in filteredUnassignedFields\"\n :key=\"field.field\"\n class=\"vpg-field-item\"\n :class=\"{ 'vpg-is-numeric': field.isNumeric }\"\n :title=\"field.field\"\n draggable=\"true\"\n @dragstart=\"handleDragStart(field.field, $event)\"\n @dragend=\"handleDragEnd\"\n >\n <span class=\"vpg-field-type-icon\" :title=\"field.type\">{{ getFieldIcon(field.type) }}</span>\n <span class=\"vpg-field-name\">{{ field.field }}</span>\n <span class=\"vpg-unique-count\">{{ field.uniqueCount }}</span>\n </div>\n <div v-if=\"filteredUnassignedFields.length === 0 && fieldSearch\" class=\"vpg-empty-hint\">\n No fields match \"{{ fieldSearch }}\"\n </div>\n <div v-else-if=\"unassignedFields.length === 0\" class=\"vpg-empty-hint\">\n All fields assigned\n </div>\n </div>\n </div>\n\n <!-- Options -->\n <div class=\"vpg-options-section\">\n <label class=\"vpg-option-toggle\">\n <input\n type=\"checkbox\"\n :checked=\"showRowTotals\"\n @change=\"emit('update:showRowTotals', ($event.target as HTMLInputElement).checked)\"\n >\n <span>Totals</span>\n </label>\n <button class=\"vpg-auto-btn\" @click=\"emit('autoSuggest')\">\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 10V3L4 14h7v7l9-11h-7z\" />\n </svg>\n Auto\n </button>\n </div>\n\n <!-- Pro Badge / Watermark -->\n <div v-if=\"showWatermark\" class=\"vpg-watermark\">\n <a href=\"https://tiny-pivot.com\" target=\"_blank\" rel=\"noopener\">\n TinyPivot\n </a>\n </div>\n </div>\n</template>\n\n<style scoped>\n.vpg-pivot-config {\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 0.5rem;\n box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n.vpg-config-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem 0.75rem;\n background: #f8fafc;\n border-bottom: 1px solid #e2e8f0;\n flex-shrink: 0;\n}\n\n.vpg-config-title {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n font-size: 0.75rem;\n font-weight: 600;\n color: #475569;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.vpg-icon {\n width: 1rem;\n height: 1rem;\n}\n\n.vpg-icon-sm {\n width: 0.875rem;\n height: 0.875rem;\n}\n\n.vpg-icon-xs {\n width: 0.75rem;\n height: 0.75rem;\n}\n\n.vpg-header-actions {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.vpg-action-btn {\n padding: 0.375rem;\n border-radius: 0.25rem;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-clear-btn {\n color: #94a3b8;\n}\n\n.vpg-clear-btn:hover {\n background: #fee2e2;\n color: #ef4444;\n}\n\n.vpg-section-label {\n font-size: 0.625rem;\n font-weight: 700;\n color: #94a3b8;\n text-transform: uppercase;\n letter-spacing: 0.1em;\n padding: 0.25rem 0.5rem;\n}\n\n.vpg-section-label .vpg-count {\n color: #cbd5e1;\n margin-left: 0.25rem;\n}\n\n.vpg-assigned-section {\n border-bottom: 1px solid #e2e8f0;\n background: linear-gradient(to bottom, #f8fafc, white);\n padding-bottom: 0.5rem;\n flex-shrink: 0;\n}\n\n.vpg-assigned-list {\n padding: 0 0.5rem;\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.vpg-assigned-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n padding: 0.375rem 0.5rem;\n border-radius: 0.5rem;\n font-size: 0.75rem;\n cursor: grab;\n transition: all 0.15s;\n}\n\n.vpg-assigned-item:active {\n cursor: grabbing;\n transform: scale(0.98);\n}\n\n.vpg-assigned-item.vpg-type-row {\n background: #eef2ff;\n border: 1px solid #c7d2fe;\n}\n\n.vpg-assigned-item.vpg-type-column {\n background: #f5f3ff;\n border: 1px solid #ddd6fe;\n}\n\n.vpg-assigned-item.vpg-type-value {\n background: #ecfdf5;\n border: 1px solid #a7f3d0;\n}\n\n.vpg-item-main {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n min-width: 0;\n}\n\n.vpg-item-badge {\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.625rem;\n font-weight: 700;\n border-radius: 0.25rem;\n}\n\n.vpg-item-badge.row {\n background: #c7d2fe;\n color: #4338ca;\n}\n\n.vpg-item-badge.column {\n background: #ddd6fe;\n color: #7c3aed;\n}\n\n.vpg-item-badge.value {\n background: #a7f3d0;\n color: #059669;\n}\n\n.vpg-item-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n color: #334155;\n}\n\n.vpg-item-actions {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n flex-shrink: 0;\n}\n\n.vpg-toggle-btn {\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 0.25rem;\n color: #94a3b8;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-toggle-btn:hover {\n background: white;\n color: #475569;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-agg-select {\n font-size: 0.625rem;\n background: white;\n border: 1px solid #a7f3d0;\n border-radius: 0.25rem;\n padding: 0.125rem 0.25rem;\n color: #059669;\n font-weight: 500;\n min-width: 70px;\n cursor: pointer;\n}\n\n.vpg-agg-select:focus {\n outline: none;\n box-shadow: 0 0 0 1px #10b981;\n}\n\n.vpg-remove-btn {\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n line-height: 1;\n color: #94a3b8;\n background: transparent;\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-remove-btn:hover {\n background: #fee2e2;\n color: #ef4444;\n}\n\n.vpg-unassigned-section {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n}\n\n.vpg-section-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 0.5rem;\n}\n\n.vpg-field-search {\n position: relative;\n margin: 0 0.5rem 0.5rem;\n}\n\n.vpg-search-icon {\n position: absolute;\n left: 0.5rem;\n top: 50%;\n transform: translateY(-50%);\n width: 0.875rem;\n height: 0.875rem;\n color: #94a3b8;\n pointer-events: none;\n}\n\n.vpg-search-input {\n width: 100%;\n padding: 0.375rem 1.75rem 0.375rem 1.75rem;\n font-size: 0.75rem;\n border: 1px solid #e2e8f0;\n border-radius: 0.375rem;\n background: white;\n color: #334155;\n}\n\n.vpg-search-input::placeholder {\n color: #94a3b8;\n}\n\n.vpg-search-input:focus {\n outline: none;\n box-shadow: 0 0 0 1px #6366f1;\n border-color: #6366f1;\n}\n\n.vpg-clear-search {\n position: absolute;\n right: 0.5rem;\n top: 50%;\n transform: translateY(-50%);\n padding: 0.125rem;\n border-radius: 0.25rem;\n color: #94a3b8;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-clear-search:hover {\n background: #f1f5f9;\n color: #475569;\n}\n\n.vpg-field-list {\n flex: 1;\n overflow-y: auto;\n padding: 0 0.5rem 0.5rem;\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.vpg-field-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.375rem 0.5rem;\n border-radius: 0.375rem;\n font-size: 0.75rem;\n cursor: grab;\n background: white;\n border: 1px solid #e2e8f0;\n color: #475569;\n transition: all 0.15s;\n}\n\n.vpg-field-item:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-field-item:active {\n cursor: grabbing;\n transform: scale(0.98);\n}\n\n.vpg-field-item.vpg-is-numeric {\n border-color: #bfdbfe;\n background: rgba(239, 246, 255, 0.3);\n}\n\n.vpg-field-type-icon {\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.625rem;\n font-weight: 700;\n background: #f1f5f9;\n border-radius: 0.25rem;\n color: #64748b;\n flex-shrink: 0;\n}\n\n.vpg-field-item.vpg-is-numeric .vpg-field-type-icon {\n background: #dbeafe;\n color: #2563eb;\n}\n\n.vpg-field-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n}\n\n.vpg-unique-count {\n font-size: 0.625rem;\n color: #94a3b8;\n font-variant-numeric: tabular-nums;\n flex-shrink: 0;\n}\n\n.vpg-empty-hint {\n font-size: 0.6875rem;\n color: #94a3b8;\n font-style: italic;\n text-align: center;\n padding: 1rem;\n}\n\n.vpg-options-section {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n border-top: 1px solid #f1f5f9;\n background: rgba(248, 250, 252, 0.5);\n flex-shrink: 0;\n}\n\n.vpg-option-toggle {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n font-size: 0.6875rem;\n color: #64748b;\n cursor: pointer;\n user-select: none;\n}\n\n.vpg-option-toggle input {\n width: 0.875rem;\n height: 0.875rem;\n border-radius: 0.25rem;\n accent-color: #10b981;\n cursor: pointer;\n}\n\n.vpg-auto-btn {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.25rem 0.5rem;\n font-size: 0.6875rem;\n font-weight: 500;\n border-radius: 0.25rem;\n background: #ecfdf5;\n color: #059669;\n border: 1px solid #a7f3d0;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-auto-btn:hover {\n background: #d1fae5;\n}\n\n.vpg-watermark {\n padding: 0.375rem 0.75rem;\n background: #f1f5f9;\n border-top: 1px solid #e2e8f0;\n text-align: center;\n flex-shrink: 0;\n}\n\n.vpg-watermark a {\n font-size: 0.625rem;\n color: #94a3b8;\n text-decoration: none;\n transition: color 0.15s;\n}\n\n.vpg-watermark a:hover {\n color: #64748b;\n}\n\n/* Scrollbar */\n.vpg-field-list::-webkit-scrollbar {\n width: 0.375rem;\n}\n\n.vpg-field-list::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.vpg-field-list::-webkit-scrollbar-thumb {\n background: #e2e8f0;\n border-radius: 9999px;\n}\n\n.vpg-field-list::-webkit-scrollbar-thumb:hover {\n background: #cbd5e1;\n}\n\n</style>\n\n<style>\n/* Dark mode - PivotConfig */\n.vpg-theme-dark .vpg-pivot-config {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-config-header {\n background: #0f172a;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-config-title {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-clear-btn {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-clear-btn:hover {\n background: rgba(239, 68, 68, 0.2);\n color: #f87171;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-section-label {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-section-label .vpg-count {\n color: #475569;\n}\n\n.vpg-theme-dark .vpg-assigned-section {\n border-color: #334155;\n background: linear-gradient(to bottom, #0f172a, #1e293b);\n}\n\n.vpg-theme-dark .vpg-assigned-item.vpg-type-row {\n background: rgba(99, 102, 241, 0.15);\n border-color: rgba(99, 102, 241, 0.3);\n}\n\n.vpg-theme-dark .vpg-assigned-item.vpg-type-column {\n background: rgba(139, 92, 246, 0.15);\n border-color: rgba(139, 92, 246, 0.3);\n}\n\n.vpg-theme-dark .vpg-assigned-item.vpg-type-value {\n background: rgba(16, 185, 129, 0.15);\n border-color: rgba(16, 185, 129, 0.3);\n}\n\n.vpg-theme-dark .vpg-item-badge.row {\n background: rgba(99, 102, 241, 0.3);\n color: #a5b4fc;\n}\n\n.vpg-theme-dark .vpg-item-badge.column {\n background: rgba(139, 92, 246, 0.3);\n color: #c4b5fd;\n}\n\n.vpg-theme-dark .vpg-item-badge.value {\n background: rgba(16, 185, 129, 0.3);\n color: #6ee7b7;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-item-name {\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-toggle-btn {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-toggle-btn:hover {\n background: #334155;\n color: #cbd5e1;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-agg-select {\n background: #0f172a;\n border-color: rgba(16, 185, 129, 0.3);\n color: #6ee7b7;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-agg-select:focus {\n box-shadow: 0 0 0 1px #10b981;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-remove-btn {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-remove-btn:hover {\n background: rgba(239, 68, 68, 0.2);\n color: #f87171;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-search-input {\n background: #0f172a;\n border-color: #334155;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-search-input::placeholder {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-search-input:focus {\n border-color: #6366f1;\n box-shadow: 0 0 0 1px #6366f1;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-search-icon {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-clear-search:hover {\n background: #334155;\n color: #cbd5e1;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-item {\n background: #0f172a;\n border-color: #334155;\n color: #cbd5e1;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-item:hover {\n border-color: #475569;\n background: #1e293b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-item.vpg-is-numeric {\n border-color: rgba(59, 130, 246, 0.3);\n background: rgba(59, 130, 246, 0.1);\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-type-icon {\n background: #334155;\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-item.vpg-is-numeric .vpg-field-type-icon {\n background: rgba(59, 130, 246, 0.3);\n color: #60a5fa;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-unique-count {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-empty-hint {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-options-section {\n border-color: #334155;\n background: rgba(15, 23, 42, 0.5);\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-option-toggle {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-auto-btn {\n background: rgba(16, 185, 129, 0.15);\n color: #6ee7b7;\n border-color: rgba(16, 185, 129, 0.3);\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-auto-btn:hover {\n background: rgba(16, 185, 129, 0.25);\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-watermark {\n background: #0f172a;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-watermark a {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-watermark a:hover {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-list::-webkit-scrollbar-thumb {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-list::-webkit-scrollbar-thumb:hover {\n background: #475569;\n}\n</style>\n\n","<script setup lang=\"ts\">\n/**\n * Pivot Table Skeleton + Data Display\n * Visual layout for pivot configuration and results\n */\nimport { computed, ref } from 'vue'\nimport type { AggregationFunction, PivotResult, PivotValueField } from '@smallwebco/tinypivot-core'\nimport { useLicense } from '../composables/useLicense'\n\ninterface ActiveFilter {\n column: string\n valueCount: number\n values: string[]\n}\n\nconst props = defineProps<{\n rowFields: string[]\n columnFields: string[]\n valueFields: PivotValueField[]\n isConfigured: boolean\n draggingField: string | null\n pivotResult: PivotResult | null\n fontSize?: 'xs' | 'sm' | 'base'\n activeFilters?: ActiveFilter[] | null\n totalRowCount?: number\n filteredRowCount?: number\n}>()\n\nconst emit = defineEmits<{\n (e: 'addRowField', field: string): void\n (e: 'removeRowField', field: string): void\n (e: 'addColumnField', field: string): void\n (e: 'removeColumnField', field: string): void\n (e: 'addValueField', field: string, aggregation: AggregationFunction): void\n (e: 'removeValueField', field: string, aggregation: AggregationFunction): void\n (e: 'updateAggregation', field: string, oldAgg: AggregationFunction, newAgg: AggregationFunction): void\n (e: 'reorderRowFields', fields: string[]): void\n (e: 'reorderColumnFields', fields: string[]): void\n}>()\n\nconst { showWatermark, canUsePivot, isDemo } = useLicense()\n\n// Drag state\nconst dragOverArea = ref<'row' | 'column' | 'value' | null>(null)\n\n// Reorder drag state\nconst reorderDragSource = ref<{ zone: 'row' | 'column', index: number } | null>(null)\nconst reorderDropTarget = ref<{ zone: 'row' | 'column', index: number } | null>(null)\n\n// Aggregation labels\nconst aggregationLabels: Record<AggregationFunction, string> = {\n sum: 'Sum',\n count: 'Count',\n avg: 'Average',\n min: 'Min',\n max: 'Max',\n countDistinct: 'Count Distinct',\n}\n\nfunction getAggregationLabel(fn: AggregationFunction): string {\n return aggregationLabels[fn]\n}\n\nfunction getAggSymbol(agg: AggregationFunction): string {\n const symbols: Record<AggregationFunction, string> = {\n sum: 'Σ',\n count: '#',\n avg: 'x̄',\n min: '↓',\n max: '↑',\n countDistinct: '◇',\n }\n return symbols[agg] || 'Σ'\n}\n\n// Font size\nconst currentFontSize = ref(props.fontSize || 'xs')\nconst fontSizeOptions = [\n { value: 'xs', label: 'S' },\n { value: 'sm', label: 'M' },\n { value: 'base', label: 'L' },\n] as const\n\n// Filter status\nconst hasActiveFilters = computed(() => props.activeFilters && props.activeFilters.length > 0)\nconst filterSummary = computed(() => {\n if (!props.activeFilters || props.activeFilters.length === 0) return ''\n const columns = props.activeFilters.map(f => f.column).join(', ')\n return columns\n})\n\n// Detailed filter tooltip\nconst filterTooltipDetails = computed(() => {\n if (!props.activeFilters || props.activeFilters.length === 0) return []\n return props.activeFilters.map(f => {\n const maxDisplay = 5\n const displayValues = f.values.slice(0, maxDisplay)\n const remaining = f.values.length - maxDisplay\n return {\n column: f.column,\n values: displayValues,\n remaining: remaining > 0 ? remaining : 0,\n }\n })\n})\n\n// Show/hide tooltip\nconst showFilterTooltip = ref(false)\n\n// Sorting\ntype SortDirection = 'asc' | 'desc'\ntype SortTarget = 'row' | number\nconst sortDirection = ref<SortDirection>('asc')\nconst sortTarget = ref<SortTarget>('row')\n\nfunction toggleSort(target: SortTarget = 'row') {\n if (sortTarget.value === target) {\n sortDirection.value = sortDirection.value === 'asc' ? 'desc' : 'asc'\n }\n else {\n sortTarget.value = target\n sortDirection.value = 'asc'\n }\n}\n\n// Sorted row indices\nconst sortedRowIndices = computed(() => {\n if (!props.pivotResult)\n return []\n\n const indices = props.pivotResult.rowHeaders.map((_, i) => i)\n const headers = props.pivotResult.rowHeaders\n const data = props.pivotResult.data\n\n indices.sort((a, b) => {\n let cmp: number\n\n if (sortTarget.value === 'row') {\n const aHeader = headers[a]?.join(' / ') || ''\n const bHeader = headers[b]?.join(' / ') || ''\n cmp = aHeader.localeCompare(bHeader, undefined, { numeric: true, sensitivity: 'base' })\n }\n else {\n const colIdx = sortTarget.value as number\n const aVal = data[a]?.[colIdx]?.value ?? null\n const bVal = data[b]?.[colIdx]?.value ?? null\n\n if (aVal === null && bVal === null)\n cmp = 0\n else if (aVal === null)\n cmp = 1\n else if (bVal === null)\n cmp = -1\n else cmp = aVal - bVal\n }\n\n return sortDirection.value === 'asc' ? cmp : -cmp\n })\n\n return indices\n})\n\n// Column headers\nconst columnHeaderCells = computed(() => {\n if (!props.pivotResult || props.pivotResult.headers.length === 0) {\n return [props.valueFields.map(vf => ({\n label: `${vf.field} (${getAggregationLabel(vf.aggregation)})`,\n colspan: 1,\n }))]\n }\n\n const result: Array<Array<{ label: string, colspan: number }>> = []\n\n for (let level = 0; level < props.pivotResult.headers.length; level++) {\n const headerRow = props.pivotResult.headers[level]\n const cells: Array<{ label: string, colspan: number }> = []\n\n let i = 0\n while (i < headerRow.length) {\n const value = headerRow[i]\n let colspan = 1\n\n while (i + colspan < headerRow.length && headerRow[i + colspan] === value) {\n colspan++\n }\n\n cells.push({ label: value, colspan })\n i += colspan\n }\n\n result.push(cells)\n }\n\n return result\n})\n\n// Selection for copy support\nconst selectedCell = ref<{ row: number, col: number } | null>(null)\nfunction handleCellClick(rowIndex: number, colIndex: number) {\n selectedCell.value = { row: rowIndex, col: colIndex }\n}\nfunction isCellSelected(rowIndex: number, colIndex: number): boolean {\n return selectedCell.value?.row === rowIndex && selectedCell.value?.col === colIndex\n}\n\n// Drag handlers\nfunction handleDragOver(area: 'row' | 'column' | 'value', event: DragEvent) {\n event.preventDefault()\n event.dataTransfer!.dropEffect = 'move'\n dragOverArea.value = area\n}\n\nfunction handleDragLeave() {\n dragOverArea.value = null\n}\n\nfunction handleDrop(area: 'row' | 'column' | 'value', event: DragEvent) {\n event.preventDefault()\n const field = event.dataTransfer?.getData('text/plain')\n\n // Skip if this is a reorder operation (handled by chip drop)\n if (!field || field.startsWith('reorder:')) {\n dragOverArea.value = null\n return\n }\n\n if (props.rowFields.includes(field))\n emit('removeRowField', field)\n if (props.columnFields.includes(field))\n emit('removeColumnField', field)\n const existingValue = props.valueFields.find(v => v.field === field)\n if (existingValue)\n emit('removeValueField', field, existingValue.aggregation)\n\n switch (area) {\n case 'row':\n emit('addRowField', field)\n break\n case 'column':\n emit('addColumnField', field)\n break\n case 'value':\n emit('addValueField', field, 'sum')\n break\n }\n dragOverArea.value = null\n}\n\n// Reorder handlers for chips within zones\nfunction handleChipDragStart(zone: 'row' | 'column', index: number, event: DragEvent) {\n reorderDragSource.value = { zone, index }\n event.dataTransfer!.effectAllowed = 'move'\n event.dataTransfer!.setData('text/plain', `reorder:${zone}:${index}`)\n // Add a slight delay to ensure visual feedback\n requestAnimationFrame(() => {\n dragOverArea.value = null\n })\n}\n\nfunction handleChipDragEnd() {\n reorderDragSource.value = null\n reorderDropTarget.value = null\n}\n\nfunction handleChipDragOver(zone: 'row' | 'column', index: number, event: DragEvent) {\n event.preventDefault()\n // Only handle reorder within same zone\n if (reorderDragSource.value && reorderDragSource.value.zone === zone) {\n event.dataTransfer!.dropEffect = 'move'\n reorderDropTarget.value = { zone, index }\n }\n}\n\nfunction handleChipDragLeave() {\n reorderDropTarget.value = null\n}\n\nfunction handleChipDrop(zone: 'row' | 'column', targetIndex: number, event: DragEvent) {\n event.preventDefault()\n event.stopPropagation()\n \n if (!reorderDragSource.value || reorderDragSource.value.zone !== zone) {\n return\n }\n \n const sourceIndex = reorderDragSource.value.index\n if (sourceIndex === targetIndex) {\n reorderDragSource.value = null\n reorderDropTarget.value = null\n return\n }\n \n // Create reordered array\n const fields = zone === 'row' ? [...props.rowFields] : [...props.columnFields]\n const [movedField] = fields.splice(sourceIndex, 1)\n fields.splice(targetIndex, 0, movedField)\n \n // Emit reorder event\n if (zone === 'row') {\n emit('reorderRowFields', fields)\n } else {\n emit('reorderColumnFields', fields)\n }\n \n reorderDragSource.value = null\n reorderDropTarget.value = null\n}\n\nfunction isChipDragSource(zone: 'row' | 'column', index: number): boolean {\n return reorderDragSource.value?.zone === zone && reorderDragSource.value?.index === index\n}\n\nfunction isChipDropTarget(zone: 'row' | 'column', index: number): boolean {\n return reorderDropTarget.value?.zone === zone && reorderDropTarget.value?.index === index\n}\n\n// Column width\nconst rowHeaderWidth = ref(180)\nconst dataColWidth = ref(80)\n</script>\n\n<template>\n <div\n class=\"vpg-pivot-skeleton\"\n :class=\"[\n `vpg-font-${currentFontSize}`,\n { 'vpg-is-dragging': draggingField },\n ]\"\n >\n <!-- Header Bar -->\n <div class=\"vpg-skeleton-header\">\n <div class=\"vpg-skeleton-title\">\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\" />\n </svg>\n <span>Pivot Table</span>\n </div>\n\n <div class=\"vpg-header-right\">\n <!-- Filter indicator with tooltip -->\n <div\n v-if=\"hasActiveFilters\"\n class=\"vpg-filter-indicator\"\n @mouseenter=\"showFilterTooltip = true\"\n @mouseleave=\"showFilterTooltip = false\"\n >\n <svg class=\"vpg-filter-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\" />\n </svg>\n <span class=\"vpg-filter-text\">\n Filtered: <strong>{{ filterSummary }}</strong>\n <span v-if=\"filteredRowCount !== undefined && totalRowCount !== undefined\" class=\"vpg-filter-count\">\n ({{ filteredRowCount.toLocaleString() }} of {{ totalRowCount.toLocaleString() }} rows)\n </span>\n </span>\n\n <!-- Tooltip -->\n <div v-if=\"showFilterTooltip\" class=\"vpg-filter-tooltip\">\n <div class=\"vpg-tooltip-header\">Active Filters</div>\n <div v-for=\"filter in filterTooltipDetails\" :key=\"filter.column\" class=\"vpg-tooltip-filter\">\n <div class=\"vpg-tooltip-column\">{{ filter.column }}</div>\n <div class=\"vpg-tooltip-values\">\n <span v-for=\"(val, idx) in filter.values\" :key=\"idx\" class=\"vpg-tooltip-value\">\n {{ val }}\n </span>\n <span v-if=\"filter.remaining > 0\" class=\"vpg-tooltip-more\">\n +{{ filter.remaining }} more\n </span>\n </div>\n </div>\n <div v-if=\"filteredRowCount !== undefined && totalRowCount !== undefined\" class=\"vpg-tooltip-summary\">\n Showing {{ filteredRowCount.toLocaleString() }} of {{ totalRowCount.toLocaleString() }} rows\n </div>\n </div>\n </div>\n\n <div v-if=\"isConfigured\" class=\"vpg-config-summary\">\n <span class=\"vpg-summary-badge vpg-rows\">{{ rowFields.length }} row{{ rowFields.length !== 1 ? 's' : '' }}</span>\n <span class=\"vpg-summary-badge vpg-cols\">{{ columnFields.length }} col{{ columnFields.length !== 1 ? 's' : '' }}</span>\n <span class=\"vpg-summary-badge vpg-vals\">{{ valueFields.length }} val{{ valueFields.length !== 1 ? 's' : '' }}</span>\n </div>\n\n <div v-if=\"isConfigured && pivotResult\" class=\"vpg-font-size-toggle\">\n <button\n v-for=\"opt in fontSizeOptions\"\n :key=\"opt.value\"\n class=\"vpg-font-size-btn\"\n :class=\"{ active: currentFontSize === opt.value }\"\n @click=\"currentFontSize = opt.value\"\n >\n {{ opt.label }}\n </button>\n </div>\n </div>\n </div>\n\n <!-- License Required Message -->\n <div v-if=\"!canUsePivot\" class=\"vpg-pro-required\">\n <div class=\"vpg-pro-content\">\n <svg class=\"vpg-pro-icon\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\" />\n </svg>\n <h3>Pro Feature</h3>\n <p>Pivot Table functionality requires a Pro license.</p>\n <a href=\"https://tiny-pivot.com/#pricing\" target=\"_blank\" class=\"vpg-pro-link\">\n Get Pro License →\n </a>\n </div>\n </div>\n\n <!-- Content when licensed -->\n <template v-else>\n <!-- Config Bar -->\n <div class=\"vpg-config-bar\">\n <!-- Row drop zone -->\n <div\n class=\"vpg-drop-zone vpg-row-zone\"\n :class=\"{ 'vpg-drag-over': dragOverArea === 'row' }\"\n @dragover=\"handleDragOver('row', $event)\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop('row', $event)\"\n >\n <div class=\"vpg-zone-header\">\n <span class=\"vpg-zone-icon vpg-row-icon\">↓</span>\n <span class=\"vpg-zone-label\">Rows</span>\n </div>\n <div class=\"vpg-zone-chips\">\n <div\n v-for=\"(field, idx) in rowFields\"\n :key=\"field\"\n class=\"vpg-mini-chip vpg-row-chip\"\n :class=\"{\n 'vpg-chip-dragging': isChipDragSource('row', idx),\n 'vpg-chip-drop-target': isChipDropTarget('row', idx),\n }\"\n draggable=\"true\"\n @dragstart=\"handleChipDragStart('row', idx, $event)\"\n @dragend=\"handleChipDragEnd\"\n @dragover=\"handleChipDragOver('row', idx, $event)\"\n @dragleave=\"handleChipDragLeave\"\n @drop=\"handleChipDrop('row', idx, $event)\"\n >\n <span class=\"vpg-drag-handle\">⋮⋮</span>\n <span class=\"vpg-mini-name\">{{ field }}</span>\n <button class=\"vpg-mini-remove\" @click.stop=\"emit('removeRowField', field)\">×</button>\n </div>\n <span v-if=\"rowFields.length === 0\" class=\"vpg-zone-hint\">Drop here</span>\n </div>\n </div>\n\n <!-- Column drop zone -->\n <div\n class=\"vpg-drop-zone vpg-column-zone\"\n :class=\"{ 'vpg-drag-over': dragOverArea === 'column' }\"\n @dragover=\"handleDragOver('column', $event)\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop('column', $event)\"\n >\n <div class=\"vpg-zone-header\">\n <span class=\"vpg-zone-icon vpg-column-icon\">→</span>\n <span class=\"vpg-zone-label\">Columns</span>\n </div>\n <div class=\"vpg-zone-chips\">\n <div\n v-for=\"(field, idx) in columnFields\"\n :key=\"field\"\n class=\"vpg-mini-chip vpg-column-chip\"\n :class=\"{\n 'vpg-chip-dragging': isChipDragSource('column', idx),\n 'vpg-chip-drop-target': isChipDropTarget('column', idx),\n }\"\n draggable=\"true\"\n @dragstart=\"handleChipDragStart('column', idx, $event)\"\n @dragend=\"handleChipDragEnd\"\n @dragover=\"handleChipDragOver('column', idx, $event)\"\n @dragleave=\"handleChipDragLeave\"\n @drop=\"handleChipDrop('column', idx, $event)\"\n >\n <span class=\"vpg-drag-handle\">⋮⋮</span>\n <span class=\"vpg-mini-name\">{{ field }}</span>\n <button class=\"vpg-mini-remove\" @click.stop=\"emit('removeColumnField', field)\">×</button>\n </div>\n <span v-if=\"columnFields.length === 0\" class=\"vpg-zone-hint\">Drop here</span>\n </div>\n </div>\n\n <!-- Values drop zone -->\n <div\n class=\"vpg-drop-zone vpg-value-zone\"\n :class=\"{ 'vpg-drag-over': dragOverArea === 'value' }\"\n @dragover=\"handleDragOver('value', $event)\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop('value', $event)\"\n >\n <div class=\"vpg-zone-header\">\n <span class=\"vpg-zone-icon vpg-value-icon\">Σ</span>\n <span class=\"vpg-zone-label\">Values</span>\n </div>\n <div class=\"vpg-zone-chips\">\n <div\n v-for=\"vf in valueFields\"\n :key=\"`${vf.field}-${vf.aggregation}`\"\n class=\"vpg-mini-chip vpg-value-chip\"\n >\n <span class=\"vpg-agg-symbol\">{{ getAggSymbol(vf.aggregation) }}</span>\n <span class=\"vpg-mini-name\">{{ vf.field }}</span>\n <button class=\"vpg-mini-remove\" @click=\"emit('removeValueField', vf.field, vf.aggregation)\">×</button>\n </div>\n <span v-if=\"valueFields.length === 0\" class=\"vpg-zone-hint\">Drop numeric</span>\n </div>\n </div>\n </div>\n\n <!-- Placeholder when not configured -->\n <div v-if=\"!isConfigured || !pivotResult\" class=\"vpg-placeholder\">\n <div class=\"vpg-placeholder-content\">\n <svg class=\"vpg-placeholder-icon\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n <span class=\"vpg-placeholder-text\">\n <template v-if=\"valueFields.length === 0\">\n Add a <strong>Values</strong> field to see your pivot table\n </template>\n <template v-else-if=\"rowFields.length === 0 && columnFields.length === 0\">\n Add <strong>Row</strong> or <strong>Column</strong> fields to group your data\n </template>\n <template v-else>\n Your pivot table will appear here\n </template>\n </span>\n </div>\n </div>\n\n <!-- Data Table -->\n <div v-else class=\"vpg-table-container\">\n <table class=\"vpg-pivot-table\">\n <thead>\n <tr v-for=\"(headerRow, levelIdx) in columnHeaderCells\" :key=\"`header-${levelIdx}`\" class=\"vpg-column-header-row\">\n <th\n v-if=\"levelIdx === 0\"\n class=\"vpg-row-header-label\"\n :rowspan=\"columnHeaderCells.length\"\n :style=\"{ width: `${rowHeaderWidth}px` }\"\n @click=\"toggleSort('row')\"\n >\n <div class=\"vpg-header-content\">\n <span>{{ rowFields.join(' / ') || 'Rows' }}</span>\n <span class=\"vpg-sort-indicator\" :class=\"{ active: sortTarget === 'row' }\">\n {{ sortTarget === 'row' ? (sortDirection === 'asc' ? '↑' : '↓') : '⇅' }}\n </span>\n </div>\n </th>\n <th\n v-for=\"(cell, idx) in headerRow\"\n :key=\"idx\"\n class=\"vpg-column-header-cell\"\n :colspan=\"cell.colspan\"\n :style=\"{ width: `${dataColWidth * cell.colspan}px` }\"\n @click=\"levelIdx === columnHeaderCells.length - 1 && toggleSort(idx)\"\n >\n <div class=\"vpg-header-content\">\n <span>{{ cell.label }}</span>\n <span v-if=\"levelIdx === columnHeaderCells.length - 1\" class=\"vpg-sort-indicator\" :class=\"{ active: sortTarget === idx }\">\n {{ sortTarget === idx ? (sortDirection === 'asc' ? '↑' : '↓') : '⇅' }}\n </span>\n </div>\n </th>\n <th\n v-if=\"pivotResult.rowTotals.length > 0 && levelIdx === 0\"\n class=\"vpg-total-header\"\n :rowspan=\"columnHeaderCells.length\"\n >\n Total\n </th>\n </tr>\n </thead>\n\n <tbody>\n <tr v-for=\"sortedIdx in sortedRowIndices\" :key=\"sortedIdx\" class=\"vpg-data-row\">\n <th\n class=\"vpg-row-header-cell\"\n :style=\"{ width: `${rowHeaderWidth}px` }\"\n >\n <span v-for=\"(val, idx) in pivotResult.rowHeaders[sortedIdx]\" :key=\"idx\" class=\"vpg-row-value\">\n {{ val }}\n </span>\n </th>\n\n <td\n v-for=\"(cell, colIdx) in pivotResult.data[sortedIdx]\"\n :key=\"colIdx\"\n class=\"vpg-data-cell\"\n :class=\"[\n isCellSelected(sortedIdx, colIdx) && 'selected',\n cell.value === null && 'vpg-is-null',\n ]\"\n :style=\"{ width: `${dataColWidth}px` }\"\n @click=\"handleCellClick(sortedIdx, colIdx)\"\n >\n {{ cell.formattedValue }}\n </td>\n\n <td v-if=\"pivotResult.rowTotals[sortedIdx]\" class=\"vpg-data-cell vpg-total-cell\">\n {{ pivotResult.rowTotals[sortedIdx].formattedValue }}\n </td>\n </tr>\n\n <tr v-if=\"pivotResult.columnTotals.length > 0\" class=\"vpg-totals-row\">\n <th class=\"vpg-row-header-cell vpg-total-label\" :style=\"{ width: `${rowHeaderWidth}px` }\">\n Total\n </th>\n <td\n v-for=\"(cell, colIdx) in pivotResult.columnTotals\"\n :key=\"colIdx\"\n class=\"vpg-data-cell vpg-total-cell\"\n :style=\"{ width: `${dataColWidth}px` }\"\n >\n {{ cell.formattedValue }}\n </td>\n <td v-if=\"pivotResult.rowTotals.length > 0\" class=\"vpg-data-cell vpg-grand-total-cell\">\n {{ pivotResult.grandTotal.formattedValue }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Footer -->\n <div v-if=\"isConfigured && pivotResult\" class=\"vpg-skeleton-footer\">\n <span>{{ pivotResult.rowHeaders.length }} rows × {{ pivotResult.data[0]?.length || 0 }} columns</span>\n </div>\n </template>\n\n <!-- Watermark / Demo Banner -->\n <div v-if=\"showWatermark && canUsePivot\" class=\"vpg-watermark\" :class=\"{ 'vpg-demo-mode': isDemo }\">\n <template v-if=\"isDemo\">\n <span class=\"vpg-demo-badge\">DEMO</span>\n <span>Pro features unlocked for evaluation</span>\n <a href=\"https://tiny-pivot.com/#pricing\" target=\"_blank\" rel=\"noopener\" class=\"vpg-get-pro\">\n Get Pro License →\n </a>\n </template>\n <template v-else>\n <a href=\"https://tiny-pivot.com\" target=\"_blank\" rel=\"noopener\">\n Powered by TinyPivot\n </a>\n </template>\n </div>\n </div>\n</template>\n\n<style scoped>\n.vpg-pivot-skeleton {\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 0.75rem;\n box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.vpg-pivot-skeleton.vpg-is-dragging {\n box-shadow: 0 0 0 2px #10b981;\n}\n\n.vpg-icon {\n width: 1rem;\n height: 1rem;\n}\n\n/* Header */\n.vpg-skeleton-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem 1rem;\n background: linear-gradient(to right, #ecfdf5, #f0fdfa);\n border-bottom: 1px solid #e2e8f0;\n flex-shrink: 0;\n}\n\n.vpg-skeleton-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.75rem;\n font-weight: 600;\n color: #475569;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.vpg-header-right {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.vpg-config-summary {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.vpg-summary-badge {\n padding: 0.125rem 0.375rem;\n font-size: 0.625rem;\n font-weight: 600;\n border-radius: 0.25rem;\n}\n\n.vpg-summary-badge.vpg-rows {\n background: #e0e7ff;\n color: #4f46e5;\n}\n\n.vpg-summary-badge.vpg-cols {\n background: #ede9fe;\n color: #7c3aed;\n}\n\n.vpg-summary-badge.vpg-vals {\n background: #d1fae5;\n color: #059669;\n}\n\n/* Filter indicator */\n.vpg-filter-indicator {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.625rem;\n background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);\n border: 1px solid #f59e0b;\n border-radius: 0.375rem;\n font-size: 0.6875rem;\n color: #92400e;\n box-shadow: 0 1px 2px rgba(245, 158, 11, 0.15);\n cursor: help;\n}\n\n.vpg-filter-icon {\n width: 0.875rem;\n height: 0.875rem;\n flex-shrink: 0;\n color: #d97706;\n}\n\n.vpg-filter-text {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n white-space: nowrap;\n}\n\n.vpg-filter-text strong {\n font-weight: 600;\n color: #78350f;\n max-width: 150px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.vpg-filter-count {\n color: #a16207;\n font-size: 0.625rem;\n}\n\n/* Filter tooltip */\n.vpg-filter-tooltip {\n position: absolute;\n top: calc(100% + 0.5rem);\n right: 0;\n min-width: 220px;\n max-width: 320px;\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 0.5rem;\n box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1);\n z-index: 100;\n overflow: hidden;\n}\n\n.vpg-tooltip-header {\n padding: 0.5rem 0.75rem;\n font-size: 0.6875rem;\n font-weight: 700;\n color: #475569;\n background: #f8fafc;\n border-bottom: 1px solid #e2e8f0;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.vpg-tooltip-filter {\n padding: 0.5rem 0.75rem;\n border-bottom: 1px solid #f1f5f9;\n}\n\n.vpg-tooltip-filter:last-of-type {\n border-bottom: none;\n}\n\n.vpg-tooltip-column {\n font-size: 0.6875rem;\n font-weight: 600;\n color: #1e293b;\n margin-bottom: 0.375rem;\n}\n\n.vpg-tooltip-values {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n}\n\n.vpg-tooltip-value {\n padding: 0.125rem 0.375rem;\n font-size: 0.625rem;\n background: #fef3c7;\n color: #92400e;\n border-radius: 0.25rem;\n border: 1px solid #fde68a;\n}\n\n.vpg-tooltip-more {\n padding: 0.125rem 0.375rem;\n font-size: 0.625rem;\n color: #64748b;\n font-style: italic;\n}\n\n.vpg-tooltip-summary {\n padding: 0.5rem 0.75rem;\n font-size: 0.625rem;\n color: #64748b;\n background: #f8fafc;\n border-top: 1px solid #e2e8f0;\n text-align: center;\n}\n\n.vpg-font-size-toggle {\n display: flex;\n background: white;\n border-radius: 0.25rem;\n border: 1px solid #e2e8f0;\n overflow: hidden;\n}\n\n.vpg-font-size-btn {\n padding: 0.125rem 0.5rem;\n font-size: 0.625rem;\n font-weight: 500;\n color: #64748b;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-font-size-btn:hover {\n background: #f1f5f9;\n}\n\n.vpg-font-size-btn.active {\n background: #10b981;\n color: white;\n}\n\n/* Pro Required */\n.vpg-pro-required {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #fef3c7, #fde68a);\n}\n\n.vpg-pro-content {\n text-align: center;\n padding: 2rem;\n}\n\n.vpg-pro-icon {\n width: 3rem;\n height: 3rem;\n color: #d97706;\n margin: 0 auto 1rem;\n}\n\n.vpg-pro-content h3 {\n font-size: 1.25rem;\n font-weight: 600;\n color: #92400e;\n margin-bottom: 0.5rem;\n}\n\n.vpg-pro-content p {\n font-size: 0.875rem;\n color: #a16207;\n margin-bottom: 1rem;\n}\n\n.vpg-pro-link {\n display: inline-block;\n padding: 0.5rem 1rem;\n background: #f59e0b;\n color: white;\n font-weight: 500;\n border-radius: 0.375rem;\n text-decoration: none;\n transition: background 0.15s;\n}\n\n.vpg-pro-link:hover {\n background: #d97706;\n}\n\n/* Config Bar */\n.vpg-config-bar {\n display: flex;\n align-items: stretch;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n background: #f8fafc;\n border-bottom: 1px solid #e2e8f0;\n flex-shrink: 0;\n}\n\n.vpg-drop-zone {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n border-radius: 0.5rem;\n border: 2px dashed;\n transition: all 0.15s;\n}\n\n.vpg-drop-zone.vpg-row-zone {\n background: rgba(238, 242, 255, 0.5);\n border-color: #c7d2fe;\n}\n\n.vpg-drop-zone.vpg-column-zone {\n background: rgba(245, 243, 255, 0.5);\n border-color: #ddd6fe;\n flex: 1;\n}\n\n.vpg-drop-zone.vpg-value-zone {\n background: rgba(236, 253, 245, 0.5);\n border-color: #a7f3d0;\n}\n\n.vpg-drop-zone.vpg-drag-over {\n border-style: solid;\n box-shadow: 0 0 0 2px currentColor inset;\n}\n\n.vpg-drop-zone.vpg-row-zone.vpg-drag-over {\n background: #eef2ff;\n border-color: #818cf8;\n}\n\n.vpg-drop-zone.vpg-column-zone.vpg-drag-over {\n background: #f5f3ff;\n border-color: #a78bfa;\n}\n\n.vpg-drop-zone.vpg-value-zone.vpg-drag-over {\n background: #ecfdf5;\n border-color: #34d399;\n}\n\n.vpg-zone-header {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n flex-shrink: 0;\n}\n\n.vpg-zone-icon {\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.75rem;\n font-weight: 700;\n border-radius: 0.25rem;\n}\n\n.vpg-zone-icon.vpg-row-icon {\n background: #c7d2fe;\n color: #4338ca;\n}\n\n.vpg-zone-icon.vpg-column-icon {\n background: #ddd6fe;\n color: #7c3aed;\n}\n\n.vpg-zone-icon.vpg-value-icon {\n background: #a7f3d0;\n color: #059669;\n}\n\n.vpg-zone-label {\n font-size: 0.625rem;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.vpg-row-zone .vpg-zone-label {\n color: #4f46e5;\n}\n\n.vpg-column-zone .vpg-zone-label {\n color: #7c3aed;\n}\n\n.vpg-value-zone .vpg-zone-label {\n color: #059669;\n}\n\n.vpg-zone-chips {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.25rem;\n}\n\n.vpg-zone-hint {\n font-size: 0.625rem;\n color: #94a3b8;\n font-style: italic;\n}\n\n.vpg-mini-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.25rem 0.5rem;\n border-radius: 0.25rem;\n font-size: 0.625rem;\n font-weight: 500;\n max-width: 100%;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n cursor: grab;\n transition: all 0.15s ease;\n}\n\n.vpg-mini-chip:active {\n cursor: grabbing;\n}\n\n.vpg-drag-handle {\n opacity: 0.3;\n font-size: 0.625rem;\n letter-spacing: -0.1em;\n margin-right: 0.125rem;\n cursor: grab;\n flex-shrink: 0;\n}\n\n.vpg-mini-chip:hover .vpg-drag-handle {\n opacity: 0.6;\n}\n\n.vpg-mini-chip.vpg-chip-dragging {\n opacity: 0.4;\n transform: scale(0.95);\n}\n\n.vpg-mini-chip.vpg-chip-drop-target {\n transform: translateX(4px);\n box-shadow: -3px 0 0 0 currentColor, 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-mini-chip.vpg-row-chip {\n background: white;\n color: #4338ca;\n border: 1px solid #c7d2fe;\n}\n\n.vpg-mini-chip.vpg-column-chip {\n background: white;\n color: #7c3aed;\n border: 1px solid #ddd6fe;\n}\n\n.vpg-mini-chip.vpg-value-chip {\n background: white;\n color: #059669;\n border: 1px solid #a7f3d0;\n}\n\n.vpg-mini-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n}\n\n.vpg-mini-remove {\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n line-height: 1;\n opacity: 0.4;\n flex-shrink: 0;\n background: transparent;\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-mini-remove:hover {\n opacity: 1;\n background: #fee2e2;\n color: #ef4444;\n}\n\n.vpg-agg-symbol {\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.625rem;\n font-weight: 700;\n background: #d1fae5;\n color: #059669;\n border-radius: 0.25rem;\n flex-shrink: 0;\n}\n\n/* Placeholder */\n.vpg-placeholder {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #f8fafc, white, rgba(236, 253, 245, 0.3));\n border-top: 1px solid #f1f5f9;\n}\n\n.vpg-placeholder-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n text-align: center;\n padding: 2rem;\n}\n\n.vpg-placeholder-icon {\n width: 4rem;\n height: 4rem;\n color: #cbd5e1;\n}\n\n.vpg-placeholder-text {\n font-size: 0.875rem;\n color: #64748b;\n}\n\n.vpg-placeholder-text strong {\n color: #334155;\n font-weight: 600;\n}\n\n/* Table */\n.vpg-table-container {\n flex: 1;\n overflow: auto;\n max-height: 100%;\n}\n\n.vpg-pivot-table {\n border-collapse: collapse;\n table-layout: fixed;\n min-width: max-content;\n}\n\n.vpg-pivot-table thead {\n position: sticky;\n top: 0;\n z-index: 30;\n box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.1);\n}\n\n.vpg-column-header-row {\n background: #e2e8f0;\n}\n\n.vpg-column-header-row th {\n background: #e2e8f0;\n}\n\n.vpg-row-header-label {\n position: sticky;\n left: 0;\n z-index: 30;\n padding: 0.5rem 0.75rem;\n text-align: left;\n font-size: 0.625rem;\n font-weight: 600;\n color: #64748b;\n text-transform: uppercase;\n border-bottom: 1px solid #cbd5e1;\n border-right: 1px solid #cbd5e1;\n background: #e2e8f0;\n cursor: pointer;\n}\n\n.vpg-row-header-label:hover {\n background: #d1d5db;\n}\n\n.vpg-column-header-cell {\n padding: 0.5rem 0.75rem;\n text-align: center;\n font-size: 0.6875rem;\n font-weight: 600;\n color: #334155;\n border-bottom: 1px solid #cbd5e1;\n border-right: 1px solid #cbd5e1;\n white-space: nowrap;\n background: #e2e8f0;\n cursor: pointer;\n}\n\n.vpg-column-header-cell:hover {\n background: rgba(203, 213, 225, 0.5);\n}\n\n.vpg-header-content {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.25rem;\n}\n\n.vpg-sort-indicator {\n flex-shrink: 0;\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #94a3b8;\n font-size: 0.75rem;\n}\n\n.vpg-sort-indicator.active {\n color: #4f46e5;\n font-weight: 700;\n}\n\n.vpg-total-header {\n padding: 0.5rem;\n text-align: center;\n font-size: 0.6875rem;\n font-weight: 700;\n color: #92400e;\n border-bottom: 1px solid #cbd5e1;\n border-left: 2px solid #f59e0b;\n background: #fde68a;\n vertical-align: middle;\n}\n\n.vpg-data-row:hover {\n background: #ecfdf5;\n}\n\n.vpg-data-row:nth-child(even) {\n background: #f8fafc;\n}\n\n.vpg-row-header-cell {\n position: sticky;\n left: 0;\n padding: 0.5rem 0.75rem;\n text-align: left;\n font-size: 0.75rem;\n font-weight: 500;\n color: #334155;\n background: white;\n border-bottom: 1px solid #e2e8f0;\n border-right: 1px solid #e2e8f0;\n white-space: nowrap;\n z-index: 10;\n}\n\n.vpg-data-row:nth-child(even) .vpg-row-header-cell {\n background: #f8fafc;\n}\n\n.vpg-row-value + .vpg-row-value::before {\n content: ' / ';\n color: #94a3b8;\n}\n\n.vpg-data-cell {\n padding: 0.5rem 0.75rem;\n text-align: right;\n font-size: 0.75rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n color: #334155;\n font-variant-numeric: tabular-nums;\n border-bottom: 1px solid #f1f5f9;\n border-right: 1px solid #f8fafc;\n cursor: cell;\n white-space: nowrap;\n}\n\n.vpg-data-cell.selected {\n background: #d1fae5;\n outline: 2px solid #10b981;\n outline-offset: -2px;\n position: relative;\n z-index: 1;\n}\n\n.vpg-data-cell.vpg-is-null {\n color: #cbd5e1;\n}\n\n.vpg-data-cell.vpg-total-cell {\n background: #fef3c7;\n font-weight: 600;\n color: #92400e;\n}\n\n.vpg-data-cell.vpg-grand-total-cell {\n background: #fde68a;\n font-weight: 700;\n color: #92400e;\n}\n\n.vpg-totals-row {\n background: #fef9e7;\n}\n\n.vpg-total-label {\n font-weight: 700;\n color: #92400e;\n background: #fef3c7;\n}\n\n/* Font sizes */\n.vpg-pivot-skeleton.vpg-font-xs .vpg-data-cell,\n.vpg-pivot-skeleton.vpg-font-xs .vpg-row-header-cell {\n font-size: 0.75rem;\n padding: 0.375rem 0.75rem;\n}\n\n.vpg-pivot-skeleton.vpg-font-sm .vpg-data-cell,\n.vpg-pivot-skeleton.vpg-font-sm .vpg-row-header-cell {\n font-size: 0.875rem;\n padding: 0.5rem 1rem;\n}\n\n.vpg-pivot-skeleton.vpg-font-base .vpg-data-cell,\n.vpg-pivot-skeleton.vpg-font-base .vpg-row-header-cell {\n font-size: 1rem;\n padding: 0.625rem 1rem;\n}\n\n/* Footer */\n.vpg-skeleton-footer {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n font-size: 0.75rem;\n color: #64748b;\n background: #f8fafc;\n border-top: 1px solid #e2e8f0;\n flex-shrink: 0;\n}\n\n/* Watermark */\n.vpg-watermark {\n padding: 0.375rem 1rem;\n background: #f1f5f9;\n border-top: 1px solid #e2e8f0;\n text-align: center;\n flex-shrink: 0;\n}\n\n.vpg-watermark a {\n font-size: 0.625rem;\n color: #94a3b8;\n text-decoration: none;\n transition: color 0.15s;\n}\n\n.vpg-watermark a:hover {\n color: #64748b;\n}\n\n/* Demo Mode Banner */\n.vpg-watermark.vpg-demo-mode {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.75rem;\n padding: 0.5rem 1rem;\n background: linear-gradient(135deg, #fef3c7, #fde68a);\n border-top: 1px solid #fcd34d;\n font-size: 0.75rem;\n color: #92400e;\n}\n\n.vpg-demo-badge {\n display: inline-flex;\n align-items: center;\n padding: 0.125rem 0.5rem;\n background: #f59e0b;\n color: white;\n font-size: 0.625rem;\n font-weight: 700;\n border-radius: 0.25rem;\n letter-spacing: 0.05em;\n}\n\n.vpg-get-pro {\n font-weight: 600;\n color: #d97706 !important;\n}\n\n.vpg-get-pro:hover {\n color: #b45309 !important;\n text-decoration: underline;\n}\n\n/* Scrollbar */\n.vpg-table-container::-webkit-scrollbar {\n width: 0.5rem;\n height: 0.5rem;\n}\n\n.vpg-table-container::-webkit-scrollbar-track {\n background: #f1f5f9;\n}\n\n.vpg-table-container::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 9999px;\n}\n\n.vpg-table-container::-webkit-scrollbar-thumb:hover {\n background: #94a3b8;\n}\n\n.vpg-table-container::-webkit-scrollbar-corner {\n background: #f1f5f9;\n}\n\n</style>\n\n<style>\n/* Dark Mode - PivotSkeleton */\n.vpg-theme-dark .vpg-pivot-skeleton {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-skeleton-header {\n background: linear-gradient(to right, rgba(16, 185, 129, 0.15), rgba(20, 184, 166, 0.1)) !important;\n border-color: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-skeleton-title {\n color: #6ee7b7 !important;\n}\n\n/* Config bar (drop zones container) */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-config-bar {\n background: #0f172a !important;\n border-color: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-drop-zones {\n background: #0f172a !important;\n border-color: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-drop-zone {\n background: #1e293b !important;\n border-color: #475569 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-drop-zone:hover {\n border-color: #64748b !important;\n background: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-drop-zone.vpg-zone-active {\n border-color: #10b981 !important;\n background: rgba(16, 185, 129, 0.2) !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-zone-label {\n color: #94a3b8 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-zone-row .vpg-zone-label { color: #a5b4fc !important; }\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-zone-column .vpg-zone-label { color: #c4b5fd !important; }\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-zone-value .vpg-zone-label { color: #6ee7b7 !important; }\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-zone-hint {\n color: #64748b !important;\n}\n\n/* Mini chips in drop zones */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-mini-chip.vpg-row-chip {\n background: #312e81 !important;\n color: #a5b4fc !important;\n border-color: #4338ca !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-mini-chip.vpg-column-chip {\n background: #4c1d95 !important;\n color: #c4b5fd !important;\n border-color: #7c3aed !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-mini-chip.vpg-value-chip {\n background: #064e3b !important;\n color: #6ee7b7 !important;\n border-color: #10b981 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-drag-handle {\n opacity: 0.4;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-mini-chip:hover .vpg-drag-handle {\n opacity: 0.7;\n}\n\n/* Font size toggle (S M L) */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-font-size-toggle {\n background: #1e293b !important;\n border-color: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-font-size-btn {\n color: #94a3b8 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-font-size-btn:hover {\n background: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-font-size-btn.active {\n background: #10b981 !important;\n color: white !important;\n}\n\n/* Summary badges (1 row, 1 col, 1 val) */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-summary-badge.vpg-rows {\n background: rgba(99, 102, 241, 0.2) !important;\n color: #a5b4fc !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-summary-badge.vpg-cols {\n background: rgba(139, 92, 246, 0.2) !important;\n color: #c4b5fd !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-summary-badge.vpg-vals {\n background: rgba(16, 185, 129, 0.2) !important;\n color: #6ee7b7 !important;\n}\n\n/* Filter indicator - dark mode */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-filter-indicator {\n background: linear-gradient(135deg, rgba(245, 158, 11, 0.2) 0%, rgba(217, 119, 6, 0.25) 100%) !important;\n border-color: #d97706 !important;\n color: #fbbf24 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-filter-icon {\n color: #fbbf24 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-filter-text strong {\n color: #fcd34d !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-filter-count {\n color: #fbbf24 !important;\n}\n\n/* Filter tooltip - dark mode */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-filter-tooltip {\n background: #1e293b !important;\n border-color: #475569 !important;\n box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.4), 0 8px 10px -6px rgba(0, 0, 0, 0.3);\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-header {\n background: #0f172a !important;\n border-color: #334155 !important;\n color: #94a3b8 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-filter {\n border-color: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-column {\n color: #e2e8f0 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-value {\n background: rgba(245, 158, 11, 0.2) !important;\n color: #fbbf24 !important;\n border-color: rgba(245, 158, 11, 0.4) !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-more {\n color: #94a3b8 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-summary {\n background: #0f172a !important;\n border-color: #334155 !important;\n color: #94a3b8 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-table-container {\n background: #1e293b;\n}\n\n.vpg-theme-dark .vpg-pivot-table {\n background: #1e293b;\n}\n\n.vpg-theme-dark .vpg-pivot-table thead {\n box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.3);\n}\n\n.vpg-theme-dark .vpg-column-header-row {\n background: #0f172a !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-column-header-cell,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-corner-cell,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-row-header-label {\n background: #0f172a !important;\n border-color: #334155 !important;\n color: #e2e8f0 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-row-header-label:hover,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-column-header-cell:hover {\n background: #1e293b !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-row-header-cell {\n background: #1e293b;\n border-color: #334155;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-cell {\n background: #1e293b;\n border-color: #334155;\n color: #cbd5e1;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-row:nth-child(even) .vpg-row-header-cell,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-row:nth-child(even) .vpg-data-cell {\n background: #0f172a;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-row:hover .vpg-row-header-cell,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-row:hover .vpg-data-cell {\n background: #334155;\n}\n\n/* Total header column */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-total-header {\n background: #451a03 !important;\n color: #fbbf24 !important;\n border-color: #334155 !important;\n}\n\n/* Total cells in rows - consistent color */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-cell.vpg-total-cell {\n background: #451a03 !important;\n color: #fbbf24 !important;\n}\n\n/* Grand total cell */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-cell.vpg-grand-total-cell {\n background: #451a03 !important;\n color: #fbbf24 !important;\n}\n\n/* Totals row - consistent color */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-totals-row {\n background: transparent !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-totals-row .vpg-row-header-cell,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-totals-row .vpg-data-cell {\n background: #451a03 !important;\n}\n\n/* Total label */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-total-label {\n background: #451a03 !important;\n color: #fbbf24 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-empty-state {\n background: #0f172a;\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-skeleton-footer {\n background: #0f172a;\n border-color: #334155;\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-demo-bar {\n background: rgba(245, 158, 11, 0.15);\n border-color: rgba(245, 158, 11, 0.3);\n color: #fbbf24;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-table-container::-webkit-scrollbar-track {\n background: #0f172a;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-table-container::-webkit-scrollbar-thumb {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-table-container::-webkit-scrollbar-thumb:hover {\n background: #475569;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-table-container::-webkit-scrollbar-corner {\n background: #0f172a;\n}\n\n/* Dark mode - Placeholder */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-placeholder {\n background: linear-gradient(135deg, #1e293b, #0f172a, rgba(16, 185, 129, 0.05));\n border-top-color: #334155;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-placeholder-icon {\n color: #475569;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-placeholder-text {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-placeholder-text strong {\n color: #e2e8f0;\n}\n</style>\n\n","<script setup lang=\"ts\">\n/**\n * TinyPivot - Main DataGrid Component\n * Excel-like data grid with optional pivot table functionality\n */\nimport { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'\nimport { useExcelGrid } from '../composables/useExcelGrid'\nimport { usePivotTable } from '../composables/usePivotTable'\nimport { useLicense } from '../composables/useLicense'\nimport {\n exportToCSV,\n exportPivotToCSV,\n copyToClipboard,\n formatSelectionForClipboard,\n} from '../composables/useGridFeatures'\nimport type { ColumnStats } from '@smallwebco/tinypivot-core'\nimport ColumnFilter from './ColumnFilter.vue'\nimport PivotConfig from './PivotConfig.vue'\nimport PivotSkeleton from './PivotSkeleton.vue'\n\nconst props = withDefaults(defineProps<{\n data: Record<string, unknown>[]\n loading?: boolean\n rowHeight?: number\n headerHeight?: number\n fontSize?: 'xs' | 'sm' | 'base'\n showPivot?: boolean\n // Feature props\n enableExport?: boolean\n enableSearch?: boolean\n enablePagination?: boolean\n pageSize?: number\n enableColumnResize?: boolean\n enableClipboard?: boolean\n theme?: 'light' | 'dark' | 'auto'\n stripedRows?: boolean\n exportFilename?: string\n enableVerticalResize?: boolean\n initialHeight?: number\n minHeight?: number\n maxHeight?: number\n}>(), {\n loading: false,\n rowHeight: 36,\n headerHeight: 40,\n fontSize: 'xs',\n showPivot: true,\n // Feature defaults\n enableExport: true,\n enableSearch: true,\n enablePagination: false,\n pageSize: 50,\n enableColumnResize: true,\n enableClipboard: true,\n theme: 'light',\n stripedRows: true,\n exportFilename: 'data-export.csv',\n enableVerticalResize: true,\n initialHeight: 600,\n minHeight: 300,\n maxHeight: 1200,\n})\n\nconst emit = defineEmits<{\n (e: 'cellClick', payload: { row: number, col: number, value: unknown, rowData: Record<string, unknown> }): void\n (e: 'selectionChange', payload: { cells: Array<{ row: number, col: number }>, values: unknown[] }): void\n (e: 'export', payload: { rowCount: number, filename: string }): void\n (e: 'copy', payload: { text: string, cellCount: number }): void\n}>()\n\nconst { showWatermark, canUsePivot, isDemo } = useLicense()\n\n// Theme handling\nconst currentTheme = computed(() => {\n if (props.theme === 'auto') {\n return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n }\n return props.theme\n})\n\n// Font size state\nconst currentFontSize = ref(props.fontSize)\n\n// Global search state\nconst globalSearchTerm = ref('')\nconst showSearchInput = ref(false)\n\n// Pagination state\nconst currentPage = ref(1)\n\n// Column resize state\nconst resizingColumnId = ref<string | null>(null)\nconst resizeStartX = ref(0)\nconst resizeStartWidth = ref(0)\n\n// Vertical resize state\nconst gridHeight = ref(props.initialHeight)\nconst isResizingVertically = ref(false)\nconst verticalResizeStartY = ref(0)\nconst verticalResizeStartHeight = ref(0)\n\n// Clipboard toast state\nconst showCopyToast = ref(false)\nconst copyToastMessage = ref('')\nconst fontSizeOptions = [\n { value: 'xs', label: 'S' },\n { value: 'sm', label: 'M' },\n { value: 'base', label: 'L' },\n] as const\n\n// Grid composable\nconst dataRef = computed(() => props.data)\nconst {\n table,\n columnKeys,\n filteredRowCount,\n totalRowCount,\n getColumnStats,\n hasActiveFilter,\n setColumnFilter,\n getColumnFilterValues,\n clearAllFilters,\n toggleSort,\n getSortDirection,\n columnFilters,\n activeFilters,\n} = useExcelGrid({ data: dataRef })\n\n// Filtered data for pivot table (respects column filters)\nconst filteredDataForPivot = computed(() => {\n const filteredRows = table.getFilteredRowModel().rows\n return filteredRows.map(row => row.original)\n})\n\n// Active filters info for display - use activeFilters from useExcelGrid\nconst activeFilterInfo = computed(() => {\n if (activeFilters.value.length === 0) return null\n return activeFilters.value.map(f => ({\n column: f.column,\n valueCount: f.values?.length || 0,\n values: f.values || [],\n }))\n})\n\n// Pivot table composable - uses filtered data\nconst {\n rowFields: pivotRowFields,\n columnFields: pivotColumnFields,\n valueFields: pivotValueFields,\n showRowTotals: pivotShowRowTotals,\n showColumnTotals: pivotShowColumnTotals,\n availableFields: pivotAvailableFields,\n isConfigured: pivotIsConfigured,\n pivotResult,\n addRowField,\n removeRowField,\n addColumnField,\n removeColumnField,\n addValueField,\n removeValueField,\n updateValueFieldAggregation,\n clearConfig: clearPivotConfig,\n autoSuggestConfig,\n} = usePivotTable(filteredDataForPivot)\n\n// Filtered data based on global search\nconst searchFilteredData = computed(() => {\n if (!globalSearchTerm.value.trim() || !props.enableSearch) {\n return rows.value\n }\n const term = globalSearchTerm.value.toLowerCase().trim()\n return rows.value.filter((row) => {\n for (const col of columnKeys.value) {\n const value = row.original[col]\n if (value === null || value === undefined) continue\n if (String(value).toLowerCase().includes(term)) {\n return true\n }\n }\n return false\n })\n})\n\n// Paginated rows\nconst totalSearchedRows = computed(() => searchFilteredData.value.length)\nconst totalPages = computed(() => {\n if (!props.enablePagination) return 1\n return Math.max(1, Math.ceil(totalSearchedRows.value / props.pageSize))\n})\n\nconst paginatedRows = computed(() => {\n if (!props.enablePagination) return searchFilteredData.value\n const start = (currentPage.value - 1) * props.pageSize\n const end = start + props.pageSize\n return searchFilteredData.value.slice(start, end)\n})\n\nconst paginationStart = computed(() => {\n if (totalSearchedRows.value === 0) return 0\n return (currentPage.value - 1) * props.pageSize + 1\n})\n\nconst paginationEnd = computed(() =>\n Math.min(currentPage.value * props.pageSize, totalSearchedRows.value),\n)\n\n// Pagination methods\nfunction goToPage(page: number) {\n currentPage.value = Math.max(1, Math.min(page, totalPages.value))\n}\n\nfunction nextPage() {\n if (currentPage.value < totalPages.value) currentPage.value++\n}\n\nfunction prevPage() {\n if (currentPage.value > 1) currentPage.value--\n}\n\n// Reset to page 1 when filters or search changes\nwatch([columnFilters, globalSearchTerm], () => {\n currentPage.value = 1\n})\n\n// Export functionality\nfunction handleExport() {\n if (viewMode.value === 'pivot') {\n handlePivotExport()\n return\n }\n\n const dataToExport = props.enableSearch && globalSearchTerm.value.trim()\n ? searchFilteredData.value.map(row => row.original)\n : rows.value.map(row => row.original)\n \n exportToCSV(dataToExport, columnKeys.value, {\n filename: props.exportFilename,\n includeHeaders: true,\n })\n \n emit('export', { rowCount: dataToExport.length, filename: props.exportFilename })\n}\n\nfunction handlePivotExport() {\n if (!pivotResult.value) return\n\n const pivotFilename = props.exportFilename.replace('.csv', '-pivot.csv')\n \n exportPivotToCSV(\n {\n headers: pivotResult.value.headers,\n rowHeaders: pivotResult.value.rowHeaders,\n data: pivotResult.value.data,\n rowTotals: pivotResult.value.rowTotals,\n columnTotals: pivotResult.value.columnTotals,\n grandTotal: pivotResult.value.grandTotal,\n showRowTotals: pivotShowRowTotals.value,\n showColumnTotals: pivotShowColumnTotals.value,\n },\n pivotRowFields.value,\n pivotColumnFields.value,\n pivotValueFields.value,\n { filename: pivotFilename },\n )\n\n const rowCount = pivotResult.value.rowHeaders.length\n emit('export', { rowCount, filename: pivotFilename })\n}\n\n// Column resize methods\nfunction startColumnResize(columnId: string, event: MouseEvent) {\n if (!props.enableColumnResize) return\n event.preventDefault()\n event.stopPropagation()\n \n resizingColumnId.value = columnId\n resizeStartX.value = event.clientX\n resizeStartWidth.value = columnWidths.value[columnId] || MIN_COL_WIDTH\n \n document.addEventListener('mousemove', handleResizeMove)\n document.addEventListener('mouseup', handleResizeEnd)\n}\n\nfunction handleResizeMove(event: MouseEvent) {\n if (!resizingColumnId.value) return\n const diff = event.clientX - resizeStartX.value\n const newWidth = Math.max(MIN_COL_WIDTH, Math.min(MAX_COL_WIDTH, resizeStartWidth.value + diff))\n columnWidths.value = {\n ...columnWidths.value,\n [resizingColumnId.value]: newWidth,\n }\n}\n\nfunction handleResizeEnd() {\n resizingColumnId.value = null\n document.removeEventListener('mousemove', handleResizeMove)\n document.removeEventListener('mouseup', handleResizeEnd)\n}\n\n// Vertical resize methods\nfunction startVerticalResize(event: MouseEvent) {\n if (!props.enableVerticalResize) return\n event.preventDefault()\n \n isResizingVertically.value = true\n verticalResizeStartY.value = event.clientY\n verticalResizeStartHeight.value = gridHeight.value\n \n document.addEventListener('mousemove', handleVerticalResizeMove)\n document.addEventListener('mouseup', handleVerticalResizeEnd)\n}\n\nfunction handleVerticalResizeMove(event: MouseEvent) {\n if (!isResizingVertically.value) return\n const diff = event.clientY - verticalResizeStartY.value\n const newHeight = Math.max(\n props.minHeight,\n Math.min(props.maxHeight, verticalResizeStartHeight.value + diff),\n )\n gridHeight.value = newHeight\n}\n\nfunction handleVerticalResizeEnd() {\n isResizingVertically.value = false\n document.removeEventListener('mousemove', handleVerticalResizeMove)\n document.removeEventListener('mouseup', handleVerticalResizeEnd)\n}\n\n// Clipboard methods\nfunction copySelectionToClipboard() {\n if (!selectionBounds.value || !props.enableClipboard) return\n \n const text = formatSelectionForClipboard(\n rows.value.map(r => r.original),\n columnKeys.value,\n selectionBounds.value,\n )\n \n copyToClipboard(\n text,\n () => {\n const cellCount = \n (selectionBounds.value!.maxRow - selectionBounds.value!.minRow + 1) *\n (selectionBounds.value!.maxCol - selectionBounds.value!.minCol + 1)\n copyToastMessage.value = `Copied ${cellCount} cell${cellCount > 1 ? 's' : ''}`\n showCopyToast.value = true\n setTimeout(() => { showCopyToast.value = false }, 2000)\n emit('copy', { text, cellCount })\n },\n (err) => {\n copyToastMessage.value = 'Copy failed'\n showCopyToast.value = true\n setTimeout(() => { showCopyToast.value = false }, 2000)\n console.error('Copy failed:', err)\n },\n )\n}\n\n// View mode\nconst viewMode = ref<'grid' | 'pivot'>('grid')\nconst showPivotConfig = ref(true)\nconst draggingField = ref<string | null>(null)\n\nfunction handlePivotDragStart(field: string) {\n draggingField.value = field\n}\n\nfunction handlePivotDragEnd() {\n draggingField.value = null\n}\n\nfunction reorderRowFields(fields: string[]) {\n pivotRowFields.value = fields\n}\n\nfunction reorderColumnFields(fields: string[]) {\n pivotColumnFields.value = fields\n}\n\n// Container refs\nconst tableContainerRef = ref<HTMLDivElement>()\nconst tableBodyRef = ref<HTMLDivElement>()\n\n// Rows\nconst rows = computed(() => table.getRowModel().rows)\n\n// Column filter dropdown state\nconst activeFilterColumn = ref<string | null>(null)\nconst filterDropdownPosition = ref({ top: 0, left: 0, maxHeight: 400 })\n\n// Column widths\nconst columnWidths = ref<Record<string, number>>({})\nconst MIN_COL_WIDTH = 120\nconst MAX_COL_WIDTH = 350\n\nfunction calculateColumnWidths() {\n if (props.data.length === 0)\n return\n\n const widths: Record<string, number> = {}\n const sampleSize = Math.min(100, props.data.length)\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n if (!ctx)\n return\n\n ctx.font = '13px system-ui, -apple-system, sans-serif'\n\n for (const key of columnKeys.value) {\n let maxWidth = ctx.measureText(key).width + 56\n\n for (let i = 0; i < sampleSize; i++) {\n const value = props.data[i][key]\n const text = value === null || value === undefined ? '' : String(value)\n const width = ctx.measureText(text).width + 28\n maxWidth = Math.max(maxWidth, width)\n }\n\n widths[key] = Math.min(Math.max(maxWidth, MIN_COL_WIDTH), MAX_COL_WIDTH)\n }\n\n columnWidths.value = widths\n}\n\nfunction openFilterDropdown(columnId: string, event: MouseEvent) {\n event.stopPropagation()\n const target = event.currentTarget as HTMLElement\n const headerCell = target.closest('.vpg-header-cell') as HTMLElement\n const rect = headerCell?.getBoundingClientRect() || target.getBoundingClientRect()\n\n const dropdownWidth = 280\n const padding = 12\n\n let left = rect.left\n if (left + dropdownWidth > window.innerWidth - padding) {\n left = window.innerWidth - dropdownWidth - padding\n }\n left = Math.max(padding, left)\n\n const spaceBelow = window.innerHeight - rect.bottom - padding\n const spaceAbove = rect.top - padding\n\n let top: number\n let maxHeight: number\n\n if (spaceBelow >= 300 || spaceBelow >= spaceAbove) {\n top = rect.bottom + 4\n maxHeight = Math.min(400, spaceBelow - 4)\n }\n else {\n maxHeight = Math.min(400, spaceAbove - 4)\n top = rect.top - maxHeight - 4\n }\n\n filterDropdownPosition.value = { top, left, maxHeight }\n activeFilterColumn.value = columnId\n}\n\nfunction closeFilterDropdown() {\n activeFilterColumn.value = null\n}\n\nfunction handleFilter(columnId: string, values: string[]) {\n setColumnFilter(columnId, values)\n}\n\nfunction handleSort(columnId: string, direction: 'asc' | 'desc' | null) {\n if (direction === null) {\n const current = getSortDirection(columnId)\n if (current) {\n toggleSort(columnId)\n if (getSortDirection(columnId)) {\n toggleSort(columnId)\n }\n }\n }\n else {\n const current = getSortDirection(columnId)\n if (current === null) {\n toggleSort(columnId)\n if (direction === 'desc' && getSortDirection(columnId) === 'asc') {\n toggleSort(columnId)\n }\n }\n else if (current !== direction) {\n toggleSort(columnId)\n }\n }\n}\n\nconst activeFilterCount = computed(() => columnFilters.value.length)\n\n// Selection state\nconst selectedCell = ref<{ row: number, col: number } | null>(null)\nconst selectionStart = ref<{ row: number, col: number } | null>(null)\nconst selectionEnd = ref<{ row: number, col: number } | null>(null)\nconst isSelecting = ref(false)\n\nfunction selectColumn(colIndex: number) {\n const maxRow = rows.value.length - 1\n if (maxRow < 0)\n return\n\n selectionStart.value = { row: 0, col: colIndex }\n selectionEnd.value = { row: maxRow, col: colIndex }\n selectedCell.value = { row: 0, col: colIndex }\n}\n\nfunction handleHeaderClick(colIndex: number, event: MouseEvent) {\n const target = event.target as HTMLElement\n if (target.closest('.vpg-dropdown-arrow')) {\n const colId = columnKeys.value[colIndex]\n openFilterDropdown(colId, event)\n }\n else {\n selectColumn(colIndex)\n }\n}\n\nconst selectionBounds = computed(() => {\n if (!selectionStart.value || !selectionEnd.value)\n return null\n return {\n minRow: Math.min(selectionStart.value.row, selectionEnd.value.row),\n maxRow: Math.max(selectionStart.value.row, selectionEnd.value.row),\n minCol: Math.min(selectionStart.value.col, selectionEnd.value.col),\n maxCol: Math.max(selectionStart.value.col, selectionEnd.value.col),\n }\n})\n\nfunction isCellInSelection(rowIndex: number, colIndex: number): boolean {\n if (!selectionBounds.value)\n return false\n const { minRow, maxRow, minCol, maxCol } = selectionBounds.value\n return rowIndex >= minRow && rowIndex <= maxRow && colIndex >= minCol && colIndex <= maxCol\n}\n\nconst selectionStats = computed(() => {\n if (!selectionBounds.value)\n return null\n const { minRow, maxRow, minCol, maxCol } = selectionBounds.value\n\n const values: number[] = []\n let count = 0\n\n for (let r = minRow; r <= maxRow; r++) {\n const row = rows.value[r]\n if (!row)\n continue\n\n for (let c = minCol; c <= maxCol; c++) {\n const colId = columnKeys.value[c]\n if (!colId)\n continue\n\n const value = row.original[colId]\n count++\n\n if (value !== null && value !== undefined && value !== '') {\n const num = typeof value === 'number' ? value : Number.parseFloat(String(value))\n if (!Number.isNaN(num)) {\n values.push(num)\n }\n }\n }\n }\n\n if (values.length === 0)\n return { count, sum: null, avg: null, numericCount: 0 }\n\n const sum = values.reduce((a, b) => a + b, 0)\n const avg = sum / values.length\n\n return { count, sum, avg, numericCount: values.length }\n})\n\nfunction formatStatValue(value: number | null): string {\n if (value === null)\n return '-'\n if (Math.abs(value) >= 1000) {\n return value.toLocaleString('en-US', { maximumFractionDigits: 2 })\n }\n return value.toLocaleString('en-US', { maximumFractionDigits: 4 })\n}\n\nfunction handleKeydown(event: KeyboardEvent) {\n // Handle Ctrl+C / Cmd+C for clipboard\n if ((event.ctrlKey || event.metaKey) && event.key === 'c' && selectionBounds.value) {\n event.preventDefault()\n copySelectionToClipboard()\n return\n }\n\n // Handle Ctrl+F / Cmd+F for search\n if ((event.ctrlKey || event.metaKey) && event.key === 'f' && props.enableSearch) {\n event.preventDefault()\n showSearchInput.value = true\n nextTick(() => {\n const input = document.querySelector('.vpg-search-input') as HTMLInputElement\n input?.focus()\n })\n return\n }\n\n if (!selectedCell.value)\n return\n if (activeFilterColumn.value)\n return\n\n const { row, col } = selectedCell.value\n const displayRows = paginatedRows.value\n const maxRow = displayRows.length - 1\n const maxCol = columnKeys.value.length - 1\n\n function updateSelection(newRow: number, newCol: number) {\n if (event.shiftKey) {\n if (!selectionStart.value) {\n selectionStart.value = { row, col }\n }\n selectionEnd.value = { row: newRow, col: newCol }\n }\n else {\n selectionStart.value = { row: newRow, col: newCol }\n selectionEnd.value = { row: newRow, col: newCol }\n }\n selectedCell.value = { row: newRow, col: newCol }\n scrollCellIntoView(newRow, newCol)\n }\n\n switch (event.key) {\n case 'ArrowUp':\n event.preventDefault()\n if (row > 0)\n updateSelection(row - 1, col)\n break\n case 'ArrowDown':\n event.preventDefault()\n if (row < maxRow)\n updateSelection(row + 1, col)\n break\n case 'ArrowLeft':\n event.preventDefault()\n if (col > 0)\n updateSelection(row, col - 1)\n break\n case 'ArrowRight':\n event.preventDefault()\n if (col < maxCol)\n updateSelection(row, col + 1)\n break\n case 'Escape':\n selectedCell.value = null\n selectionStart.value = null\n selectionEnd.value = null\n showSearchInput.value = false\n globalSearchTerm.value = ''\n break\n }\n}\n\nfunction scrollCellIntoView(rowIndex: number, colIndex: number) {\n nextTick(() => {\n const cell = tableBodyRef.value?.querySelector(\n `[data-row=\"${rowIndex}\"][data-col=\"${colIndex}\"]`,\n )\n cell?.scrollIntoView({ block: 'nearest', inline: 'nearest' })\n })\n}\n\nfunction handleMouseDown(rowIndex: number, colIndex: number, event: MouseEvent) {\n event.preventDefault()\n\n if (event.shiftKey && selectedCell.value) {\n selectionEnd.value = { row: rowIndex, col: colIndex }\n }\n else {\n selectedCell.value = { row: rowIndex, col: colIndex }\n selectionStart.value = { row: rowIndex, col: colIndex }\n selectionEnd.value = { row: rowIndex, col: colIndex }\n isSelecting.value = true\n }\n\n // Emit event\n const row = rows.value[rowIndex]\n if (row) {\n const colId = columnKeys.value[colIndex]\n emit('cellClick', {\n row: rowIndex,\n col: colIndex,\n value: row.original[colId],\n rowData: row.original,\n })\n }\n}\n\nfunction handleMouseEnter(rowIndex: number, colIndex: number) {\n if (isSelecting.value) {\n selectionEnd.value = { row: rowIndex, col: colIndex }\n }\n}\n\nfunction handleMouseUp() {\n isSelecting.value = false\n}\n\nfunction isCellSelected(rowIndex: number, colIndex: number): boolean {\n if (isCellInSelection(rowIndex, colIndex))\n return true\n return selectedCell.value?.row === rowIndex && selectedCell.value?.col === colIndex\n}\n\n// Format cell value\nconst noFormatPatterns = /^(?:.*_)?(?:id|code|year|month|quarter|day|week|date|zip|phone|fax|ssn|ein|npi|ndc|gpi|hcpcs|icd|cpt|rx|bin|pcn|group|member|claim|rx_number|script|fill)(?:_.*)?$/i\n\nfunction shouldFormatNumber(columnId: string): boolean {\n return !noFormatPatterns.test(columnId)\n}\n\nfunction formatCellValue(value: unknown, columnId: string): string {\n if (value === null || value === undefined)\n return ''\n if (value === '')\n return ''\n\n const stats = getColumnStats(columnId)\n if (stats.type === 'number') {\n const num = typeof value === 'number' ? value : Number.parseFloat(String(value))\n if (Number.isNaN(num))\n return String(value)\n\n if (shouldFormatNumber(columnId) && Math.abs(num) >= 1000) {\n return num.toLocaleString('en-US', { maximumFractionDigits: 2 })\n }\n\n if (Number.isInteger(num)) {\n return String(num)\n }\n return num.toLocaleString('en-US', { maximumFractionDigits: 4, useGrouping: false })\n }\n\n return String(value)\n}\n\nfunction handleTableScroll() {\n if (activeFilterColumn.value) {\n closeFilterDropdown()\n }\n}\n\nfunction handleWindowScroll(event: Event) {\n if (activeFilterColumn.value) {\n const target = event.target as HTMLElement\n if (target && target.closest?.('.vpg-filter-portal')) {\n return\n }\n closeFilterDropdown()\n }\n}\n\n// Initialize\nonMounted(() => {\n calculateColumnWidths()\n document.addEventListener('keydown', handleKeydown)\n document.addEventListener('mouseup', handleMouseUp)\n\n nextTick(() => {\n tableContainerRef.value?.addEventListener('scroll', handleTableScroll, { passive: true })\n })\n\n window.addEventListener('scroll', handleWindowScroll, { passive: true, capture: true })\n})\n\nonUnmounted(() => {\n document.removeEventListener('keydown', handleKeydown)\n document.removeEventListener('mouseup', handleMouseUp)\n tableContainerRef.value?.removeEventListener('scroll', handleTableScroll)\n window.removeEventListener('scroll', handleWindowScroll, { capture: true })\n})\n\nwatch(() => props.data, () => {\n nextTick(calculateColumnWidths)\n}, { immediate: true })\n\nconst totalTableWidth = computed(() => {\n return columnKeys.value.reduce((sum, key) => sum + (columnWidths.value[key] || MIN_COL_WIDTH), 0)\n})\n\nfunction handleContainerClick(event: MouseEvent) {\n if (activeFilterColumn.value) {\n const target = event.target as HTMLElement\n if (!target.closest('.vpg-filter-portal')) {\n closeFilterDropdown()\n }\n }\n}\n</script>\n\n<template>\n <div\n class=\"vpg-data-grid\"\n :class=\"[\n `vpg-font-${currentFontSize}`,\n `vpg-theme-${currentTheme}`,\n { 'vpg-striped': stripedRows },\n { 'vpg-resizing': resizingColumnId },\n { 'vpg-resizing-vertical': isResizingVertically },\n ]\"\n :style=\"{ height: `${gridHeight}px` }\"\n @click=\"handleContainerClick\"\n >\n <!-- Copy Toast -->\n <Transition name=\"vpg-toast\">\n <div v-if=\"showCopyToast\" class=\"vpg-toast\">\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n {{ copyToastMessage }}\n </div>\n </Transition>\n\n <!-- Toolbar -->\n <div class=\"vpg-toolbar\">\n <div class=\"vpg-toolbar-left\">\n <!-- View mode toggle -->\n <div v-if=\"showPivot\" class=\"vpg-view-toggle\">\n <button\n class=\"vpg-view-btn\"\n :class=\"{ active: viewMode === 'grid' }\"\n @click=\"viewMode = 'grid'\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n Grid\n </button>\n <button\n class=\"vpg-view-btn vpg-pivot-btn\"\n :class=\"{ active: viewMode === 'pivot' }\"\n @click=\"viewMode = 'pivot'\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\" />\n </svg>\n Pivot\n </button>\n </div>\n\n <!-- Grid mode controls -->\n <template v-if=\"viewMode === 'grid'\">\n <!-- Search input -->\n <div v-if=\"enableSearch\" class=\"vpg-search-container\">\n <button\n v-if=\"!showSearchInput\"\n class=\"vpg-icon-btn\"\n title=\"Search (Ctrl+F)\"\n @click=\"showSearchInput = true\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n </button>\n <div v-else class=\"vpg-search-box\">\n <svg class=\"vpg-search-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n <input\n v-model=\"globalSearchTerm\"\n type=\"text\"\n class=\"vpg-search-input\"\n placeholder=\"Search all columns...\"\n @keydown.escape=\"showSearchInput = false; globalSearchTerm = ''\"\n >\n <button\n v-if=\"globalSearchTerm\"\n class=\"vpg-search-clear\"\n @click=\"globalSearchTerm = ''\"\n >\n <svg class=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n </div>\n\n <div class=\"vpg-font-size-control\">\n <span class=\"vpg-label\">Size:</span>\n <div class=\"vpg-font-size-toggle\">\n <button\n v-for=\"opt in fontSizeOptions\"\n :key=\"opt.value\"\n class=\"vpg-font-size-btn\"\n :class=\"{ active: currentFontSize === opt.value }\"\n @click=\"currentFontSize = opt.value\"\n >\n {{ opt.label }}\n </button>\n </div>\n </div>\n\n <div v-if=\"activeFilterCount > 0\" class=\"vpg-filter-info\">\n <svg class=\"vpg-icon\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z\" clip-rule=\"evenodd\" />\n </svg>\n <span>{{ activeFilterCount }} filter{{ activeFilterCount > 1 ? 's' : '' }}</span>\n </div>\n\n <div v-if=\"globalSearchTerm\" class=\"vpg-search-info\">\n <span>{{ totalSearchedRows }} match{{ totalSearchedRows !== 1 ? 'es' : '' }}</span>\n </div>\n </template>\n\n <!-- Pivot mode controls -->\n <template v-if=\"viewMode === 'pivot' && canUsePivot\">\n <button\n class=\"vpg-config-toggle\"\n :class=\"{ active: showPivotConfig }\"\n @click=\"showPivotConfig = !showPivotConfig\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4\" />\n </svg>\n {{ showPivotConfig ? 'Hide' : 'Show' }} Config\n </button>\n\n <div v-if=\"pivotIsConfigured\" class=\"vpg-pivot-status\">\n <svg class=\"vpg-icon\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\" />\n </svg>\n <span>Pivot configured</span>\n </div>\n </template>\n </div>\n\n <div class=\"vpg-toolbar-right\">\n <button v-if=\"viewMode === 'grid' && activeFilterCount > 0\" class=\"vpg-clear-filters\" @click=\"clearAllFilters\">\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n Clear Filters\n </button>\n\n <!-- Copy button -->\n <button\n v-if=\"enableClipboard && selectionBounds && viewMode === 'grid'\"\n class=\"vpg-icon-btn\"\n title=\"Copy selection (Ctrl+C)\"\n @click=\"copySelectionToClipboard\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n </button>\n\n <!-- Export button -->\n <button\n v-if=\"enableExport && (viewMode === 'grid' || (viewMode === 'pivot' && pivotIsConfigured))\"\n class=\"vpg-export-btn\"\n :title=\"viewMode === 'pivot' ? 'Export Pivot to CSV' : 'Export to CSV'\"\n @click=\"handleExport\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\" />\n </svg>\n Export{{ viewMode === 'pivot' ? ' Pivot' : '' }}\n </button>\n </div>\n </div>\n\n <!-- Grid View -->\n <template v-if=\"viewMode === 'grid'\">\n <div ref=\"tableContainerRef\" class=\"vpg-grid-container\" tabindex=\"0\">\n <div v-if=\"loading\" class=\"vpg-loading\">\n <div class=\"vpg-spinner\" />\n <span>Loading data...</span>\n </div>\n\n <div v-else-if=\"data.length === 0\" class=\"vpg-empty\">\n <div class=\"vpg-empty-icon\">\n <svg class=\"vpg-icon-lg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n </div>\n <span>No data available</span>\n </div>\n\n <div v-else-if=\"filteredRowCount === 0\" class=\"vpg-empty\">\n <div class=\"vpg-empty-icon vpg-warning\">\n <svg class=\"vpg-icon-lg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\" />\n </svg>\n </div>\n <span>No matching records</span>\n <button class=\"vpg-clear-link\" @click=\"clearAllFilters\">\n Clear all filters\n </button>\n </div>\n\n <div v-else class=\"vpg-table-wrapper\">\n <table class=\"vpg-table\" :style=\"{ minWidth: `${totalTableWidth}px` }\">\n <thead>\n <tr>\n <th\n v-for=\"(colId, colIndex) in columnKeys\"\n :key=\"colId\"\n class=\"vpg-header-cell\"\n :class=\"{\n 'vpg-has-filter': hasActiveFilter(colId),\n 'vpg-is-sorted': getSortDirection(colId) !== null,\n 'vpg-is-active': activeFilterColumn === colId,\n }\"\n :style=\"{ width: `${columnWidths[colId] || MIN_COL_WIDTH}px`, minWidth: `${columnWidths[colId] || MIN_COL_WIDTH}px` }\"\n @click=\"handleHeaderClick(colIndex, $event)\"\n >\n <div class=\"vpg-header-content\">\n <span class=\"vpg-header-text\">{{ colId }}</span>\n <div class=\"vpg-header-icons\">\n <span v-if=\"getSortDirection(colId)\" class=\"vpg-sort-indicator\">\n <svg v-if=\"getSortDirection(colId) === 'asc'\" class=\"vpg-icon-sm\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M14.707 12.707a1 1 0 01-1.414 0L10 9.414l-3.293 3.293a1 1 0 01-1.414-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 010 1.414z\" clip-rule=\"evenodd\" />\n </svg>\n <svg v-else class=\"vpg-icon-sm\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span v-if=\"hasActiveFilter(colId)\" class=\"vpg-filter-indicator\">\n <svg class=\"vpg-icon-xs\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span class=\"vpg-dropdown-arrow\" title=\"Filter & Sort\">\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </span>\n </div>\n </div>\n <!-- Column resize handle -->\n <div\n v-if=\"enableColumnResize\"\n class=\"vpg-resize-handle\"\n @mousedown=\"startColumnResize(colId, $event)\"\n />\n </th>\n </tr>\n </thead>\n\n <tbody ref=\"tableBodyRef\">\n <tr\n v-for=\"(row, rowIndex) in paginatedRows\"\n :key=\"row.id\"\n class=\"vpg-row\"\n >\n <td\n v-for=\"(colId, colIndex) in columnKeys\"\n :key=\"colId\"\n class=\"vpg-cell\"\n :class=\"{\n 'vpg-selected': isCellSelected(rowIndex, colIndex),\n 'vpg-is-number': getColumnStats(colId).type === 'number',\n }\"\n :data-row=\"rowIndex\"\n :data-col=\"colIndex\"\n :style=\"{ width: `${columnWidths[colId] || MIN_COL_WIDTH}px`, minWidth: `${columnWidths[colId] || MIN_COL_WIDTH}px` }\"\n @mousedown=\"handleMouseDown(rowIndex, colIndex, $event)\"\n @mouseenter=\"handleMouseEnter(rowIndex, colIndex)\"\n >\n {{ formatCellValue(row.original[colId], colId) }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </template>\n\n <!-- Pivot View -->\n <template v-else>\n <div class=\"vpg-pivot-container\">\n <div v-if=\"showPivotConfig && canUsePivot\" class=\"vpg-pivot-config-panel\">\n <PivotConfig\n :available-fields=\"pivotAvailableFields\"\n :row-fields=\"pivotRowFields\"\n :column-fields=\"pivotColumnFields\"\n :value-fields=\"pivotValueFields\"\n :show-row-totals=\"pivotShowRowTotals\"\n :show-column-totals=\"pivotShowColumnTotals\"\n @update:show-row-totals=\"pivotShowRowTotals = $event\"\n @update:show-column-totals=\"pivotShowColumnTotals = $event\"\n @clear-config=\"clearPivotConfig\"\n @auto-suggest=\"autoSuggestConfig\"\n @drag-start=\"handlePivotDragStart\"\n @drag-end=\"handlePivotDragEnd\"\n @update-aggregation=\"updateValueFieldAggregation\"\n @add-row-field=\"addRowField\"\n @remove-row-field=\"removeRowField\"\n @add-column-field=\"addColumnField\"\n @remove-column-field=\"removeColumnField\"\n @add-value-field=\"addValueField\"\n @remove-value-field=\"removeValueField\"\n />\n </div>\n\n <div class=\"vpg-pivot-main\" :class=\"{ 'vpg-full-width': !showPivotConfig }\">\n <PivotSkeleton\n :row-fields=\"pivotRowFields\"\n :column-fields=\"pivotColumnFields\"\n :value-fields=\"pivotValueFields\"\n :is-configured=\"pivotIsConfigured\"\n :dragging-field=\"draggingField\"\n :pivot-result=\"pivotResult\"\n :font-size=\"currentFontSize\"\n :active-filters=\"activeFilterInfo\"\n :total-row-count=\"totalRowCount\"\n :filtered-row-count=\"filteredRowCount\"\n @add-row-field=\"addRowField\"\n @remove-row-field=\"removeRowField\"\n @add-column-field=\"addColumnField\"\n @remove-column-field=\"removeColumnField\"\n @add-value-field=\"addValueField\"\n @remove-value-field=\"removeValueField\"\n @update-aggregation=\"updateValueFieldAggregation\"\n @reorder-row-fields=\"reorderRowFields\"\n @reorder-column-fields=\"reorderColumnFields\"\n />\n </div>\n </div>\n </template>\n\n <!-- Footer -->\n <div class=\"vpg-footer\">\n <div class=\"vpg-footer-left\">\n <template v-if=\"viewMode === 'grid'\">\n <template v-if=\"enablePagination\">\n <span>{{ paginationStart.toLocaleString() }}-{{ paginationEnd.toLocaleString() }}</span>\n <span class=\"vpg-separator\">of</span>\n <span>{{ totalSearchedRows.toLocaleString() }}</span>\n <span v-if=\"totalSearchedRows !== totalRowCount\" class=\"vpg-filtered-note\">\n ({{ totalRowCount.toLocaleString() }} total)\n </span>\n </template>\n <template v-else-if=\"filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount\">\n <span>{{ totalRowCount.toLocaleString() }} records</span>\n </template>\n <template v-else>\n <span class=\"vpg-filtered-count\">{{ totalSearchedRows.toLocaleString() }}</span>\n <span class=\"vpg-separator\">of</span>\n <span>{{ totalRowCount.toLocaleString() }}</span>\n <span class=\"vpg-separator\">records</span>\n </template>\n </template>\n <template v-else>\n <span class=\"vpg-pivot-label\">Pivot Table</span>\n <span class=\"vpg-separator\">•</span>\n <span>{{ totalRowCount.toLocaleString() }} source records</span>\n </template>\n </div>\n\n <!-- Pagination controls -->\n <div v-if=\"enablePagination && viewMode === 'grid' && totalPages > 1\" class=\"vpg-pagination\">\n <button\n class=\"vpg-page-btn\"\n :disabled=\"currentPage === 1\"\n @click=\"currentPage = 1\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M11 19l-7-7 7-7m8 14l-7-7 7-7\" />\n </svg>\n </button>\n <button\n class=\"vpg-page-btn\"\n :disabled=\"currentPage === 1\"\n @click=\"prevPage\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n <span class=\"vpg-page-info\">\n Page {{ currentPage }} of {{ totalPages }}\n </span>\n <button\n class=\"vpg-page-btn\"\n :disabled=\"currentPage === totalPages\"\n @click=\"nextPage\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n <button\n class=\"vpg-page-btn\"\n :disabled=\"currentPage === totalPages\"\n @click=\"currentPage = totalPages\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 5l7 7-7 7M5 5l7 7-7 7\" />\n </svg>\n </button>\n </div>\n\n <div v-if=\"viewMode === 'grid' && selectionStats && selectionStats.count > 1\" class=\"vpg-selection-stats\">\n <span class=\"vpg-stat\">\n <span class=\"vpg-stat-label\">Count:</span>\n <span class=\"vpg-stat-value\">{{ selectionStats.count }}</span>\n </span>\n <template v-if=\"selectionStats.numericCount > 0\">\n <span class=\"vpg-stat-divider\">|</span>\n <span class=\"vpg-stat\">\n <span class=\"vpg-stat-label\">Sum:</span>\n <span class=\"vpg-stat-value\">{{ formatStatValue(selectionStats.sum) }}</span>\n </span>\n <span class=\"vpg-stat-divider\">|</span>\n <span class=\"vpg-stat\">\n <span class=\"vpg-stat-label\">Avg:</span>\n <span class=\"vpg-stat-value\">{{ formatStatValue(selectionStats.avg) }}</span>\n </span>\n </template>\n </div>\n\n <div class=\"vpg-footer-right\">\n <div v-if=\"isDemo\" class=\"vpg-demo-banner\">\n <span class=\"vpg-demo-badge\">DEMO</span>\n <span>Pro features enabled</span>\n <a href=\"https://tiny-pivot.com/#pricing\" target=\"_blank\" rel=\"noopener\">Get License →</a>\n </div>\n <span v-else-if=\"showWatermark\" class=\"vpg-watermark-inline\">\n <a href=\"https://tiny-pivot.com\" target=\"_blank\" rel=\"noopener\">TinyPivot</a>\n </span>\n </div>\n </div>\n\n <!-- Vertical Resize Handle -->\n <div\n v-if=\"enableVerticalResize\"\n class=\"vpg-vertical-resize-handle\"\n @mousedown=\"startVerticalResize\"\n >\n <div class=\"vpg-resize-grip\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n\n <!-- Filter Dropdown Portal -->\n <Teleport to=\"body\">\n <div\n v-if=\"activeFilterColumn\"\n class=\"vpg-filter-portal\"\n :style=\"{\n position: 'fixed',\n top: `${filterDropdownPosition.top}px`,\n left: `${filterDropdownPosition.left}px`,\n maxHeight: `${filterDropdownPosition.maxHeight}px`,\n zIndex: 9999,\n }\"\n >\n <ColumnFilter\n :column-id=\"activeFilterColumn\"\n :column-name=\"activeFilterColumn\"\n :stats=\"getColumnStats(activeFilterColumn)\"\n :selected-values=\"getColumnFilterValues(activeFilterColumn)\"\n :sort-direction=\"getSortDirection(activeFilterColumn)\"\n @filter=\"(values) => handleFilter(activeFilterColumn!, values)\"\n @sort=\"(dir) => handleSort(activeFilterColumn!, dir)\"\n @close=\"closeFilterDropdown\"\n />\n </div>\n </Teleport>\n </div>\n</template>\n\n<style scoped>\n.vpg-data-grid {\n display: flex;\n flex-direction: column;\n background: white;\n border-radius: 0.5rem;\n overflow: hidden;\n border: 1px solid #e2e8f0;\n box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);\n margin-bottom: 1.5rem;\n position: relative;\n}\n\n.vpg-icon {\n width: 1rem;\n height: 1rem;\n}\n\n.vpg-icon-sm {\n width: 0.875rem;\n height: 0.875rem;\n}\n\n.vpg-icon-xs {\n width: 0.75rem;\n height: 0.75rem;\n}\n\n.vpg-icon-lg {\n width: 3rem;\n height: 3rem;\n}\n\n/* Toolbar */\n.vpg-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem 1rem;\n background: #f8fafc;\n border-bottom: 1px solid #e2e8f0;\n}\n\n.vpg-toolbar-left {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.vpg-toolbar-right {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.vpg-view-toggle {\n display: flex;\n background: white;\n border-radius: 0.5rem;\n border: 1px solid #e2e8f0;\n overflow: hidden;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-view-btn {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.75rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: #64748b;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-view-btn:hover {\n background: #f8fafc;\n}\n\n.vpg-view-btn.active {\n background: #4f46e5;\n color: white;\n box-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.1);\n}\n\n.vpg-view-btn.vpg-pivot-btn.active {\n background: #10b981;\n}\n\n.vpg-font-size-control {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.vpg-label {\n font-size: 0.75rem;\n color: #64748b;\n}\n\n.vpg-font-size-toggle {\n display: flex;\n background: white;\n border-radius: 0.25rem;\n border: 1px solid #e2e8f0;\n overflow: hidden;\n}\n\n.vpg-font-size-btn {\n padding: 0.25rem 0.5rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: #64748b;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-font-size-btn:hover {\n background: #f1f5f9;\n}\n\n.vpg-font-size-btn.active {\n background: #4f46e5;\n color: white;\n}\n\n.vpg-filter-info {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.875rem;\n color: #475569;\n}\n\n.vpg-filter-info svg {\n color: #4f46e5;\n}\n\n.vpg-config-toggle {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.75rem;\n font-size: 0.75rem;\n font-weight: 500;\n border-radius: 0.375rem;\n background: white;\n border: 1px solid #e2e8f0;\n color: #475569;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-config-toggle:hover {\n background: #f8fafc;\n}\n\n.vpg-config-toggle.active {\n background: #ecfdf5;\n border-color: #a7f3d0;\n color: #059669;\n}\n\n.vpg-pivot-status {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.875rem;\n color: #059669;\n}\n\n.vpg-clear-filters {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.75rem;\n font-size: 0.875rem;\n font-weight: 500;\n color: #475569;\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 0.375rem;\n cursor: pointer;\n transition: all 0.15s;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-clear-filters:hover {\n background: #f8fafc;\n border-color: #cbd5e1;\n}\n\n/* Grid Container */\n.vpg-grid-container {\n flex: 1;\n overflow: auto;\n position: relative;\n background: rgba(248, 250, 252, 0.3);\n}\n\n.vpg-grid-container:focus {\n outline: none;\n}\n\n.vpg-loading {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.95);\n z-index: 10;\n}\n\n.vpg-spinner {\n width: 2rem;\n height: 2rem;\n border: 2px solid #e2e8f0;\n border-top-color: #4f46e5;\n border-radius: 50%;\n animation: vpg-spin 1s linear infinite;\n}\n\n@keyframes vpg-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n.vpg-loading span {\n margin-top: 0.5rem;\n font-size: 0.875rem;\n color: #64748b;\n}\n\n.vpg-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 5rem;\n gap: 0.75rem;\n}\n\n.vpg-empty-icon {\n width: 5rem;\n height: 5rem;\n border-radius: 50%;\n background: #f1f5f9;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #cbd5e1;\n margin-bottom: 0.5rem;\n}\n\n.vpg-empty-icon.vpg-warning {\n background: #fef3c7;\n color: #fcd34d;\n}\n\n.vpg-empty span {\n color: #64748b;\n font-weight: 500;\n}\n\n.vpg-clear-link {\n color: #4f46e5;\n font-size: 0.875rem;\n font-weight: 500;\n margin-top: 0.25rem;\n background: transparent;\n border: none;\n cursor: pointer;\n}\n\n.vpg-clear-link:hover {\n text-decoration: underline;\n}\n\n.vpg-table-wrapper {\n min-height: 100%;\n}\n\n.vpg-table {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n}\n\n.vpg-table thead {\n position: sticky;\n top: 0;\n z-index: 20;\n box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.1);\n}\n\n.vpg-header-cell {\n z-index: 10;\n padding: 0.75rem 1rem;\n text-align: left;\n cursor: pointer;\n user-select: none;\n background: white;\n transition: all 0.15s;\n border-bottom: 1px solid #e2e8f0;\n border-right: 1px solid #f1f5f9;\n}\n\n.vpg-header-cell:hover {\n background: #f8fafc;\n}\n\n.vpg-header-cell:last-child {\n border-right: none;\n}\n\n.vpg-header-cell.vpg-has-filter {\n background: #eef2ff;\n}\n\n.vpg-header-cell.vpg-is-sorted {\n background: #eff6ff;\n}\n\n.vpg-header-cell.vpg-has-filter.vpg-is-sorted {\n background: #ede9fe;\n}\n\n.vpg-header-cell.vpg-is-active {\n background: #e0e7ff;\n box-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.1);\n}\n\n.vpg-header-content {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n}\n\n.vpg-header-text {\n font-size: 0.75rem;\n font-weight: 600;\n color: #475569;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.vpg-header-icons {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n flex-shrink: 0;\n}\n\n.vpg-sort-indicator {\n color: #3b82f6;\n}\n\n.vpg-filter-indicator {\n color: #4f46e5;\n}\n\n.vpg-dropdown-arrow {\n padding: 0.125rem;\n border-radius: 0.25rem;\n color: #cbd5e1;\n transition: all 0.15s;\n cursor: pointer;\n}\n\n.vpg-dropdown-arrow:hover {\n background: #e2e8f0;\n color: #475569;\n}\n\n.vpg-header-cell:hover .vpg-dropdown-arrow {\n color: #94a3b8;\n}\n\n.vpg-row {\n transition: background 0.15s;\n}\n\n.vpg-row:nth-child(odd) {\n background: white;\n}\n\n.vpg-row:nth-child(even) {\n background: rgba(248, 250, 252, 0.5);\n}\n\n.vpg-row:hover {\n background: rgba(239, 246, 255, 0.4);\n}\n\n.vpg-cell {\n padding: 0.625rem 1rem;\n font-size: 0.875rem;\n color: #334155;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n cursor: cell;\n transition: all 0.15s;\n max-width: 350px;\n border-bottom: 1px solid #f1f5f9;\n border-right: 1px solid #f8fafc;\n}\n\n.vpg-cell:last-child {\n border-right: none;\n}\n\n.vpg-cell.vpg-selected {\n background: rgba(224, 231, 255, 0.8);\n outline: 2px solid #818cf8;\n outline-offset: -2px;\n position: relative;\n z-index: 1;\n}\n\n.vpg-cell.vpg-is-number {\n text-align: right;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n color: #334155;\n font-variant-numeric: tabular-nums;\n}\n\n/* Font size variations */\n.vpg-data-grid.vpg-font-xs .vpg-cell {\n font-size: 0.75rem;\n padding: 0.375rem 0.75rem;\n}\n\n.vpg-data-grid.vpg-font-xs .vpg-header-text {\n font-size: 0.625rem;\n}\n\n.vpg-data-grid.vpg-font-sm .vpg-cell {\n font-size: 0.875rem;\n padding: 0.5rem 1rem;\n}\n\n.vpg-data-grid.vpg-font-base .vpg-cell {\n font-size: 1rem;\n padding: 0.625rem 1rem;\n}\n\n.vpg-data-grid.vpg-font-base .vpg-header-text {\n font-size: 0.75rem;\n}\n\n/* Pivot Container */\n.vpg-pivot-container {\n display: flex;\n flex: 1;\n gap: 1rem;\n overflow: hidden;\n min-height: 0;\n padding: 1rem;\n}\n\n.vpg-pivot-config-panel {\n width: 14rem;\n flex-shrink: 0;\n overflow: hidden;\n}\n\n.vpg-pivot-main {\n flex: 1;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n\n.vpg-pivot-main.vpg-full-width {\n width: 100%;\n}\n\n/* Footer */\n.vpg-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background: rgba(248, 250, 252, 0.8);\n border-top: 1px solid rgba(226, 232, 240, 0.8);\n font-size: 0.875rem;\n}\n\n.vpg-footer-left {\n display: flex;\n align-items: center;\n color: #64748b;\n}\n\n.vpg-filtered-count {\n color: #4f46e5;\n font-weight: 500;\n}\n\n.vpg-separator {\n color: #94a3b8;\n margin: 0 0.25rem;\n}\n\n.vpg-pivot-label {\n color: #10b981;\n font-weight: 500;\n}\n\n.vpg-footer-right {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.vpg-selection-stats {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.25rem 0.75rem;\n background: #eef2ff;\n border-radius: 0.375rem;\n border: 1px solid #c7d2fe;\n}\n\n.vpg-stat {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.vpg-stat-label {\n font-size: 0.75rem;\n color: #4f46e5;\n font-weight: 500;\n}\n\n.vpg-stat-value {\n font-size: 0.75rem;\n color: #1e1b4b;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n}\n\n.vpg-stat-divider {\n color: #c7d2fe;\n}\n\n.vpg-watermark-inline a {\n font-size: 0.75rem;\n color: #94a3b8;\n text-decoration: none;\n transition: color 0.15s;\n}\n\n.vpg-watermark-inline a:hover {\n color: #64748b;\n}\n\n/* Demo Banner */\n.vpg-demo-banner {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.25rem 0.75rem;\n background: linear-gradient(135deg, #fef3c7, #fde68a);\n border: 1px solid #fcd34d;\n border-radius: 0.375rem;\n font-size: 0.75rem;\n color: #92400e;\n}\n\n.vpg-demo-badge {\n display: inline-flex;\n padding: 0.125rem 0.375rem;\n background: #f59e0b;\n color: white;\n font-size: 0.625rem;\n font-weight: 700;\n border-radius: 0.25rem;\n letter-spacing: 0.05em;\n}\n\n.vpg-demo-banner a {\n font-weight: 600;\n color: #d97706;\n text-decoration: none;\n}\n\n.vpg-demo-banner a:hover {\n color: #b45309;\n text-decoration: underline;\n}\n\n/* Scrollbar */\n.vpg-grid-container::-webkit-scrollbar {\n width: 0.625rem;\n height: 0.625rem;\n}\n\n.vpg-grid-container::-webkit-scrollbar-track {\n background: rgba(241, 245, 249, 0.5);\n}\n\n.vpg-grid-container::-webkit-scrollbar-thumb {\n background: rgba(203, 213, 225, 0.8);\n border-radius: 9999px;\n}\n\n.vpg-grid-container::-webkit-scrollbar-thumb:hover {\n background: rgba(148, 163, 184, 0.8);\n}\n\n.vpg-grid-container::-webkit-scrollbar-corner {\n background: rgba(241, 245, 249, 0.5);\n}\n\n/* Toast notification */\n.vpg-toast {\n position: absolute;\n top: 1rem;\n right: 1rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n background: #10b981;\n color: white;\n border-radius: 0.5rem;\n font-size: 0.875rem;\n font-weight: 500;\n box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);\n z-index: 100;\n}\n\n.vpg-toast-enter-active,\n.vpg-toast-leave-active {\n transition: all 0.2s ease;\n}\n\n.vpg-toast-enter-from,\n.vpg-toast-leave-to {\n opacity: 0;\n transform: translateY(-0.5rem);\n}\n\n/* Search */\n.vpg-search-container {\n display: flex;\n align-items: center;\n}\n\n.vpg-icon-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.375rem;\n background: transparent;\n border: none;\n border-radius: 0.375rem;\n color: #64748b;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-icon-btn:hover {\n background: #f1f5f9;\n color: #475569;\n}\n\n.vpg-search-box {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.625rem;\n background: #f8fafc;\n border: 1px solid transparent;\n border-radius: 0.5rem;\n transition: all 0.15s ease;\n}\n\n.vpg-search-box:focus-within {\n background: white;\n border-color: #e2e8f0;\n box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-search-icon {\n width: 1rem;\n height: 1rem;\n color: #94a3b8;\n flex-shrink: 0;\n}\n\n.vpg-search-input {\n border: none;\n outline: none;\n background: transparent;\n font-size: 0.8125rem;\n color: #334155;\n width: 200px;\n}\n\n.vpg-search-input:focus {\n outline: none;\n}\n\n.vpg-search-input::placeholder {\n color: #94a3b8;\n}\n\n.vpg-search-clear {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.125rem;\n background: #f1f5f9;\n border: none;\n border-radius: 50%;\n color: #64748b;\n cursor: pointer;\n}\n\n.vpg-search-clear:hover {\n background: #e2e8f0;\n color: #475569;\n}\n\n.vpg-search-info {\n font-size: 0.75rem;\n color: #64748b;\n font-style: italic;\n}\n\n/* Export button */\n.vpg-export-btn {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.75rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: #059669;\n background: #ecfdf5;\n border: 1px solid #a7f3d0;\n border-radius: 0.375rem;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-export-btn:hover {\n background: #d1fae5;\n border-color: #6ee7b7;\n}\n\n/* Column resize handle */\n.vpg-resize-handle {\n position: absolute;\n right: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: col-resize;\n background: transparent;\n transition: background 0.15s;\n}\n\n.vpg-resize-handle:hover {\n background: rgba(79, 70, 229, 0.3);\n}\n\n.vpg-header-cell {\n position: relative;\n}\n\n.vpg-data-grid.vpg-resizing {\n cursor: col-resize;\n user-select: none;\n}\n\n.vpg-data-grid.vpg-resizing .vpg-resize-handle {\n background: rgba(79, 70, 229, 0.3);\n}\n\n/* Vertical resize handle */\n.vpg-vertical-resize-handle {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 8px;\n cursor: row-resize;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n transition: background 0.15s;\n}\n\n.vpg-vertical-resize-handle:hover {\n background: rgba(79, 70, 229, 0.1);\n}\n\n.vpg-vertical-resize-handle:hover .vpg-resize-grip span {\n background: rgba(79, 70, 229, 0.6);\n}\n\n.vpg-resize-grip {\n display: flex;\n gap: 2px;\n padding: 2px 8px;\n border-radius: 4px;\n}\n\n.vpg-resize-grip span {\n width: 16px;\n height: 2px;\n background: #cbd5e1;\n border-radius: 1px;\n transition: background 0.15s;\n}\n\n.vpg-data-grid.vpg-resizing-vertical {\n cursor: row-resize;\n user-select: none;\n}\n\n.vpg-data-grid.vpg-resizing-vertical .vpg-vertical-resize-handle {\n background: rgba(79, 70, 229, 0.15);\n}\n\n.vpg-data-grid.vpg-resizing-vertical .vpg-resize-grip span {\n background: rgba(79, 70, 229, 0.8);\n}\n\n/* Pagination */\n.vpg-pagination {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.vpg-page-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 0.25rem;\n color: #475569;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-page-btn:hover:not(:disabled) {\n background: #f8fafc;\n border-color: #cbd5e1;\n}\n\n.vpg-page-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.vpg-page-info {\n font-size: 0.75rem;\n color: #64748b;\n padding: 0 0.5rem;\n}\n\n.vpg-filtered-note {\n font-size: 0.75rem;\n color: #94a3b8;\n margin-left: 0.25rem;\n}\n\n/* Dark theme */\n.vpg-data-grid.vpg-theme-dark {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-toolbar {\n background: #0f172a;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-view-toggle {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-view-btn {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-view-btn:hover {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-view-btn.active {\n background: #6366f1;\n color: white;\n}\n\n.vpg-theme-dark .vpg-view-btn.vpg-pivot-btn.active {\n background: #10b981;\n}\n\n.vpg-theme-dark .vpg-label {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-font-size-toggle {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-font-size-btn {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-font-size-btn:hover {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-grid-container {\n background: rgba(15, 23, 42, 0.5);\n}\n\n.vpg-theme-dark .vpg-header-cell {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-header-cell:hover {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-header-text {\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-dropdown-arrow {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-dropdown-arrow:hover {\n background: #475569;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-row:nth-child(odd) {\n background: #1e293b;\n}\n\n.vpg-theme-dark .vpg-row:nth-child(even) {\n background: rgba(30, 41, 59, 0.7);\n}\n\n.vpg-theme-dark .vpg-row:hover {\n background: rgba(51, 65, 85, 0.5);\n}\n\n.vpg-theme-dark .vpg-cell {\n color: #e2e8f0;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-cell.vpg-selected {\n background: rgba(99, 102, 241, 0.3);\n outline-color: #818cf8;\n}\n\n.vpg-theme-dark .vpg-footer {\n background: rgba(15, 23, 42, 0.8);\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-footer-left {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-selection-stats {\n background: rgba(99, 102, 241, 0.2);\n border-color: rgba(99, 102, 241, 0.4);\n}\n\n.vpg-theme-dark .vpg-stat-label {\n color: #a5b4fc;\n}\n\n.vpg-theme-dark .vpg-stat-value {\n color: #e0e7ff;\n}\n\n.vpg-theme-dark .vpg-stat-divider {\n color: rgba(99, 102, 241, 0.4);\n}\n\n.vpg-theme-dark .vpg-search-box {\n background: #334155;\n border-color: transparent;\n}\n\n.vpg-theme-dark .vpg-search-box:focus-within {\n background: #1e293b;\n border-color: #475569;\n}\n\n.vpg-theme-dark .vpg-search-input {\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-search-clear {\n background: #334155;\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-search-clear:hover {\n background: #475569;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-clear-filters {\n background: #1e293b;\n border-color: #334155;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-clear-filters:hover {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-page-btn {\n background: #1e293b;\n border-color: #334155;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-page-btn:hover:not(:disabled) {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-export-btn {\n background: rgba(16, 185, 129, 0.2);\n border-color: rgba(16, 185, 129, 0.4);\n color: #34d399;\n}\n\n.vpg-theme-dark .vpg-export-btn:hover {\n background: rgba(16, 185, 129, 0.3);\n}\n\n.vpg-theme-dark .vpg-config-toggle {\n background: #1e293b;\n border-color: #334155;\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-config-toggle:hover {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-config-toggle.active {\n background: rgba(16, 185, 129, 0.2);\n border-color: rgba(16, 185, 129, 0.4);\n color: #34d399;\n}\n\n.vpg-theme-dark .vpg-pivot-status {\n color: #34d399;\n}\n\n.vpg-theme-dark .vpg-watermark-inline a {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-watermark-inline a:hover {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-resize-grip span {\n background: #475569;\n}\n\n.vpg-theme-dark .vpg-vertical-resize-handle:hover .vpg-resize-grip span {\n background: rgba(129, 140, 248, 0.6);\n}\n\n.vpg-theme-dark.vpg-resizing-vertical .vpg-resize-grip span {\n background: rgba(129, 140, 248, 0.8);\n}\n\n/* Striped rows (toggleable) */\n.vpg-data-grid:not(.vpg-striped) .vpg-row:nth-child(even) {\n background: inherit;\n}\n\n.vpg-theme-dark:not(.vpg-striped) .vpg-row:nth-child(odd),\n.vpg-theme-dark:not(.vpg-striped) .vpg-row:nth-child(even) {\n background: #1e293b;\n}\n</style>\n\n"],"names":["detectColumnType","values","nonNullValues","v","sample","numberCount","dateCount","booleanCount","val","threshold","detectFieldType","data","field","row","uniqueSet","isNumeric","getColumnUniqueValues","columnKey","maxValues","nullCount","value","a","b","numA","numB","formatCellValue","type","num","date","makeKey","fields","f","parseKey","key","aggregate","fn","formatAggregatedValue","getAggregationLabel","computeAvailableFields","getUnassignedFields","availableFields","rowFields","columnFields","valueFields","assigned","isPivotConfigured","config","computePivotResult","showRowTotals","showColumnTotals","rowKeySet","colKeySet","dataMap","rowKey","colKey","colMap","valueArrays","i","vf","rowKeys","colKeys","headers","level","headerRow","parts","valueLabels","rowHeaders","pivotData","rowTotals","columnTotalsMap","rowData","rowTotalValues","colIndex","aggValue","totalCell","allValues","columnTotals","colIdx","valueIdx","allColValues","grandTotal","STORAGE_KEY_PREFIX","generateStorageKey","columns","hash","savePivotConfig","loadPivotConfig","stored","isConfigValidForFields","availableFieldNames","available","FREE_LICENSE","INVALID_LICENSE","DEMO_LICENSE","verifySignature","typeCode","signature","expiry","secret","payload","encoder","keyData","msgData","cryptoKey","sig","expectedSig","validateLicenseKey","expiryStr","year","month","day","expiresAt","configureLicenseSecret","DEMO_SECRET_HASH","hashSecret","hashBuffer","getDemoLicenseInfo","getFreeLicenseInfo","canUsePivot","info","isPro","shouldShowWatermark","isDemo","logProRequired","feature","escapeCSV","delimiter","str","exportToCSV","options","filename","includeHeaders","rows","col","csvContent","downloadFile","exportPivotToCSV","_columnFields","rowHeaderColCount","rowIdx","csvRow","rowHeader","cell","totalsRow","content","mimeType","blob","url","link","copyToClipboard","text","onSuccess","onError","formatSelectionForClipboard","selectionBounds","minRow","maxRow","minCol","maxCol","lines","r","c","colId","multiSelectFilter","columnId","filterValue","cellValue","cellString","useExcelGrid","enableSorting","enableFiltering","sorting","ref","columnFilters","columnVisibility","globalFilter","columnStatsCache","columnKeys","computed","getColumnStats","cacheKey","clearStatsCache","columnDefs","stats","table","useVueTable","updater","getCoreRowModel","getSortedRowModel","getFilteredRowModel","filteredRowCount","totalRowCount","activeFilters","hasActiveFilter","column","setColumnFilter","clearAllFilters","getColumnFilterValues","toggleSort","current","s","getSortDirection","sort","watch","licenseKey","demoMode","licenseInfo","validationPromise","setLicenseKey","enableDemoMode","demoLicense","coreConfigureLicenseSecret","useLicense","coreIsPro","coreCanUsePivot","canUseAdvancedAggregations","canUsePercentageMode","showWatermark","coreShouldShowWatermark","requirePro","usePivotTable","currentStorageKey","unassignedFields","isConfigured","pivotResult","addRowField","removeRowField","addColumnField","removeColumnField","addValueField","aggregation","removeValueField","updateValueFieldAggregation","oldAgg","newAgg","clearConfig","moveField","from","to","items","removed","autoSuggestConfig","categoricalFields","numericFields","newData","newKeys","storageKey","savedConfig","currentConfig","coreExportToCSV","coreExportPivotToCSV","coreCopyToClipboard","coreFormatSelection","usePagination","pageSize","currentPage","totalPages","paginatedData","start","end","startIndex","endIndex","goToPage","page","nextPage","prevPage","firstPage","lastPage","setPageSize","size","useGlobalSearch","searchTerm","caseSensitive","filteredData","term","clearSearch","useRowSelection","selectedRowIndices","selectedRows","idx","allSelected","someSelected","toggleRow","index","selectRow","deselectRow","selectAll","_","deselectAll","toggleAll","isSelected","selectRange","min","max","useColumnResize","initialWidths","minWidth","maxWidth","columnWidths","isResizing","resizingColumn","startResize","event","startX","startWidth","handleMouseMove","e","diff","newWidth","handleMouseUp","resetColumnWidth","resetAllWidths","props","__props","emit","__emit","searchQuery","dropdownRef","searchInputRef","localSelected","hasBlankValues","filteredValues","query","toggleValue","clearAll","applyFilter","sortAscending","sortDescending","clearFilter","handleClickOutside","handleKeydown","onMounted","nextTick","_a","onUnmounted","newValues","_createElementBlock","_createElementVNode","_hoisted_1","_hoisted_2","_toDisplayString","_hoisted_3","_hoisted_4","_normalizeClass","_hoisted_5","$event","_hoisted_6","_Fragment","_renderList","_hoisted_8","aggregationOptions","getAggSymbol","agg","assignedFields","rowSet","colSet","valueMap","valSet","assignedCount","fieldSearch","filteredUnassignedFields","search","getFieldIcon","handleDragStart","handleDragEnd","handleAggregationChange","currentAgg","toggleRowColumn","currentAssignment","removeField","assignedTo","valueConfig","_openBlock","_cache","_hoisted_7","_hoisted_9","_withModifiers","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_21","_hoisted_22","_hoisted_23","_hoisted_24","_hoisted_25","_hoisted_26","_hoisted_27","_unref","_hoisted_29","dragOverArea","reorderDragSource","reorderDropTarget","aggregationLabels","currentFontSize","fontSizeOptions","hasActiveFilters","filterSummary","filterTooltipDetails","displayValues","remaining","showFilterTooltip","sortDirection","sortTarget","target","sortedRowIndices","indices","cmp","aHeader","bHeader","_b","aVal","_d","_c","bVal","_f","_e","columnHeaderCells","result","cells","colspan","selectedCell","handleCellClick","rowIndex","isCellSelected","handleDragOver","area","handleDragLeave","handleDrop","existingValue","handleChipDragStart","zone","handleChipDragEnd","handleChipDragOver","handleChipDragLeave","handleChipDrop","targetIndex","sourceIndex","movedField","isChipDragSource","isChipDropTarget","rowHeaderWidth","dataColWidth","filter","_hoisted_10","_hoisted_11","opt","_hoisted_20","_hoisted_28","_hoisted_30","_hoisted_31","_hoisted_32","_hoisted_33","_hoisted_34","_hoisted_35","_hoisted_36","_hoisted_37","levelIdx","_hoisted_39","_normalizeStyle","_hoisted_41","_hoisted_42","sortedIdx","_hoisted_43","_hoisted_44","_hoisted_45","_hoisted_46","_hoisted_47","_hoisted_48","MIN_COL_WIDTH","MAX_COL_WIDTH","currentTheme","globalSearchTerm","showSearchInput","resizingColumnId","resizeStartX","resizeStartWidth","gridHeight","isResizingVertically","verticalResizeStartY","verticalResizeStartHeight","showCopyToast","copyToastMessage","dataRef","filteredDataForPivot","activeFilterInfo","pivotRowFields","pivotColumnFields","pivotValueFields","pivotShowRowTotals","pivotShowColumnTotals","pivotAvailableFields","pivotIsConfigured","clearPivotConfig","searchFilteredData","totalSearchedRows","paginatedRows","paginationStart","paginationEnd","handleExport","viewMode","handlePivotExport","dataToExport","pivotFilename","rowCount","startColumnResize","handleResizeMove","handleResizeEnd","startVerticalResize","handleVerticalResizeMove","handleVerticalResizeEnd","newHeight","copySelectionToClipboard","cellCount","err","showPivotConfig","draggingField","handlePivotDragStart","handlePivotDragEnd","reorderRowFields","reorderColumnFields","tableContainerRef","tableBodyRef","activeFilterColumn","filterDropdownPosition","calculateColumnWidths","widths","sampleSize","ctx","width","openFilterDropdown","headerCell","rect","dropdownWidth","padding","left","spaceBelow","spaceAbove","top","maxHeight","closeFilterDropdown","handleFilter","handleSort","direction","activeFilterCount","selectionStart","selectionEnd","isSelecting","selectColumn","handleHeaderClick","isCellInSelection","selectionStats","count","sum","avg","formatStatValue","input","updateSelection","newRow","newCol","scrollCellIntoView","handleMouseDown","handleMouseEnter","noFormatPatterns","shouldFormatNumber","handleTableScroll","handleWindowScroll","totalTableWidth","handleContainerClick","_createVNode","_Transition","_createTextVNode","_withKeys","args","PivotConfig","PivotSkeleton","_hoisted_49","_hoisted_50","_hoisted_51","_createBlock","_Teleport","ColumnFilter","dir"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tinypivot-vue.umd.cjs","sources":["../../core/dist/utils/index.js","../../core/dist/pivot/index.js","../../core/dist/license/index.js","../../core/dist/export/index.js","../src/composables/useExcelGrid.ts","../src/composables/useLicense.ts","../src/composables/usePivotTable.ts","../src/composables/useGridFeatures.ts","../src/components/ColumnFilter.vue","../src/components/PivotConfig.vue","../src/components/PivotSkeleton.vue","../src/components/DataGrid.vue"],"sourcesContent":["/**\n * Detect column data type from values\n */\nexport function detectColumnType(values) {\n const nonNullValues = values.filter(v => v !== null && v !== undefined && v !== '');\n if (nonNullValues.length === 0)\n return 'string';\n const sample = nonNullValues.slice(0, 100);\n let numberCount = 0;\n let dateCount = 0;\n let booleanCount = 0;\n for (const val of sample) {\n if (typeof val === 'boolean') {\n booleanCount++;\n }\n else if (typeof val === 'number' || (!Number.isNaN(Number(val)) && val !== '')) {\n numberCount++;\n }\n else if (val instanceof Date || !Number.isNaN(Date.parse(String(val)))) {\n dateCount++;\n }\n }\n const threshold = sample.length * 0.8;\n if (booleanCount >= threshold)\n return 'boolean';\n if (numberCount >= threshold)\n return 'number';\n if (dateCount >= threshold)\n return 'date';\n return 'string';\n}\n/**\n * Detect field type from sample data (for pivot)\n */\nexport function detectFieldType(data, field) {\n const values = data.map(row => row[field]).filter(v => v !== null && v !== undefined && v !== '');\n const sample = values.slice(0, 100);\n let numberCount = 0;\n const uniqueSet = new Set();\n for (const val of sample) {\n uniqueSet.add(String(val));\n if (typeof val === 'number' || (!Number.isNaN(Number(val)) && val !== '')) {\n numberCount++;\n }\n }\n const isNumeric = numberCount >= sample.length * 0.8;\n return {\n field,\n type: isNumeric ? 'number' : 'string',\n uniqueCount: uniqueSet.size,\n isNumeric,\n };\n}\n/**\n * Get unique values for a column (for Excel-style filter dropdown)\n */\nexport function getColumnUniqueValues(data, columnKey, maxValues = 500) {\n const values = [];\n let nullCount = 0;\n for (const row of data) {\n const value = row[columnKey];\n if (value === null || value === undefined || value === '') {\n nullCount++;\n }\n else {\n values.push(value);\n }\n }\n // Get unique values\n const uniqueSet = new Set();\n for (const val of values) {\n uniqueSet.add(String(val));\n if (uniqueSet.size >= maxValues)\n break;\n }\n const uniqueValues = Array.from(uniqueSet).sort((a, b) => {\n // Natural sort for numbers\n const numA = Number.parseFloat(a);\n const numB = Number.parseFloat(b);\n if (!Number.isNaN(numA) && !Number.isNaN(numB)) {\n return numA - numB;\n }\n return a.localeCompare(b);\n });\n return {\n uniqueValues,\n totalCount: data.length,\n nullCount,\n type: detectColumnType(values),\n };\n}\n/**\n * Format cell value for display\n */\nexport function formatCellValue(value, type) {\n if (value === null || value === undefined)\n return '';\n if (value === '')\n return '';\n switch (type) {\n case 'number': {\n const num = typeof value === 'number' ? value : Number.parseFloat(String(value));\n if (Number.isNaN(num))\n return String(value);\n // Format with commas for large numbers\n if (Math.abs(num) >= 1000) {\n return num.toLocaleString('en-US', { maximumFractionDigits: 2 });\n }\n return num.toLocaleString('en-US', { maximumFractionDigits: 4 });\n }\n case 'date': {\n const date = value instanceof Date ? value : new Date(String(value));\n if (Number.isNaN(date.getTime()))\n return String(value);\n return date.toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n }\n case 'boolean':\n return value ? 'Yes' : 'No';\n default:\n return String(value);\n }\n}\n/**\n * Format number for display with appropriate precision\n */\nexport function formatNumber(value, options) {\n if (value === null)\n return '-';\n const maxDigits = options?.maximumFractionDigits ?? (Math.abs(value) >= 1000 ? 2 : 4);\n return value.toLocaleString('en-US', { maximumFractionDigits: maxDigits });\n}\n/**\n * Create a composite key from field values (for pivot grouping)\n */\nexport function makeKey(row, fields) {\n return fields.map(f => String(row[f] ?? '(blank)')).join('|||');\n}\n/**\n * Parse composite key back to values\n */\nexport function parseKey(key) {\n return key.split('|||');\n}\n/**\n * Natural sort comparator\n */\nexport function naturalSort(a, b) {\n const numA = Number.parseFloat(a);\n const numB = Number.parseFloat(b);\n if (!Number.isNaN(numA) && !Number.isNaN(numB)) {\n return numA - numB;\n }\n return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });\n}\n/**\n * Debounce function\n */\nexport function debounce(fn, delay) {\n let timeoutId = null;\n return (...args) => {\n if (timeoutId)\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => fn(...args), delay);\n };\n}\n/**\n * Clamp a number between min and max\n */\nexport function clamp(value, min, max) {\n return Math.max(min, Math.min(max, value));\n}\n//# sourceMappingURL=index.js.map","import { detectFieldType, makeKey, parseKey } from '../utils';\n/**\n * Aggregate values based on function type\n */\nexport function aggregate(values, fn) {\n if (values.length === 0)\n return null;\n switch (fn) {\n case 'sum':\n return values.reduce((a, b) => a + b, 0);\n case 'count':\n return values.length;\n case 'avg':\n return values.reduce((a, b) => a + b, 0) / values.length;\n case 'min':\n return Math.min(...values);\n case 'max':\n return Math.max(...values);\n case 'countDistinct':\n return new Set(values).size;\n default:\n return values.reduce((a, b) => a + b, 0);\n }\n}\n/**\n * Format aggregated value for display\n */\nexport function formatAggregatedValue(value, fn) {\n if (value === null)\n return '-';\n if (fn === 'count' || fn === 'countDistinct') {\n return Math.round(value).toLocaleString();\n }\n if (Math.abs(value) >= 1000) {\n return value.toLocaleString('en-US', { maximumFractionDigits: 2 });\n }\n return value.toLocaleString('en-US', { maximumFractionDigits: 4 });\n}\n/**\n * Get aggregation function display label\n */\nexport function getAggregationLabel(fn) {\n const labels = {\n sum: 'Sum',\n count: 'Count',\n avg: 'Average',\n min: 'Min',\n max: 'Max',\n countDistinct: 'Count Distinct',\n };\n return labels[fn];\n}\n/**\n * Get aggregation function symbol\n */\nexport function getAggregationSymbol(fn) {\n const symbols = {\n sum: 'Σ',\n count: '#',\n avg: 'x̄',\n min: '↓',\n max: '↑',\n countDistinct: '◇',\n };\n return symbols[fn];\n}\n/**\n * Aggregation options for UI\n */\nexport const AGGREGATION_OPTIONS = [\n { value: 'sum', label: 'Sum', symbol: 'Σ' },\n { value: 'count', label: 'Count', symbol: '#' },\n { value: 'avg', label: 'Avg', symbol: 'x̄' },\n { value: 'min', label: 'Min', symbol: '↓' },\n { value: 'max', label: 'Max', symbol: '↑' },\n { value: 'countDistinct', label: 'Unique', symbol: '◇' },\n];\n/**\n * Compute available fields from data\n */\nexport function computeAvailableFields(data) {\n if (data.length === 0)\n return [];\n const keys = Object.keys(data[0]);\n return keys.map(field => detectFieldType(data, field));\n}\n/**\n * Get unassigned fields (not in row, column, or value fields)\n */\nexport function getUnassignedFields(availableFields, rowFields, columnFields, valueFields) {\n const assigned = new Set([\n ...rowFields,\n ...columnFields,\n ...valueFields.map(v => v.field),\n ]);\n return availableFields.filter(f => !assigned.has(f.field));\n}\n/**\n * Check if pivot is configured\n */\nexport function isPivotConfigured(config) {\n return (config.rowFields.length > 0 || config.columnFields.length > 0) && config.valueFields.length > 0;\n}\n/**\n * Build pivot result from data and config\n */\nexport function computePivotResult(data, config) {\n const { rowFields, columnFields, valueFields, showRowTotals, showColumnTotals } = config;\n if (!isPivotConfigured(config))\n return null;\n if (data.length === 0)\n return null;\n // Collect unique row and column keys\n const rowKeySet = new Set();\n const colKeySet = new Set();\n // Group data by row and column keys\n const dataMap = new Map();\n for (const row of data) {\n const rowKey = rowFields.length > 0 ? makeKey(row, rowFields) : '__all__';\n const colKey = columnFields.length > 0 ? makeKey(row, columnFields) : '__all__';\n rowKeySet.add(rowKey);\n colKeySet.add(colKey);\n if (!dataMap.has(rowKey)) {\n dataMap.set(rowKey, new Map());\n }\n const colMap = dataMap.get(rowKey);\n if (!colMap.has(colKey)) {\n colMap.set(colKey, valueFields.map(() => []));\n }\n const valueArrays = colMap.get(colKey);\n // Collect values for each value field\n for (let i = 0; i < valueFields.length; i++) {\n const vf = valueFields[i];\n const val = row[vf.field];\n if (val !== null && val !== undefined && val !== '') {\n const num = typeof val === 'number' ? val : Number.parseFloat(String(val));\n if (!Number.isNaN(num)) {\n valueArrays[i].push(num);\n }\n else if (vf.aggregation === 'count' || vf.aggregation === 'countDistinct') {\n valueArrays[i].push(1);\n }\n }\n }\n }\n // Sort keys\n const rowKeys = Array.from(rowKeySet).sort();\n const colKeys = Array.from(colKeySet).sort();\n // Build column headers\n const headers = [];\n if (columnFields.length > 0) {\n for (let level = 0; level < columnFields.length; level++) {\n const headerRow = [];\n for (const colKey of colKeys) {\n const parts = parseKey(colKey);\n headerRow.push(parts[level] || '');\n }\n headers.push(headerRow);\n }\n }\n // If multiple value fields, add value field labels as last header row\n if (valueFields.length > 1 || headers.length === 0) {\n const valueLabels = [];\n for (const colKey of colKeys) {\n for (const vf of valueFields) {\n valueLabels.push(`${vf.label || vf.field} (${getAggregationLabel(vf.aggregation)})`);\n }\n }\n if (colKeys.length === 1 && colKeys[0] === '__all__') {\n headers.push(valueFields.map(vf => `${vf.label || vf.field} (${getAggregationLabel(vf.aggregation)})`));\n }\n else {\n headers.push(valueLabels);\n }\n }\n // Build row headers\n const rowHeaders = rowKeys.map(key => {\n if (key === '__all__')\n return ['Total'];\n return parseKey(key);\n });\n // Build data matrix\n const pivotData = [];\n const rowTotals = [];\n const columnTotalsMap = new Map();\n for (const rowKey of rowKeys) {\n const rowData = [];\n const rowTotalValues = valueFields.map(() => []);\n let colIndex = 0;\n for (const colKey of colKeys) {\n const colMap = dataMap.get(rowKey);\n const valueArrays = colMap?.get(colKey) || valueFields.map(() => []);\n for (let i = 0; i < valueFields.length; i++) {\n const vf = valueFields[i];\n const values = valueArrays[i];\n const aggValue = aggregate(values, vf.aggregation);\n rowData.push({\n value: aggValue,\n count: values.length,\n formattedValue: formatAggregatedValue(aggValue, vf.aggregation),\n });\n rowTotalValues[i].push(...values);\n if (!columnTotalsMap.has(colIndex)) {\n columnTotalsMap.set(colIndex, valueFields.map(() => []));\n }\n columnTotalsMap.get(colIndex)[i].push(...values);\n colIndex++;\n }\n }\n pivotData.push(rowData);\n if (showRowTotals && colKeys.length > 1) {\n const totalCell = {\n value: null,\n count: 0,\n formattedValue: '-',\n };\n if (valueFields.length > 0) {\n const vf = valueFields[0];\n const allValues = rowTotalValues[0];\n const aggValue = aggregate(allValues, vf.aggregation);\n totalCell.value = aggValue;\n totalCell.count = allValues.length;\n totalCell.formattedValue = formatAggregatedValue(aggValue, vf.aggregation);\n }\n rowTotals.push(totalCell);\n }\n }\n // Calculate column totals\n const columnTotals = [];\n if (showColumnTotals && rowKeys.length > 1) {\n for (let colIdx = 0; colIdx < colKeys.length * valueFields.length; colIdx++) {\n const valueIdx = colIdx % valueFields.length;\n const vf = valueFields[valueIdx];\n const allColValues = [];\n for (const rowKey of rowKeys) {\n const colMap = dataMap.get(rowKey);\n const colKey = colKeys[Math.floor(colIdx / valueFields.length)];\n const valueArrays = colMap?.get(colKey) || valueFields.map(() => []);\n allColValues.push(...valueArrays[valueIdx]);\n }\n const aggValue = aggregate(allColValues, vf.aggregation);\n columnTotals.push({\n value: aggValue,\n count: allColValues.length,\n formattedValue: formatAggregatedValue(aggValue, vf.aggregation),\n });\n }\n }\n // Grand total\n const grandTotal = { value: null, count: 0, formattedValue: '-' };\n if (showRowTotals && showColumnTotals && valueFields.length > 0) {\n const vf = valueFields[0];\n const allValues = [];\n for (const row of data) {\n const val = row[vf.field];\n if (val !== null && val !== undefined && val !== '') {\n const num = typeof val === 'number' ? val : Number.parseFloat(String(val));\n if (!Number.isNaN(num)) {\n allValues.push(num);\n }\n else if (vf.aggregation === 'count' || vf.aggregation === 'countDistinct') {\n allValues.push(1);\n }\n }\n }\n const aggValue = aggregate(allValues, vf.aggregation);\n grandTotal.value = aggValue;\n grandTotal.count = allValues.length;\n grandTotal.formattedValue = formatAggregatedValue(aggValue, vf.aggregation);\n }\n return {\n headers,\n rowHeaders,\n data: pivotData,\n rowTotals,\n columnTotals,\n grandTotal,\n };\n}\n// Storage helpers for pivot config persistence\nconst STORAGE_KEY_PREFIX = 'vpg-pivot-';\n/**\n * Generate a storage key based on column names\n */\nexport function generateStorageKey(columns) {\n const sorted = [...columns].sort();\n const hash = sorted.join('|').substring(0, 100);\n return `${STORAGE_KEY_PREFIX}${hash}`;\n}\n/**\n * Save pivot config to sessionStorage\n */\nexport function savePivotConfig(key, config) {\n try {\n sessionStorage.setItem(key, JSON.stringify(config));\n }\n catch {\n // Ignore storage errors\n }\n}\n/**\n * Load pivot config from sessionStorage\n */\nexport function loadPivotConfig(key) {\n try {\n const stored = sessionStorage.getItem(key);\n if (stored) {\n return JSON.parse(stored);\n }\n }\n catch {\n // Ignore parse errors\n }\n return null;\n}\n/**\n * Check if config fields exist in available fields\n */\nexport function isConfigValidForFields(config, availableFieldNames) {\n const available = new Set(availableFieldNames);\n const allConfiguredFields = [\n ...config.rowFields,\n ...config.columnFields,\n ...config.valueFields.map(v => v.field),\n ];\n return allConfiguredFields.every(f => available.has(f));\n}\n//# sourceMappingURL=index.js.map","const FREE_LICENSE = {\n type: 'free',\n isValid: true,\n features: {\n pivot: false,\n advancedAggregations: false,\n percentageMode: false,\n sessionPersistence: false,\n noWatermark: false,\n },\n};\nconst INVALID_LICENSE = {\n type: 'free',\n isValid: false,\n features: {\n pivot: false,\n advancedAggregations: false,\n percentageMode: false,\n sessionPersistence: false,\n noWatermark: false,\n },\n};\nconst DEMO_LICENSE = {\n type: 'free',\n isValid: true,\n features: {\n pivot: true,\n advancedAggregations: true,\n percentageMode: true,\n sessionPersistence: true,\n noWatermark: false, // Still show watermark in demo\n },\n};\n/**\n * HMAC-SHA256 based license signature verification\n * Must match the server-side generation algorithm\n */\nasync function verifySignature(typeCode, signature, expiry) {\n // The secret must be configured before license validation can work\n const secret = globalThis.__TP_LICENSE_SECRET__;\n if (!secret) {\n console.warn('[TinyPivot] License secret not configured. Call configureLicenseSecret() first.');\n return false;\n }\n const payload = `TP-${typeCode}-${expiry}`;\n try {\n const encoder = new TextEncoder();\n const keyData = encoder.encode(secret);\n const msgData = encoder.encode(payload);\n const cryptoKey = await crypto.subtle.importKey('raw', keyData, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);\n const sig = await crypto.subtle.sign('HMAC', cryptoKey, msgData);\n const sigArray = Array.from(new Uint8Array(sig));\n const expectedSig = sigArray\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n .slice(0, 12)\n .toUpperCase();\n return signature === expectedSig;\n }\n catch {\n // Fallback for environments without crypto.subtle (SSR, older browsers)\n return false;\n }\n}\n/**\n * Validate a license key and extract info\n */\nexport async function validateLicenseKey(key) {\n // Free tier - no key needed\n if (!key || key === '') {\n return FREE_LICENSE;\n }\n // License key format: TP-{TYPE}-{SIGNATURE}-{EXPIRY}\n // Example: TP-PRO1-A1B2C3D4E5F6-20251231\n const parts = key.split('-');\n if (parts.length !== 4 || parts[0] !== 'TP') {\n return INVALID_LICENSE;\n }\n const typeCode = parts[1];\n const signature = parts[2];\n const expiryStr = parts[3];\n // Verify cryptographic signature\n const isValidSignature = await verifySignature(typeCode, signature, expiryStr);\n if (!isValidSignature) {\n return INVALID_LICENSE;\n }\n // Parse expiry date\n const year = Number.parseInt(expiryStr.slice(0, 4));\n const month = Number.parseInt(expiryStr.slice(4, 6)) - 1;\n const day = Number.parseInt(expiryStr.slice(6, 8));\n const expiresAt = new Date(year, month, day);\n if (expiresAt < new Date()) {\n return { ...INVALID_LICENSE, expiresAt };\n }\n // Determine license type\n let type = 'free';\n if (typeCode === 'PRO1')\n type = 'pro-single';\n else if (typeCode === 'PROU')\n type = 'pro-unlimited';\n else if (typeCode === 'PROT')\n type = 'pro-team';\n return {\n type,\n isValid: true,\n expiresAt,\n features: {\n pivot: type !== 'free',\n advancedAggregations: type !== 'free',\n percentageMode: type !== 'free',\n sessionPersistence: type !== 'free',\n noWatermark: type !== 'free',\n },\n };\n}\n/**\n * Configure the license secret (for SSR/build-time injection)\n */\nexport function configureLicenseSecret(secret) {\n globalThis.__TP_LICENSE_SECRET__ = secret;\n}\n// Hardcoded SHA-256 hash of the demo secret\nconst DEMO_SECRET_HASH = 'A48AA0618518D3E62F31FCFCA2DD2B86E7FE0863E2F90756FB0A960AE7A51583';\n/**\n * Hash a string using SHA-256 (async for Web Crypto API)\n */\nasync function hashSecret(secret) {\n try {\n const encoder = new TextEncoder();\n const data = encoder.encode(secret);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('').toUpperCase();\n }\n catch {\n return '';\n }\n}\n/**\n * Validate demo secret and return demo license info if valid\n * Returns null if secret is invalid\n */\nexport async function getDemoLicenseInfo(secret) {\n if (!secret) {\n return null;\n }\n const hash = await hashSecret(secret);\n if (hash !== DEMO_SECRET_HASH) {\n return null;\n }\n return DEMO_LICENSE;\n}\n/**\n * Get free license info\n */\nexport function getFreeLicenseInfo() {\n return FREE_LICENSE;\n}\n/**\n * Check if license allows pivot feature\n */\nexport function canUsePivot(info) {\n return info.features.pivot;\n}\n/**\n * Check if license is pro (any tier)\n */\nexport function isPro(info) {\n return info.isValid && info.type !== 'free';\n}\n/**\n * Check if watermark should be shown\n */\nexport function shouldShowWatermark(info, isDemo) {\n return isDemo || !info.features.noWatermark;\n}\n/**\n * Log pro requirement warning\n */\nexport function logProRequired(feature) {\n console.warn(`[TinyPivot] \"${feature}\" requires a Pro license. ` +\n `Visit https://tiny-pivot.com/#pricing to upgrade.`);\n}\n//# sourceMappingURL=index.js.map","/**\n * Escape CSV value\n */\nfunction escapeCSV(value, delimiter = ',') {\n if (value === null || value === undefined)\n return '';\n const str = String(value);\n if (str.includes(delimiter) || str.includes('\"') || str.includes('\\n')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n}\n/**\n * CSV Export functionality\n */\nexport function exportToCSV(data, columns, options = {}) {\n const { filename = 'export.csv', includeHeaders = true, delimiter = ',' } = options;\n const rows = [];\n if (includeHeaders) {\n rows.push(columns.map(col => escapeCSV(col, delimiter)).join(delimiter));\n }\n for (const row of data) {\n const values = columns.map(col => escapeCSV(row[col], delimiter));\n rows.push(values.join(delimiter));\n }\n const csvContent = rows.join('\\n');\n downloadFile(csvContent, filename, 'text/csv;charset=utf-8;');\n}\n/**\n * Export pivot table to CSV\n */\nexport function exportPivotToCSV(pivotData, rowFields, _columnFields, valueFields, options = {}) {\n const { filename = 'pivot-export.csv', delimiter = ',' } = options;\n const rows = [];\n const { headers, rowHeaders, data, rowTotals, columnTotals, grandTotal, showRowTotals, showColumnTotals } = pivotData;\n // Calculate number of row header columns\n const rowHeaderColCount = rowFields.length || 1;\n // Build column headers\n if (headers.length > 0) {\n // Multi-level column headers\n for (let level = 0; level < headers.length; level++) {\n const headerRow = [];\n // Empty cells for row field columns\n for (let i = 0; i < rowHeaderColCount; i++) {\n headerRow.push(level === headers.length - 1 ? escapeCSV(rowFields[i] || '', delimiter) : '');\n }\n // Column header values\n for (const val of headers[level]) {\n headerRow.push(escapeCSV(val, delimiter));\n }\n // Row totals header\n if (showRowTotals && rowTotals && rowTotals.length > 0) {\n if (level === headers.length - 1) {\n for (const vf of valueFields) {\n headerRow.push(escapeCSV(`Total (${vf.aggregation})`, delimiter));\n }\n }\n else {\n for (let i = 0; i < valueFields.length; i++) {\n headerRow.push('');\n }\n }\n }\n rows.push(headerRow.join(delimiter));\n }\n }\n else {\n // Simple header with value fields only\n const headerRow = [];\n for (let i = 0; i < rowHeaderColCount; i++) {\n headerRow.push(escapeCSV(rowFields[i] || '', delimiter));\n }\n for (const vf of valueFields) {\n headerRow.push(escapeCSV(`${vf.field} (${vf.aggregation})`, delimiter));\n }\n if (showRowTotals && rowTotals && rowTotals.length > 0) {\n headerRow.push(escapeCSV('Total', delimiter));\n }\n rows.push(headerRow.join(delimiter));\n }\n // Build data rows\n for (let rowIdx = 0; rowIdx < rowHeaders.length; rowIdx++) {\n const csvRow = [];\n // Row headers\n const rowHeader = rowHeaders[rowIdx] || [];\n for (let i = 0; i < rowHeaderColCount; i++) {\n csvRow.push(escapeCSV(rowHeader[i] || '', delimiter));\n }\n // Data cells\n const rowData = data[rowIdx] || [];\n for (const cell of rowData) {\n csvRow.push(escapeCSV(cell?.formattedValue || '', delimiter));\n }\n // Row total\n if (showRowTotals && rowTotals && rowTotals[rowIdx]) {\n csvRow.push(escapeCSV(rowTotals[rowIdx].formattedValue || '', delimiter));\n }\n rows.push(csvRow.join(delimiter));\n }\n // Column totals row\n if (showColumnTotals && columnTotals && columnTotals.length > 0) {\n const totalsRow = [];\n // Label for totals row\n totalsRow.push(escapeCSV('Total', delimiter));\n for (let i = 1; i < rowHeaderColCount; i++) {\n totalsRow.push('');\n }\n // Column total values\n for (const cell of columnTotals) {\n totalsRow.push(escapeCSV(cell?.formattedValue || '', delimiter));\n }\n // Grand total\n if (showRowTotals && grandTotal) {\n totalsRow.push(escapeCSV(grandTotal.formattedValue || '', delimiter));\n }\n rows.push(totalsRow.join(delimiter));\n }\n const csvContent = rows.join('\\n');\n downloadFile(csvContent, filename, 'text/csv;charset=utf-8;');\n}\n/**\n * Download file helper\n */\nfunction downloadFile(content, filename, mimeType) {\n const blob = new Blob([content], { type: mimeType });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n link.style.display = 'none';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n}\n/**\n * Copy text to clipboard\n */\nexport function copyToClipboard(text, onSuccess, onError) {\n navigator.clipboard.writeText(text).then(onSuccess).catch(onError);\n}\n/**\n * Format selected cells for clipboard (tab-separated)\n */\nexport function formatSelectionForClipboard(rows, columns, selectionBounds) {\n const { minRow, maxRow, minCol, maxCol } = selectionBounds;\n const lines = [];\n for (let r = minRow; r <= maxRow; r++) {\n const row = rows[r];\n if (!row)\n continue;\n const values = [];\n for (let c = minCol; c <= maxCol; c++) {\n const colId = columns[c];\n if (!colId)\n continue;\n const value = row[colId];\n values.push(value === null || value === undefined ? '' : String(value));\n }\n lines.push(values.join('\\t'));\n }\n return lines.join('\\n');\n}\n//# sourceMappingURL=index.js.map","/**\n * Excel-like Grid Composable for Vue\n * Provides Excel-like filtering, sorting, and data manipulation functionality\n */\nimport type { ColumnDef, ColumnFiltersState, FilterFn, SortingState, VisibilityState } from '@tanstack/vue-table'\nimport {\n getCoreRowModel,\n getFilteredRowModel,\n getSortedRowModel,\n useVueTable,\n} from '@tanstack/vue-table'\nimport { type Ref, computed, ref, watch } from 'vue'\nimport type { ColumnStats } from '@smallwebco/tinypivot-core'\nimport { getColumnUniqueValues, formatCellValue } from '@smallwebco/tinypivot-core'\n\n// Re-export for convenience\nexport { getColumnUniqueValues, formatCellValue }\n\nexport interface ExcelGridOptions<T> {\n data: Ref<T[]>\n columns?: string[]\n enableSorting?: boolean\n enableFiltering?: boolean\n pageSize?: number\n}\n\n/**\n * Multi-value filter function for Excel-style filtering\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst multiSelectFilter: FilterFn<any> = (row, columnId, filterValue) => {\n if (!filterValue || !Array.isArray(filterValue) || filterValue.length === 0) {\n return true\n }\n\n const cellValue = row.getValue(columnId)\n const cellString = cellValue === null || cellValue === undefined || cellValue === ''\n ? '(blank)'\n : String(cellValue)\n\n return filterValue.includes(cellString)\n}\n\n/**\n * Create Excel-like grid composable\n */\nexport function useExcelGrid<T extends Record<string, unknown>>(options: ExcelGridOptions<T>) {\n const { data, enableSorting = true, enableFiltering = true } = options\n\n // State\n const sorting = ref<SortingState>([])\n const columnFilters = ref<ColumnFiltersState>([])\n const columnVisibility = ref<VisibilityState>({})\n const globalFilter = ref('')\n\n // Column statistics cache\n const columnStatsCache = ref<Record<string, ColumnStats>>({})\n\n // Compute columns from data\n const columnKeys = computed(() => {\n if (data.value.length === 0) return []\n return Object.keys(data.value[0] as Record<string, unknown>)\n })\n\n // Get column stats (memoized)\n function getColumnStats(columnKey: string): ColumnStats {\n const cacheKey = `${columnKey}-${data.value.length}`\n if (!columnStatsCache.value[cacheKey]) {\n columnStatsCache.value[cacheKey] = getColumnUniqueValues(data.value, columnKey)\n }\n return columnStatsCache.value[cacheKey]\n }\n\n // Clear stats cache when data changes\n function clearStatsCache() {\n columnStatsCache.value = {}\n }\n\n // Create column definitions dynamically\n const columnDefs = computed<ColumnDef<T, unknown>[]>(() => {\n return columnKeys.value.map(key => {\n const stats = getColumnStats(key)\n\n return {\n id: key,\n accessorKey: key,\n header: key,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n cell: (info: any) => formatCellValue(info.getValue(), stats.type),\n filterFn: multiSelectFilter,\n meta: {\n type: stats.type,\n uniqueCount: stats.uniqueValues.length,\n },\n } as ColumnDef<T, unknown>\n })\n })\n\n // Create table instance\n const table = useVueTable({\n get data() { return data.value },\n get columns() { return columnDefs.value },\n state: {\n get sorting() { return sorting.value },\n get columnFilters() { return columnFilters.value },\n get columnVisibility() { return columnVisibility.value },\n get globalFilter() { return globalFilter.value },\n },\n onSortingChange: updater => {\n sorting.value = typeof updater === 'function' ? updater(sorting.value) : updater\n },\n onColumnFiltersChange: updater => {\n columnFilters.value = typeof updater === 'function' ? updater(columnFilters.value) : updater\n },\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: enableSorting ? getSortedRowModel() : undefined,\n getFilteredRowModel: enableFiltering ? getFilteredRowModel() : undefined,\n filterFns: {\n multiSelect: multiSelectFilter,\n },\n enableSorting,\n enableFilters: enableFiltering,\n })\n\n // Computed properties\n const filteredRowCount = computed(() => table.getFilteredRowModel().rows.length)\n const totalRowCount = computed(() => data.value.length)\n\n // Active filters\n const activeFilters = computed(() => {\n return columnFilters.value.map(f => ({\n column: f.id,\n values: f.value as string[],\n }))\n })\n\n // Check if column has active filter\n function hasActiveFilter(columnId: string): boolean {\n const column = table.getColumn(columnId)\n if (!column) return false\n const filterValue = column.getFilterValue()\n return filterValue !== undefined && Array.isArray(filterValue) && filterValue.length > 0\n }\n\n // Set column filter\n function setColumnFilter(columnId: string, values: string[]) {\n const column = table.getColumn(columnId)\n if (column) {\n column.setFilterValue(values.length === 0 ? undefined : values)\n // Force sync columnFilters ref with table state\n columnFilters.value = table.getState().columnFilters\n }\n }\n\n // Clear all filters\n function clearAllFilters() {\n table.resetColumnFilters()\n globalFilter.value = ''\n // Force sync columnFilters ref with table state\n columnFilters.value = []\n }\n\n // Get filter values for a specific column\n function getColumnFilterValues(columnId: string): string[] {\n const column = table.getColumn(columnId)\n if (!column) return []\n const filterValue = column.getFilterValue()\n return Array.isArray(filterValue) ? filterValue : []\n }\n\n // Toggle column sort\n function toggleSort(columnId: string) {\n const current = sorting.value.find(s => s.id === columnId)\n if (!current) {\n sorting.value = [{ id: columnId, desc: false }]\n } else if (!current.desc) {\n sorting.value = [{ id: columnId, desc: true }]\n } else {\n sorting.value = []\n }\n }\n\n // Get sort direction for column\n function getSortDirection(columnId: string): 'asc' | 'desc' | null {\n const sort = sorting.value.find(s => s.id === columnId)\n if (!sort) return null\n return sort.desc ? 'desc' : 'asc'\n }\n\n // Watch data changes to clear cache\n watch(data, () => {\n clearStatsCache()\n })\n\n return {\n // Table instance\n table,\n\n // State\n sorting,\n columnFilters,\n columnVisibility,\n globalFilter,\n columnKeys,\n\n // Computed\n filteredRowCount,\n totalRowCount,\n activeFilters,\n\n // Methods\n getColumnStats,\n clearStatsCache,\n hasActiveFilter,\n setColumnFilter,\n getColumnFilterValues,\n clearAllFilters,\n toggleSort,\n getSortDirection,\n }\n}\n\n","/**\n * License Management Composable for Vue\n * Wraps core license logic with Vue reactivity\n */\nimport { computed, ref } from 'vue'\nimport type { LicenseInfo } from '@smallwebco/tinypivot-core'\nimport {\n validateLicenseKey,\n configureLicenseSecret as coreConfigureLicenseSecret,\n getDemoLicenseInfo,\n getFreeLicenseInfo,\n canUsePivot as coreCanUsePivot,\n isPro as coreIsPro,\n shouldShowWatermark as coreShouldShowWatermark,\n logProRequired,\n} from '@smallwebco/tinypivot-core'\n\n// License state\nconst licenseKey = ref<string | null>(null)\nconst demoMode = ref(false)\nconst licenseInfo = ref<LicenseInfo>(getFreeLicenseInfo())\n\n// Cached validation result\nlet validationPromise: Promise<LicenseInfo> | null = null\n\n/**\n * Set the license key for the library\n * Returns a promise that resolves when validation is complete\n */\nexport async function setLicenseKey(key: string): Promise<void> {\n licenseKey.value = key\n\n // Start validation\n validationPromise = validateLicenseKey(key)\n licenseInfo.value = await validationPromise\n validationPromise = null\n\n if (!licenseInfo.value.isValid) {\n console.warn('[TinyPivot] Invalid or expired license key. Running in free mode.')\n } else if (licenseInfo.value.type !== 'free') {\n console.info(`[TinyPivot] Pro license activated (${licenseInfo.value.type})`)\n }\n}\n\n/**\n * Enable demo mode - unlocks all features for evaluation\n * Requires the correct demo secret\n * Shows \"Demo Mode\" watermark\n */\nexport async function enableDemoMode(secret: string): Promise<boolean> {\n const demoLicense = await getDemoLicenseInfo(secret)\n if (!demoLicense) {\n console.warn('[TinyPivot] Demo mode activation failed - invalid secret')\n return false\n }\n demoMode.value = true\n licenseInfo.value = demoLicense\n console.info('[TinyPivot] Demo mode enabled - all Pro features unlocked for evaluation')\n return true\n}\n\n/**\n * Configure the license secret\n */\nexport function configureLicenseSecret(secret: string): void {\n coreConfigureLicenseSecret(secret)\n}\n\n/**\n * Composable for accessing license information\n */\nexport function useLicense() {\n const isDemo = computed(() => demoMode.value)\n\n const isPro = computed(() => demoMode.value || coreIsPro(licenseInfo.value))\n\n const canUsePivot = computed(() => demoMode.value || coreCanUsePivot(licenseInfo.value))\n\n const canUseAdvancedAggregations = computed(\n () => demoMode.value || licenseInfo.value.features.advancedAggregations\n )\n\n const canUsePercentageMode = computed(\n () => demoMode.value || licenseInfo.value.features.percentageMode\n )\n\n const showWatermark = computed(() => coreShouldShowWatermark(licenseInfo.value, demoMode.value))\n\n function requirePro(feature: string): boolean {\n if (!isPro.value) {\n logProRequired(feature)\n return false\n }\n return true\n }\n\n return {\n licenseInfo: computed(() => licenseInfo.value),\n isDemo,\n isPro,\n canUsePivot,\n canUseAdvancedAggregations,\n canUsePercentageMode,\n showWatermark,\n requirePro,\n }\n}\n\n","/**\n * Pivot Table Composable for Vue\n * Wraps core pivot logic with Vue reactivity\n */\nimport { type Ref, computed, ref, watch } from 'vue'\nimport type { AggregationFunction, FieldStats, PivotConfig, PivotValueField } from '@smallwebco/tinypivot-core'\nimport {\n computeAvailableFields,\n getUnassignedFields,\n isPivotConfigured,\n computePivotResult,\n generateStorageKey,\n savePivotConfig,\n loadPivotConfig,\n isConfigValidForFields,\n getAggregationLabel,\n} from '@smallwebco/tinypivot-core'\nimport { useLicense } from './useLicense'\n\n// Re-export for convenience\nexport { getAggregationLabel }\n\n/**\n * Main pivot table composable\n */\nexport function usePivotTable(data: Ref<Record<string, unknown>[]>) {\n const { canUsePivot, requirePro } = useLicense()\n\n // Configuration state\n const rowFields = ref<string[]>([])\n const columnFields = ref<string[]>([])\n const valueFields = ref<PivotValueField[]>([])\n const showRowTotals = ref(true)\n const showColumnTotals = ref(true)\n\n // Track current storage key\n const currentStorageKey = ref<string | null>(null)\n\n // Compute available fields from data\n const availableFields = computed((): FieldStats[] => {\n return computeAvailableFields(data.value)\n })\n\n // Get fields that haven't been assigned yet\n const unassignedFields = computed(() => {\n return getUnassignedFields(\n availableFields.value,\n rowFields.value,\n columnFields.value,\n valueFields.value\n )\n })\n\n // Check if pivot is configured\n const isConfigured = computed(() => {\n return isPivotConfigured({\n rowFields: rowFields.value,\n columnFields: columnFields.value,\n valueFields: valueFields.value,\n showRowTotals: showRowTotals.value,\n showColumnTotals: showColumnTotals.value,\n })\n })\n\n // Build pivot result\n const pivotResult = computed(() => {\n if (!isConfigured.value) return null\n\n // Check license for pivot feature\n if (!canUsePivot.value) return null\n\n return computePivotResult(data.value, {\n rowFields: rowFields.value,\n columnFields: columnFields.value,\n valueFields: valueFields.value,\n showRowTotals: showRowTotals.value,\n showColumnTotals: showColumnTotals.value,\n })\n })\n\n // Actions with license checks\n function addRowField(field: string) {\n if (!requirePro('Pivot Table - Row Fields')) return\n if (!rowFields.value.includes(field)) {\n rowFields.value = [...rowFields.value, field]\n }\n }\n\n function removeRowField(field: string) {\n rowFields.value = rowFields.value.filter(f => f !== field)\n }\n\n function addColumnField(field: string) {\n if (!requirePro('Pivot Table - Column Fields')) return\n if (!columnFields.value.includes(field)) {\n columnFields.value = [...columnFields.value, field]\n }\n }\n\n function removeColumnField(field: string) {\n columnFields.value = columnFields.value.filter(f => f !== field)\n }\n\n function addValueField(field: string, aggregation: AggregationFunction = 'sum') {\n if (!requirePro('Pivot Table - Value Fields')) return\n if (valueFields.value.some(v => v.field === field && v.aggregation === aggregation)) {\n return\n }\n valueFields.value = [...valueFields.value, { field, aggregation }]\n }\n\n function removeValueField(field: string, aggregation?: AggregationFunction) {\n if (aggregation) {\n valueFields.value = valueFields.value.filter(\n v => !(v.field === field && v.aggregation === aggregation)\n )\n } else {\n valueFields.value = valueFields.value.filter(v => v.field !== field)\n }\n }\n\n function updateValueFieldAggregation(\n field: string,\n oldAgg: AggregationFunction,\n newAgg: AggregationFunction\n ) {\n valueFields.value = valueFields.value.map(v => {\n if (v.field === field && v.aggregation === oldAgg) {\n return { ...v, aggregation: newAgg }\n }\n return v\n })\n }\n\n function clearConfig() {\n rowFields.value = []\n columnFields.value = []\n valueFields.value = []\n }\n\n function moveField(\n from: { area: 'row' | 'column' | 'value'; index: number },\n to: { area: 'row' | 'column' | 'value'; index: number }\n ) {\n if (from.area === to.area) {\n if (from.area === 'row') {\n const items = [...rowFields.value]\n const [removed] = items.splice(from.index, 1)\n items.splice(to.index, 0, removed)\n rowFields.value = items\n } else if (from.area === 'column') {\n const items = [...columnFields.value]\n const [removed] = items.splice(from.index, 1)\n items.splice(to.index, 0, removed)\n columnFields.value = items\n }\n }\n }\n\n function autoSuggestConfig() {\n if (!requirePro('Pivot Table - Auto Suggest')) return\n if (availableFields.value.length === 0) return\n\n const categoricalFields = availableFields.value.filter(f => !f.isNumeric && f.uniqueCount < 50)\n const numericFields = availableFields.value.filter(f => f.isNumeric)\n\n if (categoricalFields.length > 0 && numericFields.length > 0) {\n rowFields.value = [categoricalFields[0].field]\n valueFields.value = [{ field: numericFields[0].field, aggregation: 'sum' }]\n }\n }\n\n // Watch data to restore or validate config\n watch(\n data,\n newData => {\n if (newData.length === 0) return\n\n const newKeys = Object.keys(newData[0])\n const storageKey = generateStorageKey(newKeys)\n\n if (storageKey !== currentStorageKey.value) {\n currentStorageKey.value = storageKey\n\n const savedConfig = loadPivotConfig(storageKey)\n if (savedConfig && isConfigValidForFields(savedConfig, newKeys)) {\n rowFields.value = savedConfig.rowFields\n columnFields.value = savedConfig.columnFields\n valueFields.value = savedConfig.valueFields\n showRowTotals.value = savedConfig.showRowTotals\n showColumnTotals.value = savedConfig.showColumnTotals\n } else {\n const currentConfig: PivotConfig = {\n rowFields: rowFields.value,\n columnFields: columnFields.value,\n valueFields: valueFields.value,\n showRowTotals: showRowTotals.value,\n showColumnTotals: showColumnTotals.value,\n }\n if (!isConfigValidForFields(currentConfig, newKeys)) {\n clearConfig()\n }\n }\n } else {\n const currentConfig: PivotConfig = {\n rowFields: rowFields.value,\n columnFields: columnFields.value,\n valueFields: valueFields.value,\n showRowTotals: showRowTotals.value,\n showColumnTotals: showColumnTotals.value,\n }\n if (!isConfigValidForFields(currentConfig, newKeys)) {\n clearConfig()\n }\n }\n },\n { immediate: true }\n )\n\n // Watch config changes and save to sessionStorage\n watch(\n [rowFields, columnFields, valueFields, showRowTotals, showColumnTotals],\n () => {\n if (!currentStorageKey.value) return\n\n const config: PivotConfig = {\n rowFields: rowFields.value,\n columnFields: columnFields.value,\n valueFields: valueFields.value,\n showRowTotals: showRowTotals.value,\n showColumnTotals: showColumnTotals.value,\n }\n savePivotConfig(currentStorageKey.value, config)\n },\n { deep: true }\n )\n\n return {\n // State\n rowFields,\n columnFields,\n valueFields,\n showRowTotals,\n showColumnTotals,\n\n // Computed\n availableFields,\n unassignedFields,\n isConfigured,\n pivotResult,\n\n // Actions\n addRowField,\n removeRowField,\n addColumnField,\n removeColumnField,\n addValueField,\n removeValueField,\n updateValueFieldAggregation,\n clearConfig,\n moveField,\n autoSuggestConfig,\n }\n}\n\n","/**\n * Grid Features Composable for Vue\n * Provides CSV export, clipboard, pagination, and other utility features\n */\nimport { computed, ref, type Ref } from 'vue'\nimport type { PaginationOptions, SelectionBounds, PivotValueField } from '@smallwebco/tinypivot-core'\nimport {\n exportToCSV as coreExportToCSV,\n exportPivotToCSV as coreExportPivotToCSV,\n copyToClipboard as coreCopyToClipboard,\n formatSelectionForClipboard as coreFormatSelection,\n} from '@smallwebco/tinypivot-core'\nimport type { PivotExportData, ExportOptions } from '@smallwebco/tinypivot-core'\n\n// Re-export core functions\nexport {\n exportToCSV,\n exportPivotToCSV,\n copyToClipboard,\n formatSelectionForClipboard,\n}\n\n/**\n * CSV Export functionality wrapper\n */\nfunction exportToCSV<T extends Record<string, unknown>>(\n data: T[],\n columns: string[],\n options?: ExportOptions\n): void {\n coreExportToCSV(data, columns, options)\n}\n\n/**\n * Pivot CSV export wrapper\n */\nfunction exportPivotToCSV(\n pivotData: PivotExportData,\n rowFields: string[],\n columnFields: string[],\n valueFields: PivotValueField[],\n options?: ExportOptions\n): void {\n coreExportPivotToCSV(pivotData, rowFields, columnFields, valueFields, options)\n}\n\n/**\n * Copy to clipboard wrapper\n */\nfunction copyToClipboard(\n text: string,\n onSuccess?: () => void,\n onError?: (err: Error) => void\n): void {\n coreCopyToClipboard(text, onSuccess, onError)\n}\n\n/**\n * Format selection for clipboard wrapper\n */\nfunction formatSelectionForClipboard<T extends Record<string, unknown>>(\n rows: T[],\n columns: string[],\n selectionBounds: SelectionBounds\n): string {\n return coreFormatSelection(rows, columns, selectionBounds)\n}\n\n/**\n * Pagination composable\n */\nexport function usePagination<T>(data: Ref<T[]>, options: PaginationOptions = {}) {\n const pageSize = ref(options.pageSize ?? 50)\n const currentPage = ref(options.currentPage ?? 1)\n\n const totalPages = computed(() =>\n Math.max(1, Math.ceil(data.value.length / pageSize.value))\n )\n\n const paginatedData = computed(() => {\n const start = (currentPage.value - 1) * pageSize.value\n const end = start + pageSize.value\n return data.value.slice(start, end)\n })\n\n const startIndex = computed(() => (currentPage.value - 1) * pageSize.value + 1)\n const endIndex = computed(() =>\n Math.min(currentPage.value * pageSize.value, data.value.length)\n )\n\n function goToPage(page: number) {\n currentPage.value = Math.max(1, Math.min(page, totalPages.value))\n }\n\n function nextPage() {\n if (currentPage.value < totalPages.value) {\n currentPage.value++\n }\n }\n\n function prevPage() {\n if (currentPage.value > 1) {\n currentPage.value--\n }\n }\n\n function firstPage() {\n currentPage.value = 1\n }\n\n function lastPage() {\n currentPage.value = totalPages.value\n }\n\n function setPageSize(size: number) {\n pageSize.value = size\n currentPage.value = 1\n }\n\n return {\n pageSize,\n currentPage,\n totalPages,\n paginatedData,\n startIndex,\n endIndex,\n goToPage,\n nextPage,\n prevPage,\n firstPage,\n lastPage,\n setPageSize,\n }\n}\n\n/**\n * Global search/filter composable\n */\nexport function useGlobalSearch<T extends Record<string, unknown>>(\n data: Ref<T[]>,\n columns: Ref<string[]>\n) {\n const searchTerm = ref('')\n const caseSensitive = ref(false)\n\n const filteredData = computed(() => {\n if (!searchTerm.value.trim()) {\n return data.value\n }\n\n const term = caseSensitive.value\n ? searchTerm.value.trim()\n : searchTerm.value.trim().toLowerCase()\n\n return data.value.filter(row => {\n for (const col of columns.value) {\n const value = row[col]\n if (value === null || value === undefined) continue\n\n const strValue = caseSensitive.value ? String(value) : String(value).toLowerCase()\n\n if (strValue.includes(term)) {\n return true\n }\n }\n return false\n })\n })\n\n function clearSearch() {\n searchTerm.value = ''\n }\n\n return {\n searchTerm,\n caseSensitive,\n filteredData,\n clearSearch,\n }\n}\n\n/**\n * Row selection composable\n */\nexport function useRowSelection<T>(data: Ref<T[]>) {\n const selectedRowIndices = ref<Set<number>>(new Set())\n\n const selectedRows = computed(() => {\n return Array.from(selectedRowIndices.value)\n .sort((a, b) => a - b)\n .map(idx => data.value[idx])\n .filter(Boolean)\n })\n\n const allSelected = computed(() => {\n return data.value.length > 0 && selectedRowIndices.value.size === data.value.length\n })\n\n const someSelected = computed(() => {\n return selectedRowIndices.value.size > 0 && selectedRowIndices.value.size < data.value.length\n })\n\n function toggleRow(index: number) {\n if (selectedRowIndices.value.has(index)) {\n selectedRowIndices.value.delete(index)\n } else {\n selectedRowIndices.value.add(index)\n }\n selectedRowIndices.value = new Set(selectedRowIndices.value)\n }\n\n function selectRow(index: number) {\n selectedRowIndices.value.add(index)\n selectedRowIndices.value = new Set(selectedRowIndices.value)\n }\n\n function deselectRow(index: number) {\n selectedRowIndices.value.delete(index)\n selectedRowIndices.value = new Set(selectedRowIndices.value)\n }\n\n function selectAll() {\n selectedRowIndices.value = new Set(data.value.map((_, idx) => idx))\n }\n\n function deselectAll() {\n selectedRowIndices.value = new Set()\n }\n\n function toggleAll() {\n if (allSelected.value) {\n deselectAll()\n } else {\n selectAll()\n }\n }\n\n function isSelected(index: number): boolean {\n return selectedRowIndices.value.has(index)\n }\n\n function selectRange(startIndex: number, endIndex: number) {\n const min = Math.min(startIndex, endIndex)\n const max = Math.max(startIndex, endIndex)\n for (let i = min; i <= max; i++) {\n selectedRowIndices.value.add(i)\n }\n selectedRowIndices.value = new Set(selectedRowIndices.value)\n }\n\n return {\n selectedRowIndices,\n selectedRows,\n allSelected,\n someSelected,\n toggleRow,\n selectRow,\n deselectRow,\n selectAll,\n deselectAll,\n toggleAll,\n isSelected,\n selectRange,\n }\n}\n\n/**\n * Column resizing composable\n */\nexport function useColumnResize(\n initialWidths: Ref<Record<string, number>>,\n minWidth = 60,\n maxWidth = 600\n) {\n const columnWidths = ref<Record<string, number>>({ ...initialWidths.value })\n const isResizing = ref(false)\n const resizingColumn = ref<string | null>(null)\n\n function startResize(columnId: string, event: MouseEvent) {\n isResizing.value = true\n resizingColumn.value = columnId\n const startX = event.clientX\n const startWidth = columnWidths.value[columnId] || 150\n\n const handleMouseMove = (e: MouseEvent) => {\n const diff = e.clientX - startX\n const newWidth = Math.max(minWidth, Math.min(maxWidth, startWidth + diff))\n columnWidths.value = {\n ...columnWidths.value,\n [columnId]: newWidth,\n }\n }\n\n const handleMouseUp = () => {\n isResizing.value = false\n resizingColumn.value = null\n document.removeEventListener('mousemove', handleMouseMove)\n document.removeEventListener('mouseup', handleMouseUp)\n }\n\n document.addEventListener('mousemove', handleMouseMove)\n document.addEventListener('mouseup', handleMouseUp)\n }\n\n function resetColumnWidth(columnId: string) {\n if (initialWidths.value[columnId]) {\n columnWidths.value = {\n ...columnWidths.value,\n [columnId]: initialWidths.value[columnId],\n }\n }\n }\n\n function resetAllWidths() {\n columnWidths.value = { ...initialWidths.value }\n }\n\n return {\n columnWidths,\n isResizing,\n resizingColumn,\n startResize,\n resetColumnWidth,\n resetAllWidths,\n }\n}\n\n","<script setup lang=\"ts\">\n/**\n * Column Filter Dropdown Component\n * Shows unique values with checkboxes, search, and sort controls\n */\nimport { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'\nimport type { ColumnStats } from '@smallwebco/tinypivot-core'\n\nconst props = defineProps<{\n columnId: string\n columnName: string\n stats: ColumnStats\n selectedValues: string[]\n sortDirection: 'asc' | 'desc' | null\n}>()\n\nconst emit = defineEmits<{\n filter: [values: string[]]\n sort: [direction: 'asc' | 'desc' | null]\n close: []\n}>()\n\n// Local state\nconst searchQuery = ref('')\nconst dropdownRef = ref<HTMLDivElement>()\nconst searchInputRef = ref<HTMLInputElement>()\n\n// Get all possible values including blank\nconst allPossibleValues = computed(() => {\n const values = [...props.stats.uniqueValues]\n if (props.stats.nullCount > 0) {\n values.unshift('(blank)')\n }\n return values\n})\n\n// Initialize with selected values\nconst localSelected = ref<Set<string>>(new Set(props.selectedValues))\n\n// Include blank option if there are null values\nconst hasBlankValues = computed(() => props.stats.nullCount > 0)\n\n// Filtered unique values based on search\nconst filteredValues = computed(() => {\n const values = props.stats.uniqueValues\n if (!searchQuery.value)\n return values\n\n const query = searchQuery.value.toLowerCase()\n return values.filter(v => v.toLowerCase().includes(query))\n})\n\n// All values including blank\nconst allValues = computed(() => {\n const values = [...filteredValues.value]\n if (hasBlankValues.value && (!searchQuery.value || '(blank)'.includes(searchQuery.value.toLowerCase()))) {\n values.unshift('(blank)')\n }\n return values\n})\n\n// Check states\nconst isAllSelected = computed(() => {\n return allValues.value.every(v => localSelected.value.has(v))\n})\n\nconst isNoneSelected = computed(() => {\n return localSelected.value.size === 0\n})\n\n// Toggle single value\nfunction toggleValue(value: string) {\n if (localSelected.value.has(value)) {\n localSelected.value.delete(value)\n }\n else {\n localSelected.value.add(value)\n }\n localSelected.value = new Set(localSelected.value)\n}\n\n// Select all visible\nfunction selectAll() {\n for (const value of allValues.value) {\n localSelected.value.add(value)\n }\n localSelected.value = new Set(localSelected.value)\n}\n\n// Clear all\nfunction clearAll() {\n localSelected.value.clear()\n localSelected.value = new Set(localSelected.value)\n}\n\n// Apply filter\nfunction applyFilter() {\n if (localSelected.value.size === 0) {\n emit('filter', [])\n }\n else {\n emit('filter', Array.from(localSelected.value))\n }\n emit('close')\n}\n\n// Sort handlers\nfunction sortAscending() {\n emit('sort', props.sortDirection === 'asc' ? null : 'asc')\n}\n\nfunction sortDescending() {\n emit('sort', props.sortDirection === 'desc' ? null : 'desc')\n}\n\n// Clear filter only\nfunction clearFilter() {\n localSelected.value.clear()\n localSelected.value = new Set(localSelected.value)\n emit('filter', [])\n emit('close')\n}\n\n// Click outside handler\nfunction handleClickOutside(event: MouseEvent) {\n if (dropdownRef.value && !dropdownRef.value.contains(event.target as Node)) {\n emit('close')\n }\n}\n\n// Keyboard handling\nfunction handleKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape') {\n emit('close')\n }\n else if (event.key === 'Enter' && event.ctrlKey) {\n applyFilter()\n }\n}\n\n// Focus search on mount\nonMounted(() => {\n nextTick(() => {\n searchInputRef.value?.focus()\n })\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleKeydown)\n})\n\nonUnmounted(() => {\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleKeydown)\n})\n\n// Sync with props\nwatch(() => props.selectedValues, (newValues) => {\n localSelected.value = new Set(newValues)\n}, { immediate: true })\n</script>\n\n<template>\n <div ref=\"dropdownRef\" class=\"vpg-filter-dropdown\">\n <!-- Header -->\n <div class=\"vpg-filter-header\">\n <span class=\"vpg-filter-title\">{{ columnName }}</span>\n <span class=\"vpg-filter-count\">\n {{ stats.uniqueValues.length.toLocaleString() }} unique\n </span>\n </div>\n\n <!-- Sort Controls -->\n <div class=\"vpg-sort-controls\">\n <button\n class=\"vpg-sort-btn\"\n :class=\"{ active: sortDirection === 'asc' }\"\n title=\"Sort A to Z\"\n @click=\"sortAscending\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12\" />\n </svg>\n <span>A→Z</span>\n </button>\n <button\n class=\"vpg-sort-btn\"\n :class=\"{ active: sortDirection === 'desc' }\"\n title=\"Sort Z to A\"\n @click=\"sortDescending\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4\" />\n </svg>\n <span>Z→A</span>\n </button>\n </div>\n\n <div class=\"vpg-divider\" />\n\n <!-- Search -->\n <div class=\"vpg-search-container\">\n <svg class=\"vpg-search-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n <input\n ref=\"searchInputRef\"\n v-model=\"searchQuery\"\n type=\"text\"\n placeholder=\"Search values...\"\n class=\"vpg-search-input\"\n >\n <button v-if=\"searchQuery\" class=\"vpg-clear-search\" @click=\"searchQuery = ''\">\n ×\n </button>\n </div>\n\n <!-- Select All / Clear All -->\n <div class=\"vpg-bulk-actions\">\n <button class=\"vpg-bulk-btn\" @click=\"selectAll\">\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n Select All\n </button>\n <button class=\"vpg-bulk-btn\" @click=\"clearAll\">\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n Clear All\n </button>\n </div>\n\n <!-- Values List -->\n <div class=\"vpg-values-list\">\n <label\n v-for=\"value in allValues\"\n :key=\"value\"\n class=\"vpg-value-item\"\n :class=\"{ selected: localSelected.has(value) }\"\n >\n <input\n type=\"checkbox\"\n :checked=\"localSelected.has(value)\"\n class=\"vpg-value-checkbox\"\n @change=\"toggleValue(value)\"\n >\n <span class=\"vpg-value-text\" :class=\"{ 'vpg-blank': value === '(blank)' }\">\n {{ value }}\n </span>\n </label>\n\n <div v-if=\"allValues.length === 0\" class=\"vpg-no-results\">\n No matching values\n </div>\n </div>\n\n <!-- Footer -->\n <div class=\"vpg-filter-footer\">\n <button class=\"vpg-btn-clear\" @click=\"clearFilter\">\n Clear Filter\n </button>\n <button class=\"vpg-btn-apply\" @click=\"applyFilter\">\n Apply\n </button>\n </div>\n </div>\n</template>\n\n<style scoped>\n.vpg-filter-dropdown {\n position: absolute;\n z-index: 50;\n background: white;\n border-radius: 0.375rem;\n box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n border: 1px solid #e2e8f0;\n min-width: 220px;\n max-width: 280px;\n top: 100%;\n left: 0;\n margin-top: 2px;\n max-height: calc(100vh - 100px);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.vpg-filter-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.625rem;\n background: #f8fafc;\n border-bottom: 1px solid #e2e8f0;\n border-radius: 0.375rem 0.375rem 0 0;\n}\n\n.vpg-filter-title {\n font-size: 0.75rem;\n font-weight: 600;\n color: #1e293b;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.vpg-filter-count {\n font-size: 0.625rem;\n color: #64748b;\n}\n\n.vpg-sort-controls {\n display: flex;\n gap: 0.25rem;\n padding: 0.5rem;\n background: #f8fafc;\n}\n\n.vpg-sort-btn {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.25rem 0.5rem;\n font-size: 0.6875rem;\n font-weight: 500;\n border-radius: 0.25rem;\n color: #475569;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-sort-btn:hover {\n background: #e2e8f0;\n}\n\n.vpg-sort-btn.active {\n background: #e0e7ff;\n color: #4338ca;\n}\n\n.vpg-icon-sm {\n width: 0.75rem;\n height: 0.75rem;\n}\n\n.vpg-divider {\n height: 1px;\n background: #e2e8f0;\n}\n\n.vpg-search-container {\n position: relative;\n padding: 0.375rem 0.5rem;\n}\n\n.vpg-search-icon {\n position: absolute;\n left: 0.875rem;\n top: 50%;\n transform: translateY(-50%);\n width: 0.875rem;\n height: 0.875rem;\n color: #94a3b8;\n}\n\n.vpg-search-input {\n width: 100%;\n padding: 0.25rem 1.5rem 0.25rem 1.75rem;\n font-size: 0.75rem;\n border: 1px solid #cbd5e1;\n border-radius: 0.25rem;\n outline: none;\n}\n\n.vpg-search-input:focus {\n border-color: #6366f1;\n box-shadow: 0 0 0 1px #6366f1;\n}\n\n.vpg-clear-search {\n position: absolute;\n right: 0.875rem;\n top: 50%;\n transform: translateY(-50%);\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #94a3b8;\n font-size: 0.875rem;\n line-height: 1;\n background: transparent;\n border: none;\n cursor: pointer;\n}\n\n.vpg-clear-search:hover {\n color: #475569;\n}\n\n.vpg-bulk-actions {\n display: flex;\n gap: 0.375rem;\n padding: 0.25rem 0.5rem;\n border-bottom: 1px solid #f1f5f9;\n}\n\n.vpg-bulk-btn {\n display: flex;\n align-items: center;\n gap: 0.125rem;\n padding: 0.125rem 0.375rem;\n font-size: 0.625rem;\n font-weight: 500;\n color: #475569;\n background: transparent;\n border: none;\n border-radius: 0.25rem;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-bulk-btn:hover {\n color: #4f46e5;\n background: #eef2ff;\n}\n\n.vpg-values-list {\n max-height: 200px;\n overflow-y: auto;\n padding: 0.125rem 0.25rem;\n flex: 1;\n min-height: 0;\n}\n\n.vpg-value-item {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.375rem;\n border-radius: 0.25rem;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.vpg-value-item:hover {\n background: #f1f5f9;\n}\n\n.vpg-value-item.selected {\n background: #eef2ff;\n}\n\n.vpg-value-checkbox {\n width: 0.875rem;\n height: 0.875rem;\n accent-color: #4f46e5;\n border-radius: 0.25rem;\n}\n\n.vpg-value-text {\n font-size: 0.75rem;\n color: #334155;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n}\n\n.vpg-value-text.vpg-blank {\n font-style: italic;\n color: #94a3b8;\n}\n\n.vpg-no-results {\n text-align: center;\n padding: 0.75rem;\n font-size: 0.75rem;\n color: #94a3b8;\n}\n\n.vpg-filter-footer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0.5rem 0.625rem;\n background: #f8fafc;\n border-top: 1px solid #e2e8f0;\n border-radius: 0 0 0.375rem 0.375rem;\n}\n\n.vpg-btn-clear {\n padding: 0.25rem 0.5rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: #475569;\n background: transparent;\n border: none;\n border-radius: 0.25rem;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-btn-clear:hover {\n background: #e2e8f0;\n color: #1e293b;\n}\n\n.vpg-btn-apply {\n padding: 0.25rem 0.75rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: white;\n background: #4f46e5;\n border: none;\n border-radius: 0.25rem;\n cursor: pointer;\n transition: all 0.15s;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-btn-apply:hover {\n background: #4338ca;\n}\n</style>\n\n","<script setup lang=\"ts\">\n/**\n * Pivot Table Configuration Panel\n * Draggable fields with aggregation selection\n */\nimport { computed, ref } from 'vue'\nimport type { AggregationFunction, PivotValueField } from '@smallwebco/tinypivot-core'\nimport { useLicense } from '../composables/useLicense'\n\ninterface FieldStats {\n field: string\n type: 'string' | 'number' | 'date' | 'boolean' | 'mixed'\n uniqueCount: number\n isNumeric: boolean\n}\n\nconst props = defineProps<{\n availableFields: FieldStats[]\n rowFields: string[]\n columnFields: string[]\n valueFields: PivotValueField[]\n showRowTotals: boolean\n showColumnTotals: boolean\n}>()\n\nconst emit = defineEmits<{\n (e: 'update:showRowTotals', value: boolean): void\n (e: 'update:showColumnTotals', value: boolean): void\n (e: 'clearConfig'): void\n (e: 'autoSuggest'): void\n (e: 'dragStart', field: string, event: DragEvent): void\n (e: 'dragEnd'): void\n (e: 'updateAggregation', field: string, oldAgg: AggregationFunction, newAgg: AggregationFunction): void\n (e: 'addRowField', field: string): void\n (e: 'removeRowField', field: string): void\n (e: 'addColumnField', field: string): void\n (e: 'removeColumnField', field: string): void\n (e: 'addValueField', field: string, aggregation: AggregationFunction): void\n (e: 'removeValueField', field: string, aggregation: AggregationFunction): void\n}>()\n\nconst { isPro, showWatermark } = useLicense()\n\n// Aggregation options\nconst aggregationOptions: { value: AggregationFunction, label: string, symbol: string }[] = [\n { value: 'sum', label: 'Sum', symbol: 'Σ' },\n { value: 'count', label: 'Count', symbol: '#' },\n { value: 'avg', label: 'Avg', symbol: 'x̄' },\n { value: 'min', label: 'Min', symbol: '↓' },\n { value: 'max', label: 'Max', symbol: '↑' },\n { value: 'countDistinct', label: 'Unique', symbol: '◇' },\n]\n\nfunction getAggSymbol(agg: AggregationFunction): string {\n return aggregationOptions.find(a => a.value === agg)?.symbol || 'Σ'\n}\n\nfunction getAggLabel(agg: AggregationFunction): string {\n return aggregationOptions.find(a => a.value === agg)?.label || 'Sum'\n}\n\n// Assigned fields\nconst assignedFields = computed(() => {\n const rowSet = new Set(props.rowFields)\n const colSet = new Set(props.columnFields)\n const valueMap = new Map(props.valueFields.map(v => [v.field, v]))\n\n return props.availableFields\n .filter(f => rowSet.has(f.field) || colSet.has(f.field) || valueMap.has(f.field))\n .map(f => ({\n ...f,\n assignedTo: rowSet.has(f.field)\n ? 'row' as const\n : colSet.has(f.field)\n ? 'column' as const\n : 'value' as const,\n valueConfig: valueMap.get(f.field),\n }))\n})\n\n// Unassigned fields\nconst unassignedFields = computed(() => {\n const rowSet = new Set(props.rowFields)\n const colSet = new Set(props.columnFields)\n const valSet = new Set(props.valueFields.map(v => v.field))\n\n return props.availableFields.filter(f =>\n !rowSet.has(f.field) && !colSet.has(f.field) && !valSet.has(f.field),\n )\n})\n\nconst assignedCount = computed(() => assignedFields.value.length)\n\n// Field search\nconst fieldSearch = ref('')\nconst filteredUnassignedFields = computed(() => {\n if (!fieldSearch.value.trim())\n return unassignedFields.value\n const search = fieldSearch.value.toLowerCase().trim()\n return unassignedFields.value.filter(f => f.field.toLowerCase().includes(search))\n})\n\n// Field type icons\nfunction getFieldIcon(type: FieldStats['type']): string {\n switch (type) {\n case 'number': return '#'\n case 'date': return '📅'\n case 'boolean': return '✓'\n default: return 'Aa'\n }\n}\n\nfunction handleDragStart(field: string, event: DragEvent) {\n event.dataTransfer?.setData('text/plain', field)\n event.dataTransfer!.effectAllowed = 'move'\n emit('dragStart', field, event)\n}\n\nfunction handleDragEnd() {\n emit('dragEnd')\n}\n\nfunction handleAggregationChange(field: string, currentAgg: AggregationFunction, newAgg: AggregationFunction) {\n emit('updateAggregation', field, currentAgg, newAgg)\n}\n\nfunction toggleRowColumn(field: string, currentAssignment: 'row' | 'column') {\n if (currentAssignment === 'row') {\n emit('removeRowField', field)\n emit('addColumnField', field)\n }\n else {\n emit('removeColumnField', field)\n emit('addRowField', field)\n }\n}\n\nfunction removeField(field: string, assignedTo: 'row' | 'column' | 'value', valueConfig?: PivotValueField) {\n if (assignedTo === 'row') {\n emit('removeRowField', field)\n }\n else if (assignedTo === 'column') {\n emit('removeColumnField', field)\n }\n else if (valueConfig) {\n emit('removeValueField', field, valueConfig.aggregation)\n }\n}\n</script>\n\n<template>\n <div class=\"vpg-pivot-config\">\n <!-- Header -->\n <div class=\"vpg-config-header\">\n <h3 class=\"vpg-config-title\">\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 10h16M4 14h16M4 18h16\" />\n </svg>\n Fields\n </h3>\n <div class=\"vpg-header-actions\">\n <button\n v-if=\"assignedCount > 0\"\n class=\"vpg-action-btn vpg-clear-btn\"\n title=\"Clear all\"\n @click=\"emit('clearConfig')\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Assigned Fields -->\n <div v-if=\"assignedCount > 0\" class=\"vpg-assigned-section\">\n <div class=\"vpg-section-label\">Active</div>\n <div class=\"vpg-assigned-list\">\n <div\n v-for=\"field in assignedFields\"\n :key=\"field.field\"\n class=\"vpg-assigned-item\"\n :class=\"[`vpg-type-${field.assignedTo}`]\"\n :title=\"field.field\"\n draggable=\"true\"\n @dragstart=\"handleDragStart(field.field, $event)\"\n @dragend=\"handleDragEnd\"\n >\n <div class=\"vpg-item-main\">\n <span class=\"vpg-item-badge\" :class=\"field.assignedTo\">\n {{ field.assignedTo === 'row' ? 'R' : field.assignedTo === 'column' ? 'C' : getAggSymbol(field.valueConfig?.aggregation || 'sum') }}\n </span>\n <span class=\"vpg-item-name\">{{ field.field }}</span>\n </div>\n\n <div class=\"vpg-item-actions\">\n <button\n v-if=\"field.assignedTo === 'row' || field.assignedTo === 'column'\"\n class=\"vpg-toggle-btn\"\n :title=\"field.assignedTo === 'row' ? 'Move to Columns' : 'Move to Rows'\"\n @click.stop=\"toggleRowColumn(field.field, field.assignedTo)\"\n >\n <svg class=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4\" />\n </svg>\n </button>\n\n <select\n v-if=\"field.assignedTo === 'value' && field.valueConfig\"\n class=\"vpg-agg-select\"\n :value=\"field.valueConfig.aggregation\"\n @change=\"handleAggregationChange(field.field, field.valueConfig!.aggregation, ($event.target as HTMLSelectElement).value as AggregationFunction)\"\n @click.stop\n >\n <option v-for=\"agg in aggregationOptions\" :key=\"agg.value\" :value=\"agg.value\">\n {{ agg.symbol }} {{ agg.label }}\n </option>\n </select>\n\n <button\n class=\"vpg-remove-btn\"\n title=\"Remove\"\n @click.stop=\"removeField(field.field, field.assignedTo, field.valueConfig)\"\n >\n ×\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Unassigned Fields -->\n <div class=\"vpg-unassigned-section\">\n <div class=\"vpg-section-header\">\n <div class=\"vpg-section-label\">\n Available <span class=\"vpg-count\">{{ unassignedFields.length }}</span>\n </div>\n </div>\n\n <!-- Field Search -->\n <div class=\"vpg-field-search\">\n <svg class=\"vpg-search-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n <input\n v-model=\"fieldSearch\"\n type=\"text\"\n placeholder=\"Search fields...\"\n class=\"vpg-search-input\"\n >\n <button v-if=\"fieldSearch\" class=\"vpg-clear-search\" @click=\"fieldSearch = ''\">\n <svg class=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n <div class=\"vpg-field-list\">\n <div\n v-for=\"field in filteredUnassignedFields\"\n :key=\"field.field\"\n class=\"vpg-field-item\"\n :class=\"{ 'vpg-is-numeric': field.isNumeric }\"\n :title=\"field.field\"\n draggable=\"true\"\n @dragstart=\"handleDragStart(field.field, $event)\"\n @dragend=\"handleDragEnd\"\n >\n <span class=\"vpg-field-type-icon\" :title=\"field.type\">{{ getFieldIcon(field.type) }}</span>\n <span class=\"vpg-field-name\">{{ field.field }}</span>\n <span class=\"vpg-unique-count\">{{ field.uniqueCount }}</span>\n </div>\n <div v-if=\"filteredUnassignedFields.length === 0 && fieldSearch\" class=\"vpg-empty-hint\">\n No fields match \"{{ fieldSearch }}\"\n </div>\n <div v-else-if=\"unassignedFields.length === 0\" class=\"vpg-empty-hint\">\n All fields assigned\n </div>\n </div>\n </div>\n\n <!-- Options -->\n <div class=\"vpg-options-section\">\n <label class=\"vpg-option-toggle\">\n <input\n type=\"checkbox\"\n :checked=\"showRowTotals\"\n @change=\"emit('update:showRowTotals', ($event.target as HTMLInputElement).checked)\"\n >\n <span>Totals</span>\n </label>\n <button class=\"vpg-auto-btn\" @click=\"emit('autoSuggest')\">\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 10V3L4 14h7v7l9-11h-7z\" />\n </svg>\n Auto\n </button>\n </div>\n\n <!-- Pro Badge / Watermark -->\n <div v-if=\"showWatermark\" class=\"vpg-watermark\">\n <a href=\"https://tiny-pivot.com\" target=\"_blank\" rel=\"noopener\">\n TinyPivot\n </a>\n </div>\n </div>\n</template>\n\n<style scoped>\n.vpg-pivot-config {\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 0.5rem;\n box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n.vpg-config-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem 0.75rem;\n background: #f8fafc;\n border-bottom: 1px solid #e2e8f0;\n flex-shrink: 0;\n}\n\n.vpg-config-title {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n font-size: 0.75rem;\n font-weight: 600;\n color: #475569;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.vpg-icon {\n width: 1rem;\n height: 1rem;\n}\n\n.vpg-icon-sm {\n width: 0.875rem;\n height: 0.875rem;\n}\n\n.vpg-icon-xs {\n width: 0.75rem;\n height: 0.75rem;\n}\n\n.vpg-header-actions {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.vpg-action-btn {\n padding: 0.375rem;\n border-radius: 0.25rem;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-clear-btn {\n color: #94a3b8;\n}\n\n.vpg-clear-btn:hover {\n background: #fee2e2;\n color: #ef4444;\n}\n\n.vpg-section-label {\n font-size: 0.625rem;\n font-weight: 700;\n color: #94a3b8;\n text-transform: uppercase;\n letter-spacing: 0.1em;\n padding: 0.25rem 0.5rem;\n}\n\n.vpg-section-label .vpg-count {\n color: #cbd5e1;\n margin-left: 0.25rem;\n}\n\n.vpg-assigned-section {\n border-bottom: 1px solid #e2e8f0;\n background: linear-gradient(to bottom, #f8fafc, white);\n padding-bottom: 0.5rem;\n flex-shrink: 0;\n}\n\n.vpg-assigned-list {\n padding: 0 0.5rem;\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.vpg-assigned-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n padding: 0.375rem 0.5rem;\n border-radius: 0.5rem;\n font-size: 0.75rem;\n cursor: grab;\n transition: all 0.15s;\n}\n\n.vpg-assigned-item:active {\n cursor: grabbing;\n transform: scale(0.98);\n}\n\n.vpg-assigned-item.vpg-type-row {\n background: #eef2ff;\n border: 1px solid #c7d2fe;\n}\n\n.vpg-assigned-item.vpg-type-column {\n background: #f5f3ff;\n border: 1px solid #ddd6fe;\n}\n\n.vpg-assigned-item.vpg-type-value {\n background: #ecfdf5;\n border: 1px solid #a7f3d0;\n}\n\n.vpg-item-main {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n min-width: 0;\n}\n\n.vpg-item-badge {\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.625rem;\n font-weight: 700;\n border-radius: 0.25rem;\n}\n\n.vpg-item-badge.row {\n background: #c7d2fe;\n color: #4338ca;\n}\n\n.vpg-item-badge.column {\n background: #ddd6fe;\n color: #7c3aed;\n}\n\n.vpg-item-badge.value {\n background: #a7f3d0;\n color: #059669;\n}\n\n.vpg-item-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n color: #334155;\n}\n\n.vpg-item-actions {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n flex-shrink: 0;\n}\n\n.vpg-toggle-btn {\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 0.25rem;\n color: #94a3b8;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-toggle-btn:hover {\n background: white;\n color: #475569;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-agg-select {\n font-size: 0.625rem;\n background: white;\n border: 1px solid #a7f3d0;\n border-radius: 0.25rem;\n padding: 0.125rem 0.25rem;\n color: #059669;\n font-weight: 500;\n min-width: 70px;\n cursor: pointer;\n}\n\n.vpg-agg-select:focus {\n outline: none;\n box-shadow: 0 0 0 1px #10b981;\n}\n\n.vpg-remove-btn {\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n line-height: 1;\n color: #94a3b8;\n background: transparent;\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-remove-btn:hover {\n background: #fee2e2;\n color: #ef4444;\n}\n\n.vpg-unassigned-section {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n}\n\n.vpg-section-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 0.5rem;\n}\n\n.vpg-field-search {\n position: relative;\n margin: 0 0.5rem 0.5rem;\n}\n\n.vpg-search-icon {\n position: absolute;\n left: 0.5rem;\n top: 50%;\n transform: translateY(-50%);\n width: 0.875rem;\n height: 0.875rem;\n color: #94a3b8;\n pointer-events: none;\n}\n\n.vpg-search-input {\n width: 100%;\n padding: 0.375rem 1.75rem 0.375rem 1.75rem;\n font-size: 0.75rem;\n border: 1px solid #e2e8f0;\n border-radius: 0.375rem;\n background: white;\n color: #334155;\n}\n\n.vpg-search-input::placeholder {\n color: #94a3b8;\n}\n\n.vpg-search-input:focus {\n outline: none;\n box-shadow: 0 0 0 1px #6366f1;\n border-color: #6366f1;\n}\n\n.vpg-clear-search {\n position: absolute;\n right: 0.5rem;\n top: 50%;\n transform: translateY(-50%);\n padding: 0.125rem;\n border-radius: 0.25rem;\n color: #94a3b8;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-clear-search:hover {\n background: #f1f5f9;\n color: #475569;\n}\n\n.vpg-field-list {\n flex: 1;\n overflow-y: auto;\n padding: 0 0.5rem 0.5rem;\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.vpg-field-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.375rem 0.5rem;\n border-radius: 0.375rem;\n font-size: 0.75rem;\n cursor: grab;\n background: white;\n border: 1px solid #e2e8f0;\n color: #475569;\n transition: all 0.15s;\n}\n\n.vpg-field-item:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-field-item:active {\n cursor: grabbing;\n transform: scale(0.98);\n}\n\n.vpg-field-item.vpg-is-numeric {\n border-color: #bfdbfe;\n background: rgba(239, 246, 255, 0.3);\n}\n\n.vpg-field-type-icon {\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.625rem;\n font-weight: 700;\n background: #f1f5f9;\n border-radius: 0.25rem;\n color: #64748b;\n flex-shrink: 0;\n}\n\n.vpg-field-item.vpg-is-numeric .vpg-field-type-icon {\n background: #dbeafe;\n color: #2563eb;\n}\n\n.vpg-field-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n}\n\n.vpg-unique-count {\n font-size: 0.625rem;\n color: #94a3b8;\n font-variant-numeric: tabular-nums;\n flex-shrink: 0;\n}\n\n.vpg-empty-hint {\n font-size: 0.6875rem;\n color: #94a3b8;\n font-style: italic;\n text-align: center;\n padding: 1rem;\n}\n\n.vpg-options-section {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n border-top: 1px solid #f1f5f9;\n background: rgba(248, 250, 252, 0.5);\n flex-shrink: 0;\n}\n\n.vpg-option-toggle {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n font-size: 0.6875rem;\n color: #64748b;\n cursor: pointer;\n user-select: none;\n}\n\n.vpg-option-toggle input {\n width: 0.875rem;\n height: 0.875rem;\n border-radius: 0.25rem;\n accent-color: #10b981;\n cursor: pointer;\n}\n\n.vpg-auto-btn {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.25rem 0.5rem;\n font-size: 0.6875rem;\n font-weight: 500;\n border-radius: 0.25rem;\n background: #ecfdf5;\n color: #059669;\n border: 1px solid #a7f3d0;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-auto-btn:hover {\n background: #d1fae5;\n}\n\n.vpg-watermark {\n padding: 0.375rem 0.75rem;\n background: #f1f5f9;\n border-top: 1px solid #e2e8f0;\n text-align: center;\n flex-shrink: 0;\n}\n\n.vpg-watermark a {\n font-size: 0.625rem;\n color: #94a3b8;\n text-decoration: none;\n transition: color 0.15s;\n}\n\n.vpg-watermark a:hover {\n color: #64748b;\n}\n\n/* Scrollbar */\n.vpg-field-list::-webkit-scrollbar {\n width: 0.375rem;\n}\n\n.vpg-field-list::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.vpg-field-list::-webkit-scrollbar-thumb {\n background: #e2e8f0;\n border-radius: 9999px;\n}\n\n.vpg-field-list::-webkit-scrollbar-thumb:hover {\n background: #cbd5e1;\n}\n\n</style>\n\n<style>\n/* Dark mode - PivotConfig */\n.vpg-theme-dark .vpg-pivot-config {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-config-header {\n background: #0f172a;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-config-title {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-clear-btn {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-clear-btn:hover {\n background: rgba(239, 68, 68, 0.2);\n color: #f87171;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-section-label {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-section-label .vpg-count {\n color: #475569;\n}\n\n.vpg-theme-dark .vpg-assigned-section {\n border-color: #334155;\n background: linear-gradient(to bottom, #0f172a, #1e293b);\n}\n\n.vpg-theme-dark .vpg-assigned-item.vpg-type-row {\n background: rgba(99, 102, 241, 0.15);\n border-color: rgba(99, 102, 241, 0.3);\n}\n\n.vpg-theme-dark .vpg-assigned-item.vpg-type-column {\n background: rgba(139, 92, 246, 0.15);\n border-color: rgba(139, 92, 246, 0.3);\n}\n\n.vpg-theme-dark .vpg-assigned-item.vpg-type-value {\n background: rgba(16, 185, 129, 0.15);\n border-color: rgba(16, 185, 129, 0.3);\n}\n\n.vpg-theme-dark .vpg-item-badge.row {\n background: rgba(99, 102, 241, 0.3);\n color: #a5b4fc;\n}\n\n.vpg-theme-dark .vpg-item-badge.column {\n background: rgba(139, 92, 246, 0.3);\n color: #c4b5fd;\n}\n\n.vpg-theme-dark .vpg-item-badge.value {\n background: rgba(16, 185, 129, 0.3);\n color: #6ee7b7;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-item-name {\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-toggle-btn {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-toggle-btn:hover {\n background: #334155;\n color: #cbd5e1;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-agg-select {\n background: #0f172a;\n border-color: rgba(16, 185, 129, 0.3);\n color: #6ee7b7;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-agg-select:focus {\n box-shadow: 0 0 0 1px #10b981;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-remove-btn {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-remove-btn:hover {\n background: rgba(239, 68, 68, 0.2);\n color: #f87171;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-search-input {\n background: #0f172a;\n border-color: #334155;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-search-input::placeholder {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-search-input:focus {\n border-color: #6366f1;\n box-shadow: 0 0 0 1px #6366f1;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-search-icon {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-clear-search:hover {\n background: #334155;\n color: #cbd5e1;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-item {\n background: #0f172a;\n border-color: #334155;\n color: #cbd5e1;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-item:hover {\n border-color: #475569;\n background: #1e293b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-item.vpg-is-numeric {\n border-color: rgba(59, 130, 246, 0.3);\n background: rgba(59, 130, 246, 0.1);\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-type-icon {\n background: #334155;\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-item.vpg-is-numeric .vpg-field-type-icon {\n background: rgba(59, 130, 246, 0.3);\n color: #60a5fa;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-unique-count {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-empty-hint {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-options-section {\n border-color: #334155;\n background: rgba(15, 23, 42, 0.5);\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-option-toggle {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-auto-btn {\n background: rgba(16, 185, 129, 0.15);\n color: #6ee7b7;\n border-color: rgba(16, 185, 129, 0.3);\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-auto-btn:hover {\n background: rgba(16, 185, 129, 0.25);\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-watermark {\n background: #0f172a;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-watermark a {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-watermark a:hover {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-list::-webkit-scrollbar-thumb {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-pivot-config .vpg-field-list::-webkit-scrollbar-thumb:hover {\n background: #475569;\n}\n</style>\n\n","<script setup lang=\"ts\">\n/**\n * Pivot Table Skeleton + Data Display\n * Visual layout for pivot configuration and results\n */\nimport { computed, ref } from 'vue'\nimport type { AggregationFunction, PivotResult, PivotValueField } from '@smallwebco/tinypivot-core'\nimport { useLicense } from '../composables/useLicense'\n\ninterface ActiveFilter {\n column: string\n valueCount: number\n values: string[]\n}\n\nconst props = defineProps<{\n rowFields: string[]\n columnFields: string[]\n valueFields: PivotValueField[]\n isConfigured: boolean\n draggingField: string | null\n pivotResult: PivotResult | null\n fontSize?: 'xs' | 'sm' | 'base'\n activeFilters?: ActiveFilter[] | null\n totalRowCount?: number\n filteredRowCount?: number\n}>()\n\nconst emit = defineEmits<{\n (e: 'addRowField', field: string): void\n (e: 'removeRowField', field: string): void\n (e: 'addColumnField', field: string): void\n (e: 'removeColumnField', field: string): void\n (e: 'addValueField', field: string, aggregation: AggregationFunction): void\n (e: 'removeValueField', field: string, aggregation: AggregationFunction): void\n (e: 'updateAggregation', field: string, oldAgg: AggregationFunction, newAgg: AggregationFunction): void\n (e: 'reorderRowFields', fields: string[]): void\n (e: 'reorderColumnFields', fields: string[]): void\n}>()\n\nconst { showWatermark, canUsePivot, isDemo } = useLicense()\n\n// Drag state\nconst dragOverArea = ref<'row' | 'column' | 'value' | null>(null)\n\n// Reorder drag state\nconst reorderDragSource = ref<{ zone: 'row' | 'column', index: number } | null>(null)\nconst reorderDropTarget = ref<{ zone: 'row' | 'column', index: number } | null>(null)\n\n// Aggregation labels\nconst aggregationLabels: Record<AggregationFunction, string> = {\n sum: 'Sum',\n count: 'Count',\n avg: 'Average',\n min: 'Min',\n max: 'Max',\n countDistinct: 'Count Distinct',\n}\n\nfunction getAggregationLabel(fn: AggregationFunction): string {\n return aggregationLabels[fn]\n}\n\nfunction getAggSymbol(agg: AggregationFunction): string {\n const symbols: Record<AggregationFunction, string> = {\n sum: 'Σ',\n count: '#',\n avg: 'x̄',\n min: '↓',\n max: '↑',\n countDistinct: '◇',\n }\n return symbols[agg] || 'Σ'\n}\n\n// Font size\nconst currentFontSize = ref(props.fontSize || 'xs')\nconst fontSizeOptions = [\n { value: 'xs', label: 'S' },\n { value: 'sm', label: 'M' },\n { value: 'base', label: 'L' },\n] as const\n\n// Filter status\nconst hasActiveFilters = computed(() => props.activeFilters && props.activeFilters.length > 0)\nconst filterSummary = computed(() => {\n if (!props.activeFilters || props.activeFilters.length === 0) return ''\n const columns = props.activeFilters.map(f => f.column).join(', ')\n return columns\n})\n\n// Detailed filter tooltip\nconst filterTooltipDetails = computed(() => {\n if (!props.activeFilters || props.activeFilters.length === 0) return []\n return props.activeFilters.map(f => {\n const maxDisplay = 5\n const displayValues = f.values.slice(0, maxDisplay)\n const remaining = f.values.length - maxDisplay\n return {\n column: f.column,\n values: displayValues,\n remaining: remaining > 0 ? remaining : 0,\n }\n })\n})\n\n// Show/hide tooltip\nconst showFilterTooltip = ref(false)\n\n// Sorting\ntype SortDirection = 'asc' | 'desc'\ntype SortTarget = 'row' | number\nconst sortDirection = ref<SortDirection>('asc')\nconst sortTarget = ref<SortTarget>('row')\n\nfunction toggleSort(target: SortTarget = 'row') {\n if (sortTarget.value === target) {\n sortDirection.value = sortDirection.value === 'asc' ? 'desc' : 'asc'\n }\n else {\n sortTarget.value = target\n sortDirection.value = 'asc'\n }\n}\n\n// Sorted row indices\nconst sortedRowIndices = computed(() => {\n if (!props.pivotResult)\n return []\n\n const indices = props.pivotResult.rowHeaders.map((_, i) => i)\n const headers = props.pivotResult.rowHeaders\n const data = props.pivotResult.data\n\n indices.sort((a, b) => {\n let cmp: number\n\n if (sortTarget.value === 'row') {\n const aHeader = headers[a]?.join(' / ') || ''\n const bHeader = headers[b]?.join(' / ') || ''\n cmp = aHeader.localeCompare(bHeader, undefined, { numeric: true, sensitivity: 'base' })\n }\n else {\n const colIdx = sortTarget.value as number\n const aVal = data[a]?.[colIdx]?.value ?? null\n const bVal = data[b]?.[colIdx]?.value ?? null\n\n if (aVal === null && bVal === null)\n cmp = 0\n else if (aVal === null)\n cmp = 1\n else if (bVal === null)\n cmp = -1\n else cmp = aVal - bVal\n }\n\n return sortDirection.value === 'asc' ? cmp : -cmp\n })\n\n return indices\n})\n\n// Column headers\nconst columnHeaderCells = computed(() => {\n if (!props.pivotResult || props.pivotResult.headers.length === 0) {\n return [props.valueFields.map(vf => ({\n label: `${vf.field} (${getAggregationLabel(vf.aggregation)})`,\n colspan: 1,\n }))]\n }\n\n const result: Array<Array<{ label: string, colspan: number }>> = []\n\n for (let level = 0; level < props.pivotResult.headers.length; level++) {\n const headerRow = props.pivotResult.headers[level]\n const cells: Array<{ label: string, colspan: number }> = []\n\n let i = 0\n while (i < headerRow.length) {\n const value = headerRow[i]\n let colspan = 1\n\n while (i + colspan < headerRow.length && headerRow[i + colspan] === value) {\n colspan++\n }\n\n cells.push({ label: value, colspan })\n i += colspan\n }\n\n result.push(cells)\n }\n\n return result\n})\n\n// Selection for copy support\nconst selectedCell = ref<{ row: number, col: number } | null>(null)\nfunction handleCellClick(rowIndex: number, colIndex: number) {\n selectedCell.value = { row: rowIndex, col: colIndex }\n}\nfunction isCellSelected(rowIndex: number, colIndex: number): boolean {\n return selectedCell.value?.row === rowIndex && selectedCell.value?.col === colIndex\n}\n\n// Drag handlers\nfunction handleDragOver(area: 'row' | 'column' | 'value', event: DragEvent) {\n event.preventDefault()\n event.dataTransfer!.dropEffect = 'move'\n dragOverArea.value = area\n}\n\nfunction handleDragLeave() {\n dragOverArea.value = null\n}\n\nfunction handleDrop(area: 'row' | 'column' | 'value', event: DragEvent) {\n event.preventDefault()\n const field = event.dataTransfer?.getData('text/plain')\n\n // Skip if this is a reorder operation (handled by chip drop)\n if (!field || field.startsWith('reorder:')) {\n dragOverArea.value = null\n return\n }\n\n if (props.rowFields.includes(field))\n emit('removeRowField', field)\n if (props.columnFields.includes(field))\n emit('removeColumnField', field)\n const existingValue = props.valueFields.find(v => v.field === field)\n if (existingValue)\n emit('removeValueField', field, existingValue.aggregation)\n\n switch (area) {\n case 'row':\n emit('addRowField', field)\n break\n case 'column':\n emit('addColumnField', field)\n break\n case 'value':\n emit('addValueField', field, 'sum')\n break\n }\n dragOverArea.value = null\n}\n\n// Reorder handlers for chips within zones\nfunction handleChipDragStart(zone: 'row' | 'column', index: number, event: DragEvent) {\n reorderDragSource.value = { zone, index }\n event.dataTransfer!.effectAllowed = 'move'\n event.dataTransfer!.setData('text/plain', `reorder:${zone}:${index}`)\n // Add a slight delay to ensure visual feedback\n requestAnimationFrame(() => {\n dragOverArea.value = null\n })\n}\n\nfunction handleChipDragEnd() {\n reorderDragSource.value = null\n reorderDropTarget.value = null\n}\n\nfunction handleChipDragOver(zone: 'row' | 'column', index: number, event: DragEvent) {\n event.preventDefault()\n // Only handle reorder within same zone\n if (reorderDragSource.value && reorderDragSource.value.zone === zone) {\n event.dataTransfer!.dropEffect = 'move'\n reorderDropTarget.value = { zone, index }\n }\n}\n\nfunction handleChipDragLeave() {\n reorderDropTarget.value = null\n}\n\nfunction handleChipDrop(zone: 'row' | 'column', targetIndex: number, event: DragEvent) {\n event.preventDefault()\n event.stopPropagation()\n \n if (!reorderDragSource.value || reorderDragSource.value.zone !== zone) {\n return\n }\n \n const sourceIndex = reorderDragSource.value.index\n if (sourceIndex === targetIndex) {\n reorderDragSource.value = null\n reorderDropTarget.value = null\n return\n }\n \n // Create reordered array\n const fields = zone === 'row' ? [...props.rowFields] : [...props.columnFields]\n const [movedField] = fields.splice(sourceIndex, 1)\n fields.splice(targetIndex, 0, movedField)\n \n // Emit reorder event\n if (zone === 'row') {\n emit('reorderRowFields', fields)\n } else {\n emit('reorderColumnFields', fields)\n }\n \n reorderDragSource.value = null\n reorderDropTarget.value = null\n}\n\nfunction isChipDragSource(zone: 'row' | 'column', index: number): boolean {\n return reorderDragSource.value?.zone === zone && reorderDragSource.value?.index === index\n}\n\nfunction isChipDropTarget(zone: 'row' | 'column', index: number): boolean {\n return reorderDropTarget.value?.zone === zone && reorderDropTarget.value?.index === index\n}\n\n// Column width\nconst rowHeaderWidth = ref(180)\nconst dataColWidth = ref(80)\n</script>\n\n<template>\n <div\n class=\"vpg-pivot-skeleton\"\n :class=\"[\n `vpg-font-${currentFontSize}`,\n { 'vpg-is-dragging': draggingField },\n ]\"\n >\n <!-- Header Bar -->\n <div class=\"vpg-skeleton-header\">\n <div class=\"vpg-skeleton-title\">\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\" />\n </svg>\n <span>Pivot Table</span>\n </div>\n\n <div class=\"vpg-header-right\">\n <!-- Filter indicator with tooltip -->\n <div\n v-if=\"hasActiveFilters\"\n class=\"vpg-filter-indicator\"\n @mouseenter=\"showFilterTooltip = true\"\n @mouseleave=\"showFilterTooltip = false\"\n >\n <svg class=\"vpg-filter-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\" />\n </svg>\n <span class=\"vpg-filter-text\">\n Filtered: <strong>{{ filterSummary }}</strong>\n <span v-if=\"filteredRowCount !== undefined && totalRowCount !== undefined\" class=\"vpg-filter-count\">\n ({{ filteredRowCount.toLocaleString() }} of {{ totalRowCount.toLocaleString() }} rows)\n </span>\n </span>\n\n <!-- Tooltip -->\n <div v-if=\"showFilterTooltip\" class=\"vpg-filter-tooltip\">\n <div class=\"vpg-tooltip-header\">Active Filters</div>\n <div v-for=\"filter in filterTooltipDetails\" :key=\"filter.column\" class=\"vpg-tooltip-filter\">\n <div class=\"vpg-tooltip-column\">{{ filter.column }}</div>\n <div class=\"vpg-tooltip-values\">\n <span v-for=\"(val, idx) in filter.values\" :key=\"idx\" class=\"vpg-tooltip-value\">\n {{ val }}\n </span>\n <span v-if=\"filter.remaining > 0\" class=\"vpg-tooltip-more\">\n +{{ filter.remaining }} more\n </span>\n </div>\n </div>\n <div v-if=\"filteredRowCount !== undefined && totalRowCount !== undefined\" class=\"vpg-tooltip-summary\">\n Showing {{ filteredRowCount.toLocaleString() }} of {{ totalRowCount.toLocaleString() }} rows\n </div>\n </div>\n </div>\n\n <div v-if=\"isConfigured\" class=\"vpg-config-summary\">\n <span class=\"vpg-summary-badge vpg-rows\">{{ rowFields.length }} row{{ rowFields.length !== 1 ? 's' : '' }}</span>\n <span class=\"vpg-summary-badge vpg-cols\">{{ columnFields.length }} col{{ columnFields.length !== 1 ? 's' : '' }}</span>\n <span class=\"vpg-summary-badge vpg-vals\">{{ valueFields.length }} val{{ valueFields.length !== 1 ? 's' : '' }}</span>\n </div>\n\n <div v-if=\"isConfigured && pivotResult\" class=\"vpg-font-size-toggle\">\n <button\n v-for=\"opt in fontSizeOptions\"\n :key=\"opt.value\"\n class=\"vpg-font-size-btn\"\n :class=\"{ active: currentFontSize === opt.value }\"\n @click=\"currentFontSize = opt.value\"\n >\n {{ opt.label }}\n </button>\n </div>\n </div>\n </div>\n\n <!-- License Required Message -->\n <div v-if=\"!canUsePivot\" class=\"vpg-pro-required\">\n <div class=\"vpg-pro-content\">\n <svg class=\"vpg-pro-icon\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\" />\n </svg>\n <h3>Pro Feature</h3>\n <p>Pivot Table functionality requires a Pro license.</p>\n <a href=\"https://tiny-pivot.com/#pricing\" target=\"_blank\" class=\"vpg-pro-link\">\n Get Pro License →\n </a>\n </div>\n </div>\n\n <!-- Content when licensed -->\n <template v-else>\n <!-- Config Bar -->\n <div class=\"vpg-config-bar\">\n <!-- Row drop zone -->\n <div\n class=\"vpg-drop-zone vpg-row-zone\"\n :class=\"{ 'vpg-drag-over': dragOverArea === 'row' }\"\n @dragover=\"handleDragOver('row', $event)\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop('row', $event)\"\n >\n <div class=\"vpg-zone-header\">\n <span class=\"vpg-zone-icon vpg-row-icon\">↓</span>\n <span class=\"vpg-zone-label\">Rows</span>\n </div>\n <div class=\"vpg-zone-chips\">\n <div\n v-for=\"(field, idx) in rowFields\"\n :key=\"field\"\n class=\"vpg-mini-chip vpg-row-chip\"\n :class=\"{\n 'vpg-chip-dragging': isChipDragSource('row', idx),\n 'vpg-chip-drop-target': isChipDropTarget('row', idx),\n }\"\n draggable=\"true\"\n @dragstart=\"handleChipDragStart('row', idx, $event)\"\n @dragend=\"handleChipDragEnd\"\n @dragover=\"handleChipDragOver('row', idx, $event)\"\n @dragleave=\"handleChipDragLeave\"\n @drop=\"handleChipDrop('row', idx, $event)\"\n >\n <span class=\"vpg-drag-handle\">⋮⋮</span>\n <span class=\"vpg-mini-name\">{{ field }}</span>\n <button class=\"vpg-mini-remove\" @click.stop=\"emit('removeRowField', field)\">×</button>\n </div>\n <span v-if=\"rowFields.length === 0\" class=\"vpg-zone-hint\">Drop here</span>\n </div>\n </div>\n\n <!-- Column drop zone -->\n <div\n class=\"vpg-drop-zone vpg-column-zone\"\n :class=\"{ 'vpg-drag-over': dragOverArea === 'column' }\"\n @dragover=\"handleDragOver('column', $event)\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop('column', $event)\"\n >\n <div class=\"vpg-zone-header\">\n <span class=\"vpg-zone-icon vpg-column-icon\">→</span>\n <span class=\"vpg-zone-label\">Columns</span>\n </div>\n <div class=\"vpg-zone-chips\">\n <div\n v-for=\"(field, idx) in columnFields\"\n :key=\"field\"\n class=\"vpg-mini-chip vpg-column-chip\"\n :class=\"{\n 'vpg-chip-dragging': isChipDragSource('column', idx),\n 'vpg-chip-drop-target': isChipDropTarget('column', idx),\n }\"\n draggable=\"true\"\n @dragstart=\"handleChipDragStart('column', idx, $event)\"\n @dragend=\"handleChipDragEnd\"\n @dragover=\"handleChipDragOver('column', idx, $event)\"\n @dragleave=\"handleChipDragLeave\"\n @drop=\"handleChipDrop('column', idx, $event)\"\n >\n <span class=\"vpg-drag-handle\">⋮⋮</span>\n <span class=\"vpg-mini-name\">{{ field }}</span>\n <button class=\"vpg-mini-remove\" @click.stop=\"emit('removeColumnField', field)\">×</button>\n </div>\n <span v-if=\"columnFields.length === 0\" class=\"vpg-zone-hint\">Drop here</span>\n </div>\n </div>\n\n <!-- Values drop zone -->\n <div\n class=\"vpg-drop-zone vpg-value-zone\"\n :class=\"{ 'vpg-drag-over': dragOverArea === 'value' }\"\n @dragover=\"handleDragOver('value', $event)\"\n @dragleave=\"handleDragLeave\"\n @drop=\"handleDrop('value', $event)\"\n >\n <div class=\"vpg-zone-header\">\n <span class=\"vpg-zone-icon vpg-value-icon\">Σ</span>\n <span class=\"vpg-zone-label\">Values</span>\n </div>\n <div class=\"vpg-zone-chips\">\n <div\n v-for=\"vf in valueFields\"\n :key=\"`${vf.field}-${vf.aggregation}`\"\n class=\"vpg-mini-chip vpg-value-chip\"\n >\n <span class=\"vpg-agg-symbol\">{{ getAggSymbol(vf.aggregation) }}</span>\n <span class=\"vpg-mini-name\">{{ vf.field }}</span>\n <button class=\"vpg-mini-remove\" @click=\"emit('removeValueField', vf.field, vf.aggregation)\">×</button>\n </div>\n <span v-if=\"valueFields.length === 0\" class=\"vpg-zone-hint\">Drop numeric</span>\n </div>\n </div>\n </div>\n\n <!-- Placeholder when not configured -->\n <div v-if=\"!isConfigured || !pivotResult\" class=\"vpg-placeholder\">\n <div class=\"vpg-placeholder-content\">\n <svg class=\"vpg-placeholder-icon\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n <span class=\"vpg-placeholder-text\">\n <template v-if=\"valueFields.length === 0\">\n Add a <strong>Values</strong> field to see your pivot table\n </template>\n <template v-else-if=\"rowFields.length === 0 && columnFields.length === 0\">\n Add <strong>Row</strong> or <strong>Column</strong> fields to group your data\n </template>\n <template v-else>\n Your pivot table will appear here\n </template>\n </span>\n </div>\n </div>\n\n <!-- Data Table -->\n <div v-else class=\"vpg-table-container\">\n <table class=\"vpg-pivot-table\">\n <thead>\n <tr v-for=\"(headerRow, levelIdx) in columnHeaderCells\" :key=\"`header-${levelIdx}`\" class=\"vpg-column-header-row\">\n <th\n v-if=\"levelIdx === 0\"\n class=\"vpg-row-header-label\"\n :rowspan=\"columnHeaderCells.length\"\n :style=\"{ width: `${rowHeaderWidth}px` }\"\n @click=\"toggleSort('row')\"\n >\n <div class=\"vpg-header-content\">\n <span>{{ rowFields.join(' / ') || 'Rows' }}</span>\n <span class=\"vpg-sort-indicator\" :class=\"{ active: sortTarget === 'row' }\">\n {{ sortTarget === 'row' ? (sortDirection === 'asc' ? '↑' : '↓') : '⇅' }}\n </span>\n </div>\n </th>\n <th\n v-for=\"(cell, idx) in headerRow\"\n :key=\"idx\"\n class=\"vpg-column-header-cell\"\n :colspan=\"cell.colspan\"\n :style=\"{ width: `${dataColWidth * cell.colspan}px` }\"\n @click=\"levelIdx === columnHeaderCells.length - 1 && toggleSort(idx)\"\n >\n <div class=\"vpg-header-content\">\n <span>{{ cell.label }}</span>\n <span v-if=\"levelIdx === columnHeaderCells.length - 1\" class=\"vpg-sort-indicator\" :class=\"{ active: sortTarget === idx }\">\n {{ sortTarget === idx ? (sortDirection === 'asc' ? '↑' : '↓') : '⇅' }}\n </span>\n </div>\n </th>\n <th\n v-if=\"pivotResult.rowTotals.length > 0 && levelIdx === 0\"\n class=\"vpg-total-header\"\n :rowspan=\"columnHeaderCells.length\"\n >\n Total\n </th>\n </tr>\n </thead>\n\n <tbody>\n <tr v-for=\"sortedIdx in sortedRowIndices\" :key=\"sortedIdx\" class=\"vpg-data-row\">\n <th\n class=\"vpg-row-header-cell\"\n :style=\"{ width: `${rowHeaderWidth}px` }\"\n >\n <span v-for=\"(val, idx) in pivotResult.rowHeaders[sortedIdx]\" :key=\"idx\" class=\"vpg-row-value\">\n {{ val }}\n </span>\n </th>\n\n <td\n v-for=\"(cell, colIdx) in pivotResult.data[sortedIdx]\"\n :key=\"colIdx\"\n class=\"vpg-data-cell\"\n :class=\"[\n isCellSelected(sortedIdx, colIdx) && 'selected',\n cell.value === null && 'vpg-is-null',\n ]\"\n :style=\"{ width: `${dataColWidth}px` }\"\n @click=\"handleCellClick(sortedIdx, colIdx)\"\n >\n {{ cell.formattedValue }}\n </td>\n\n <td v-if=\"pivotResult.rowTotals[sortedIdx]\" class=\"vpg-data-cell vpg-total-cell\">\n {{ pivotResult.rowTotals[sortedIdx].formattedValue }}\n </td>\n </tr>\n\n <tr v-if=\"pivotResult.columnTotals.length > 0\" class=\"vpg-totals-row\">\n <th class=\"vpg-row-header-cell vpg-total-label\" :style=\"{ width: `${rowHeaderWidth}px` }\">\n Total\n </th>\n <td\n v-for=\"(cell, colIdx) in pivotResult.columnTotals\"\n :key=\"colIdx\"\n class=\"vpg-data-cell vpg-total-cell\"\n :style=\"{ width: `${dataColWidth}px` }\"\n >\n {{ cell.formattedValue }}\n </td>\n <td v-if=\"pivotResult.rowTotals.length > 0\" class=\"vpg-data-cell vpg-grand-total-cell\">\n {{ pivotResult.grandTotal.formattedValue }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Footer -->\n <div v-if=\"isConfigured && pivotResult\" class=\"vpg-skeleton-footer\">\n <span>{{ pivotResult.rowHeaders.length }} rows × {{ pivotResult.data[0]?.length || 0 }} columns</span>\n </div>\n </template>\n\n <!-- Watermark / Demo Banner -->\n <div v-if=\"showWatermark && canUsePivot\" class=\"vpg-watermark\" :class=\"{ 'vpg-demo-mode': isDemo }\">\n <template v-if=\"isDemo\">\n <span class=\"vpg-demo-badge\">DEMO</span>\n <span>Pro features unlocked for evaluation</span>\n <a href=\"https://tiny-pivot.com/#pricing\" target=\"_blank\" rel=\"noopener\" class=\"vpg-get-pro\">\n Get Pro License →\n </a>\n </template>\n <template v-else>\n <a href=\"https://tiny-pivot.com\" target=\"_blank\" rel=\"noopener\">\n Powered by TinyPivot\n </a>\n </template>\n </div>\n </div>\n</template>\n\n<style scoped>\n.vpg-pivot-skeleton {\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 0.75rem;\n box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.vpg-pivot-skeleton.vpg-is-dragging {\n box-shadow: 0 0 0 2px #10b981;\n}\n\n.vpg-icon {\n width: 1rem;\n height: 1rem;\n}\n\n/* Header */\n.vpg-skeleton-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem 1rem;\n background: linear-gradient(to right, #ecfdf5, #f0fdfa);\n border-bottom: 1px solid #e2e8f0;\n flex-shrink: 0;\n}\n\n.vpg-skeleton-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.75rem;\n font-weight: 600;\n color: #475569;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.vpg-header-right {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.vpg-config-summary {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.vpg-summary-badge {\n padding: 0.125rem 0.375rem;\n font-size: 0.625rem;\n font-weight: 600;\n border-radius: 0.25rem;\n}\n\n.vpg-summary-badge.vpg-rows {\n background: #e0e7ff;\n color: #4f46e5;\n}\n\n.vpg-summary-badge.vpg-cols {\n background: #ede9fe;\n color: #7c3aed;\n}\n\n.vpg-summary-badge.vpg-vals {\n background: #d1fae5;\n color: #059669;\n}\n\n/* Filter indicator */\n.vpg-filter-indicator {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.625rem;\n background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);\n border: 1px solid #f59e0b;\n border-radius: 0.375rem;\n font-size: 0.6875rem;\n color: #92400e;\n box-shadow: 0 1px 2px rgba(245, 158, 11, 0.15);\n cursor: help;\n}\n\n.vpg-filter-icon {\n width: 0.875rem;\n height: 0.875rem;\n flex-shrink: 0;\n color: #d97706;\n}\n\n.vpg-filter-text {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n white-space: nowrap;\n}\n\n.vpg-filter-text strong {\n font-weight: 600;\n color: #78350f;\n max-width: 150px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.vpg-filter-count {\n color: #a16207;\n font-size: 0.625rem;\n}\n\n/* Filter tooltip */\n.vpg-filter-tooltip {\n position: absolute;\n top: calc(100% + 0.5rem);\n right: 0;\n min-width: 220px;\n max-width: 320px;\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 0.5rem;\n box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1);\n z-index: 100;\n overflow: hidden;\n}\n\n.vpg-tooltip-header {\n padding: 0.5rem 0.75rem;\n font-size: 0.6875rem;\n font-weight: 700;\n color: #475569;\n background: #f8fafc;\n border-bottom: 1px solid #e2e8f0;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.vpg-tooltip-filter {\n padding: 0.5rem 0.75rem;\n border-bottom: 1px solid #f1f5f9;\n}\n\n.vpg-tooltip-filter:last-of-type {\n border-bottom: none;\n}\n\n.vpg-tooltip-column {\n font-size: 0.6875rem;\n font-weight: 600;\n color: #1e293b;\n margin-bottom: 0.375rem;\n}\n\n.vpg-tooltip-values {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n}\n\n.vpg-tooltip-value {\n padding: 0.125rem 0.375rem;\n font-size: 0.625rem;\n background: #fef3c7;\n color: #92400e;\n border-radius: 0.25rem;\n border: 1px solid #fde68a;\n}\n\n.vpg-tooltip-more {\n padding: 0.125rem 0.375rem;\n font-size: 0.625rem;\n color: #64748b;\n font-style: italic;\n}\n\n.vpg-tooltip-summary {\n padding: 0.5rem 0.75rem;\n font-size: 0.625rem;\n color: #64748b;\n background: #f8fafc;\n border-top: 1px solid #e2e8f0;\n text-align: center;\n}\n\n.vpg-font-size-toggle {\n display: flex;\n background: white;\n border-radius: 0.25rem;\n border: 1px solid #e2e8f0;\n overflow: hidden;\n}\n\n.vpg-font-size-btn {\n padding: 0.125rem 0.5rem;\n font-size: 0.625rem;\n font-weight: 500;\n color: #64748b;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-font-size-btn:hover {\n background: #f1f5f9;\n}\n\n.vpg-font-size-btn.active {\n background: #10b981;\n color: white;\n}\n\n/* Pro Required */\n.vpg-pro-required {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #fef3c7, #fde68a);\n}\n\n.vpg-pro-content {\n text-align: center;\n padding: 2rem;\n}\n\n.vpg-pro-icon {\n width: 3rem;\n height: 3rem;\n color: #d97706;\n margin: 0 auto 1rem;\n}\n\n.vpg-pro-content h3 {\n font-size: 1.25rem;\n font-weight: 600;\n color: #92400e;\n margin-bottom: 0.5rem;\n}\n\n.vpg-pro-content p {\n font-size: 0.875rem;\n color: #a16207;\n margin-bottom: 1rem;\n}\n\n.vpg-pro-link {\n display: inline-block;\n padding: 0.5rem 1rem;\n background: #f59e0b;\n color: white;\n font-weight: 500;\n border-radius: 0.375rem;\n text-decoration: none;\n transition: background 0.15s;\n}\n\n.vpg-pro-link:hover {\n background: #d97706;\n}\n\n/* Config Bar */\n.vpg-config-bar {\n display: flex;\n align-items: stretch;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n background: #f8fafc;\n border-bottom: 1px solid #e2e8f0;\n flex-shrink: 0;\n}\n\n.vpg-drop-zone {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n border-radius: 0.5rem;\n border: 2px dashed;\n transition: all 0.15s;\n}\n\n.vpg-drop-zone.vpg-row-zone {\n background: rgba(238, 242, 255, 0.5);\n border-color: #c7d2fe;\n}\n\n.vpg-drop-zone.vpg-column-zone {\n background: rgba(245, 243, 255, 0.5);\n border-color: #ddd6fe;\n flex: 1;\n}\n\n.vpg-drop-zone.vpg-value-zone {\n background: rgba(236, 253, 245, 0.5);\n border-color: #a7f3d0;\n}\n\n.vpg-drop-zone.vpg-drag-over {\n border-style: solid;\n box-shadow: 0 0 0 2px currentColor inset;\n}\n\n.vpg-drop-zone.vpg-row-zone.vpg-drag-over {\n background: #eef2ff;\n border-color: #818cf8;\n}\n\n.vpg-drop-zone.vpg-column-zone.vpg-drag-over {\n background: #f5f3ff;\n border-color: #a78bfa;\n}\n\n.vpg-drop-zone.vpg-value-zone.vpg-drag-over {\n background: #ecfdf5;\n border-color: #34d399;\n}\n\n.vpg-zone-header {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n flex-shrink: 0;\n}\n\n.vpg-zone-icon {\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.75rem;\n font-weight: 700;\n border-radius: 0.25rem;\n}\n\n.vpg-zone-icon.vpg-row-icon {\n background: #c7d2fe;\n color: #4338ca;\n}\n\n.vpg-zone-icon.vpg-column-icon {\n background: #ddd6fe;\n color: #7c3aed;\n}\n\n.vpg-zone-icon.vpg-value-icon {\n background: #a7f3d0;\n color: #059669;\n}\n\n.vpg-zone-label {\n font-size: 0.625rem;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.vpg-row-zone .vpg-zone-label {\n color: #4f46e5;\n}\n\n.vpg-column-zone .vpg-zone-label {\n color: #7c3aed;\n}\n\n.vpg-value-zone .vpg-zone-label {\n color: #059669;\n}\n\n.vpg-zone-chips {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.25rem;\n}\n\n.vpg-zone-hint {\n font-size: 0.625rem;\n color: #94a3b8;\n font-style: italic;\n}\n\n.vpg-mini-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.25rem 0.5rem;\n border-radius: 0.25rem;\n font-size: 0.625rem;\n font-weight: 500;\n max-width: 100%;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n cursor: grab;\n transition: all 0.15s ease;\n}\n\n.vpg-mini-chip:active {\n cursor: grabbing;\n}\n\n.vpg-drag-handle {\n opacity: 0.3;\n font-size: 0.625rem;\n letter-spacing: -0.1em;\n margin-right: 0.125rem;\n cursor: grab;\n flex-shrink: 0;\n}\n\n.vpg-mini-chip:hover .vpg-drag-handle {\n opacity: 0.6;\n}\n\n.vpg-mini-chip.vpg-chip-dragging {\n opacity: 0.4;\n transform: scale(0.95);\n}\n\n.vpg-mini-chip.vpg-chip-drop-target {\n transform: translateX(4px);\n box-shadow: -3px 0 0 0 currentColor, 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-mini-chip.vpg-row-chip {\n background: white;\n color: #4338ca;\n border: 1px solid #c7d2fe;\n}\n\n.vpg-mini-chip.vpg-column-chip {\n background: white;\n color: #7c3aed;\n border: 1px solid #ddd6fe;\n}\n\n.vpg-mini-chip.vpg-value-chip {\n background: white;\n color: #059669;\n border: 1px solid #a7f3d0;\n}\n\n.vpg-mini-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n}\n\n.vpg-mini-remove {\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n line-height: 1;\n opacity: 0.4;\n flex-shrink: 0;\n background: transparent;\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-mini-remove:hover {\n opacity: 1;\n background: #fee2e2;\n color: #ef4444;\n}\n\n.vpg-agg-symbol {\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.625rem;\n font-weight: 700;\n background: #d1fae5;\n color: #059669;\n border-radius: 0.25rem;\n flex-shrink: 0;\n}\n\n/* Placeholder */\n.vpg-placeholder {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #f8fafc, white, rgba(236, 253, 245, 0.3));\n border-top: 1px solid #f1f5f9;\n}\n\n.vpg-placeholder-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n text-align: center;\n padding: 2rem;\n}\n\n.vpg-placeholder-icon {\n width: 4rem;\n height: 4rem;\n color: #cbd5e1;\n}\n\n.vpg-placeholder-text {\n font-size: 0.875rem;\n color: #64748b;\n}\n\n.vpg-placeholder-text strong {\n color: #334155;\n font-weight: 600;\n}\n\n/* Table */\n.vpg-table-container {\n flex: 1;\n overflow: auto;\n max-height: 100%;\n}\n\n.vpg-pivot-table {\n border-collapse: collapse;\n table-layout: fixed;\n min-width: max-content;\n}\n\n.vpg-pivot-table thead {\n position: sticky;\n top: 0;\n z-index: 30;\n box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.1);\n}\n\n.vpg-column-header-row {\n background: #e2e8f0;\n}\n\n.vpg-column-header-row th {\n background: #e2e8f0;\n}\n\n.vpg-row-header-label {\n position: sticky;\n left: 0;\n z-index: 30;\n padding: 0.5rem 0.75rem;\n text-align: left;\n font-size: 0.625rem;\n font-weight: 600;\n color: #64748b;\n text-transform: uppercase;\n border-bottom: 1px solid #cbd5e1;\n border-right: 1px solid #cbd5e1;\n background: #e2e8f0;\n cursor: pointer;\n}\n\n.vpg-row-header-label:hover {\n background: #d1d5db;\n}\n\n.vpg-column-header-cell {\n padding: 0.5rem 0.75rem;\n text-align: center;\n font-size: 0.6875rem;\n font-weight: 600;\n color: #334155;\n border-bottom: 1px solid #cbd5e1;\n border-right: 1px solid #cbd5e1;\n white-space: nowrap;\n background: #e2e8f0;\n cursor: pointer;\n}\n\n.vpg-column-header-cell:hover {\n background: rgba(203, 213, 225, 0.5);\n}\n\n.vpg-header-content {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.25rem;\n}\n\n.vpg-sort-indicator {\n flex-shrink: 0;\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #94a3b8;\n font-size: 0.75rem;\n}\n\n.vpg-sort-indicator.active {\n color: #4f46e5;\n font-weight: 700;\n}\n\n.vpg-total-header {\n padding: 0.5rem;\n text-align: center;\n font-size: 0.6875rem;\n font-weight: 700;\n color: #92400e;\n border-bottom: 1px solid #cbd5e1;\n border-left: 2px solid #f59e0b;\n background: #fde68a;\n vertical-align: middle;\n}\n\n.vpg-data-row:hover {\n background: #ecfdf5;\n}\n\n.vpg-data-row:nth-child(even) {\n background: #f8fafc;\n}\n\n.vpg-row-header-cell {\n position: sticky;\n left: 0;\n padding: 0.5rem 0.75rem;\n text-align: left;\n font-size: 0.75rem;\n font-weight: 500;\n color: #334155;\n background: white;\n border-bottom: 1px solid #e2e8f0;\n border-right: 1px solid #e2e8f0;\n white-space: nowrap;\n z-index: 10;\n}\n\n.vpg-data-row:nth-child(even) .vpg-row-header-cell {\n background: #f8fafc;\n}\n\n.vpg-row-value + .vpg-row-value::before {\n content: ' / ';\n color: #94a3b8;\n}\n\n.vpg-data-cell {\n padding: 0.5rem 0.75rem;\n text-align: right;\n font-size: 0.75rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n color: #334155;\n font-variant-numeric: tabular-nums;\n border-bottom: 1px solid #f1f5f9;\n border-right: 1px solid #f8fafc;\n cursor: cell;\n white-space: nowrap;\n}\n\n.vpg-data-cell.selected {\n background: #d1fae5;\n outline: 2px solid #10b981;\n outline-offset: -2px;\n position: relative;\n z-index: 1;\n}\n\n.vpg-data-cell.vpg-is-null {\n color: #cbd5e1;\n}\n\n.vpg-data-cell.vpg-total-cell {\n background: #fef3c7;\n font-weight: 600;\n color: #92400e;\n}\n\n.vpg-data-cell.vpg-grand-total-cell {\n background: #fde68a;\n font-weight: 700;\n color: #92400e;\n}\n\n.vpg-totals-row {\n background: #fef9e7;\n}\n\n.vpg-total-label {\n font-weight: 700;\n color: #92400e;\n background: #fef3c7;\n}\n\n/* Font sizes */\n.vpg-pivot-skeleton.vpg-font-xs .vpg-data-cell,\n.vpg-pivot-skeleton.vpg-font-xs .vpg-row-header-cell {\n font-size: 0.75rem;\n padding: 0.375rem 0.75rem;\n}\n\n.vpg-pivot-skeleton.vpg-font-sm .vpg-data-cell,\n.vpg-pivot-skeleton.vpg-font-sm .vpg-row-header-cell {\n font-size: 0.875rem;\n padding: 0.5rem 1rem;\n}\n\n.vpg-pivot-skeleton.vpg-font-base .vpg-data-cell,\n.vpg-pivot-skeleton.vpg-font-base .vpg-row-header-cell {\n font-size: 1rem;\n padding: 0.625rem 1rem;\n}\n\n/* Footer */\n.vpg-skeleton-footer {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n font-size: 0.75rem;\n color: #64748b;\n background: #f8fafc;\n border-top: 1px solid #e2e8f0;\n flex-shrink: 0;\n}\n\n/* Watermark */\n.vpg-watermark {\n padding: 0.375rem 1rem;\n background: #f1f5f9;\n border-top: 1px solid #e2e8f0;\n text-align: center;\n flex-shrink: 0;\n}\n\n.vpg-watermark a {\n font-size: 0.625rem;\n color: #94a3b8;\n text-decoration: none;\n transition: color 0.15s;\n}\n\n.vpg-watermark a:hover {\n color: #64748b;\n}\n\n/* Demo Mode Banner */\n.vpg-watermark.vpg-demo-mode {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.75rem;\n padding: 0.5rem 1rem;\n background: linear-gradient(135deg, #fef3c7, #fde68a);\n border-top: 1px solid #fcd34d;\n font-size: 0.75rem;\n color: #92400e;\n}\n\n.vpg-demo-badge {\n display: inline-flex;\n align-items: center;\n padding: 0.125rem 0.5rem;\n background: #f59e0b;\n color: white;\n font-size: 0.625rem;\n font-weight: 700;\n border-radius: 0.25rem;\n letter-spacing: 0.05em;\n}\n\n.vpg-get-pro {\n font-weight: 600;\n color: #d97706 !important;\n}\n\n.vpg-get-pro:hover {\n color: #b45309 !important;\n text-decoration: underline;\n}\n\n/* Scrollbar */\n.vpg-table-container::-webkit-scrollbar {\n width: 0.5rem;\n height: 0.5rem;\n}\n\n.vpg-table-container::-webkit-scrollbar-track {\n background: #f1f5f9;\n}\n\n.vpg-table-container::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 9999px;\n}\n\n.vpg-table-container::-webkit-scrollbar-thumb:hover {\n background: #94a3b8;\n}\n\n.vpg-table-container::-webkit-scrollbar-corner {\n background: #f1f5f9;\n}\n\n</style>\n\n<style>\n/* Dark Mode - PivotSkeleton */\n.vpg-theme-dark .vpg-pivot-skeleton {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-skeleton-header {\n background: linear-gradient(to right, rgba(16, 185, 129, 0.15), rgba(20, 184, 166, 0.1)) !important;\n border-color: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-skeleton-title {\n color: #6ee7b7 !important;\n}\n\n/* Config bar (drop zones container) */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-config-bar {\n background: #0f172a !important;\n border-color: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-drop-zones {\n background: #0f172a !important;\n border-color: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-drop-zone {\n background: #1e293b !important;\n border-color: #475569 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-drop-zone:hover {\n border-color: #64748b !important;\n background: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-drop-zone.vpg-zone-active {\n border-color: #10b981 !important;\n background: rgba(16, 185, 129, 0.2) !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-zone-label {\n color: #94a3b8 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-zone-row .vpg-zone-label { color: #a5b4fc !important; }\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-zone-column .vpg-zone-label { color: #c4b5fd !important; }\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-zone-value .vpg-zone-label { color: #6ee7b7 !important; }\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-zone-hint {\n color: #64748b !important;\n}\n\n/* Mini chips in drop zones */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-mini-chip.vpg-row-chip {\n background: #312e81 !important;\n color: #a5b4fc !important;\n border-color: #4338ca !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-mini-chip.vpg-column-chip {\n background: #4c1d95 !important;\n color: #c4b5fd !important;\n border-color: #7c3aed !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-mini-chip.vpg-value-chip {\n background: #064e3b !important;\n color: #6ee7b7 !important;\n border-color: #10b981 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-drag-handle {\n opacity: 0.4;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-mini-chip:hover .vpg-drag-handle {\n opacity: 0.7;\n}\n\n/* Font size toggle (S M L) */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-font-size-toggle {\n background: #1e293b !important;\n border-color: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-font-size-btn {\n color: #94a3b8 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-font-size-btn:hover {\n background: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-font-size-btn.active {\n background: #10b981 !important;\n color: white !important;\n}\n\n/* Summary badges (1 row, 1 col, 1 val) */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-summary-badge.vpg-rows {\n background: rgba(99, 102, 241, 0.2) !important;\n color: #a5b4fc !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-summary-badge.vpg-cols {\n background: rgba(139, 92, 246, 0.2) !important;\n color: #c4b5fd !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-summary-badge.vpg-vals {\n background: rgba(16, 185, 129, 0.2) !important;\n color: #6ee7b7 !important;\n}\n\n/* Filter indicator - dark mode */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-filter-indicator {\n background: linear-gradient(135deg, rgba(245, 158, 11, 0.2) 0%, rgba(217, 119, 6, 0.25) 100%) !important;\n border-color: #d97706 !important;\n color: #fbbf24 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-filter-icon {\n color: #fbbf24 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-filter-text strong {\n color: #fcd34d !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-filter-count {\n color: #fbbf24 !important;\n}\n\n/* Filter tooltip - dark mode */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-filter-tooltip {\n background: #1e293b !important;\n border-color: #475569 !important;\n box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.4), 0 8px 10px -6px rgba(0, 0, 0, 0.3);\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-header {\n background: #0f172a !important;\n border-color: #334155 !important;\n color: #94a3b8 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-filter {\n border-color: #334155 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-column {\n color: #e2e8f0 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-value {\n background: rgba(245, 158, 11, 0.2) !important;\n color: #fbbf24 !important;\n border-color: rgba(245, 158, 11, 0.4) !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-more {\n color: #94a3b8 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-tooltip-summary {\n background: #0f172a !important;\n border-color: #334155 !important;\n color: #94a3b8 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-table-container {\n background: #1e293b;\n}\n\n.vpg-theme-dark .vpg-pivot-table {\n background: #1e293b;\n}\n\n.vpg-theme-dark .vpg-pivot-table thead {\n box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.3);\n}\n\n.vpg-theme-dark .vpg-column-header-row {\n background: #0f172a !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-column-header-cell,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-corner-cell,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-row-header-label {\n background: #0f172a !important;\n border-color: #334155 !important;\n color: #e2e8f0 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-row-header-label:hover,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-column-header-cell:hover {\n background: #1e293b !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-row-header-cell {\n background: #1e293b;\n border-color: #334155;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-cell {\n background: #1e293b;\n border-color: #334155;\n color: #cbd5e1;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-row:nth-child(even) .vpg-row-header-cell,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-row:nth-child(even) .vpg-data-cell {\n background: #0f172a;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-row:hover .vpg-row-header-cell,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-row:hover .vpg-data-cell {\n background: #334155;\n}\n\n/* Total header column */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-total-header {\n background: #451a03 !important;\n color: #fbbf24 !important;\n border-color: #334155 !important;\n}\n\n/* Total cells in rows - consistent color */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-cell.vpg-total-cell {\n background: #451a03 !important;\n color: #fbbf24 !important;\n}\n\n/* Grand total cell */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-data-cell.vpg-grand-total-cell {\n background: #451a03 !important;\n color: #fbbf24 !important;\n}\n\n/* Totals row - consistent color */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-totals-row {\n background: transparent !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-totals-row .vpg-row-header-cell,\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-totals-row .vpg-data-cell {\n background: #451a03 !important;\n}\n\n/* Total label */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-total-label {\n background: #451a03 !important;\n color: #fbbf24 !important;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-empty-state {\n background: #0f172a;\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-skeleton-footer {\n background: #0f172a;\n border-color: #334155;\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-demo-bar {\n background: rgba(245, 158, 11, 0.15);\n border-color: rgba(245, 158, 11, 0.3);\n color: #fbbf24;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-table-container::-webkit-scrollbar-track {\n background: #0f172a;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-table-container::-webkit-scrollbar-thumb {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-table-container::-webkit-scrollbar-thumb:hover {\n background: #475569;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-table-container::-webkit-scrollbar-corner {\n background: #0f172a;\n}\n\n/* Dark mode - Placeholder */\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-placeholder {\n background: linear-gradient(135deg, #1e293b, #0f172a, rgba(16, 185, 129, 0.05));\n border-top-color: #334155;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-placeholder-icon {\n color: #475569;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-placeholder-text {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-pivot-skeleton .vpg-placeholder-text strong {\n color: #e2e8f0;\n}\n</style>\n\n","<script setup lang=\"ts\">\n/**\n * TinyPivot - Main DataGrid Component\n * Excel-like data grid with optional pivot table functionality\n */\nimport { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'\nimport { useExcelGrid } from '../composables/useExcelGrid'\nimport { usePivotTable } from '../composables/usePivotTable'\nimport { useLicense } from '../composables/useLicense'\nimport {\n exportToCSV,\n exportPivotToCSV,\n copyToClipboard,\n formatSelectionForClipboard,\n} from '../composables/useGridFeatures'\nimport type { ColumnStats } from '@smallwebco/tinypivot-core'\nimport ColumnFilter from './ColumnFilter.vue'\nimport PivotConfig from './PivotConfig.vue'\nimport PivotSkeleton from './PivotSkeleton.vue'\n\nconst props = withDefaults(defineProps<{\n data: Record<string, unknown>[]\n loading?: boolean\n rowHeight?: number\n headerHeight?: number\n fontSize?: 'xs' | 'sm' | 'base'\n showPivot?: boolean\n // Feature props\n enableExport?: boolean\n enableSearch?: boolean\n enablePagination?: boolean\n pageSize?: number\n enableColumnResize?: boolean\n enableClipboard?: boolean\n theme?: 'light' | 'dark' | 'auto'\n stripedRows?: boolean\n exportFilename?: string\n enableVerticalResize?: boolean\n initialHeight?: number\n minHeight?: number\n maxHeight?: number\n}>(), {\n loading: false,\n rowHeight: 36,\n headerHeight: 40,\n fontSize: 'xs',\n showPivot: true,\n // Feature defaults\n enableExport: true,\n enableSearch: true,\n enablePagination: false,\n pageSize: 50,\n enableColumnResize: true,\n enableClipboard: true,\n theme: 'light',\n stripedRows: true,\n exportFilename: 'data-export.csv',\n enableVerticalResize: true,\n initialHeight: 600,\n minHeight: 300,\n maxHeight: 1200,\n})\n\nconst emit = defineEmits<{\n (e: 'cellClick', payload: { row: number, col: number, value: unknown, rowData: Record<string, unknown> }): void\n (e: 'selectionChange', payload: { cells: Array<{ row: number, col: number }>, values: unknown[] }): void\n (e: 'export', payload: { rowCount: number, filename: string }): void\n (e: 'copy', payload: { text: string, cellCount: number }): void\n}>()\n\nconst { showWatermark, canUsePivot, isDemo } = useLicense()\n\n// Theme handling\nconst currentTheme = computed(() => {\n if (props.theme === 'auto') {\n return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n }\n return props.theme\n})\n\n// Font size state\nconst currentFontSize = ref(props.fontSize)\n\n// Global search state\nconst globalSearchTerm = ref('')\nconst showSearchInput = ref(false)\n\n// Pagination state\nconst currentPage = ref(1)\n\n// Column resize state\nconst resizingColumnId = ref<string | null>(null)\nconst resizeStartX = ref(0)\nconst resizeStartWidth = ref(0)\n\n// Vertical resize state\nconst gridHeight = ref(props.initialHeight)\nconst isResizingVertically = ref(false)\nconst verticalResizeStartY = ref(0)\nconst verticalResizeStartHeight = ref(0)\n\n// Clipboard toast state\nconst showCopyToast = ref(false)\nconst copyToastMessage = ref('')\nconst fontSizeOptions = [\n { value: 'xs', label: 'S' },\n { value: 'sm', label: 'M' },\n { value: 'base', label: 'L' },\n] as const\n\n// Grid composable\nconst dataRef = computed(() => props.data)\nconst {\n table,\n columnKeys,\n filteredRowCount,\n totalRowCount,\n getColumnStats,\n hasActiveFilter,\n setColumnFilter,\n getColumnFilterValues,\n clearAllFilters,\n toggleSort,\n getSortDirection,\n columnFilters,\n activeFilters,\n} = useExcelGrid({ data: dataRef })\n\n// Filtered data for pivot table (respects column filters)\nconst filteredDataForPivot = computed(() => {\n const filteredRows = table.getFilteredRowModel().rows\n return filteredRows.map(row => row.original)\n})\n\n// Active filters info for display - use activeFilters from useExcelGrid\nconst activeFilterInfo = computed(() => {\n if (activeFilters.value.length === 0) return null\n return activeFilters.value.map(f => ({\n column: f.column,\n valueCount: f.values?.length || 0,\n values: f.values || [],\n }))\n})\n\n// Pivot table composable - uses filtered data\nconst {\n rowFields: pivotRowFields,\n columnFields: pivotColumnFields,\n valueFields: pivotValueFields,\n showRowTotals: pivotShowRowTotals,\n showColumnTotals: pivotShowColumnTotals,\n availableFields: pivotAvailableFields,\n isConfigured: pivotIsConfigured,\n pivotResult,\n addRowField,\n removeRowField,\n addColumnField,\n removeColumnField,\n addValueField,\n removeValueField,\n updateValueFieldAggregation,\n clearConfig: clearPivotConfig,\n autoSuggestConfig,\n} = usePivotTable(filteredDataForPivot)\n\n// Filtered data based on global search\nconst searchFilteredData = computed(() => {\n if (!globalSearchTerm.value.trim() || !props.enableSearch) {\n return rows.value\n }\n const term = globalSearchTerm.value.toLowerCase().trim()\n return rows.value.filter((row) => {\n for (const col of columnKeys.value) {\n const value = row.original[col]\n if (value === null || value === undefined) continue\n if (String(value).toLowerCase().includes(term)) {\n return true\n }\n }\n return false\n })\n})\n\n// Paginated rows\nconst totalSearchedRows = computed(() => searchFilteredData.value.length)\nconst totalPages = computed(() => {\n if (!props.enablePagination) return 1\n return Math.max(1, Math.ceil(totalSearchedRows.value / props.pageSize))\n})\n\nconst paginatedRows = computed(() => {\n if (!props.enablePagination) return searchFilteredData.value\n const start = (currentPage.value - 1) * props.pageSize\n const end = start + props.pageSize\n return searchFilteredData.value.slice(start, end)\n})\n\nconst paginationStart = computed(() => {\n if (totalSearchedRows.value === 0) return 0\n return (currentPage.value - 1) * props.pageSize + 1\n})\n\nconst paginationEnd = computed(() =>\n Math.min(currentPage.value * props.pageSize, totalSearchedRows.value),\n)\n\n// Pagination methods\nfunction goToPage(page: number) {\n currentPage.value = Math.max(1, Math.min(page, totalPages.value))\n}\n\nfunction nextPage() {\n if (currentPage.value < totalPages.value) currentPage.value++\n}\n\nfunction prevPage() {\n if (currentPage.value > 1) currentPage.value--\n}\n\n// Reset to page 1 when filters or search changes\nwatch([columnFilters, globalSearchTerm], () => {\n currentPage.value = 1\n})\n\n// Export functionality\nfunction handleExport() {\n if (viewMode.value === 'pivot') {\n handlePivotExport()\n return\n }\n\n const dataToExport = props.enableSearch && globalSearchTerm.value.trim()\n ? searchFilteredData.value.map(row => row.original)\n : rows.value.map(row => row.original)\n \n exportToCSV(dataToExport, columnKeys.value, {\n filename: props.exportFilename,\n includeHeaders: true,\n })\n \n emit('export', { rowCount: dataToExport.length, filename: props.exportFilename })\n}\n\nfunction handlePivotExport() {\n if (!pivotResult.value) return\n\n const pivotFilename = props.exportFilename.replace('.csv', '-pivot.csv')\n \n exportPivotToCSV(\n {\n headers: pivotResult.value.headers,\n rowHeaders: pivotResult.value.rowHeaders,\n data: pivotResult.value.data,\n rowTotals: pivotResult.value.rowTotals,\n columnTotals: pivotResult.value.columnTotals,\n grandTotal: pivotResult.value.grandTotal,\n showRowTotals: pivotShowRowTotals.value,\n showColumnTotals: pivotShowColumnTotals.value,\n },\n pivotRowFields.value,\n pivotColumnFields.value,\n pivotValueFields.value,\n { filename: pivotFilename },\n )\n\n const rowCount = pivotResult.value.rowHeaders.length\n emit('export', { rowCount, filename: pivotFilename })\n}\n\n// Column resize methods\nfunction startColumnResize(columnId: string, event: MouseEvent) {\n if (!props.enableColumnResize) return\n event.preventDefault()\n event.stopPropagation()\n \n resizingColumnId.value = columnId\n resizeStartX.value = event.clientX\n resizeStartWidth.value = columnWidths.value[columnId] || MIN_COL_WIDTH\n \n document.addEventListener('mousemove', handleResizeMove)\n document.addEventListener('mouseup', handleResizeEnd)\n}\n\nfunction handleResizeMove(event: MouseEvent) {\n if (!resizingColumnId.value) return\n const diff = event.clientX - resizeStartX.value\n const newWidth = Math.max(MIN_COL_WIDTH, Math.min(MAX_COL_WIDTH, resizeStartWidth.value + diff))\n columnWidths.value = {\n ...columnWidths.value,\n [resizingColumnId.value]: newWidth,\n }\n}\n\nfunction handleResizeEnd() {\n resizingColumnId.value = null\n document.removeEventListener('mousemove', handleResizeMove)\n document.removeEventListener('mouseup', handleResizeEnd)\n}\n\n// Vertical resize methods\nfunction startVerticalResize(event: MouseEvent) {\n if (!props.enableVerticalResize) return\n event.preventDefault()\n \n isResizingVertically.value = true\n verticalResizeStartY.value = event.clientY\n verticalResizeStartHeight.value = gridHeight.value\n \n document.addEventListener('mousemove', handleVerticalResizeMove)\n document.addEventListener('mouseup', handleVerticalResizeEnd)\n}\n\nfunction handleVerticalResizeMove(event: MouseEvent) {\n if (!isResizingVertically.value) return\n const diff = event.clientY - verticalResizeStartY.value\n const newHeight = Math.max(\n props.minHeight,\n Math.min(props.maxHeight, verticalResizeStartHeight.value + diff),\n )\n gridHeight.value = newHeight\n}\n\nfunction handleVerticalResizeEnd() {\n isResizingVertically.value = false\n document.removeEventListener('mousemove', handleVerticalResizeMove)\n document.removeEventListener('mouseup', handleVerticalResizeEnd)\n}\n\n// Clipboard methods\nfunction copySelectionToClipboard() {\n if (!selectionBounds.value || !props.enableClipboard) return\n \n const text = formatSelectionForClipboard(\n rows.value.map(r => r.original),\n columnKeys.value,\n selectionBounds.value,\n )\n \n copyToClipboard(\n text,\n () => {\n const cellCount = \n (selectionBounds.value!.maxRow - selectionBounds.value!.minRow + 1) *\n (selectionBounds.value!.maxCol - selectionBounds.value!.minCol + 1)\n copyToastMessage.value = `Copied ${cellCount} cell${cellCount > 1 ? 's' : ''}`\n showCopyToast.value = true\n setTimeout(() => { showCopyToast.value = false }, 2000)\n emit('copy', { text, cellCount })\n },\n (err) => {\n copyToastMessage.value = 'Copy failed'\n showCopyToast.value = true\n setTimeout(() => { showCopyToast.value = false }, 2000)\n console.error('Copy failed:', err)\n },\n )\n}\n\n// View mode\nconst viewMode = ref<'grid' | 'pivot'>('grid')\nconst showPivotConfig = ref(true)\nconst draggingField = ref<string | null>(null)\n\nfunction handlePivotDragStart(field: string) {\n draggingField.value = field\n}\n\nfunction handlePivotDragEnd() {\n draggingField.value = null\n}\n\nfunction reorderRowFields(fields: string[]) {\n pivotRowFields.value = fields\n}\n\nfunction reorderColumnFields(fields: string[]) {\n pivotColumnFields.value = fields\n}\n\n// Container refs\nconst tableContainerRef = ref<HTMLDivElement>()\nconst tableBodyRef = ref<HTMLDivElement>()\n\n// Rows\nconst rows = computed(() => table.getRowModel().rows)\n\n// Column filter dropdown state\nconst activeFilterColumn = ref<string | null>(null)\nconst filterDropdownPosition = ref({ top: 0, left: 0, maxHeight: 400 })\n\n// Column widths\nconst columnWidths = ref<Record<string, number>>({})\nconst MIN_COL_WIDTH = 120\nconst MAX_COL_WIDTH = 350\n\nfunction calculateColumnWidths() {\n if (props.data.length === 0)\n return\n\n const widths: Record<string, number> = {}\n const sampleSize = Math.min(100, props.data.length)\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n if (!ctx)\n return\n\n ctx.font = '13px system-ui, -apple-system, sans-serif'\n\n for (const key of columnKeys.value) {\n let maxWidth = ctx.measureText(key).width + 56\n\n for (let i = 0; i < sampleSize; i++) {\n const value = props.data[i][key]\n const text = value === null || value === undefined ? '' : String(value)\n const width = ctx.measureText(text).width + 28\n maxWidth = Math.max(maxWidth, width)\n }\n\n widths[key] = Math.min(Math.max(maxWidth, MIN_COL_WIDTH), MAX_COL_WIDTH)\n }\n\n columnWidths.value = widths\n}\n\nfunction openFilterDropdown(columnId: string, event: MouseEvent) {\n event.stopPropagation()\n const target = event.currentTarget as HTMLElement\n const headerCell = target.closest('.vpg-header-cell') as HTMLElement\n const rect = headerCell?.getBoundingClientRect() || target.getBoundingClientRect()\n\n const dropdownWidth = 280\n const padding = 12\n\n let left = rect.left\n if (left + dropdownWidth > window.innerWidth - padding) {\n left = window.innerWidth - dropdownWidth - padding\n }\n left = Math.max(padding, left)\n\n const spaceBelow = window.innerHeight - rect.bottom - padding\n const spaceAbove = rect.top - padding\n\n let top: number\n let maxHeight: number\n\n if (spaceBelow >= 300 || spaceBelow >= spaceAbove) {\n top = rect.bottom + 4\n maxHeight = Math.min(400, spaceBelow - 4)\n }\n else {\n maxHeight = Math.min(400, spaceAbove - 4)\n top = rect.top - maxHeight - 4\n }\n\n filterDropdownPosition.value = { top, left, maxHeight }\n activeFilterColumn.value = columnId\n}\n\nfunction closeFilterDropdown() {\n activeFilterColumn.value = null\n}\n\nfunction handleFilter(columnId: string, values: string[]) {\n setColumnFilter(columnId, values)\n}\n\nfunction handleSort(columnId: string, direction: 'asc' | 'desc' | null) {\n if (direction === null) {\n const current = getSortDirection(columnId)\n if (current) {\n toggleSort(columnId)\n if (getSortDirection(columnId)) {\n toggleSort(columnId)\n }\n }\n }\n else {\n const current = getSortDirection(columnId)\n if (current === null) {\n toggleSort(columnId)\n if (direction === 'desc' && getSortDirection(columnId) === 'asc') {\n toggleSort(columnId)\n }\n }\n else if (current !== direction) {\n toggleSort(columnId)\n }\n }\n}\n\nconst activeFilterCount = computed(() => columnFilters.value.length)\n\n// Selection state\nconst selectedCell = ref<{ row: number, col: number } | null>(null)\nconst selectionStart = ref<{ row: number, col: number } | null>(null)\nconst selectionEnd = ref<{ row: number, col: number } | null>(null)\nconst isSelecting = ref(false)\n\nfunction selectColumn(colIndex: number) {\n const maxRow = rows.value.length - 1\n if (maxRow < 0)\n return\n\n selectionStart.value = { row: 0, col: colIndex }\n selectionEnd.value = { row: maxRow, col: colIndex }\n selectedCell.value = { row: 0, col: colIndex }\n}\n\nfunction handleHeaderClick(colIndex: number, event: MouseEvent) {\n const target = event.target as HTMLElement\n if (target.closest('.vpg-dropdown-arrow')) {\n const colId = columnKeys.value[colIndex]\n openFilterDropdown(colId, event)\n }\n else {\n selectColumn(colIndex)\n }\n}\n\nconst selectionBounds = computed(() => {\n if (!selectionStart.value || !selectionEnd.value)\n return null\n return {\n minRow: Math.min(selectionStart.value.row, selectionEnd.value.row),\n maxRow: Math.max(selectionStart.value.row, selectionEnd.value.row),\n minCol: Math.min(selectionStart.value.col, selectionEnd.value.col),\n maxCol: Math.max(selectionStart.value.col, selectionEnd.value.col),\n }\n})\n\nfunction isCellInSelection(rowIndex: number, colIndex: number): boolean {\n if (!selectionBounds.value)\n return false\n const { minRow, maxRow, minCol, maxCol } = selectionBounds.value\n return rowIndex >= minRow && rowIndex <= maxRow && colIndex >= minCol && colIndex <= maxCol\n}\n\nconst selectionStats = computed(() => {\n if (!selectionBounds.value)\n return null\n const { minRow, maxRow, minCol, maxCol } = selectionBounds.value\n\n const values: number[] = []\n let count = 0\n\n for (let r = minRow; r <= maxRow; r++) {\n const row = rows.value[r]\n if (!row)\n continue\n\n for (let c = minCol; c <= maxCol; c++) {\n const colId = columnKeys.value[c]\n if (!colId)\n continue\n\n const value = row.original[colId]\n count++\n\n if (value !== null && value !== undefined && value !== '') {\n const num = typeof value === 'number' ? value : Number.parseFloat(String(value))\n if (!Number.isNaN(num)) {\n values.push(num)\n }\n }\n }\n }\n\n if (values.length === 0)\n return { count, sum: null, avg: null, numericCount: 0 }\n\n const sum = values.reduce((a, b) => a + b, 0)\n const avg = sum / values.length\n\n return { count, sum, avg, numericCount: values.length }\n})\n\nfunction formatStatValue(value: number | null): string {\n if (value === null)\n return '-'\n if (Math.abs(value) >= 1000) {\n return value.toLocaleString('en-US', { maximumFractionDigits: 2 })\n }\n return value.toLocaleString('en-US', { maximumFractionDigits: 4 })\n}\n\nfunction handleKeydown(event: KeyboardEvent) {\n // Handle Ctrl+C / Cmd+C for clipboard\n if ((event.ctrlKey || event.metaKey) && event.key === 'c' && selectionBounds.value) {\n event.preventDefault()\n copySelectionToClipboard()\n return\n }\n\n // Handle Ctrl+F / Cmd+F for search\n if ((event.ctrlKey || event.metaKey) && event.key === 'f' && props.enableSearch) {\n event.preventDefault()\n showSearchInput.value = true\n nextTick(() => {\n const input = document.querySelector('.vpg-search-input') as HTMLInputElement\n input?.focus()\n })\n return\n }\n\n if (!selectedCell.value)\n return\n if (activeFilterColumn.value)\n return\n\n const { row, col } = selectedCell.value\n const displayRows = paginatedRows.value\n const maxRow = displayRows.length - 1\n const maxCol = columnKeys.value.length - 1\n\n function updateSelection(newRow: number, newCol: number) {\n if (event.shiftKey) {\n if (!selectionStart.value) {\n selectionStart.value = { row, col }\n }\n selectionEnd.value = { row: newRow, col: newCol }\n }\n else {\n selectionStart.value = { row: newRow, col: newCol }\n selectionEnd.value = { row: newRow, col: newCol }\n }\n selectedCell.value = { row: newRow, col: newCol }\n scrollCellIntoView(newRow, newCol)\n }\n\n switch (event.key) {\n case 'ArrowUp':\n event.preventDefault()\n if (row > 0)\n updateSelection(row - 1, col)\n break\n case 'ArrowDown':\n event.preventDefault()\n if (row < maxRow)\n updateSelection(row + 1, col)\n break\n case 'ArrowLeft':\n event.preventDefault()\n if (col > 0)\n updateSelection(row, col - 1)\n break\n case 'ArrowRight':\n event.preventDefault()\n if (col < maxCol)\n updateSelection(row, col + 1)\n break\n case 'Escape':\n selectedCell.value = null\n selectionStart.value = null\n selectionEnd.value = null\n showSearchInput.value = false\n globalSearchTerm.value = ''\n break\n }\n}\n\nfunction scrollCellIntoView(rowIndex: number, colIndex: number) {\n nextTick(() => {\n const cell = tableBodyRef.value?.querySelector(\n `[data-row=\"${rowIndex}\"][data-col=\"${colIndex}\"]`,\n )\n cell?.scrollIntoView({ block: 'nearest', inline: 'nearest' })\n })\n}\n\nfunction handleMouseDown(rowIndex: number, colIndex: number, event: MouseEvent) {\n event.preventDefault()\n\n if (event.shiftKey && selectedCell.value) {\n selectionEnd.value = { row: rowIndex, col: colIndex }\n }\n else {\n selectedCell.value = { row: rowIndex, col: colIndex }\n selectionStart.value = { row: rowIndex, col: colIndex }\n selectionEnd.value = { row: rowIndex, col: colIndex }\n isSelecting.value = true\n }\n\n // Emit event\n const row = rows.value[rowIndex]\n if (row) {\n const colId = columnKeys.value[colIndex]\n emit('cellClick', {\n row: rowIndex,\n col: colIndex,\n value: row.original[colId],\n rowData: row.original,\n })\n }\n}\n\nfunction handleMouseEnter(rowIndex: number, colIndex: number) {\n if (isSelecting.value) {\n selectionEnd.value = { row: rowIndex, col: colIndex }\n }\n}\n\nfunction handleMouseUp() {\n isSelecting.value = false\n}\n\nfunction isCellSelected(rowIndex: number, colIndex: number): boolean {\n if (isCellInSelection(rowIndex, colIndex))\n return true\n return selectedCell.value?.row === rowIndex && selectedCell.value?.col === colIndex\n}\n\n// Format cell value\nconst noFormatPatterns = /^(?:.*_)?(?:id|code|year|month|quarter|day|week|date|zip|phone|fax|ssn|ein|npi|ndc|gpi|hcpcs|icd|cpt|rx|bin|pcn|group|member|claim|rx_number|script|fill)(?:_.*)?$/i\n\nfunction shouldFormatNumber(columnId: string): boolean {\n return !noFormatPatterns.test(columnId)\n}\n\nfunction formatCellValue(value: unknown, columnId: string): string {\n if (value === null || value === undefined)\n return ''\n if (value === '')\n return ''\n\n const stats = getColumnStats(columnId)\n if (stats.type === 'number') {\n const num = typeof value === 'number' ? value : Number.parseFloat(String(value))\n if (Number.isNaN(num))\n return String(value)\n\n if (shouldFormatNumber(columnId) && Math.abs(num) >= 1000) {\n return num.toLocaleString('en-US', { maximumFractionDigits: 2 })\n }\n\n if (Number.isInteger(num)) {\n return String(num)\n }\n return num.toLocaleString('en-US', { maximumFractionDigits: 4, useGrouping: false })\n }\n\n return String(value)\n}\n\nfunction handleTableScroll() {\n if (activeFilterColumn.value) {\n closeFilterDropdown()\n }\n}\n\nfunction handleWindowScroll(event: Event) {\n if (activeFilterColumn.value) {\n const target = event.target as HTMLElement\n if (target && target.closest?.('.vpg-filter-portal')) {\n return\n }\n closeFilterDropdown()\n }\n}\n\n// Initialize\nonMounted(() => {\n calculateColumnWidths()\n document.addEventListener('keydown', handleKeydown)\n document.addEventListener('mouseup', handleMouseUp)\n\n nextTick(() => {\n tableContainerRef.value?.addEventListener('scroll', handleTableScroll, { passive: true })\n })\n\n window.addEventListener('scroll', handleWindowScroll, { passive: true, capture: true })\n})\n\nonUnmounted(() => {\n document.removeEventListener('keydown', handleKeydown)\n document.removeEventListener('mouseup', handleMouseUp)\n tableContainerRef.value?.removeEventListener('scroll', handleTableScroll)\n window.removeEventListener('scroll', handleWindowScroll, { capture: true })\n})\n\nwatch(() => props.data, () => {\n nextTick(calculateColumnWidths)\n}, { immediate: true })\n\nconst totalTableWidth = computed(() => {\n return columnKeys.value.reduce((sum, key) => sum + (columnWidths.value[key] || MIN_COL_WIDTH), 0)\n})\n\nfunction handleContainerClick(event: MouseEvent) {\n if (activeFilterColumn.value) {\n const target = event.target as HTMLElement\n if (!target.closest('.vpg-filter-portal')) {\n closeFilterDropdown()\n }\n }\n}\n</script>\n\n<template>\n <div\n class=\"vpg-data-grid\"\n :class=\"[\n `vpg-font-${currentFontSize}`,\n `vpg-theme-${currentTheme}`,\n { 'vpg-striped': stripedRows },\n { 'vpg-resizing': resizingColumnId },\n { 'vpg-resizing-vertical': isResizingVertically },\n ]\"\n :style=\"{ height: `${gridHeight}px` }\"\n @click=\"handleContainerClick\"\n >\n <!-- Copy Toast -->\n <Transition name=\"vpg-toast\">\n <div v-if=\"showCopyToast\" class=\"vpg-toast\">\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n {{ copyToastMessage }}\n </div>\n </Transition>\n\n <!-- Toolbar -->\n <div class=\"vpg-toolbar\">\n <div class=\"vpg-toolbar-left\">\n <!-- View mode toggle -->\n <div v-if=\"showPivot\" class=\"vpg-view-toggle\">\n <button\n class=\"vpg-view-btn\"\n :class=\"{ active: viewMode === 'grid' }\"\n @click=\"viewMode = 'grid'\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n Grid\n </button>\n <button\n class=\"vpg-view-btn vpg-pivot-btn\"\n :class=\"{ active: viewMode === 'pivot' }\"\n @click=\"viewMode = 'pivot'\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\" />\n </svg>\n Pivot\n </button>\n </div>\n\n <!-- Grid mode controls -->\n <template v-if=\"viewMode === 'grid'\">\n <!-- Search input -->\n <div v-if=\"enableSearch\" class=\"vpg-search-container\">\n <button\n v-if=\"!showSearchInput\"\n class=\"vpg-icon-btn\"\n title=\"Search (Ctrl+F)\"\n @click=\"showSearchInput = true\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n </button>\n <div v-else class=\"vpg-search-box\">\n <svg class=\"vpg-search-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n <input\n v-model=\"globalSearchTerm\"\n type=\"text\"\n class=\"vpg-search-input\"\n placeholder=\"Search all columns...\"\n @keydown.escape=\"showSearchInput = false; globalSearchTerm = ''\"\n >\n <button\n v-if=\"globalSearchTerm\"\n class=\"vpg-search-clear\"\n @click=\"globalSearchTerm = ''\"\n >\n <svg class=\"vpg-icon-xs\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n </div>\n\n <div class=\"vpg-font-size-control\">\n <span class=\"vpg-label\">Size:</span>\n <div class=\"vpg-font-size-toggle\">\n <button\n v-for=\"opt in fontSizeOptions\"\n :key=\"opt.value\"\n class=\"vpg-font-size-btn\"\n :class=\"{ active: currentFontSize === opt.value }\"\n @click=\"currentFontSize = opt.value\"\n >\n {{ opt.label }}\n </button>\n </div>\n </div>\n\n <div v-if=\"activeFilterCount > 0\" class=\"vpg-filter-info\">\n <svg class=\"vpg-icon\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z\" clip-rule=\"evenodd\" />\n </svg>\n <span>{{ activeFilterCount }} filter{{ activeFilterCount > 1 ? 's' : '' }}</span>\n </div>\n\n <div v-if=\"globalSearchTerm\" class=\"vpg-search-info\">\n <span>{{ totalSearchedRows }} match{{ totalSearchedRows !== 1 ? 'es' : '' }}</span>\n </div>\n </template>\n\n <!-- Pivot mode controls -->\n <template v-if=\"viewMode === 'pivot' && canUsePivot\">\n <button\n class=\"vpg-config-toggle\"\n :class=\"{ active: showPivotConfig }\"\n @click=\"showPivotConfig = !showPivotConfig\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4\" />\n </svg>\n {{ showPivotConfig ? 'Hide' : 'Show' }} Config\n </button>\n\n <div v-if=\"pivotIsConfigured\" class=\"vpg-pivot-status\">\n <svg class=\"vpg-icon\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\" />\n </svg>\n <span>Pivot configured</span>\n </div>\n </template>\n </div>\n\n <div class=\"vpg-toolbar-right\">\n <button v-if=\"viewMode === 'grid' && activeFilterCount > 0\" class=\"vpg-clear-filters\" @click=\"clearAllFilters\">\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n Clear Filters\n </button>\n\n <!-- Copy button -->\n <button\n v-if=\"enableClipboard && selectionBounds && viewMode === 'grid'\"\n class=\"vpg-icon-btn\"\n title=\"Copy selection (Ctrl+C)\"\n @click=\"copySelectionToClipboard\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n </button>\n\n <!-- Export button -->\n <button\n v-if=\"enableExport && (viewMode === 'grid' || (viewMode === 'pivot' && pivotIsConfigured))\"\n class=\"vpg-export-btn\"\n :title=\"viewMode === 'pivot' ? 'Export Pivot to CSV' : 'Export to CSV'\"\n @click=\"handleExport\"\n >\n <svg class=\"vpg-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\" />\n </svg>\n Export{{ viewMode === 'pivot' ? ' Pivot' : '' }}\n </button>\n </div>\n </div>\n\n <!-- Grid View -->\n <template v-if=\"viewMode === 'grid'\">\n <div ref=\"tableContainerRef\" class=\"vpg-grid-container\" tabindex=\"0\">\n <div v-if=\"loading\" class=\"vpg-loading\">\n <div class=\"vpg-spinner\" />\n <span>Loading data...</span>\n </div>\n\n <div v-else-if=\"data.length === 0\" class=\"vpg-empty\">\n <div class=\"vpg-empty-icon\">\n <svg class=\"vpg-icon-lg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n </div>\n <span>No data available</span>\n </div>\n\n <div v-else-if=\"filteredRowCount === 0\" class=\"vpg-empty\">\n <div class=\"vpg-empty-icon vpg-warning\">\n <svg class=\"vpg-icon-lg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z\" />\n </svg>\n </div>\n <span>No matching records</span>\n <button class=\"vpg-clear-link\" @click=\"clearAllFilters\">\n Clear all filters\n </button>\n </div>\n\n <div v-else class=\"vpg-table-wrapper\">\n <table class=\"vpg-table\" :style=\"{ minWidth: `${totalTableWidth}px` }\">\n <thead>\n <tr>\n <th\n v-for=\"(colId, colIndex) in columnKeys\"\n :key=\"colId\"\n class=\"vpg-header-cell\"\n :class=\"{\n 'vpg-has-filter': hasActiveFilter(colId),\n 'vpg-is-sorted': getSortDirection(colId) !== null,\n 'vpg-is-active': activeFilterColumn === colId,\n }\"\n :style=\"{ width: `${columnWidths[colId] || MIN_COL_WIDTH}px`, minWidth: `${columnWidths[colId] || MIN_COL_WIDTH}px` }\"\n @click=\"handleHeaderClick(colIndex, $event)\"\n >\n <div class=\"vpg-header-content\">\n <span class=\"vpg-header-text\">{{ colId }}</span>\n <div class=\"vpg-header-icons\">\n <span v-if=\"getSortDirection(colId)\" class=\"vpg-sort-indicator\">\n <svg v-if=\"getSortDirection(colId) === 'asc'\" class=\"vpg-icon-sm\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M14.707 12.707a1 1 0 01-1.414 0L10 9.414l-3.293 3.293a1 1 0 01-1.414-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 010 1.414z\" clip-rule=\"evenodd\" />\n </svg>\n <svg v-else class=\"vpg-icon-sm\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span v-if=\"hasActiveFilter(colId)\" class=\"vpg-filter-indicator\">\n <svg class=\"vpg-icon-xs\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span class=\"vpg-dropdown-arrow\" title=\"Filter & Sort\">\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </span>\n </div>\n </div>\n <!-- Column resize handle -->\n <div\n v-if=\"enableColumnResize\"\n class=\"vpg-resize-handle\"\n @mousedown=\"startColumnResize(colId, $event)\"\n />\n </th>\n </tr>\n </thead>\n\n <tbody ref=\"tableBodyRef\">\n <tr\n v-for=\"(row, rowIndex) in paginatedRows\"\n :key=\"row.id\"\n class=\"vpg-row\"\n >\n <td\n v-for=\"(colId, colIndex) in columnKeys\"\n :key=\"colId\"\n class=\"vpg-cell\"\n :class=\"{\n 'vpg-selected': isCellSelected(rowIndex, colIndex),\n 'vpg-is-number': getColumnStats(colId).type === 'number',\n }\"\n :data-row=\"rowIndex\"\n :data-col=\"colIndex\"\n :style=\"{ width: `${columnWidths[colId] || MIN_COL_WIDTH}px`, minWidth: `${columnWidths[colId] || MIN_COL_WIDTH}px` }\"\n @mousedown=\"handleMouseDown(rowIndex, colIndex, $event)\"\n @mouseenter=\"handleMouseEnter(rowIndex, colIndex)\"\n >\n {{ formatCellValue(row.original[colId], colId) }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </template>\n\n <!-- Pivot View -->\n <template v-else>\n <div class=\"vpg-pivot-container\">\n <div v-if=\"showPivotConfig && canUsePivot\" class=\"vpg-pivot-config-panel\">\n <PivotConfig\n :available-fields=\"pivotAvailableFields\"\n :row-fields=\"pivotRowFields\"\n :column-fields=\"pivotColumnFields\"\n :value-fields=\"pivotValueFields\"\n :show-row-totals=\"pivotShowRowTotals\"\n :show-column-totals=\"pivotShowColumnTotals\"\n @update:show-row-totals=\"pivotShowRowTotals = $event\"\n @update:show-column-totals=\"pivotShowColumnTotals = $event\"\n @clear-config=\"clearPivotConfig\"\n @auto-suggest=\"autoSuggestConfig\"\n @drag-start=\"handlePivotDragStart\"\n @drag-end=\"handlePivotDragEnd\"\n @update-aggregation=\"updateValueFieldAggregation\"\n @add-row-field=\"addRowField\"\n @remove-row-field=\"removeRowField\"\n @add-column-field=\"addColumnField\"\n @remove-column-field=\"removeColumnField\"\n @add-value-field=\"addValueField\"\n @remove-value-field=\"removeValueField\"\n />\n </div>\n\n <div class=\"vpg-pivot-main\" :class=\"{ 'vpg-full-width': !showPivotConfig }\">\n <PivotSkeleton\n :row-fields=\"pivotRowFields\"\n :column-fields=\"pivotColumnFields\"\n :value-fields=\"pivotValueFields\"\n :is-configured=\"pivotIsConfigured\"\n :dragging-field=\"draggingField\"\n :pivot-result=\"pivotResult\"\n :font-size=\"currentFontSize\"\n :active-filters=\"activeFilterInfo\"\n :total-row-count=\"totalRowCount\"\n :filtered-row-count=\"filteredRowCount\"\n @add-row-field=\"addRowField\"\n @remove-row-field=\"removeRowField\"\n @add-column-field=\"addColumnField\"\n @remove-column-field=\"removeColumnField\"\n @add-value-field=\"addValueField\"\n @remove-value-field=\"removeValueField\"\n @update-aggregation=\"updateValueFieldAggregation\"\n @reorder-row-fields=\"reorderRowFields\"\n @reorder-column-fields=\"reorderColumnFields\"\n />\n </div>\n </div>\n </template>\n\n <!-- Footer -->\n <div class=\"vpg-footer\">\n <div class=\"vpg-footer-left\">\n <template v-if=\"viewMode === 'grid'\">\n <template v-if=\"enablePagination\">\n <span>{{ paginationStart.toLocaleString() }}-{{ paginationEnd.toLocaleString() }}</span>\n <span class=\"vpg-separator\">of</span>\n <span>{{ totalSearchedRows.toLocaleString() }}</span>\n <span v-if=\"totalSearchedRows !== totalRowCount\" class=\"vpg-filtered-note\">\n ({{ totalRowCount.toLocaleString() }} total)\n </span>\n </template>\n <template v-else-if=\"filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount\">\n <span>{{ totalRowCount.toLocaleString() }} records</span>\n </template>\n <template v-else>\n <span class=\"vpg-filtered-count\">{{ totalSearchedRows.toLocaleString() }}</span>\n <span class=\"vpg-separator\">of</span>\n <span>{{ totalRowCount.toLocaleString() }}</span>\n <span class=\"vpg-separator\">records</span>\n </template>\n </template>\n <template v-else>\n <span class=\"vpg-pivot-label\">Pivot Table</span>\n <span class=\"vpg-separator\">•</span>\n <span>{{ totalRowCount.toLocaleString() }} source records</span>\n </template>\n </div>\n\n <!-- Pagination controls -->\n <div v-if=\"enablePagination && viewMode === 'grid' && totalPages > 1\" class=\"vpg-pagination\">\n <button\n class=\"vpg-page-btn\"\n :disabled=\"currentPage === 1\"\n @click=\"currentPage = 1\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M11 19l-7-7 7-7m8 14l-7-7 7-7\" />\n </svg>\n </button>\n <button\n class=\"vpg-page-btn\"\n :disabled=\"currentPage === 1\"\n @click=\"prevPage\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n <span class=\"vpg-page-info\">\n Page {{ currentPage }} of {{ totalPages }}\n </span>\n <button\n class=\"vpg-page-btn\"\n :disabled=\"currentPage === totalPages\"\n @click=\"nextPage\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n <button\n class=\"vpg-page-btn\"\n :disabled=\"currentPage === totalPages\"\n @click=\"currentPage = totalPages\"\n >\n <svg class=\"vpg-icon-sm\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 5l7 7-7 7M5 5l7 7-7 7\" />\n </svg>\n </button>\n </div>\n\n <div v-if=\"viewMode === 'grid' && selectionStats && selectionStats.count > 1\" class=\"vpg-selection-stats\">\n <span class=\"vpg-stat\">\n <span class=\"vpg-stat-label\">Count:</span>\n <span class=\"vpg-stat-value\">{{ selectionStats.count }}</span>\n </span>\n <template v-if=\"selectionStats.numericCount > 0\">\n <span class=\"vpg-stat-divider\">|</span>\n <span class=\"vpg-stat\">\n <span class=\"vpg-stat-label\">Sum:</span>\n <span class=\"vpg-stat-value\">{{ formatStatValue(selectionStats.sum) }}</span>\n </span>\n <span class=\"vpg-stat-divider\">|</span>\n <span class=\"vpg-stat\">\n <span class=\"vpg-stat-label\">Avg:</span>\n <span class=\"vpg-stat-value\">{{ formatStatValue(selectionStats.avg) }}</span>\n </span>\n </template>\n </div>\n\n <div class=\"vpg-footer-right\">\n <div v-if=\"isDemo\" class=\"vpg-demo-banner\">\n <span class=\"vpg-demo-badge\">DEMO</span>\n <span>Pro features enabled</span>\n <a href=\"https://tiny-pivot.com/#pricing\" target=\"_blank\" rel=\"noopener\">Get License →</a>\n </div>\n <span v-else-if=\"showWatermark\" class=\"vpg-watermark-inline\">\n <a href=\"https://tiny-pivot.com\" target=\"_blank\" rel=\"noopener\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"7\" height=\"7\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"7\"/><rect x=\"14\" y=\"14\" width=\"7\" height=\"7\"/><rect x=\"3\" y=\"14\" width=\"7\" height=\"7\"/></svg>\n Powered by TinyPivot\n </a>\n </span>\n </div>\n </div>\n\n <!-- Vertical Resize Handle -->\n <div\n v-if=\"enableVerticalResize\"\n class=\"vpg-vertical-resize-handle\"\n @mousedown=\"startVerticalResize\"\n >\n <div class=\"vpg-resize-grip\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n\n <!-- Filter Dropdown Portal -->\n <Teleport to=\"body\">\n <div\n v-if=\"activeFilterColumn\"\n class=\"vpg-filter-portal\"\n :style=\"{\n position: 'fixed',\n top: `${filterDropdownPosition.top}px`,\n left: `${filterDropdownPosition.left}px`,\n maxHeight: `${filterDropdownPosition.maxHeight}px`,\n zIndex: 9999,\n }\"\n >\n <ColumnFilter\n :column-id=\"activeFilterColumn\"\n :column-name=\"activeFilterColumn\"\n :stats=\"getColumnStats(activeFilterColumn)\"\n :selected-values=\"getColumnFilterValues(activeFilterColumn)\"\n :sort-direction=\"getSortDirection(activeFilterColumn)\"\n @filter=\"(values) => handleFilter(activeFilterColumn!, values)\"\n @sort=\"(dir) => handleSort(activeFilterColumn!, dir)\"\n @close=\"closeFilterDropdown\"\n />\n </div>\n </Teleport>\n </div>\n</template>\n\n<style scoped>\n.vpg-data-grid {\n display: flex;\n flex-direction: column;\n background: white;\n border-radius: 0.5rem;\n overflow: hidden;\n border: 1px solid #e2e8f0;\n box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);\n margin-bottom: 1.5rem;\n position: relative;\n}\n\n.vpg-icon {\n width: 1rem;\n height: 1rem;\n}\n\n.vpg-icon-sm {\n width: 0.875rem;\n height: 0.875rem;\n}\n\n.vpg-icon-xs {\n width: 0.75rem;\n height: 0.75rem;\n}\n\n.vpg-icon-lg {\n width: 3rem;\n height: 3rem;\n}\n\n/* Toolbar */\n.vpg-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem 1rem;\n background: #f8fafc;\n border-bottom: 1px solid #e2e8f0;\n}\n\n.vpg-toolbar-left {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.vpg-toolbar-right {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.vpg-view-toggle {\n display: flex;\n background: white;\n border-radius: 0.5rem;\n border: 1px solid #e2e8f0;\n overflow: hidden;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-view-btn {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.75rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: #64748b;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-view-btn:hover {\n background: #f8fafc;\n}\n\n.vpg-view-btn.active {\n background: #4f46e5;\n color: white;\n box-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.1);\n}\n\n.vpg-view-btn.vpg-pivot-btn.active {\n background: #10b981;\n}\n\n.vpg-font-size-control {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.vpg-label {\n font-size: 0.75rem;\n color: #64748b;\n}\n\n.vpg-font-size-toggle {\n display: flex;\n background: white;\n border-radius: 0.25rem;\n border: 1px solid #e2e8f0;\n overflow: hidden;\n}\n\n.vpg-font-size-btn {\n padding: 0.25rem 0.5rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: #64748b;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-font-size-btn:hover {\n background: #f1f5f9;\n}\n\n.vpg-font-size-btn.active {\n background: #4f46e5;\n color: white;\n}\n\n.vpg-filter-info {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.875rem;\n color: #475569;\n}\n\n.vpg-filter-info svg {\n color: #4f46e5;\n}\n\n.vpg-config-toggle {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.75rem;\n font-size: 0.75rem;\n font-weight: 500;\n border-radius: 0.375rem;\n background: white;\n border: 1px solid #e2e8f0;\n color: #475569;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-config-toggle:hover {\n background: #f8fafc;\n}\n\n.vpg-config-toggle.active {\n background: #ecfdf5;\n border-color: #a7f3d0;\n color: #059669;\n}\n\n.vpg-pivot-status {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.875rem;\n color: #059669;\n}\n\n.vpg-clear-filters {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.75rem;\n font-size: 0.875rem;\n font-weight: 500;\n color: #475569;\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 0.375rem;\n cursor: pointer;\n transition: all 0.15s;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-clear-filters:hover {\n background: #f8fafc;\n border-color: #cbd5e1;\n}\n\n/* Grid Container */\n.vpg-grid-container {\n flex: 1;\n overflow: auto;\n position: relative;\n background: rgba(248, 250, 252, 0.3);\n}\n\n.vpg-grid-container:focus {\n outline: none;\n}\n\n.vpg-loading {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.95);\n z-index: 10;\n}\n\n.vpg-spinner {\n width: 2rem;\n height: 2rem;\n border: 2px solid #e2e8f0;\n border-top-color: #4f46e5;\n border-radius: 50%;\n animation: vpg-spin 1s linear infinite;\n}\n\n@keyframes vpg-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n.vpg-loading span {\n margin-top: 0.5rem;\n font-size: 0.875rem;\n color: #64748b;\n}\n\n.vpg-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 5rem;\n gap: 0.75rem;\n}\n\n.vpg-empty-icon {\n width: 5rem;\n height: 5rem;\n border-radius: 50%;\n background: #f1f5f9;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #cbd5e1;\n margin-bottom: 0.5rem;\n}\n\n.vpg-empty-icon.vpg-warning {\n background: #fef3c7;\n color: #fcd34d;\n}\n\n.vpg-empty span {\n color: #64748b;\n font-weight: 500;\n}\n\n.vpg-clear-link {\n color: #4f46e5;\n font-size: 0.875rem;\n font-weight: 500;\n margin-top: 0.25rem;\n background: transparent;\n border: none;\n cursor: pointer;\n}\n\n.vpg-clear-link:hover {\n text-decoration: underline;\n}\n\n.vpg-table-wrapper {\n min-height: 100%;\n}\n\n.vpg-table {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n}\n\n.vpg-table thead {\n position: sticky;\n top: 0;\n z-index: 20;\n box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.1);\n}\n\n.vpg-header-cell {\n z-index: 10;\n padding: 0.75rem 1rem;\n text-align: left;\n cursor: pointer;\n user-select: none;\n background: white;\n transition: all 0.15s;\n border-bottom: 1px solid #e2e8f0;\n border-right: 1px solid #f1f5f9;\n}\n\n.vpg-header-cell:hover {\n background: #f8fafc;\n}\n\n.vpg-header-cell:last-child {\n border-right: none;\n}\n\n.vpg-header-cell.vpg-has-filter {\n background: #eef2ff;\n}\n\n.vpg-header-cell.vpg-is-sorted {\n background: #eff6ff;\n}\n\n.vpg-header-cell.vpg-has-filter.vpg-is-sorted {\n background: #ede9fe;\n}\n\n.vpg-header-cell.vpg-is-active {\n background: #e0e7ff;\n box-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.1);\n}\n\n.vpg-header-content {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n}\n\n.vpg-header-text {\n font-size: 0.75rem;\n font-weight: 600;\n color: #475569;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.vpg-header-icons {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n flex-shrink: 0;\n}\n\n.vpg-sort-indicator {\n color: #3b82f6;\n}\n\n.vpg-filter-indicator {\n color: #4f46e5;\n}\n\n.vpg-dropdown-arrow {\n padding: 0.125rem;\n border-radius: 0.25rem;\n color: #cbd5e1;\n transition: all 0.15s;\n cursor: pointer;\n}\n\n.vpg-dropdown-arrow:hover {\n background: #e2e8f0;\n color: #475569;\n}\n\n.vpg-header-cell:hover .vpg-dropdown-arrow {\n color: #94a3b8;\n}\n\n.vpg-row {\n transition: background 0.15s;\n}\n\n.vpg-row:nth-child(odd) {\n background: white;\n}\n\n.vpg-row:nth-child(even) {\n background: rgba(248, 250, 252, 0.5);\n}\n\n.vpg-row:hover {\n background: rgba(239, 246, 255, 0.4);\n}\n\n.vpg-cell {\n padding: 0.625rem 1rem;\n font-size: 0.875rem;\n color: #334155;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n cursor: cell;\n transition: all 0.15s;\n max-width: 350px;\n border-bottom: 1px solid #f1f5f9;\n border-right: 1px solid #f8fafc;\n}\n\n.vpg-cell:last-child {\n border-right: none;\n}\n\n.vpg-cell.vpg-selected {\n background: rgba(224, 231, 255, 0.8);\n outline: 2px solid #818cf8;\n outline-offset: -2px;\n position: relative;\n z-index: 1;\n}\n\n.vpg-cell.vpg-is-number {\n text-align: right;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n color: #334155;\n font-variant-numeric: tabular-nums;\n}\n\n/* Font size variations */\n.vpg-data-grid.vpg-font-xs .vpg-cell {\n font-size: 0.75rem;\n padding: 0.375rem 0.75rem;\n}\n\n.vpg-data-grid.vpg-font-xs .vpg-header-text {\n font-size: 0.625rem;\n}\n\n.vpg-data-grid.vpg-font-sm .vpg-cell {\n font-size: 0.875rem;\n padding: 0.5rem 1rem;\n}\n\n.vpg-data-grid.vpg-font-base .vpg-cell {\n font-size: 1rem;\n padding: 0.625rem 1rem;\n}\n\n.vpg-data-grid.vpg-font-base .vpg-header-text {\n font-size: 0.75rem;\n}\n\n/* Pivot Container */\n.vpg-pivot-container {\n display: flex;\n flex: 1;\n gap: 1rem;\n overflow: hidden;\n min-height: 0;\n padding: 1rem;\n}\n\n.vpg-pivot-config-panel {\n width: 14rem;\n flex-shrink: 0;\n overflow: hidden;\n}\n\n.vpg-pivot-main {\n flex: 1;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n\n.vpg-pivot-main.vpg-full-width {\n width: 100%;\n}\n\n/* Footer */\n.vpg-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background: rgba(248, 250, 252, 0.8);\n border-top: 1px solid rgba(226, 232, 240, 0.8);\n font-size: 0.875rem;\n}\n\n.vpg-footer-left {\n display: flex;\n align-items: center;\n color: #64748b;\n}\n\n.vpg-filtered-count {\n color: #4f46e5;\n font-weight: 500;\n}\n\n.vpg-separator {\n color: #94a3b8;\n margin: 0 0.25rem;\n}\n\n.vpg-pivot-label {\n color: #10b981;\n font-weight: 500;\n}\n\n.vpg-footer-right {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.vpg-selection-stats {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.25rem 0.75rem;\n background: #eef2ff;\n border-radius: 0.375rem;\n border: 1px solid #c7d2fe;\n}\n\n.vpg-stat {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.vpg-stat-label {\n font-size: 0.75rem;\n color: #4f46e5;\n font-weight: 500;\n}\n\n.vpg-stat-value {\n font-size: 0.75rem;\n color: #1e1b4b;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n}\n\n.vpg-stat-divider {\n color: #c7d2fe;\n}\n\n.vpg-watermark-inline a {\n font-size: 0.75rem;\n color: #94a3b8;\n text-decoration: none;\n transition: color 0.15s;\n}\n\n.vpg-watermark-inline a:hover {\n color: #64748b;\n}\n\n/* Demo Banner */\n.vpg-demo-banner {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.25rem 0.75rem;\n background: linear-gradient(135deg, #fef3c7, #fde68a);\n border: 1px solid #fcd34d;\n border-radius: 0.375rem;\n font-size: 0.75rem;\n color: #92400e;\n}\n\n.vpg-demo-badge {\n display: inline-flex;\n padding: 0.125rem 0.375rem;\n background: #f59e0b;\n color: white;\n font-size: 0.625rem;\n font-weight: 700;\n border-radius: 0.25rem;\n letter-spacing: 0.05em;\n}\n\n.vpg-demo-banner a {\n font-weight: 600;\n color: #d97706;\n text-decoration: none;\n}\n\n.vpg-demo-banner a:hover {\n color: #b45309;\n text-decoration: underline;\n}\n\n/* Scrollbar */\n.vpg-grid-container::-webkit-scrollbar {\n width: 0.625rem;\n height: 0.625rem;\n}\n\n.vpg-grid-container::-webkit-scrollbar-track {\n background: rgba(241, 245, 249, 0.5);\n}\n\n.vpg-grid-container::-webkit-scrollbar-thumb {\n background: rgba(203, 213, 225, 0.8);\n border-radius: 9999px;\n}\n\n.vpg-grid-container::-webkit-scrollbar-thumb:hover {\n background: rgba(148, 163, 184, 0.8);\n}\n\n.vpg-grid-container::-webkit-scrollbar-corner {\n background: rgba(241, 245, 249, 0.5);\n}\n\n/* Toast notification */\n.vpg-toast {\n position: absolute;\n top: 1rem;\n right: 1rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n background: #10b981;\n color: white;\n border-radius: 0.5rem;\n font-size: 0.875rem;\n font-weight: 500;\n box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);\n z-index: 100;\n}\n\n.vpg-toast-enter-active,\n.vpg-toast-leave-active {\n transition: all 0.2s ease;\n}\n\n.vpg-toast-enter-from,\n.vpg-toast-leave-to {\n opacity: 0;\n transform: translateY(-0.5rem);\n}\n\n/* Search */\n.vpg-search-container {\n display: flex;\n align-items: center;\n}\n\n.vpg-icon-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.375rem;\n background: transparent;\n border: none;\n border-radius: 0.375rem;\n color: #64748b;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-icon-btn:hover {\n background: #f1f5f9;\n color: #475569;\n}\n\n.vpg-search-box {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.625rem;\n background: #f8fafc;\n border: 1px solid transparent;\n border-radius: 0.5rem;\n transition: all 0.15s ease;\n}\n\n.vpg-search-box:focus-within {\n background: white;\n border-color: #e2e8f0;\n box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.05);\n}\n\n.vpg-search-icon {\n width: 1rem;\n height: 1rem;\n color: #94a3b8;\n flex-shrink: 0;\n}\n\n.vpg-search-input {\n border: none;\n outline: none;\n background: transparent;\n font-size: 0.8125rem;\n color: #334155;\n width: 200px;\n}\n\n.vpg-search-input:focus {\n outline: none;\n}\n\n.vpg-search-input::placeholder {\n color: #94a3b8;\n}\n\n.vpg-search-clear {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.125rem;\n background: #f1f5f9;\n border: none;\n border-radius: 50%;\n color: #64748b;\n cursor: pointer;\n}\n\n.vpg-search-clear:hover {\n background: #e2e8f0;\n color: #475569;\n}\n\n.vpg-search-info {\n font-size: 0.75rem;\n color: #64748b;\n font-style: italic;\n}\n\n/* Export button */\n.vpg-export-btn {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.75rem;\n font-size: 0.75rem;\n font-weight: 500;\n color: #059669;\n background: #ecfdf5;\n border: 1px solid #a7f3d0;\n border-radius: 0.375rem;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-export-btn:hover {\n background: #d1fae5;\n border-color: #6ee7b7;\n}\n\n/* Column resize handle */\n.vpg-resize-handle {\n position: absolute;\n right: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: col-resize;\n background: transparent;\n transition: background 0.15s;\n}\n\n.vpg-resize-handle:hover {\n background: rgba(79, 70, 229, 0.3);\n}\n\n.vpg-header-cell {\n position: relative;\n}\n\n.vpg-data-grid.vpg-resizing {\n cursor: col-resize;\n user-select: none;\n}\n\n.vpg-data-grid.vpg-resizing .vpg-resize-handle {\n background: rgba(79, 70, 229, 0.3);\n}\n\n/* Vertical resize handle */\n.vpg-vertical-resize-handle {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 8px;\n cursor: row-resize;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n transition: background 0.15s;\n}\n\n.vpg-vertical-resize-handle:hover {\n background: rgba(79, 70, 229, 0.1);\n}\n\n.vpg-vertical-resize-handle:hover .vpg-resize-grip span {\n background: rgba(79, 70, 229, 0.6);\n}\n\n.vpg-resize-grip {\n display: flex;\n gap: 2px;\n padding: 2px 8px;\n border-radius: 4px;\n}\n\n.vpg-resize-grip span {\n width: 16px;\n height: 2px;\n background: #cbd5e1;\n border-radius: 1px;\n transition: background 0.15s;\n}\n\n.vpg-data-grid.vpg-resizing-vertical {\n cursor: row-resize;\n user-select: none;\n}\n\n.vpg-data-grid.vpg-resizing-vertical .vpg-vertical-resize-handle {\n background: rgba(79, 70, 229, 0.15);\n}\n\n.vpg-data-grid.vpg-resizing-vertical .vpg-resize-grip span {\n background: rgba(79, 70, 229, 0.8);\n}\n\n/* Pagination */\n.vpg-pagination {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.vpg-page-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 0.25rem;\n color: #475569;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.vpg-page-btn:hover:not(:disabled) {\n background: #f8fafc;\n border-color: #cbd5e1;\n}\n\n.vpg-page-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.vpg-page-info {\n font-size: 0.75rem;\n color: #64748b;\n padding: 0 0.5rem;\n}\n\n.vpg-filtered-note {\n font-size: 0.75rem;\n color: #94a3b8;\n margin-left: 0.25rem;\n}\n\n/* Dark theme */\n.vpg-data-grid.vpg-theme-dark {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-toolbar {\n background: #0f172a;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-view-toggle {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-view-btn {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-view-btn:hover {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-view-btn.active {\n background: #6366f1;\n color: white;\n}\n\n.vpg-theme-dark .vpg-view-btn.vpg-pivot-btn.active {\n background: #10b981;\n}\n\n.vpg-theme-dark .vpg-label {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-font-size-toggle {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-font-size-btn {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-font-size-btn:hover {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-grid-container {\n background: rgba(15, 23, 42, 0.5);\n}\n\n.vpg-theme-dark .vpg-header-cell {\n background: #1e293b;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-header-cell:hover {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-header-text {\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-dropdown-arrow {\n color: #64748b;\n}\n\n.vpg-theme-dark .vpg-dropdown-arrow:hover {\n background: #475569;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-row:nth-child(odd) {\n background: #1e293b;\n}\n\n.vpg-theme-dark .vpg-row:nth-child(even) {\n background: rgba(30, 41, 59, 0.7);\n}\n\n.vpg-theme-dark .vpg-row:hover {\n background: rgba(51, 65, 85, 0.5);\n}\n\n.vpg-theme-dark .vpg-cell {\n color: #e2e8f0;\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-cell.vpg-selected {\n background: rgba(99, 102, 241, 0.3);\n outline-color: #818cf8;\n}\n\n.vpg-theme-dark .vpg-footer {\n background: rgba(15, 23, 42, 0.8);\n border-color: #334155;\n}\n\n.vpg-theme-dark .vpg-footer-left {\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-selection-stats {\n background: rgba(99, 102, 241, 0.2);\n border-color: rgba(99, 102, 241, 0.4);\n}\n\n.vpg-theme-dark .vpg-stat-label {\n color: #a5b4fc;\n}\n\n.vpg-theme-dark .vpg-stat-value {\n color: #e0e7ff;\n}\n\n.vpg-theme-dark .vpg-stat-divider {\n color: rgba(99, 102, 241, 0.4);\n}\n\n.vpg-theme-dark .vpg-search-box {\n background: #334155;\n border-color: transparent;\n}\n\n.vpg-theme-dark .vpg-search-box:focus-within {\n background: #1e293b;\n border-color: #475569;\n}\n\n.vpg-theme-dark .vpg-search-input {\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-search-clear {\n background: #334155;\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-search-clear:hover {\n background: #475569;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-clear-filters {\n background: #1e293b;\n border-color: #334155;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-clear-filters:hover {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-page-btn {\n background: #1e293b;\n border-color: #334155;\n color: #e2e8f0;\n}\n\n.vpg-theme-dark .vpg-page-btn:hover:not(:disabled) {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-export-btn {\n background: rgba(16, 185, 129, 0.2);\n border-color: rgba(16, 185, 129, 0.4);\n color: #34d399;\n}\n\n.vpg-theme-dark .vpg-export-btn:hover {\n background: rgba(16, 185, 129, 0.3);\n}\n\n.vpg-theme-dark .vpg-config-toggle {\n background: #1e293b;\n border-color: #334155;\n color: #94a3b8;\n}\n\n.vpg-theme-dark .vpg-config-toggle:hover {\n background: #334155;\n}\n\n.vpg-theme-dark .vpg-config-toggle.active {\n background: rgba(16, 185, 129, 0.2);\n border-color: rgba(16, 185, 129, 0.4);\n color: #34d399;\n}\n\n.vpg-theme-dark .vpg-pivot-status {\n color: #34d399;\n}\n\n.vpg-theme-dark .vpg-watermark-inline a {\n color: #94a3b8;\n background: linear-gradient(135deg, #1e293b 0%, #334155 100%);\n border-color: #475569;\n}\n\n.vpg-theme-dark .vpg-watermark-inline a:hover {\n color: #cbd5e1;\n background: linear-gradient(135deg, #334155 0%, #475569 100%);\n border-color: #64748b;\n}\n\n.vpg-theme-dark .vpg-resize-grip span {\n background: #475569;\n}\n\n.vpg-theme-dark .vpg-vertical-resize-handle:hover .vpg-resize-grip span {\n background: rgba(129, 140, 248, 0.6);\n}\n\n.vpg-theme-dark.vpg-resizing-vertical .vpg-resize-grip span {\n background: rgba(129, 140, 248, 0.8);\n}\n\n/* Striped rows (toggleable) */\n.vpg-data-grid:not(.vpg-striped) .vpg-row:nth-child(even) {\n background: inherit;\n}\n\n.vpg-theme-dark:not(.vpg-striped) .vpg-row:nth-child(odd),\n.vpg-theme-dark:not(.vpg-striped) .vpg-row:nth-child(even) {\n background: #1e293b;\n}\n</style>\n\n"],"names":["detectColumnType","values","nonNullValues","v","sample","numberCount","dateCount","booleanCount","val","threshold","detectFieldType","data","field","row","uniqueSet","isNumeric","getColumnUniqueValues","columnKey","maxValues","nullCount","value","a","b","numA","numB","formatCellValue","type","num","date","makeKey","fields","f","parseKey","key","aggregate","fn","formatAggregatedValue","getAggregationLabel","computeAvailableFields","getUnassignedFields","availableFields","rowFields","columnFields","valueFields","assigned","isPivotConfigured","config","computePivotResult","showRowTotals","showColumnTotals","rowKeySet","colKeySet","dataMap","rowKey","colKey","colMap","valueArrays","i","vf","rowKeys","colKeys","headers","level","headerRow","parts","valueLabels","rowHeaders","pivotData","rowTotals","columnTotalsMap","rowData","rowTotalValues","colIndex","aggValue","totalCell","allValues","columnTotals","colIdx","valueIdx","allColValues","grandTotal","STORAGE_KEY_PREFIX","generateStorageKey","columns","hash","savePivotConfig","loadPivotConfig","stored","isConfigValidForFields","availableFieldNames","available","FREE_LICENSE","INVALID_LICENSE","DEMO_LICENSE","verifySignature","typeCode","signature","expiry","secret","payload","encoder","keyData","msgData","cryptoKey","sig","expectedSig","validateLicenseKey","expiryStr","year","month","day","expiresAt","configureLicenseSecret","DEMO_SECRET_HASH","hashSecret","hashBuffer","getDemoLicenseInfo","getFreeLicenseInfo","canUsePivot","info","isPro","shouldShowWatermark","isDemo","logProRequired","feature","escapeCSV","delimiter","str","exportToCSV","options","filename","includeHeaders","rows","col","csvContent","downloadFile","exportPivotToCSV","_columnFields","rowHeaderColCount","rowIdx","csvRow","rowHeader","cell","totalsRow","content","mimeType","blob","url","link","copyToClipboard","text","onSuccess","onError","formatSelectionForClipboard","selectionBounds","minRow","maxRow","minCol","maxCol","lines","r","c","colId","multiSelectFilter","columnId","filterValue","cellValue","cellString","useExcelGrid","enableSorting","enableFiltering","sorting","ref","columnFilters","columnVisibility","globalFilter","columnStatsCache","columnKeys","computed","getColumnStats","cacheKey","clearStatsCache","columnDefs","stats","table","useVueTable","updater","getCoreRowModel","getSortedRowModel","getFilteredRowModel","filteredRowCount","totalRowCount","activeFilters","hasActiveFilter","column","setColumnFilter","clearAllFilters","getColumnFilterValues","toggleSort","current","s","getSortDirection","sort","watch","licenseKey","demoMode","licenseInfo","validationPromise","setLicenseKey","enableDemoMode","demoLicense","coreConfigureLicenseSecret","useLicense","coreIsPro","coreCanUsePivot","canUseAdvancedAggregations","canUsePercentageMode","showWatermark","coreShouldShowWatermark","requirePro","usePivotTable","currentStorageKey","unassignedFields","isConfigured","pivotResult","addRowField","removeRowField","addColumnField","removeColumnField","addValueField","aggregation","removeValueField","updateValueFieldAggregation","oldAgg","newAgg","clearConfig","moveField","from","to","items","removed","autoSuggestConfig","categoricalFields","numericFields","newData","newKeys","storageKey","savedConfig","currentConfig","coreExportToCSV","coreExportPivotToCSV","coreCopyToClipboard","coreFormatSelection","usePagination","pageSize","currentPage","totalPages","paginatedData","start","end","startIndex","endIndex","goToPage","page","nextPage","prevPage","firstPage","lastPage","setPageSize","size","useGlobalSearch","searchTerm","caseSensitive","filteredData","term","clearSearch","useRowSelection","selectedRowIndices","selectedRows","idx","allSelected","someSelected","toggleRow","index","selectRow","deselectRow","selectAll","_","deselectAll","toggleAll","isSelected","selectRange","min","max","useColumnResize","initialWidths","minWidth","maxWidth","columnWidths","isResizing","resizingColumn","startResize","event","startX","startWidth","handleMouseMove","e","diff","newWidth","handleMouseUp","resetColumnWidth","resetAllWidths","props","__props","emit","__emit","searchQuery","dropdownRef","searchInputRef","localSelected","hasBlankValues","filteredValues","query","toggleValue","clearAll","applyFilter","sortAscending","sortDescending","clearFilter","handleClickOutside","handleKeydown","onMounted","nextTick","_a","onUnmounted","newValues","_createElementBlock","_createElementVNode","_hoisted_1","_hoisted_2","_toDisplayString","_hoisted_3","_hoisted_4","_normalizeClass","_hoisted_5","$event","_hoisted_6","_Fragment","_renderList","_hoisted_8","aggregationOptions","getAggSymbol","agg","assignedFields","rowSet","colSet","valueMap","valSet","assignedCount","fieldSearch","filteredUnassignedFields","search","getFieldIcon","handleDragStart","handleDragEnd","handleAggregationChange","currentAgg","toggleRowColumn","currentAssignment","removeField","assignedTo","valueConfig","_openBlock","_cache","_hoisted_7","_hoisted_9","_withModifiers","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_21","_hoisted_22","_hoisted_23","_hoisted_24","_hoisted_25","_hoisted_26","_hoisted_27","_unref","_hoisted_29","dragOverArea","reorderDragSource","reorderDropTarget","aggregationLabels","currentFontSize","fontSizeOptions","hasActiveFilters","filterSummary","filterTooltipDetails","displayValues","remaining","showFilterTooltip","sortDirection","sortTarget","target","sortedRowIndices","indices","cmp","aHeader","bHeader","_b","aVal","_d","_c","bVal","_f","_e","columnHeaderCells","result","cells","colspan","selectedCell","handleCellClick","rowIndex","isCellSelected","handleDragOver","area","handleDragLeave","handleDrop","existingValue","handleChipDragStart","zone","handleChipDragEnd","handleChipDragOver","handleChipDragLeave","handleChipDrop","targetIndex","sourceIndex","movedField","isChipDragSource","isChipDropTarget","rowHeaderWidth","dataColWidth","filter","_hoisted_10","_hoisted_11","opt","_hoisted_20","_hoisted_28","_hoisted_30","_hoisted_31","_hoisted_32","_hoisted_33","_hoisted_34","_hoisted_35","_hoisted_36","_hoisted_37","levelIdx","_hoisted_39","_normalizeStyle","_hoisted_41","_hoisted_42","sortedIdx","_hoisted_43","_hoisted_44","_hoisted_45","_hoisted_46","_hoisted_47","_hoisted_48","MIN_COL_WIDTH","MAX_COL_WIDTH","currentTheme","globalSearchTerm","showSearchInput","resizingColumnId","resizeStartX","resizeStartWidth","gridHeight","isResizingVertically","verticalResizeStartY","verticalResizeStartHeight","showCopyToast","copyToastMessage","dataRef","filteredDataForPivot","activeFilterInfo","pivotRowFields","pivotColumnFields","pivotValueFields","pivotShowRowTotals","pivotShowColumnTotals","pivotAvailableFields","pivotIsConfigured","clearPivotConfig","searchFilteredData","totalSearchedRows","paginatedRows","paginationStart","paginationEnd","handleExport","viewMode","handlePivotExport","dataToExport","pivotFilename","rowCount","startColumnResize","handleResizeMove","handleResizeEnd","startVerticalResize","handleVerticalResizeMove","handleVerticalResizeEnd","newHeight","copySelectionToClipboard","cellCount","err","showPivotConfig","draggingField","handlePivotDragStart","handlePivotDragEnd","reorderRowFields","reorderColumnFields","tableContainerRef","tableBodyRef","activeFilterColumn","filterDropdownPosition","calculateColumnWidths","widths","sampleSize","ctx","width","openFilterDropdown","headerCell","rect","dropdownWidth","padding","left","spaceBelow","spaceAbove","top","maxHeight","closeFilterDropdown","handleFilter","handleSort","direction","activeFilterCount","selectionStart","selectionEnd","isSelecting","selectColumn","handleHeaderClick","isCellInSelection","selectionStats","count","sum","avg","formatStatValue","input","updateSelection","newRow","newCol","scrollCellIntoView","handleMouseDown","handleMouseEnter","noFormatPatterns","shouldFormatNumber","handleTableScroll","handleWindowScroll","totalTableWidth","handleContainerClick","_createVNode","_Transition","_createTextVNode","_withKeys","args","PivotConfig","PivotSkeleton","_hoisted_49","_hoisted_50","_hoisted_51","_createBlock","_Teleport","ColumnFilter","dir"],"mappings":"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"}
|