@keenmate/web-treeview
v1.0.0
Published
Framework-agnostic web component wrapper for @keenmate/svelte-treeview. Works with React, Vue, Angular, or vanilla JavaScript.
Downloads
5
Readme
Svelte TreeView Web Component
A framework-agnostic web component wrapper for @keenmate/svelte-treeview. This component allows you to use the powerful Svelte TreeView in any web framework including React, Vue, Angular, or vanilla JavaScript.
Note: This is a wrapper around the original Svelte TreeView component. For comprehensive documentation about features, search options, and advanced configurations, please refer to the Svelte TreeView documentation.
✨ Features
- 🌐 Framework Agnostic: Works with React, Vue, Angular, or vanilla JavaScript
- 🔍 Full-text Search: Built-in search with FlexSearch integration
- 🎯 Drag & Drop: Native drag and drop support with customizable handlers
- 🎨 Custom Templates: Flexible template system using slots or functions
- 📱 Responsive: Mobile-friendly with touch support
- ⚡ Performance: Virtual scrolling for large datasets
- 🎭 TypeScript: Full TypeScript support with type definitions
- 🧩 Extensible: Rich API with events and methods
- 🎯 Accessible: ARIA compliant and keyboard navigation
📦 Installation
npm install @keenmate/svelte-treeview-webcomponent🚀 Quick Start
Vanilla HTML/JavaScript
<!DOCTYPE html>
<html>
<head>
<script type="module" src="./node_modules/@keenmate/svelte-treeview-webcomponent/dist/web-treeview.js"></script>
</head>
<body>
<svelte-tree-view
id="my-tree"
id-member="id"
path-member="path"
display-value-member="name"
expand-level="2">
</svelte-tree-view>
<script>
const tree = document.getElementById('my-tree');
tree.data = [
{ id: '1', path: '1', name: 'Documents' },
{ id: '2', path: '1.1', name: 'Projects' },
{ id: '3', path: '1.1.1', name: 'Web App' },
{ id: '4', path: '1.1.1.1', name: 'index.html' }
];
// Event listeners
tree.addEventListener('node-clicked', (e) => {
console.log('Clicked:', e.detail.node.data.name);
});
</script>
</body>
</html>React
import React, { useEffect, useRef } from 'react';
import '@keenmate/svelte-treeview-webcomponent';
import type { SvelteTreeView } from '@keenmate/svelte-treeview-webcomponent';
const MyComponent = () => {
const treeRef = useRef<SvelteTreeView>(null);
useEffect(() => {
if (treeRef.current) {
treeRef.current.data = [
{ id: '1', path: '1', name: 'Root' },
{ id: '2', path: '1.1', name: 'Child' }
];
}
}, []);
return (
<svelte-tree-view
ref={treeRef}
id-member="id"
path-member="path"
expand-level={2}
onNodeClicked={(e) => console.log('Node clicked:', e.detail.node)}
/>
);
};Vue 3
<template>
<svelte-tree-view
ref="treeRef"
id-member="id"
path-member="path"
:expand-level="2"
@node-clicked="handleNodeClick"
/>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import '@keenmate/svelte-treeview-webcomponent';
const treeRef = ref();
onMounted(() => {
treeRef.value.data = [
{ id: '1', path: '1', name: 'Root' },
{ id: '2', path: '1.1', name: 'Child' }
];
});
const handleNodeClick = (event) => {
console.log('Node clicked:', event.detail.node);
};
</script>Property Naming Convention
Important: This web component automatically converts between JavaScript camelCase properties and HTML kebab-case attributes:
| JavaScript Property | HTML Attribute | Description |
|-------------------|----------------|-------------|
| idMember | id-member | Property name for unique identifier |
| pathMember | path-member | Property name for hierarchical path |
| displayValueMember | display-value-member | Property name for display text |
| searchValueMember | search-value-member | Property name for search text |
| expandLevel | expand-level | Initial expansion level |
| scrollHighlightClass | scroll-highlight-class | CSS class for scroll highlighting |
Examples:
<!-- HTML attributes (kebab-case) -->
<svelte-tree-view
display-value-member="name"
expand-level="2"
scroll-highlight-class="highlight">
</svelte-tree-view>// JavaScript properties (camelCase)
tree.displayValueMember = 'name';
tree.expandLevel = 2;
tree.scrollHighlightClass = 'highlight';🎨 Custom Templates
Use HTML templates with slot attributes to customize rendering:
<svelte-tree-view id-member="id" path-member="path">
<!-- Custom node template -->
<template slot="node-template">
<div class="custom-node">
<span class="icon">\${node.data.type === 'folder' ? '📁' : '📄'}</span>
<span class="name">\${node.data.name}</span>
<span class="size">\${node.data.size || ''}</span>
</div>
</template>
<!-- Header template -->
<template slot="tree-header">
<h3>📂 File Explorer</h3>
</template>
<!-- Empty state template -->
<template slot="no-data-found">
<div class="empty-state">No files found 📭</div>
</template>
</svelte-tree-view>Or set templates programmatically:
const tree = document.querySelector('svelte-tree-view');
tree.setNodeTemplate((node) => `
<div class="custom-node">
<strong>\${node.data.name}</strong>
<small>\${node.path}</small>
</div>
`);🔧 Configuration
Required Attributes
id-member: Property name for unique node identifierspath-member: Property name for hierarchical paths (e.g., "1", "1.1", "1.2.3")
Optional Attributes
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| expand-level | number | 2 | Default expansion level |
| search-text | string | "" | Current search query |
| tree-path-separator | string | "." | Path separator character |
| should-toggle-on-node-click | boolean | true | Toggle expansion on click |
| should-use-internal-search-index | boolean | true | Enable FlexSearch integration |
| should-display-debug-information | boolean | false | Show debug info |
Visual Styling
| Attribute | Description |
|-----------|-------------|
| selected-node-class | CSS class for selected nodes |
| drag-over-node-class | CSS class during drag over |
| expand-icon-class | CSS class for expand icons |
| collapse-icon-class | CSS class for collapse icons |
| leaf-icon-class | CSS class for leaf node icons |
🎯 API Methods
const tree = document.querySelector('svelte-tree-view');
// Expansion control
await tree.expandNodes('1.2'); // Expand specific path
await tree.collapseNodes('1.2'); // Collapse specific path
tree.expandAll(); // Expand all nodes
tree.collapseAll(); // Collapse all nodes
// Search and filtering
tree.filterNodes('search term'); // Filter visible nodes
const results = tree.searchNodes('query'); // Get search results
// Navigation
await tree.scrollToPath('1.2.3', {
behavior: 'smooth',
block: 'center'
});
// Event handlers
tree.onNodeClicked = (node) => console.log('Clicked:', node);
tree.onNodeDragStart = (node, event) => console.log('Drag start:', node);
tree.onNodeDragOver = (node, event) => console.log('Drag over:', node);
tree.onNodeDrop = (dropNode, draggedNode, event) => {
console.log('Dropped:', draggedNode, 'on:', dropNode);
};🎪 Events
Listen for custom events:
tree.addEventListener('node-clicked', (e) => {
console.log('Node clicked:', e.detail.node);
});
tree.addEventListener('selected-node-changed', (e) => {
console.log('Selection changed:', e.detail.selectedNode);
});
tree.addEventListener('search-text-changed', (e) => {
console.log('Search changed:', e.detail.searchText);
});
tree.addEventListener('node-drag-start', (e) => {
console.log('Drag started:', e.detail.node, e.detail.event);
});
tree.addEventListener('node-drop', (e) => {
console.log('Node dropped:', e.detail.node, e.detail.draggedNode);
});🗄️ Data Format
The component expects hierarchical data using LTree-style paths:
const data = [
{
id: '1', // Unique identifier
path: '1', // Hierarchical path
name: 'Documents', // Display name
// ... custom properties
},
{
id: '2',
path: '1.1', // Child of '1'
name: 'Projects',
},
{
id: '3',
path: '1.1.1', // Child of '1.1'
name: 'Web App',
},
{
id: '4',
path: '1.2', // Another child of '1'
name: 'Images',
}
];🎨 Styling
The component includes default styles but can be customized:
/* Custom CSS variables */
svelte-tree-view {
--tree-indent: 20px;
--node-height: 32px;
--selected-bg: #e3f2fd;
--hover-bg: #f5f5f5;
--icon-size: 16px;
--font-size: 14px;
}
/* Custom node styling */
svelte-tree-view .custom-node {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 8px;
border-radius: 4px;
}
svelte-tree-view .custom-node:hover {
background-color: var(--hover-bg);
}📚 Examples
Check out the examples/ directory for complete implementations:
vanilla.html- Pure JavaScript implementationreact.tsx- React integrationvue.vue- Vue 3 composition API
Relationship to Svelte TreeView
This web component is a wrapper around @keenmate/svelte-treeview. It provides:
- ✅ Framework-agnostic interface via web components
- ✅ Shadow DOM encapsulation for style isolation
- ✅ HTML attribute ↔ JavaScript property conversion (kebab-case ↔ camelCase)
- ✅ Template slot → Svelte snippet conversion
- ✅ Custom event dispatching for framework integration
For detailed documentation about the underlying TreeView features, search options, advanced configurations, and all available properties, please refer to the Svelte TreeView documentation.
Key differences from direct Svelte usage:
- Attributes: Use kebab-case HTML attributes instead of camelCase props
- Data binding: Set
dataproperty programmatically instead of binding - Events: Listen for CustomEvents instead of component events
- Templates: Use HTML
<template slot="...">instead of Svelte snippets
🤝 Contributing
Contributions are welcome! Please read the contributing guide for details.
📄 License
MIT License - see LICENSE for details.
🔗 Related Projects
- @keenmate/svelte-treeview - Original Svelte component
- FlexSearch - Search engine integration
🆘 Support
Made with ❤️ by KeenMate
