dataframe-sandbox / src /lib /ConfigPanel.svelte
hmb's picture
hmb HF Staff
Initial commit: Dataframe demo with Vite + Svelte (no SvelteKit routing)
951c359
<script lang="ts">
import { createEventDispatcher } from "svelte";
import { sampleDatasets } from "./sampleData";
const dispatch = createEventDispatcher();
export let selectedDataset = "basic";
export let currentTheme = "default";
export let editable = true;
export let show_row_numbers = true;
export let show_search: "none" | "search" | "filter" = "search";
export let show_copy_button = true;
export let show_fullscreen_button = true;
export let show_label = true;
export let label = "Sample Data";
export let max_height = 500;
export let line_breaks = true;
export let wrap = false;
export let max_chars: number | undefined = undefined;
// Controls panel state
let activeControlsTab = "properties"; // "properties" or "actions"
function switchDataset(dataset: string) {
selectedDataset = dataset;
dispatch('datasetChange', { dataset });
}
function applyTheme(theme: string) {
currentTheme = theme;
dispatch('themeChange', { theme });
}
function addCustomColumn() {
dispatch('addColumn');
}
function addCustomRow() {
dispatch('addRow');
}
</script>
<!-- Storybook Controls Panel -->
<div class="h-full flex flex-col w-full">
<!-- Controls Tab Header -->
<div class="p-4 border-b-2 border-[#e0e0e0] bg-[#f8fafc]">
<div class="flex items-center justify-between">
<h2 class="text-xs font-bold text-[#2e3438] uppercase tracking-wider">Controls</h2>
<div class="flex space-x-4">
<button
on:click={() => activeControlsTab = "properties"}
class="flex items-center py-2.5 !px-4 text-sm font-medium transition-all duration-200 rounded-lg
{activeControlsTab === 'properties'
? 'text-[#F87701] bg-white border border-[#F87701]'
: 'text-[#64748b] hover:text-[#F87701] hover:bg-white/50 border border-transparent'}"
>
<span class="mr-2">⚙️</span>
Properties
</button>
<button
on:click={() => activeControlsTab = "actions"}
class="flex items-center py-2.5 !px-4 text-sm font-medium transition-all duration-200 rounded-lg
{activeControlsTab === 'actions'
? 'text-[#F87701] bg-white border border-[#F87701]'
: 'text-[#64748b] hover:text-[#F87701] hover:bg-white/50 border border-transparent'}"
>
<span class="mr-2">📝</span>
Actions
</button>
</div>
</div>
</div>
<!-- Controls Content -->
<div class="flex-1 overflow-x-scroll overflow-y-scroll p-4 min-h-0">
{#if activeControlsTab === "properties"}
<!-- Properties Tab Content -->
<div class="flex space-x-8 min-w-max">
<!-- Boolean Controls -->
<div class="min-w-[300px]">
<h4 class="text-xs font-bold text-[#2e3438] uppercase tracking-wider mb-4">Display</h4>
<div class="space-y-4">
<label class="flex items-center justify-between py-3 px-3 hover:bg-[#f6f9fc] rounded-lg transition-all duration-200">
<span class="text-[14px] text-[#2e3438]">editable</span>
<input
type="checkbox"
bind:checked={editable}
class="w-5 h-5 rounded border-[#e0e0e0] text-[#F87701] focus:ring-[#F87701] focus:ring-2 bg-white"
>
</label>
<label class="flex items-center justify-between py-3 px-3 hover:bg-[#f6f9fc] rounded-lg transition-all duration-200">
<span class="text-[14px] text-[#2e3438]">show_row_numbers</span>
<input
type="checkbox"
bind:checked={show_row_numbers}
class="w-5 h-5 rounded border-[#e0e0e0] text-[#F87701] focus:ring-[#F87701] focus:ring-2 bg-white"
>
</label>
<label class="flex items-center justify-between py-3 px-3 hover:bg-[#f6f9fc] rounded-lg transition-all duration-200">
<span class="text-[14px] text-[#2e3438]">show_copy_button</span>
<input
type="checkbox"
bind:checked={show_copy_button}
class="w-5 h-5 rounded border-[#e0e0e0] text-[#F87701] focus:ring-[#F87701] focus:ring-2 bg-white"
>
</label>
<label class="flex items-center justify-between py-3 px-3 hover:bg-[#f6f9fc] rounded-lg transition-all duration-200">
<span class="text-[14px] text-[#2e3438]">show_fullscreen_button</span>
<input
type="checkbox"
bind:checked={show_fullscreen_button}
class="w-5 h-5 rounded border-[#e0e0e0] text-[#F87701] focus:ring-[#F87701] focus:ring-2 bg-white"
>
</label>
<label class="flex items-center justify-between py-3 px-3 hover:bg-[#f6f9fc] rounded-lg transition-all duration-200">
<span class="text-[14px] text-[#2e3438]">show_label</span>
<input
type="checkbox"
bind:checked={show_label}
class="w-5 h-5 rounded border-[#e0e0e0] text-[#F87701] focus:ring-[#F87701] focus:ring-2 bg-white"
>
</label>
<label class="flex items-center justify-between py-3 px-3 hover:bg-[#f6f9fc] rounded-lg transition-all duration-200">
<span class="text-[14px] text-[#2e3438]">line_breaks</span>
<input
type="checkbox"
bind:checked={line_breaks}
class="w-5 h-5 rounded border-[#e0e0e0] text-[#F87701] focus:ring-[#F87701] focus:ring-2 bg-white"
>
</label>
<label class="flex items-center justify-between py-3 px-3 hover:bg-[#f6f9fc] rounded-lg transition-all duration-200">
<span class="text-[14px] text-[#2e3438]">wrap</span>
<input
type="checkbox"
bind:checked={wrap}
class="w-5 h-5 rounded border-[#e0e0e0] text-[#F87701] focus:ring-[#F87701] focus:ring-2 bg-white"
>
</label>
</div>
</div>
<!-- Options Controls -->
<div class="min-w-[250px]">
<h4 class="text-xs font-bold text-[#2e3438] uppercase tracking-wider mb-4">Options</h4>
<div class="space-y-2">
<label for="show-search" class="block text-sm font-medium text-[#374151] mb-2">Search Type</label>
<div class="relative">
<select
id="show-search"
bind:value={show_search}
class="w-full px-4 py-3 !rounded-sm text-sm border-2 border-[#e5e7eb] rounded-lg bg-[#f9fafb] text-[#374151] focus:ring-2 focus:ring-[#F87701] focus:border-[#F87701] focus:bg-white transition-all duration-200 appearance-none cursor-pointer shadow-sm"
>
<option value="none">None</option>
<option value="search">Search</option>
<option value="filter">Filter</option>
</select>
<div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
<svg class="w-4 h-4 text-[#9ca3af]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</div>
</div>
<p class="text-xs text-[#6b7280] mt-1">Configure search functionality</p>
</div>
</div>
<!-- Number Controls -->
<div class="min-w-[250px]">
<h4 class="text-xs font-bold text-[#2e3438] uppercase tracking-wider mb-4">Numbers</h4>
<div class="space-y-6">
<div class="space-y-2">
<label for="max-height" class="block text-sm font-medium text-[#374151]">Maximum Height</label>
<div class="relative">
<input
id="max-height"
type="number"
bind:value={max_height}
min="200"
max="1000"
step="50"
class="w-full px-4 py-3 text-sm !rounded-sm border-2 border-[#e5e7eb] rounded-lg bg-[#f9fafb] text-[#374151] focus:ring-2 focus:ring-[#F87701] focus:border-[#F87701] focus:bg-white transition-all duration-200 shadow-sm"
>
<div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
<span class="text-xs text-[#9ca3af] font-medium">px</span>
</div>
</div>
<p class="text-xs text-[#6b7280]">Height constraint for the table (200-1000px)</p>
</div>
<div class="space-y-2">
<label for="max-chars" class="block text-sm font-medium text-[#374151]">Character Limit</label>
<input
id="max-chars"
type="number"
bind:value={max_chars}
min="10"
max="1000"
step="10"
placeholder="No limit"
class="w-full px-4 py-3 text-sm !rounded-sm border-2 border-[#e5e7eb] rounded-lg bg-[#f9fafb] text-[#374151] placeholder-[#9ca3af] focus:ring-2 focus:ring-[#F87701] focus:border-[#F87701] focus:bg-white transition-all duration-200 shadow-sm"
>
<p class="text-xs text-[#6b7280]">Maximum characters per cell (leave empty for no limit)</p>
</div>
</div>
</div>
<!-- Text Controls -->
<div class="min-w-[250px]">
<h4 class="text-xs font-bold text-[#2e3438] uppercase tracking-wider mb-4">Text</h4>
<div class="space-y-2">
<label for="label-input" class="block text-sm font-medium text-[#374151]">Table Label</label>
<div class="relative">
<input
id="label-input"
type="text"
bind:value={label}
placeholder="Enter table label..."
class="w-full px-4 py-3 text-sm !rounded-sm border-2 border-[#e5e7eb] rounded-lg bg-[#f9fafb] text-[#374151] placeholder-[#9ca3af] focus:ring-2 focus:ring-[#F87701] focus:border-[#F87701] focus:bg-white transition-all duration-200 shadow-sm"
>
<div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
<svg class="w-4 h-4 text-[#9ca3af]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a.997.997 0 01-1.414 0l-7-7A1.997 1.997 0 013 12V7a4 4 0 014-4z"></path>
</svg>
</div>
</div>
<p class="text-xs text-[#6b7280]">Display label shown above the dataframe</p>
</div>
</div>
</div>
{:else if activeControlsTab === "actions"}
<!-- Actions Tab Content -->
<div class="flex space-x-8 min-w-max">
<!-- Data Manipulation Section -->
<div class="min-w-[300px]">
<div>
<h4 class="text-xs font-bold text-[#2e3438] uppercase tracking-wider mb-3">Data Manipulation</h4>
<p class="text-sm text-[#64748b] mb-5 leading-relaxed">Add new rows and columns to the dataframe</p>
<div class="grid grid-cols-1 gap-3">
<button
on:click={addCustomColumn}
class="flex items-center justify-center px-6 py-4 text-sm font-semibold bg-gradient-to-r from-[#F87701] to-[#0f8bda] text-white rounded-xl hover:from-[#0f8bda] hover:to-[#0569b5] focus:ring-2 focus:ring-[#F87701] focus:ring-offset-2 transition-all duration-200"
>
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4"></path>
</svg>
Add Column
</button>
<button
on:click={addCustomRow}
class="flex items-center justify-center px-6 py-4 text-sm font-semibold bg-gradient-to-r from-[#10b981] to-[#059669] text-white rounded-xl hover:from-[#059669] hover:to-[#047857] focus:ring-2 focus:ring-[#10b981] focus:ring-offset-2 transition-all duration-200"
>
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h6m-6 4h6m2 5H7a2 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"></path>
</svg>
Add Row
</button>
</div>
</div>
<div class="border-t border-[#e2e8f0] pt-6">
<h4 class="text-xs font-bold text-[#2e3438] uppercase tracking-wider mb-3">Export Options</h4>
<p class="text-sm text-[#64748b] mb-5 leading-relaxed">Export your data in different formats</p>
<div class="grid grid-cols-1 gap-3">
<button
class="flex items-center justify-center px-4 py-3 text-sm font-medium bg-[#f59e0b] text-white rounded-lg hover:bg-[#d97706] focus:ring-2 focus:ring-[#f59e0b] focus:ring-offset-2 transition-all duration-200 shadow-sm"
>
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 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"></path>
</svg>
Export as CSV
</button>
<button
class="flex items-center justify-center px-4 py-3 text-sm font-medium bg-[#8b5cf6] text-white rounded-lg hover:bg-[#7c3aed] focus:ring-2 focus:ring-[#8b5cf6] focus:ring-offset-2 transition-all duration-200 shadow-sm"
>
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
</svg>
Copy to Clipboard
</button>
</div>
</div>
</div>
<!-- Export & Reset Actions -->
<div class="min-w-[300px]">
<h4 class="text-xs font-bold text-[#2e3438] uppercase tracking-wider mb-3">Export Options</h4>
<p class="text-sm text-[#64748b] mb-5 leading-relaxed">Export your data in different formats</p>
<div class="grid grid-cols-1 gap-3 mb-6">
<button
class="flex items-center justify-center px-5 py-3 text-sm font-semibold bg-gradient-to-r from-[#f59e0b] to-[#d97706] text-white rounded-xl hover:from-[#d97706] hover:to-[#b45309] focus:ring-2 focus:ring-[#f59e0b] focus:ring-offset-2 transition-all duration-200"
>
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 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"></path>
</svg>
Export CSV
</button>
<button
class="flex items-center justify-center px-5 py-3 text-sm font-semibold bg-gradient-to-r from-[#6366f1] to-[#4f46e5] text-white rounded-xl hover:from-[#4f46e5] hover:to-[#4338ca] focus:ring-2 focus:ring-[#6366f1] focus:ring-offset-2 transition-all duration-200"
>
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
</svg>
Copy to Clipboard
</button>
</div>
<div class="border-t border-[#e2e8f0] pt-4">
<h4 class="text-xs font-bold text-[#2e3438] uppercase tracking-wider mb-3">Reset Actions</h4>
<button
class="w-full flex items-center justify-center px-5 py-3 text-sm font-semibold bg-gradient-to-r from-[#ef4444] to-[#dc2626] text-white rounded-xl hover:from-[#dc2626] hover:to-[#b91c1c] focus:ring-2 focus:ring-[#ef4444] focus:ring-offset-2 transition-all duration-200"
>
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
</svg>
Reset Data
</button>
</div>
</div>
</div>
{/if}
</div>
</div>