@zveltio/components 1.0.0

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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/admin/ColumnList/ColumnList.svelte +68 -0
  4. package/admin/ColumnList/component.json +13 -0
  5. package/admin/MetadataSettings/MetadataSettings.svelte +62 -0
  6. package/admin/MetadataSettings/component.json +9 -0
  7. package/admin/RelationshipManager/RelationshipManager.svelte +86 -0
  8. package/admin/RelationshipManager/component.json +10 -0
  9. package/admin/RoleManager/RoleManager.svelte +167 -0
  10. package/admin/RoleManager/component.json +17 -0
  11. package/admin/TableDesigner/TableDesigner.svelte +37 -0
  12. package/admin/TableDesigner/component.json +14 -0
  13. package/ai/AIFeedback/AIFeedback.svelte +43 -0
  14. package/ai/AIInsightWidget/AIInsightWidget.svelte +56 -0
  15. package/ai/AIQueryBuilder/AIQueryBuilder.svelte +91 -0
  16. package/ai/Omnisearch/Omnisearch.svelte +112 -0
  17. package/ai/VoiceSearch/VoiceSearch.svelte +73 -0
  18. package/attachments/AttachmentManager/AttachmentManager.svelte +175 -0
  19. package/attachments/AttachmentManager/component.json +21 -0
  20. package/charts/SimpleBarChart/SimpleBarChart.svelte +28 -0
  21. package/charts/SimpleBarChart/component.json +14 -0
  22. package/common/AddressInput/AddressInput.svelte +88 -0
  23. package/common/AddressInput/component.json +12 -0
  24. package/common/Alert/Alert.svelte +20 -0
  25. package/common/Alert/component.json +15 -0
  26. package/common/Button/Button.svelte +28 -0
  27. package/common/Button/component.json +16 -0
  28. package/common/Card/Card.svelte +25 -0
  29. package/common/Card/component.json +13 -0
  30. package/common/DynamicDataTable/DynamicDataTable.svelte +84 -0
  31. package/common/DynamicDataTable/component.json +14 -0
  32. package/common/Input/Input.svelte +21 -0
  33. package/common/Input/component.json +16 -0
  34. package/common/Loading/Loading.svelte +12 -0
  35. package/common/Loading/component.json +12 -0
  36. package/common/Modal/Modal.svelte +31 -0
  37. package/common/Modal/component.json +14 -0
  38. package/common/Pagination/Pagination.svelte +40 -0
  39. package/common/Pagination/component.json +1 -0
  40. package/common/PermissionGuard/PermissionGuard.svelte +53 -0
  41. package/common/PermissionGuard/component.json +21 -0
  42. package/common/SearchableSelect/SearchableSelect.svelte +136 -0
  43. package/common/SearchableSelect/component.json +17 -0
  44. package/common/StatusBadge/StatusBadge.svelte +22 -0
  45. package/common/StatusBadge/component.json +1 -0
  46. package/dashboard/RecentActivity/RecentActivity.svelte +70 -0
  47. package/dashboard/RecentActivity/component.json +1 -0
  48. package/forms/FormField/FormField.svelte +39 -0
  49. package/forms/FormField/component.json +17 -0
  50. package/navigation/NavGroup/NavGroup.svelte +40 -0
  51. package/navigation/NavGroup/component.json +1 -0
  52. package/navigation/NavLink/NavLink.svelte +18 -0
  53. package/navigation/NavLink/component.json +15 -0
  54. package/navigation/SmartNavbar/SmartNavbar.svelte +184 -0
  55. package/navigation/SmartNavbar/component.json +20 -0
  56. package/package.json +53 -0
  57. package/pages/Settings/Settings.svelte +154 -0
  58. package/pages/Settings/component.json +11 -0
  59. package/src/lib/index.ts +53 -0
  60. package/views/ListView/ListView.svelte +19 -0
  61. package/views/ListView/component.json +13 -0
@@ -0,0 +1,39 @@
1
+ <script lang="ts">
2
+ let {
3
+ key,
4
+ label,
5
+ type = 'text',
6
+ value = $bindable(),
7
+ options = [],
8
+ error = '',
9
+ onLookupSearch = null
10
+ }: {
11
+ key: string;
12
+ label: string;
13
+ type?: string;
14
+ value?: any;
15
+ options?: Array<{value: any; label: string}>;
16
+ error?: string;
17
+ onLookupSearch?: ((query: string) => Promise<any[]>) | null;
18
+ } = $props();
19
+ </script>
20
+
21
+ <div class="form-control">
22
+ <label class="label"><span class="label-text">{label}</span></label>
23
+
24
+ {#if type === 'text' || type === 'email' || type === 'number'}
25
+ <input {type} bind:value class="input input-bordered {error ? 'input-error' : ''}" />
26
+ {:else if type === 'textarea'}
27
+ <textarea bind:value class="textarea textarea-bordered {error ? 'input-error' : ''}"></textarea>
28
+ {:else if type === 'select'}
29
+ <select bind:value class="select select-bordered {error ? 'input-error' : ''}">
30
+ {#each options as opt}
31
+ <option value={opt.value}>{opt.label}</option>
32
+ {/each}
33
+ </select>
34
+ {:else if type === 'boolean'}
35
+ <input type="checkbox" bind:checked={value} class="checkbox" />
36
+ {/if}
37
+
38
+ {#if error}<label class="label"><span class="label-text-alt text-error">{error}</span></label>{/if}
39
+ </div>
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "FormField",
3
+ "category": "forms",
4
+ "description": "FormField - Svelte 5 component",
5
+ "dependencies": {
6
+ "packages": [],
7
+ "components": []
8
+ },
9
+ "props": {
10
+ "key": "string",
11
+ "label": "string",
12
+ "type": "string",
13
+ "value": "$bindable<any>",
14
+ "options": "Array",
15
+ "error": "string"
16
+ }
17
+ }
@@ -0,0 +1,40 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ let {
5
+ children,
6
+ label,
7
+ icon = null,
8
+ collapsed = $bindable(false)
9
+ }: {
10
+ children: Snippet;
11
+ label: string;
12
+ icon?: Snippet | null;
13
+ collapsed?: boolean;
14
+ } = $props();
15
+ </script>
16
+
17
+ <div class="nav-group">
18
+ <button
19
+ class="flex items-center gap-2 w-full px-3 py-2 text-sm font-semibold opacity-70 hover:opacity-100"
20
+ onclick={() => collapsed = !collapsed}
21
+ >
22
+ {#if icon}{@render icon()}{/if}
23
+ <span class="flex-1 text-left">{label}</span>
24
+ <svg
25
+ xmlns="http://www.w3.org/2000/svg"
26
+ class="h-4 w-4 transition-transform {collapsed ? '' : 'rotate-90'}"
27
+ fill="none"
28
+ viewBox="0 0 24 24"
29
+ stroke="currentColor"
30
+ >
31
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
32
+ </svg>
33
+ </button>
34
+
35
+ {#if !collapsed}
36
+ <div class="ml-4 space-y-1">
37
+ {@render children()}
38
+ </div>
39
+ {/if}
40
+ </div>
@@ -0,0 +1 @@
1
+ {"name":"NavGroup","category":"navigation","dependencies":{"packages":[],"components":[]},"props":{}}
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ let {
3
+ href,
4
+ label,
5
+ icon = null,
6
+ active = false
7
+ }: {
8
+ href: string;
9
+ label: string;
10
+ icon?: any;
11
+ active?: boolean;
12
+ } = $props();
13
+ </script>
14
+
15
+ <a {href} class="btn btn-ghost {active ? 'btn-active' : ''}">
16
+ {#if icon}<svelte:component this={icon} size={16} />{/if}
17
+ <span>{label}</span>
18
+ </a>
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "NavLink",
3
+ "category": "navigation",
4
+ "description": "NavLink - Svelte 5 component",
5
+ "dependencies": {
6
+ "packages": [],
7
+ "components": []
8
+ },
9
+ "props": {
10
+ "href": "string",
11
+ "label": "string",
12
+ "icon": "Component",
13
+ "active": "boolean"
14
+ }
15
+ }
@@ -0,0 +1,184 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SmartNavbar - Intelligent navbar with dynamic positioning
4
+ * Positions: top, bottom, left, right
5
+ * Includes: user menu, theme switcher, logo, nav items
6
+ */
7
+ import type { Snippet } from 'svelte';
8
+
9
+ interface NavItem {
10
+ label: string;
11
+ href: string;
12
+ icon?: Snippet;
13
+ }
14
+
15
+ interface User {
16
+ name?: string;
17
+ email?: string;
18
+ avatar?: string;
19
+ }
20
+
21
+ let {
22
+ position = 'top',
23
+ user = null,
24
+ navItems = [],
25
+ logo = null,
26
+ currentTheme = 'light',
27
+ onThemeToggle,
28
+ onLogout = null,
29
+ onPositionChange = null,
30
+ isDraggable = false
31
+ }: {
32
+ position?: 'top' | 'bottom' | 'left' | 'right';
33
+ user?: User | null;
34
+ navItems?: NavItem[];
35
+ logo?: Snippet | null;
36
+ currentTheme?: string;
37
+ onThemeToggle: (theme: string) => void;
38
+ onLogout?: (() => void) | null;
39
+ onPositionChange?: ((position: string) => Promise<void>) | null;
40
+ isDraggable?: boolean;
41
+ } = $props();
42
+
43
+ let dragging = $state(false);
44
+ let showPositionMenu = $state(false);
45
+
46
+ const isHorizontal = $derived(position === 'top' || position === 'bottom');
47
+ const isVertical = $derived(position === 'left' || position === 'right');
48
+
49
+ const positionClasses = {
50
+ top: 'top-0 left-0 right-0 flex-row border-b',
51
+ bottom: 'bottom-0 left-0 right-0 flex-row border-t',
52
+ left: 'top-0 bottom-0 left-0 flex-col border-r w-64',
53
+ right: 'top-0 bottom-0 right-0 flex-col border-l w-64'
54
+ };
55
+
56
+ async function changePosition(newPos: 'top' | 'bottom' | 'left' | 'right') {
57
+ if (onPositionChange) {
58
+ await onPositionChange(newPos);
59
+ }
60
+ showPositionMenu = false;
61
+ }
62
+
63
+ function handleThemeToggle() {
64
+ const newTheme = currentTheme === 'light' ? 'dark' : 'light';
65
+ onThemeToggle(newTheme);
66
+ }
67
+ </script>
68
+
69
+ <nav
70
+ class="navbar bg-base-100 border-base-200 fixed z-50 {positionClasses[position]} {dragging ? 'opacity-50' : ''}"
71
+ class:draggable={isDraggable}
72
+ >
73
+ <!-- Logo/Brand -->
74
+ <div class="flex-none {isVertical ? 'px-4 py-3 border-b border-base-200 w-full' : ''}">
75
+ {#if logo}
76
+ {@render logo()}
77
+ {:else}
78
+ <a href="/" class="btn btn-ghost text-xl font-bold">App</a>
79
+ {/if}
80
+ </div>
81
+
82
+ <!-- Nav Items -->
83
+ {#if navItems.length > 0}
84
+ <div class="flex-1 {isVertical ? 'flex-col p-2 space-y-1' : 'px-4'}">
85
+ {#each navItems as item}
86
+ <a
87
+ href={item.href}
88
+ class="btn btn-ghost {isVertical ? 'w-full justify-start' : 'btn-sm'}"
89
+ >
90
+ {#if item.icon}
91
+ <span class="w-5 h-5">{@render item.icon()}</span>
92
+ {/if}
93
+ {item.label}
94
+ </a>
95
+ {/each}
96
+ </div>
97
+ {/if}
98
+
99
+ <!-- Actions (Theme, Position, User) -->
100
+ <div class="flex-none {isVertical ? 'p-2 border-t border-base-200 space-y-2 w-full' : 'gap-2'}">
101
+ <!-- Theme Toggle -->
102
+ <button
103
+ class="btn btn-ghost btn-circle btn-sm"
104
+ onclick={handleThemeToggle}
105
+ title="Toggle theme"
106
+ >
107
+ {#if currentTheme === 'light'}
108
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
109
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
110
+ </svg>
111
+ {:else}
112
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
113
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
114
+ </svg>
115
+ {/if}
116
+ </button>
117
+
118
+ <!-- Position Menu (if draggable) -->
119
+ {#if isDraggable && onPositionChange}
120
+ <div class="dropdown {isVertical ? 'dropdown-right' : 'dropdown-end'}">
121
+ <button
122
+ tabindex="0"
123
+ class="btn btn-ghost btn-circle btn-sm"
124
+ title="Change position"
125
+ >
126
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
127
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
128
+ </svg>
129
+ </button>
130
+ <ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-40">
131
+ <li><button onclick={() => changePosition('top')}>Top</button></li>
132
+ <li><button onclick={() => changePosition('bottom')}>Bottom</button></li>
133
+ <li><button onclick={() => changePosition('left')}>Left</button></li>
134
+ <li><button onclick={() => changePosition('right')}>Right</button></li>
135
+ </ul>
136
+ </div>
137
+ {/if}
138
+
139
+ <!-- User Menu -->
140
+ {#if user}
141
+ <div class="dropdown {isVertical ? 'dropdown-right' : 'dropdown-end'}">
142
+ <button tabindex="0" class="btn btn-ghost btn-circle avatar placeholder">
143
+ {#if user.avatar}
144
+ <div class="w-10 rounded-full">
145
+ <img src={user.avatar} alt={user.name} />
146
+ </div>
147
+ {:else}
148
+ <div class="w-10 rounded-full bg-neutral text-neutral-content">
149
+ <span class="text-sm">{user.name?.substring(0, 2).toUpperCase() || 'U'}</span>
150
+ </div>
151
+ {/if}
152
+ </button>
153
+ <ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52">
154
+ <li class="menu-title">
155
+ <span>{user.name || user.email}</span>
156
+ </li>
157
+ <li><a href="/private/profile">Profile</a></li>
158
+ <li><a href="/private/settings">Settings</a></li>
159
+ <li class="divider"></li>
160
+ {#if onLogout}
161
+ <li><button onclick={onLogout}>Logout</button></li>
162
+ {/if}
163
+ </ul>
164
+ </div>
165
+ {/if}
166
+ </div>
167
+ </nav>
168
+
169
+ <!-- Spacer to prevent content overlap -->
170
+ {#if position === 'top'}
171
+ <div class="h-16"></div>
172
+ {:else if position === 'bottom'}
173
+ <div class="h-16"></div>
174
+ {:else if position === 'left'}
175
+ <div class="w-64 flex-shrink-0"></div>
176
+ {:else if position === 'right'}
177
+ <div class="w-64 flex-shrink-0"></div>
178
+ {/if}
179
+
180
+ <style>
181
+ .draggable {
182
+ cursor: move;
183
+ }
184
+ </style>
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "SmartNavbar",
3
+ "category": "navigation",
4
+ "description": "Intelligent navbar with dynamic positioning (top/bottom/left/right), user menu, and theme switcher",
5
+ "dependencies": {
6
+ "packages": [],
7
+ "components": []
8
+ },
9
+ "props": {
10
+ "position": "'top'|'bottom'|'left'|'right' - Navbar position",
11
+ "user": "{name?, email?, avatar?} - Current user",
12
+ "navItems": "Array<{label, href, icon?}> - Navigation items",
13
+ "logo": "Snippet - Custom logo",
14
+ "currentTheme": "string - Current theme",
15
+ "onThemeToggle": "(theme: string) => void - Theme change callback",
16
+ "onLogout": "(() => void) | null - Logout callback",
17
+ "onPositionChange": "((position: string) => Promise<void>) | null - Position change callback",
18
+ "isDraggable": "boolean - Enable position menu"
19
+ }
20
+ }
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@zveltio/components",
3
+ "version": "1.0.0",
4
+ "description": "Official Zveltio UI component library — Svelte 5 + DaisyUI/Tailwind",
5
+ "type": "module",
6
+ "svelte": "./src/lib/index.ts",
7
+ "types": "./src/lib/index.ts",
8
+ "exports": {
9
+ ".": {
10
+ "svelte": "./src/lib/index.ts",
11
+ "types": "./src/lib/index.ts",
12
+ "import": "./src/lib/index.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "src",
17
+ "admin",
18
+ "ai",
19
+ "attachments",
20
+ "charts",
21
+ "common",
22
+ "dashboard",
23
+ "forms",
24
+ "navigation",
25
+ "pages",
26
+ "views"
27
+ ],
28
+ "scripts": {
29
+ "check": "svelte-check --tsconfig ./tsconfig.json"
30
+ },
31
+ "peerDependencies": {
32
+ "svelte": "^5.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "svelte": "^5.0.0",
36
+ "svelte-check": "^4.0.0",
37
+ "typescript": "^5.4.0"
38
+ },
39
+ "keywords": [
40
+ "svelte",
41
+ "svelte5",
42
+ "zveltio",
43
+ "components",
44
+ "ui",
45
+ "daisy",
46
+ "tailwind"
47
+ ],
48
+ "license": "MIT",
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/liviumarianiordache/zveltio-components.git"
52
+ }
53
+ }
@@ -0,0 +1,154 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SettingsPage - User preferences management
4
+ * Handles: theme, navbar position, display preferences
5
+ */
6
+ interface Preferences {
7
+ theme?: string;
8
+ navbar_position?: 'top' | 'bottom' | 'left' | 'right';
9
+ nav_collapsed?: boolean;
10
+ }
11
+
12
+ let {
13
+ preferences = $bindable<Preferences>({}),
14
+ onSave,
15
+ saving = false
16
+ }: {
17
+ preferences?: Preferences;
18
+ onSave: (prefs: Preferences) => Promise<void>;
19
+ saving?: boolean;
20
+ } = $props();
21
+
22
+ let localPrefs = $state<Preferences>({ ...preferences });
23
+ let hasChanges = $derived(
24
+ JSON.stringify(localPrefs) !== JSON.stringify(preferences)
25
+ );
26
+
27
+ async function handleSave() {
28
+ await onSave(localPrefs);
29
+ }
30
+
31
+ function handleReset() {
32
+ localPrefs = { ...preferences };
33
+ }
34
+ </script>
35
+
36
+ <div class="max-w-4xl mx-auto space-y-6">
37
+ <div>
38
+ <h1 class="text-3xl font-bold">Settings</h1>
39
+ <p class="text-sm opacity-60 mt-1">Manage your account preferences</p>
40
+ </div>
41
+
42
+ <!-- Appearance Section -->
43
+ <div class="card bg-base-100 border border-base-200">
44
+ <div class="card-body">
45
+ <h2 class="card-title">Appearance</h2>
46
+
47
+ <div class="form-control">
48
+ <label class="label">
49
+ <span class="label-text">Theme</span>
50
+ </label>
51
+ <select bind:value={localPrefs.theme} class="select select-bordered">
52
+ <option value="light">Light</option>
53
+ <option value="dark">Dark</option>
54
+ <option value="auto">Auto (System)</option>
55
+ </select>
56
+ </div>
57
+
58
+ <div class="form-control mt-4">
59
+ <label class="label">
60
+ <span class="label-text">Navbar Position</span>
61
+ </label>
62
+ <div class="grid grid-cols-2 gap-3">
63
+ {#each ['top', 'bottom', 'left', 'right'] as pos}
64
+ <label class="cursor-pointer">
65
+ <input
66
+ type="radio"
67
+ bind:group={localPrefs.navbar_position}
68
+ value={pos}
69
+ class="radio radio-primary"
70
+ />
71
+ <span class="ml-2 capitalize">{pos}</span>
72
+ </label>
73
+ {/each}
74
+ </div>
75
+ <label class="label">
76
+ <span class="label-text-alt">Changes apply immediately after saving</span>
77
+ </label>
78
+ </div>
79
+ </div>
80
+ </div>
81
+
82
+ <!-- Navigation Section -->
83
+ <div class="card bg-base-100 border border-base-200">
84
+ <div class="card-body">
85
+ <h2 class="card-title">Navigation</h2>
86
+
87
+ <div class="form-control">
88
+ <label class="label cursor-pointer justify-start gap-3">
89
+ <input
90
+ type="checkbox"
91
+ bind:checked={localPrefs.nav_collapsed}
92
+ class="toggle toggle-primary"
93
+ />
94
+ <span class="label-text">Collapse sidebar by default</span>
95
+ </label>
96
+ </div>
97
+ </div>
98
+ </div>
99
+
100
+ <!-- Preview Section -->
101
+ <div class="card bg-base-100 border border-base-200">
102
+ <div class="card-body">
103
+ <h2 class="card-title">Preview</h2>
104
+ <div class="relative h-40 bg-base-200 rounded-lg overflow-hidden">
105
+ <!-- Navbar Preview -->
106
+ {#if localPrefs.navbar_position === 'top'}
107
+ <div class="absolute top-0 left-0 right-0 h-12 bg-primary flex items-center justify-center text-primary-content text-xs">
108
+ Navbar (Top)
109
+ </div>
110
+ {:else if localPrefs.navbar_position === 'bottom'}
111
+ <div class="absolute bottom-0 left-0 right-0 h-12 bg-primary flex items-center justify-center text-primary-content text-xs">
112
+ Navbar (Bottom)
113
+ </div>
114
+ {:else if localPrefs.navbar_position === 'left'}
115
+ <div class="absolute top-0 bottom-0 left-0 w-16 bg-primary flex items-center justify-center text-primary-content text-xs writing-vertical">
116
+ <span class="rotate-90">Navbar</span>
117
+ </div>
118
+ {:else if localPrefs.navbar_position === 'right'}
119
+ <div class="absolute top-0 bottom-0 right-0 w-16 bg-primary flex items-center justify-center text-primary-content text-xs">
120
+ <span class="rotate-90">Navbar</span>
121
+ </div>
122
+ {/if}
123
+
124
+ <!-- Content Area -->
125
+ <div class="absolute inset-0 flex items-center justify-center text-xs opacity-50">
126
+ Content Area
127
+ </div>
128
+ </div>
129
+ </div>
130
+ </div>
131
+
132
+ <!-- Actions -->
133
+ <div class="flex justify-end gap-3 sticky bottom-4 bg-base-100 p-4 rounded-lg shadow-lg border border-base-200">
134
+ <button
135
+ class="btn btn-ghost"
136
+ onclick={handleReset}
137
+ disabled={!hasChanges || saving}
138
+ >
139
+ Reset
140
+ </button>
141
+ <button
142
+ class="btn btn-primary"
143
+ onclick={handleSave}
144
+ disabled={!hasChanges || saving}
145
+ >
146
+ {#if saving}
147
+ <span class="loading loading-spinner loading-sm"></span>
148
+ Saving...
149
+ {:else}
150
+ Save Changes
151
+ {/if}
152
+ </button>
153
+ </div>
154
+ </div>
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "Settings",
3
+ "category": "pages",
4
+ "description": "User preferences management page (theme, navbar position, navigation)",
5
+ "dependencies": {"packages": [], "components": []},
6
+ "props": {
7
+ "preferences": "$bindable<{theme?, navbar_position?, nav_collapsed?}>",
8
+ "onSave": "(prefs: Preferences) => Promise<void>",
9
+ "saving": "boolean"
10
+ }
11
+ }
@@ -0,0 +1,53 @@
1
+ // @zveltio/components — Official Zveltio UI component library
2
+ // Svelte 5 + DaisyUI/Tailwind
3
+
4
+ // ── Admin ─────────────────────────────────────────────────────────────────
5
+ export { default as ColumnList } from '../../admin/ColumnList/ColumnList.svelte';
6
+ export { default as MetadataSettings } from '../../admin/MetadataSettings/MetadataSettings.svelte';
7
+ export { default as RelationshipManager } from '../../admin/RelationshipManager/RelationshipManager.svelte';
8
+ export { default as RoleManager } from '../../admin/RoleManager/RoleManager.svelte';
9
+ export { default as TableDesigner } from '../../admin/TableDesigner/TableDesigner.svelte';
10
+
11
+ // ── AI ────────────────────────────────────────────────────────────────────
12
+ export { default as AIFeedback } from '../../ai/AIFeedback/AIFeedback.svelte';
13
+ export { default as AIInsightWidget } from '../../ai/AIInsightWidget/AIInsightWidget.svelte';
14
+ export { default as AIQueryBuilder } from '../../ai/AIQueryBuilder/AIQueryBuilder.svelte';
15
+ export { default as Omnisearch } from '../../ai/Omnisearch/Omnisearch.svelte';
16
+ export { default as VoiceSearch } from '../../ai/VoiceSearch/VoiceSearch.svelte';
17
+
18
+ // ── Attachments ───────────────────────────────────────────────────────────
19
+ export { default as AttachmentManager } from '../../attachments/AttachmentManager/AttachmentManager.svelte';
20
+
21
+ // ── Charts ────────────────────────────────────────────────────────────────
22
+ export { default as SimpleBarChart } from '../../charts/SimpleBarChart/SimpleBarChart.svelte';
23
+
24
+ // ── Common ────────────────────────────────────────────────────────────────
25
+ export { default as AddressInput } from '../../common/AddressInput/AddressInput.svelte';
26
+ export { default as Alert } from '../../common/Alert/Alert.svelte';
27
+ export { default as Button } from '../../common/Button/Button.svelte';
28
+ export { default as Card } from '../../common/Card/Card.svelte';
29
+ export { default as DynamicDataTable } from '../../common/DynamicDataTable/DynamicDataTable.svelte';
30
+ export { default as Input } from '../../common/Input/Input.svelte';
31
+ export { default as Loading } from '../../common/Loading/Loading.svelte';
32
+ export { default as Modal } from '../../common/Modal/Modal.svelte';
33
+ export { default as Pagination } from '../../common/Pagination/Pagination.svelte';
34
+ export { default as PermissionGuard } from '../../common/PermissionGuard/PermissionGuard.svelte';
35
+ export { default as SearchableSelect } from '../../common/SearchableSelect/SearchableSelect.svelte';
36
+ export { default as StatusBadge } from '../../common/StatusBadge/StatusBadge.svelte';
37
+
38
+ // ── Dashboard ─────────────────────────────────────────────────────────────
39
+ export { default as RecentActivity } from '../../dashboard/RecentActivity/RecentActivity.svelte';
40
+
41
+ // ── Forms ─────────────────────────────────────────────────────────────────
42
+ export { default as FormField } from '../../forms/FormField/FormField.svelte';
43
+
44
+ // ── Navigation ────────────────────────────────────────────────────────────
45
+ export { default as NavGroup } from '../../navigation/NavGroup/NavGroup.svelte';
46
+ export { default as NavLink } from '../../navigation/NavLink/NavLink.svelte';
47
+ export { default as SmartNavbar } from '../../navigation/SmartNavbar/SmartNavbar.svelte';
48
+
49
+ // ── Pages ─────────────────────────────────────────────────────────────────
50
+ export { default as Settings } from '../../pages/Settings/Settings.svelte';
51
+
52
+ // ── Views ─────────────────────────────────────────────────────────────────
53
+ export { default as ListView } from '../../views/ListView/ListView.svelte';
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ let {
3
+ items = [],
4
+ onRowClick = null
5
+ }: {
6
+ items: any[];
7
+ onRowClick?: ((item: any) => void) | null;
8
+ } = $props();
9
+ </script>
10
+
11
+ <div class="space-y-2">
12
+ {#each items as item}
13
+ <div class="card bg-base-100 shadow cursor-pointer hover:shadow-lg transition" onclick={() => onRowClick?.(item)}>
14
+ <div class="card-body p-4">
15
+ <pre class="text-xs">{JSON.stringify(item, null, 2)}</pre>
16
+ </div>
17
+ </div>
18
+ {/each}
19
+ </div>
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "ListView",
3
+ "category": "views",
4
+ "description": "ListView - Svelte 5 component",
5
+ "dependencies": {
6
+ "packages": [],
7
+ "components": []
8
+ },
9
+ "props": {
10
+ "items": "Array",
11
+ "onRowClick": "function"
12
+ }
13
+ }