Radius/add network structure

This commit is contained in:
Luca Haid
2025-12-09 05:34:24 +00:00
parent 60556e5d63
commit 167b038c20
37 changed files with 6833 additions and 2920 deletions
+551
View File
@@ -0,0 +1,551 @@
# TT-Core Component Library (Vue 3)
Modern, reusable Vue 3 components and utilities for TheTool applications. Built with the Composition API and designed for maximum performance and developer experience.
**Version:** 2.0.0 (Vue 3)
## 📦 What's Included
### Components
#### Data Display
- **`<tt-data-table>`** - Enhanced data table with loading states, skeletons, and placeholders
- **`<tt-status-chip>`** - Smart online/offline status chip with lazy loading and IP copy
#### Feedback
- **`<tt-loading-indicator>`** - Processing indicator with animated progress bar
- **`<tt-skeleton>`** - Skeleton loader for loading states
#### Forms
- **`<tt-smart-autocomplete>`** - Advanced autocomplete with mode switching (XINON/ESTMK)
- **`<tt-file-dropzone>`** - Drag & drop file upload component
#### Overlays
- **`<tt-dialog>`** - Modern modal dialog with portal rendering
#### Navigation
- **`<tt-view-switcher>`** - Tab-based view switching with mobile support
### Utilities
Available globally via `window.TT_CORE`:
```javascript
// Clipboard
TT_CORE.copyToClipboard(text)
// Formatting
TT_CORE.formatBytes(bytes, decimals)
TT_CORE.formatDuration(seconds)
TT_CORE.formatNumber(num, decimals, decimalSep, thousandsSep)
TT_CORE.formatBits(bps)
// Validation
TT_CORE.calculateSimilarity(str1, str2)
TT_CORE.validateData(street, zip, city, info, threshold)
TT_CORE.validateEmail(email)
TT_CORE.generatePassword(length)
// Script Loading
TT_CORE.loadScript(src)
TT_CORE.loadScripts([src1, src2, ...])
```
### Composables (Vue 3 Composition API)
```javascript
// Use in setup() function with Composition API
import { useIntersectionObserver, useInfiniteScroll, useAsyncData } from 'window.TT_CORE';
// Intersection Observer
const { targetRef } = TT_CORE.useIntersectionObserver((entry) => {
console.log('Element is visible!', entry);
}, { threshold: 0.1 });
// Infinite Scroll
const items = ref([...]);
const { sentinelRef, visibleItems, loadMore } = TT_CORE.useInfiniteScroll(items, {
initialCount: 50,
incrementBy: 50
});
// Async Data Fetching
const { data, isLoading, hasError, fetchData } = TT_CORE.useAsyncData();
await fetchData('/api/users');
```
### Mixins (Options API - Backward Compatibility)
```javascript
// Use with Options API (if not using Composition API)
export default {
mixins: [
TT_CORE.createIntersectionObserverMixin({ threshold: 0.1 }),
TT_CORE.createInfiniteScrollMixin({ initialCount: 50 }),
TT_CORE.createAsyncDataMixin()
]
}
```
## 🚀 Quick Start with Vue 3 CDN
### 1. Include Vue 3 and TT-Core
```html
<!DOCTYPE html>
<html>
<head>
<!-- TT-Core CSS -->
<link rel="stylesheet" href="/public/plugins/vue/tt-core/styles/tt-core.css">
<!-- Vue 3 CDN -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<tt-data-table :items="users" :is-loading="loading">
<!-- ... -->
</tt-data-table>
</div>
<!-- TT-Core Library -->
<script src="/public/plugins/vue/tt-core/index.js" type="module"></script>
<!-- TT-Core Components -->
<script src="/public/plugins/vue/tt-core/components/data-display/TtDataTable.js"></script>
<script src="/public/plugins/vue/tt-core/components/data-display/TtStatusChip.js"></script>
<script src="/public/plugins/vue/tt-core/components/feedback/TtLoadingIndicator.js"></script>
<script src="/public/plugins/vue/tt-core/components/feedback/TtSkeleton.js"></script>
<script src="/public/plugins/vue/tt-core/components/forms/TtSmartAutocomplete.js"></script>
<script src="/public/plugins/vue/tt-core/components/forms/TtFileDropzone.js"></script>
<script src="/public/plugins/vue/tt-core/components/overlays/TtDialog.js"></script>
<script src="/public/plugins/vue/tt-core/components/navigation/TtViewSwitcher.js"></script>
<!-- Your App -->
<script>
const { createApp, ref } = Vue;
const app = createApp({
setup() {
const users = ref([
{ name: 'John', email: 'john@example.com' },
{ name: 'Jane', email: 'jane@example.com' }
]);
const loading = ref(false);
return { users, loading };
}
});
// IMPORTANT: Register TT-Core components with your app
TT_CORE.registerComponents(app);
app.mount('#app');
</script>
</body>
</html>
```
## 📘 Component Usage Examples
### Data Table
```vue
<script setup>
import { ref } from 'vue';
const users = ref([...]);
const loading = ref(false);
const hasSearched = ref(true);
</script>
<template>
<tt-data-table
:items="users"
:is-loading="loading"
:has-searched="hasSearched"
density="compact"
>
<template #head>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Status</th>
</tr>
</thead>
</template>
<template #skeleton-row>
<td><tt-skeleton /></td>
<td><tt-skeleton /></td>
<td><tt-skeleton width="80px" /></td>
</template>
<template #row="{ item, index }">
<td>{{ item.name }}</td>
<td>{{ item.email }}</td>
<td>
<tt-status-chip
:username="item.username"
@scan-ip="handleScan"
/>
</td>
</template>
</tt-data-table>
</template>
```
### Smart Autocomplete (v-model support)
```vue
<script setup>
import { ref } from 'vue';
const customerName = ref('');
const handleSelect = ({ custnum, display }) => {
console.log('Selected:', custnum, display);
};
</script>
<template>
<tt-smart-autocomplete
v-model="customerName"
placeholder="Suche Kunde..."
@select="handleSelect"
@enter="search"
/>
</template>
```
### File Dropzone
```vue
<script setup>
const handleFile = async (file) => {
console.log('File selected:', file.name);
// Process file...
};
</script>
<template>
<tt-file-dropzone
accept=".xlsx,.xls"
@file-selected="handleFile"
buttonText="Datei auswählen"
/>
</template>
```
### Dialog/Modal
```vue
<script setup>
import { ref } from 'vue';
const showModal = ref(false);
</script>
<template>
<tt-dialog
:show="showModal"
title="User Details"
size="wide"
@close="showModal = false"
>
<p>Modal content here...</p>
<template #footer>
<button @click="save">Save</button>
<button @click="showModal = false">Cancel</button>
</template>
</tt-dialog>
</template>
```
### View Switcher (v-model support)
```vue
<script setup>
import { ref } from 'vue';
const currentView = ref('users');
const views = [
{ id: 'users', name: 'Users', icon: 'fa fa-users' },
{ id: 'settings', name: 'Settings', icon: 'fa fa-cog' }
];
</script>
<template>
<tt-view-switcher
v-model="currentView"
:options="views"
/>
<div v-if="currentView === 'users'">Users View</div>
<div v-else-if="currentView === 'settings'">Settings View</div>
</template>
```
## 🎯 Using Composables in Your Components
### Intersection Observer
```vue
<script setup>
const { targetRef } = window.TT_CORE.useIntersectionObserver((entry) => {
console.log('Element visible!', entry);
}, { threshold: 0.5, once: true });
</script>
<template>
<div ref="targetRef">
I will trigger when 50% visible!
</div>
</template>
```
### Infinite Scroll
```vue
<script setup>
import { ref } from 'vue';
const allItems = ref([/* 1000 items */]);
const { sentinelRef, visibleItems, hasMore } = window.TT_CORE.useInfiniteScroll(allItems, {
initialCount: 50,
incrementBy: 25
});
</script>
<template>
<div>
<div v-for="item in visibleItems" :key="item.id">
{{ item.name }}
</div>
<!-- Sentinel element for infinite scroll -->
<div ref="sentinelRef" v-if="hasMore">Loading more...</div>
</div>
</template>
```
### Async Data Fetching
```vue
<script setup>
import { onMounted } from 'vue';
const { data, isLoading, hasError, errorMessage, fetchData } = window.TT_CORE.useAsyncData();
onMounted(async () => {
await fetchData('/api/users');
});
</script>
<template>
<div>
<div v-if="isLoading">Loading...</div>
<div v-else-if="hasError">Error: {{ errorMessage }}</div>
<div v-else>
<div v-for="user in data" :key="user.id">
{{ user.name }}
</div>
</div>
</div>
</template>
```
## 🔧 Options API (Traditional Vue Syntax)
If you prefer the Options API over Composition API:
```vue
<template>
<div>
<tt-data-table :items="users" :is-loading="loading">
<!-- ... -->
</tt-data-table>
</div>
</template>
<script>
export default {
mixins: [
window.TT_CORE.createInfiniteScrollMixin({
initialCount: 50,
itemsKey: 'users'
})
],
data() {
return {
users: [],
loading: false
};
},
mounted() {
this.loadUsers();
},
methods: {
async loadUsers() {
this.loading = true;
// ... fetch logic
this.loading = false;
}
}
}
</script>
```
## 📝 Migration from Vue 2
### Key Changes
1. **Component Registration:**
- Vue 2: Components auto-register globally via `Vue.component()`
- Vue 3: Must call `TT_CORE.registerComponents(app)` after creating your app
2. **v-model:**
- Vue 2: `v-model``value` prop + `input` event
- Vue 3: `v-model``modelValue` prop + `update:modelValue` event
3. **Lifecycle Hooks:**
- `beforeDestroy``beforeUnmount`
- `destroyed``unmounted`
4. **Composables:**
- Vue 2: Use mixins with `createXxxMixin()`
- Vue 3: Use composables with `useXxx()` in `setup()`
### Update Your Code:
```javascript
// Vue 2
const app = new Vue({
el: '#app',
data: { ... }
});
// Vue 3
const { createApp } = Vue;
const app = createApp({
setup() {
// Composition API
}
});
TT_CORE.registerComponents(app); // ← REQUIRED!
app.mount('#app');
```
## 🎨 Styling
All components use the `.tt-scope` class for scoping. Customize via CSS variables:
```css
:root {
--tt-brand-blue: #005384;
--tt-accent: #005384;
--tt-accent-2: #1e88c9;
--tt-ok: #0f9d58;
--tt-bad: #e03131;
--tt-border: #e6e9ef;
--tt-radius: 10px;
--tt-shadow: 0 8px 24px rgba(0, 83, 132, .08);
}
```
## 📁 Directory Structure
```
tt-core/
├── index.js # Main entry point (Vue 3)
├── README.md # This file
├── MIGRATION_GUIDE.md # Detailed migration guide
├── SUMMARY.md # Project summary
├── utils/ # Utility functions
│ ├── clipboard.js
│ ├── formatting.js
│ ├── validation.js
│ └── script-loader.js
├── components/ # Vue 3 components
│ ├── data-display/
│ │ ├── TtDataTable.js
│ │ └── TtStatusChip.js
│ ├── feedback/
│ │ ├── TtLoadingIndicator.js
│ │ └── TtSkeleton.js
│ ├── forms/
│ │ ├── TtSmartAutocomplete.js
│ │ └── TtFileDropzone.js
│ ├── overlays/
│ │ └── TtDialog.js
│ └── navigation/
│ └── TtViewSwitcher.js
├── composables/ # Vue 3 composables + mixins
│ ├── useIntersectionObserver.js
│ ├── useInfiniteScroll.js
│ └── useAsyncData.js
└── styles/ # CSS styles
└── tt-core.css
```
## 🚀 Performance Tips
1. **Lazy Load Components:** Only load components you need
2. **Use Composition API:** Better tree-shaking and performance
3. **Leverage Composables:** Reuse logic across components
4. **CSS Variables:** Fast theme changes without re-rendering
## 🐛 Troubleshooting
### Components not rendering?
Make sure you called `TT_CORE.registerComponents(app)` after creating your Vue app!
```javascript
const app = createApp({...});
TT_CORE.registerComponents(app); // ← Don't forget!
app.mount('#app');
```
### v-model not working?
Vue 3 uses `modelValue` instead of `value`. TT-Core components support both automatically.
### Composables not working?
Make sure you're using them inside `setup()` or `<script setup>`:
```vue
<script setup>
// ✅ Correct
const { data } = TT_CORE.useAsyncData();
</script>
<script>
export default {
// ❌ Wrong - can't use composables here
data() {
const { data } = TT_CORE.useAsyncData(); // Error!
}
}
</script>
```
## 📚 Additional Resources
- [Vue 3 Documentation](https://vuejs.org/)
- [Composition API Guide](https://vuejs.org/guide/extras/composition-api-faq.html)
- [Migration from Vue 2](https://v3-migration.vuejs.org/)
## 📝 License
Internal use only - TheTool Development Team
---
**Version:** 2.0.0 (Vue 3)
**Last Updated:** December 2024