@keenmate/web-treeview
Version:
Framework-agnostic web component wrapper for @keenmate/svelte-treeview. Works with React, Vue, Angular, or vanilla JavaScript.
390 lines (306 loc) • 11.6 kB
Markdown
# Svelte TreeView Web Component
[](https://badge.fury.io/js/@keenmate%2Fsvelte-treeview-webcomponent)
[](https://opensource.org/licenses/MIT)
**A framework-agnostic web component wrapper for [ /svelte-treeview](https://github.com/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](https://github.com/keenmate/svelte-treeview#readme).
## ✨ 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
```bash
npm install /svelte-treeview-webcomponent
```
## 🚀 Quick Start
### Vanilla HTML/JavaScript
```html
<!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
```tsx
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
```vue
<template>
<svelte-tree-view
ref="treeRef"
id-member="id"
path-member="path"
:expand-level="2"
-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
<!-- HTML attributes (kebab-case) -->
<svelte-tree-view
display-value-member="name"
expand-level="2"
scroll-highlight-class="highlight">
</svelte-tree-view>
```
```javascript
// JavaScript properties (camelCase)
tree.displayValueMember = 'name';
tree.expandLevel = 2;
tree.scrollHighlightClass = 'highlight';
```
## 🎨 Custom Templates
Use HTML templates with slot attributes to customize rendering:
```html
<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:
```javascript
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 identifiers
- `path-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
```javascript
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:
```javascript
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:
```javascript
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:
```css
/* 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`](./examples/vanilla.html) - Pure JavaScript implementation
- [`react.tsx`](./examples/react.tsx) - React integration
- [`vue.vue`](./examples/vue.vue) - Vue 3 composition API
## Relationship to Svelte TreeView
This web component is a **wrapper** around [ /svelte-treeview](https://github.com/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**](https://github.com/keenmate/svelte-treeview#readme).
### Key differences from direct Svelte usage:
1. **Attributes**: Use kebab-case HTML attributes instead of camelCase props
2. **Data binding**: Set `data` property programmatically instead of binding
3. **Events**: Listen for CustomEvents instead of component events
4. **Templates**: Use HTML `<template slot="...">` instead of Svelte snippets
## 🤝 Contributing
Contributions are welcome! Please read the [contributing guide](CONTRIBUTING.md) for details.
## 📄 License
MIT License - see [LICENSE](LICENSE) for details.
## 🔗 Related Projects
- [ /svelte-treeview](https://github.com/keenmate/svelte-treeview) - Original Svelte component
- [FlexSearch](https://github.com/nextapps-de/flexsearch) - Search engine integration
## 🆘 Support
- 📖 [Documentation](https://github.com/keenmate/svelte-treeview-webcomponent/wiki)
- 🐛 [Issue Tracker](https://github.com/keenmate/svelte-treeview-webcomponent/issues)
- 💬 [Discussions](https://github.com/keenmate/svelte-treeview-webcomponent/discussions)
---
Made with ❤️ by [KeenMate](https://github.com/keenmate)