@indexeddb-orm/idb-orm 0.0.1
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.
- package/.vscode/extensions.json +5 -0
- package/README.md +1280 -0
- package/angular-demo-app/README.md +84 -0
- package/angular-demo-app/angular.json +109 -0
- package/angular-demo-app/package-lock.json +14215 -0
- package/angular-demo-app/package.json +41 -0
- package/angular-demo-app/src/app/app.component.ts +481 -0
- package/angular-demo-app/src/app/app.routes.ts +8 -0
- package/angular-demo-app/src/app/components/actions.component.ts +202 -0
- package/angular-demo-app/src/app/components/cloud-sync-demo.component.ts +296 -0
- package/angular-demo-app/src/app/components/live-query-demo.component.ts +307 -0
- package/angular-demo-app/src/app/components/main-info.component.ts +148 -0
- package/angular-demo-app/src/app/components/posts-live-query-demo.component.ts +336 -0
- package/angular-demo-app/src/app/components/typescript-demo.component.ts +268 -0
- package/angular-demo-app/src/entities/post-tag.entity.ts +25 -0
- package/angular-demo-app/src/entities/post.entity.ts +49 -0
- package/angular-demo-app/src/entities/profile.entity.ts +42 -0
- package/angular-demo-app/src/entities/tag.entity.ts +36 -0
- package/angular-demo-app/src/entities/user.entity.ts +59 -0
- package/angular-demo-app/src/favicon.ico +1 -0
- package/angular-demo-app/src/index.html +16 -0
- package/angular-demo-app/src/main.ts +13 -0
- package/angular-demo-app/src/services/app-logic.service.ts +449 -0
- package/angular-demo-app/src/services/cloud-sync.service.ts +95 -0
- package/angular-demo-app/src/services/database.service.ts +26 -0
- package/angular-demo-app/src/services/live-query.service.ts +63 -0
- package/angular-demo-app/src/services/posts-live-query.service.ts +86 -0
- package/angular-demo-app/src/services/typescript-demo.service.ts +59 -0
- package/angular-demo-app/src/styles.scss +50 -0
- package/angular-demo-app/tsconfig.app.json +13 -0
- package/angular-demo-app/tsconfig.json +34 -0
- package/angular-demo-app/tsconfig.spec.json +13 -0
- package/dist/Database.d.ts +206 -0
- package/dist/Database.js +288 -0
- package/dist/decorators/Column.d.ts +79 -0
- package/dist/decorators/Column.js +236 -0
- package/dist/decorators/Entity.d.ts +32 -0
- package/dist/decorators/Entity.js +44 -0
- package/dist/decorators/Relation.d.ts +70 -0
- package/dist/decorators/Relation.js +120 -0
- package/dist/decorators/index.d.ts +3 -0
- package/dist/decorators/index.js +3 -0
- package/dist/errors/ValidationError.d.ts +4 -0
- package/dist/errors/ValidationError.js +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +7 -0
- package/dist/metadata/Column.d.ts +8 -0
- package/dist/metadata/Column.js +44 -0
- package/dist/metadata/Entity.d.ts +11 -0
- package/dist/metadata/Entity.js +21 -0
- package/dist/metadata/Relation.d.ts +20 -0
- package/dist/metadata/Relation.js +74 -0
- package/dist/metadata/index.d.ts +3 -0
- package/dist/metadata/index.js +3 -0
- package/dist/services/AggregationService.d.ts +38 -0
- package/dist/services/AggregationService.js +229 -0
- package/dist/services/BaseEntity.d.ts +32 -0
- package/dist/services/BaseEntity.js +62 -0
- package/dist/services/CloudSyncService.d.ts +100 -0
- package/dist/services/CloudSyncService.js +196 -0
- package/dist/services/DecoratorUtils.d.ts +12 -0
- package/dist/services/DecoratorUtils.js +10 -0
- package/dist/services/EntityFactory.d.ts +25 -0
- package/dist/services/EntityFactory.js +27 -0
- package/dist/services/EntityRegistry.d.ts +61 -0
- package/dist/services/EntityRegistry.js +56 -0
- package/dist/services/EntitySchema.d.ts +56 -0
- package/dist/services/EntitySchema.js +125 -0
- package/dist/services/MigrationManager.d.ts +70 -0
- package/dist/services/MigrationManager.js +181 -0
- package/dist/services/RelationLoader.d.ts +66 -0
- package/dist/services/RelationLoader.js +310 -0
- package/dist/services/SchemaBuilder.d.ts +68 -0
- package/dist/services/SchemaBuilder.js +191 -0
- package/dist/services/index.d.ts +7 -0
- package/dist/services/index.js +7 -0
- package/dist/types.d.ts +152 -0
- package/dist/types.js +1 -0
- package/dist/utils/logger.d.ts +12 -0
- package/dist/utils/logger.js +16 -0
- package/eslint.config.js +49 -0
- package/homepage/favicon.svg +36 -0
- package/homepage/index.html +1725 -0
- package/package.json +78 -0
- package/react-demo-app/README.md +61 -0
- package/react-demo-app/eslint.config.js +60 -0
- package/react-demo-app/index.html +13 -0
- package/react-demo-app/package-lock.json +4955 -0
- package/react-demo-app/package.json +39 -0
- package/react-demo-app/src/App.tsx +172 -0
- package/react-demo-app/src/assets/react.svg +1 -0
- package/react-demo-app/src/components/Actions.tsx +171 -0
- package/react-demo-app/src/components/CloudSyncDemo.tsx +191 -0
- package/react-demo-app/src/components/LiveQueryDemo.tsx +122 -0
- package/react-demo-app/src/components/MainInfo.tsx +75 -0
- package/react-demo-app/src/components/PostsLiveQueryDemo.tsx +185 -0
- package/react-demo-app/src/components/TypeScriptDemo.tsx +190 -0
- package/react-demo-app/src/database/Database.ts +30 -0
- package/react-demo-app/src/entities/Post.ts +48 -0
- package/react-demo-app/src/entities/PostTag.ts +26 -0
- package/react-demo-app/src/entities/Profile.ts +41 -0
- package/react-demo-app/src/entities/Tag.ts +35 -0
- package/react-demo-app/src/entities/User.ts +61 -0
- package/react-demo-app/src/hooks/useAppLogic.ts +565 -0
- package/react-demo-app/src/hooks/useCloudSyncDemo.ts +84 -0
- package/react-demo-app/src/hooks/useLiveQueryDemo.ts +68 -0
- package/react-demo-app/src/hooks/usePostsLiveQueryDemo.ts +64 -0
- package/react-demo-app/src/hooks/useTypeScriptDemo.ts +43 -0
- package/react-demo-app/src/index.css +26 -0
- package/react-demo-app/src/main.tsx +18 -0
- package/react-demo-app/src/migrations/001-add-user-email-index.ts +17 -0
- package/react-demo-app/src/migrations/002-add-post-category.ts +37 -0
- package/react-demo-app/src/migrations/index.ts +8 -0
- package/react-demo-app/src/vite-env.d.ts +1 -0
- package/react-demo-app/tsconfig.app.json +22 -0
- package/react-demo-app/tsconfig.json +6 -0
- package/react-demo-app/vite.config.ts +10 -0
- package/src/Database.ts +405 -0
- package/src/errors/ValidationError.ts +9 -0
- package/src/index.ts +13 -0
- package/src/metadata/Column.ts +74 -0
- package/src/metadata/Entity.ts +42 -0
- package/src/metadata/Relation.ts +121 -0
- package/src/metadata/index.ts +5 -0
- package/src/services/AggregationService.ts +348 -0
- package/src/services/BaseEntity.ts +77 -0
- package/src/services/CloudSyncService.ts +248 -0
- package/src/services/EntityFactory.ts +35 -0
- package/src/services/EntityRegistry.ts +109 -0
- package/src/services/EntitySchema.ts +154 -0
- package/src/services/MigrationManager.ts +276 -0
- package/src/services/RelationLoader.ts +532 -0
- package/src/services/SchemaBuilder.ts +237 -0
- package/src/services/index.ts +7 -0
- package/src/types.d.ts +1 -0
- package/src/types.ts +169 -0
- package/src/utils/logger.ts +40 -0
- package/svelte-demo-app/README.md +61 -0
- package/svelte-demo-app/package-lock.json +3000 -0
- package/svelte-demo-app/package.json +30 -0
- package/svelte-demo-app/src/app.d.ts +12 -0
- package/svelte-demo-app/src/app.html +13 -0
- package/svelte-demo-app/src/components/Actions.svelte +121 -0
- package/svelte-demo-app/src/components/CloudSyncDemo.svelte +333 -0
- package/svelte-demo-app/src/components/LiveQueryDemo.svelte +191 -0
- package/svelte-demo-app/src/components/MainInfo.svelte +133 -0
- package/svelte-demo-app/src/components/PostsLiveQueryDemo.svelte +330 -0
- package/svelte-demo-app/src/components/TypeScriptDemo.svelte +251 -0
- package/svelte-demo-app/src/database/Database.ts +29 -0
- package/svelte-demo-app/src/entities/Post.ts +46 -0
- package/svelte-demo-app/src/entities/PostTag.ts +22 -0
- package/svelte-demo-app/src/entities/Profile.ts +39 -0
- package/svelte-demo-app/src/entities/Tag.ts +33 -0
- package/svelte-demo-app/src/entities/User.ts +62 -0
- package/svelte-demo-app/src/lib/database/Database.ts +30 -0
- package/svelte-demo-app/src/lib/entities/Post.ts +47 -0
- package/svelte-demo-app/src/lib/entities/PostTag.ts +23 -0
- package/svelte-demo-app/src/lib/entities/Profile.ts +40 -0
- package/svelte-demo-app/src/lib/entities/Tag.ts +34 -0
- package/svelte-demo-app/src/lib/entities/User.ts +59 -0
- package/svelte-demo-app/src/lib/index.ts +7 -0
- package/svelte-demo-app/src/lib/migrations/001-add-user-email-index.ts +17 -0
- package/svelte-demo-app/src/lib/migrations/002-add-post-category.ts +37 -0
- package/svelte-demo-app/src/lib/migrations/index.ts +8 -0
- package/svelte-demo-app/src/migrations/001-add-user-email-index.ts +17 -0
- package/svelte-demo-app/src/migrations/002-add-post-category.ts +37 -0
- package/svelte-demo-app/src/migrations/index.ts +8 -0
- package/svelte-demo-app/src/routes/+layout.js +3 -0
- package/svelte-demo-app/src/routes/+layout.svelte +228 -0
- package/svelte-demo-app/src/routes/+page.js +3 -0
- package/svelte-demo-app/src/routes/+page.svelte +1305 -0
- package/svelte-demo-app/src/stores/appStore.js +603 -0
- package/svelte-demo-app/svelte.config.js +18 -0
- package/svelte-demo-app/tsconfig.json +14 -0
- package/svelte-demo-app/vite.config.ts +6 -0
- package/tests/aggregation.e2e.test.ts +87 -0
- package/tests/base-entity.e2e.test.ts +47 -0
- package/tests/database-api.e2e.test.ts +177 -0
- package/tests/decorators.e2e.test.ts +40 -0
- package/tests/entity-schema.e2e.test.ts +58 -0
- package/tests/relation-loader-table-names.test.ts +192 -0
- package/tests/relations.e2e.test.ts +178 -0
- package/tests/zod-runtime.e2e.test.ts +69 -0
- package/tsconfig.json +21 -0
- package/vitest.config.ts +21 -0
- package/vitest.setup.ts +27 -0
- package/vue-demo-app/README.md +61 -0
- package/vue-demo-app/index.html +13 -0
- package/vue-demo-app/package-lock.json +1537 -0
- package/vue-demo-app/package.json +27 -0
- package/vue-demo-app/src/App.vue +100 -0
- package/vue-demo-app/src/components/Actions.vue +135 -0
- package/vue-demo-app/src/components/CloudSyncDemo.vue +139 -0
- package/vue-demo-app/src/components/LiveQueryDemo.vue +122 -0
- package/vue-demo-app/src/components/MainInfo.vue +80 -0
- package/vue-demo-app/src/components/PostsLiveQueryDemo.vue +136 -0
- package/vue-demo-app/src/components/TypeScriptDemo.vue +133 -0
- package/vue-demo-app/src/database/Database.ts +29 -0
- package/vue-demo-app/src/entities/Post.ts +48 -0
- package/vue-demo-app/src/entities/PostTag.ts +24 -0
- package/vue-demo-app/src/entities/Profile.ts +41 -0
- package/vue-demo-app/src/entities/Tag.ts +35 -0
- package/vue-demo-app/src/entities/User.ts +61 -0
- package/vue-demo-app/src/main.ts +29 -0
- package/vue-demo-app/src/migrations/001-add-user-email-index.ts +23 -0
- package/vue-demo-app/src/migrations/002-add-post-category.ts +46 -0
- package/vue-demo-app/src/migrations/index.ts +14 -0
- package/vue-demo-app/src/services/useAppLogic.ts +565 -0
- package/vue-demo-app/src/services/useCloudSyncDemo.ts +84 -0
- package/vue-demo-app/src/services/useLiveQueryDemo.ts +82 -0
- package/vue-demo-app/src/services/usePostsLiveQueryDemo.ts +77 -0
- package/vue-demo-app/src/services/useTypeScriptDemo.ts +56 -0
- package/vue-demo-app/src/vite-env.d.ts +1 -0
- package/vue-demo-app/tsconfig.json +25 -0
- package/vue-demo-app/tsconfig.node.json +10 -0
- package/vue-demo-app/vite.config.ts +16 -0
|
@@ -0,0 +1,1305 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import { page } from '$app/stores';
|
|
4
|
+
import { getContext } from 'svelte';
|
|
5
|
+
import { db } from '$lib/database/Database';
|
|
6
|
+
import { newEntity } from 'idb-orm';
|
|
7
|
+
import { UserEntity } from '$lib/entities/User';
|
|
8
|
+
import { PostEntity } from '$lib/entities/Post';
|
|
9
|
+
import { ProfileEntity } from '$lib/entities/Profile';
|
|
10
|
+
|
|
11
|
+
// Get stores from layout
|
|
12
|
+
const users = getContext('users');
|
|
13
|
+
const tabIndex = getContext('tabIndex');
|
|
14
|
+
const mobileOpen = getContext('mobileOpen');
|
|
15
|
+
const syncStatus = getContext('syncStatus');
|
|
16
|
+
const userStats = getContext('userStats');
|
|
17
|
+
const allUsers = getContext('allUsers');
|
|
18
|
+
const allPosts = getContext('allPosts');
|
|
19
|
+
const allProfiles = getContext('allProfiles');
|
|
20
|
+
const postStats = getContext('postStats');
|
|
21
|
+
|
|
22
|
+
// Get functions from layout
|
|
23
|
+
const setTabIndex = getContext('setTabIndex');
|
|
24
|
+
const toggleMobileOpen = getContext('toggleMobileOpen');
|
|
25
|
+
const loadUsers = getContext('loadUsers');
|
|
26
|
+
const addUser = getContext('addUser');
|
|
27
|
+
const testZodValidation = getContext('testZodValidation');
|
|
28
|
+
const testSchemaMigration = getContext('testSchemaMigration');
|
|
29
|
+
const toggleAutoReset = getContext('toggleAutoReset');
|
|
30
|
+
const testRelations = getContext('testRelations');
|
|
31
|
+
const testTransactions = getContext('testTransactions');
|
|
32
|
+
const testCompoundIndexes = getContext('testCompoundIndexes');
|
|
33
|
+
const testAggregations = getContext('testAggregations');
|
|
34
|
+
const clearAll = getContext('clearAll');
|
|
35
|
+
|
|
36
|
+
// Tabs configuration
|
|
37
|
+
const tabs = [
|
|
38
|
+
{ key: 'admin', label: 'Admin' },
|
|
39
|
+
{ key: 'cloud-sync', label: 'Cloud Sync' }
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
// Initialize data on mount
|
|
43
|
+
onMount(async () => {
|
|
44
|
+
await loadUsers();
|
|
45
|
+
});
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<!-- Material-UI App Bar -->
|
|
49
|
+
<header class="app-bar">
|
|
50
|
+
<div class="toolbar">
|
|
51
|
+
<button
|
|
52
|
+
class="mobile-menu-button"
|
|
53
|
+
on:click={toggleMobileOpen}
|
|
54
|
+
aria-label="open drawer"
|
|
55
|
+
>
|
|
56
|
+
<svg class="menu-icon" viewBox="0 0 24 24">
|
|
57
|
+
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/>
|
|
58
|
+
</svg>
|
|
59
|
+
</button>
|
|
60
|
+
<h1 class="title">Dexie ORM Demo</h1>
|
|
61
|
+
</div>
|
|
62
|
+
</header>
|
|
63
|
+
|
|
64
|
+
<div class="main-layout">
|
|
65
|
+
<!-- Mobile Drawer -->
|
|
66
|
+
<div class="mobile-drawer" class:open={$mobileOpen}>
|
|
67
|
+
<nav class="drawer-content">
|
|
68
|
+
<ul class="nav-list">
|
|
69
|
+
{#each tabs as tab, index}
|
|
70
|
+
<li>
|
|
71
|
+
<button
|
|
72
|
+
class="nav-item"
|
|
73
|
+
class:active={$tabIndex === index}
|
|
74
|
+
on:click={() => {
|
|
75
|
+
setTabIndex(index);
|
|
76
|
+
toggleMobileOpen();
|
|
77
|
+
}}
|
|
78
|
+
>
|
|
79
|
+
{tab.label}
|
|
80
|
+
</button>
|
|
81
|
+
</li>
|
|
82
|
+
{/each}
|
|
83
|
+
</ul>
|
|
84
|
+
</nav>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<!-- Desktop Drawer -->
|
|
88
|
+
<aside class="desktop-drawer">
|
|
89
|
+
<nav class="drawer-content">
|
|
90
|
+
<ul class="nav-list">
|
|
91
|
+
{#each tabs as tab, index}
|
|
92
|
+
<li>
|
|
93
|
+
<button
|
|
94
|
+
class="nav-item"
|
|
95
|
+
class:active={$tabIndex === index}
|
|
96
|
+
on:click={() => setTabIndex(index)}
|
|
97
|
+
>
|
|
98
|
+
{tab.label}
|
|
99
|
+
</button>
|
|
100
|
+
</li>
|
|
101
|
+
{/each}
|
|
102
|
+
</ul>
|
|
103
|
+
</nav>
|
|
104
|
+
</aside>
|
|
105
|
+
|
|
106
|
+
<!-- Main Content -->
|
|
107
|
+
<main class="main-content">
|
|
108
|
+
{#if $tabIndex === 0}
|
|
109
|
+
<!-- Admin Tab Content - 1:1 with React -->
|
|
110
|
+
<div class="tab-content">
|
|
111
|
+
<!-- Main Info - Material-UI Paper -->
|
|
112
|
+
<div class="main-info">
|
|
113
|
+
<div class="info-card">
|
|
114
|
+
<div class="info-header">
|
|
115
|
+
<svg class="info-icon" viewBox="0 0 24 24">
|
|
116
|
+
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
|
|
117
|
+
</svg>
|
|
118
|
+
<h2>Dexie ORM for IndexedDB — Overview</h2>
|
|
119
|
+
</div>
|
|
120
|
+
<p class="info-description">
|
|
121
|
+
TypeScript ORM built on the latest Dexie 4 with first-class type safety and Zod runtime validation.
|
|
122
|
+
</p>
|
|
123
|
+
<div class="info-features">
|
|
124
|
+
<div class="feature">
|
|
125
|
+
<svg class="feature-icon" viewBox="0 0 24 24">
|
|
126
|
+
<path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0L19.2 12l-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/>
|
|
127
|
+
</svg>
|
|
128
|
+
<span><strong>Entity config</strong> via defineEntity()</span>
|
|
129
|
+
</div>
|
|
130
|
+
<div class="feature">
|
|
131
|
+
<svg class="feature-icon" viewBox="0 0 24 24">
|
|
132
|
+
<path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9H9V9h10v2zm-4 4H9v-2h6v2zm4-8H9V5h10v2z"/>
|
|
133
|
+
</svg>
|
|
134
|
+
<span><strong>Automatic schema</strong> with PK, indexes, unique</span>
|
|
135
|
+
</div>
|
|
136
|
+
<div class="feature">
|
|
137
|
+
<svg class="feature-icon" viewBox="0 0 24 24">
|
|
138
|
+
<path d="M16 4c0-1.11.89-2 2-2s2 .89 2 2-.89 2-2 2-2-.89-2-2zm4 18v-6h2.5l-2.54-7.63A1.5 1.5 0 0 0 18.54 7H16c-.8 0-1.54.5-1.85 1.26L12.5 14H10v8h2v-6h2.5l2.5 6H20zM12.5 11.5c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5S11 9.17 11 10s.67 1.5 1.5 1.5z"/>
|
|
139
|
+
</svg>
|
|
140
|
+
<span><strong>Relations</strong> with helpers</span>
|
|
141
|
+
</div>
|
|
142
|
+
<div class="feature">
|
|
143
|
+
<svg class="feature-icon" viewBox="0 0 24 24">
|
|
144
|
+
<path d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/>
|
|
145
|
+
</svg>
|
|
146
|
+
<span><strong>Zod validation</strong> at runtime</span>
|
|
147
|
+
</div>
|
|
148
|
+
<div class="feature">
|
|
149
|
+
<svg class="feature-icon" viewBox="0 0 24 24">
|
|
150
|
+
<path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/>
|
|
151
|
+
</svg>
|
|
152
|
+
<span><strong>Aggregations</strong> (count, avg, sum)</span>
|
|
153
|
+
</div>
|
|
154
|
+
<div class="feature">
|
|
155
|
+
<svg class="feature-icon" viewBox="0 0 24 24">
|
|
156
|
+
<path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/>
|
|
157
|
+
</svg>
|
|
158
|
+
<span><strong>Live queries</strong> with useLiveQuery()</span>
|
|
159
|
+
</div>
|
|
160
|
+
<div class="feature">
|
|
161
|
+
<svg class="feature-icon" viewBox="0 0 24 24">
|
|
162
|
+
<path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4z"/>
|
|
163
|
+
</svg>
|
|
164
|
+
<span><strong>TypeScript</strong> full type safety</span>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="feature">
|
|
167
|
+
<svg class="feature-icon" viewBox="0 0 24 24">
|
|
168
|
+
<path d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z"/>
|
|
169
|
+
</svg>
|
|
170
|
+
<span><strong>Cloud sync</strong> with Dexie Cloud</span>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
<div class="info-button-section">
|
|
174
|
+
<button class="info-button">
|
|
175
|
+
<svg class="button-icon" viewBox="0 0 24 24">
|
|
176
|
+
<path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/>
|
|
177
|
+
</svg>
|
|
178
|
+
View full documentation
|
|
179
|
+
</button>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
|
|
184
|
+
<!-- Admin Actions - 1:1 z React Material-UI -->
|
|
185
|
+
<div class="admin-section">
|
|
186
|
+
<h2 class="admin-title">Admin Actions</h2>
|
|
187
|
+
<div class="actions-grid">
|
|
188
|
+
<button class="action-button outlined" on:click={addUser}>
|
|
189
|
+
<svg class="action-icon" viewBox="0 0 24 24">
|
|
190
|
+
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
|
|
191
|
+
</svg>
|
|
192
|
+
Add User
|
|
193
|
+
</button>
|
|
194
|
+
|
|
195
|
+
<button class="action-button outlined" on:click={testZodValidation}>
|
|
196
|
+
<svg class="action-icon" viewBox="0 0 24 24">
|
|
197
|
+
<path d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/>
|
|
198
|
+
</svg>
|
|
199
|
+
Test Zod
|
|
200
|
+
</button>
|
|
201
|
+
|
|
202
|
+
<button class="action-button outlined" on:click={testSchemaMigration}>
|
|
203
|
+
<svg class="action-icon" viewBox="0 0 24 24">
|
|
204
|
+
<path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9H9V9h10v2zm-4 4H9v-2h6v2zm4-8H9V5h10v2z"/>
|
|
205
|
+
</svg>
|
|
206
|
+
Schema
|
|
207
|
+
</button>
|
|
208
|
+
|
|
209
|
+
<button class="action-button outlined" on:click={toggleAutoReset}>
|
|
210
|
+
<svg class="action-icon" viewBox="0 0 24 24">
|
|
211
|
+
<path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"/>
|
|
212
|
+
</svg>
|
|
213
|
+
Auto-Reset
|
|
214
|
+
</button>
|
|
215
|
+
|
|
216
|
+
<button class="action-button outlined" on:click={testRelations}>
|
|
217
|
+
<svg class="action-icon" viewBox="0 0 24 24">
|
|
218
|
+
<path d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/>
|
|
219
|
+
</svg>
|
|
220
|
+
Relations
|
|
221
|
+
</button>
|
|
222
|
+
|
|
223
|
+
<button class="action-button outlined" on:click={testTransactions}>
|
|
224
|
+
<svg class="action-icon" viewBox="0 0 24 24">
|
|
225
|
+
<path d="M13 10V3L4 14h7v7l9-11h-7z"/>
|
|
226
|
+
</svg>
|
|
227
|
+
Transactions
|
|
228
|
+
</button>
|
|
229
|
+
|
|
230
|
+
<button class="action-button outlined" on:click={testCompoundIndexes}>
|
|
231
|
+
<svg class="action-icon" viewBox="0 0 24 24">
|
|
232
|
+
<path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
|
|
233
|
+
</svg>
|
|
234
|
+
Indexes
|
|
235
|
+
</button>
|
|
236
|
+
|
|
237
|
+
<button class="action-button outlined" on:click={testAggregations}>
|
|
238
|
+
<svg class="action-icon" viewBox="0 0 24 24">
|
|
239
|
+
<path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/>
|
|
240
|
+
</svg>
|
|
241
|
+
Aggregations
|
|
242
|
+
</button>
|
|
243
|
+
|
|
244
|
+
<button class="action-button outlined clear-button" on:click={clearAll}>
|
|
245
|
+
<svg class="action-icon" viewBox="0 0 24 24">
|
|
246
|
+
<path d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
|
|
247
|
+
</svg>
|
|
248
|
+
Clear All
|
|
249
|
+
</button>
|
|
250
|
+
</div>
|
|
251
|
+
</div>
|
|
252
|
+
|
|
253
|
+
<!-- Users Section - 1:1 z React Material-UI Paper -->
|
|
254
|
+
{#if $users.length > 0}
|
|
255
|
+
<div class="users-section">
|
|
256
|
+
<h3 class="users-title">Users ({$users.length})</h3>
|
|
257
|
+
<div class="users-stack">
|
|
258
|
+
{#each $users as user}
|
|
259
|
+
<div class="user-paper">
|
|
260
|
+
<strong>{user.name}</strong> ({user.email})<br />
|
|
261
|
+
Age: {user.age}, Tags: {user.tags?.join(', ') || 'none'}
|
|
262
|
+
</div>
|
|
263
|
+
{/each}
|
|
264
|
+
</div>
|
|
265
|
+
</div>
|
|
266
|
+
{/if}
|
|
267
|
+
|
|
268
|
+
<!-- Live Query Demo - 1:1 z React -->
|
|
269
|
+
<div class="live-query-demo">
|
|
270
|
+
<div class="demo-card">
|
|
271
|
+
<div class="demo-header">
|
|
272
|
+
<svg class="demo-icon" viewBox="0 0 24 24">
|
|
273
|
+
<path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/>
|
|
274
|
+
</svg>
|
|
275
|
+
<h2>Live Query Demo</h2>
|
|
276
|
+
</div>
|
|
277
|
+
|
|
278
|
+
<div class="demo-grid">
|
|
279
|
+
<div class="demo-section">
|
|
280
|
+
<div class="section-card">
|
|
281
|
+
<h3 class="section-title">
|
|
282
|
+
<svg class="section-icon" viewBox="0 0 24 24">
|
|
283
|
+
<path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/>
|
|
284
|
+
</svg>
|
|
285
|
+
Statistics
|
|
286
|
+
</h3>
|
|
287
|
+
<div class="stats-grid">
|
|
288
|
+
<div class="stat-item">
|
|
289
|
+
<span class="stat-label">Total Users:</span>
|
|
290
|
+
<span class="stat-value">{$allUsers.length}</span>
|
|
291
|
+
</div>
|
|
292
|
+
<div class="stat-item">
|
|
293
|
+
<span class="stat-label">Adult Users:</span>
|
|
294
|
+
<span class="stat-value">{$allUsers.filter(u => u.age >= 18).length}</span>
|
|
295
|
+
</div>
|
|
296
|
+
<div class="stat-item">
|
|
297
|
+
<span class="stat-label">First User:</span>
|
|
298
|
+
<span class="stat-value">{$allUsers[0]?.name || 'None'}</span>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
|
|
304
|
+
<div class="demo-section">
|
|
305
|
+
<div class="section-card">
|
|
306
|
+
<h3 class="section-title">
|
|
307
|
+
<svg class="section-icon" viewBox="0 0 24 24">
|
|
308
|
+
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
|
|
309
|
+
</svg>
|
|
310
|
+
Users with Profiles
|
|
311
|
+
</h3>
|
|
312
|
+
<div class="users-list">
|
|
313
|
+
{#each $allUsers.slice(0, 3) as user}
|
|
314
|
+
<div class="user-item">
|
|
315
|
+
<strong>{user.name}</strong> ({user.email})
|
|
316
|
+
</div>
|
|
317
|
+
{/each}
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
</div>
|
|
321
|
+
|
|
322
|
+
<div class="demo-section">
|
|
323
|
+
<div class="section-card">
|
|
324
|
+
<h3 class="section-title">
|
|
325
|
+
<svg class="section-icon" viewBox="0 0 24 24">
|
|
326
|
+
<path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z"/>
|
|
327
|
+
</svg>
|
|
328
|
+
Posts
|
|
329
|
+
</h3>
|
|
330
|
+
<div class="posts-list">
|
|
331
|
+
{#each $allPosts.slice(0, 3) as post}
|
|
332
|
+
<div class="post-item">
|
|
333
|
+
<strong>{post.title}</strong>
|
|
334
|
+
<span class="post-status" class:published={post.published}>
|
|
335
|
+
{post.published ? 'Published' : 'Draft'}
|
|
336
|
+
</span>
|
|
337
|
+
</div>
|
|
338
|
+
{/each}
|
|
339
|
+
</div>
|
|
340
|
+
</div>
|
|
341
|
+
</div>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
</div>
|
|
345
|
+
|
|
346
|
+
<!-- TypeScript Demo - 1:1 z React -->
|
|
347
|
+
<div class="typescript-demo">
|
|
348
|
+
<div class="demo-card typescript-card">
|
|
349
|
+
<div class="demo-header">
|
|
350
|
+
<svg class="demo-icon" viewBox="0 0 24 24">
|
|
351
|
+
<path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4z"/>
|
|
352
|
+
</svg>
|
|
353
|
+
<h2>TypeScript Demo</h2>
|
|
354
|
+
</div>
|
|
355
|
+
|
|
356
|
+
<div class="demo-content">
|
|
357
|
+
<h3 class="section-title">
|
|
358
|
+
<svg class="section-icon" viewBox="0 0 24 24">
|
|
359
|
+
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
|
|
360
|
+
</svg>
|
|
361
|
+
Users
|
|
362
|
+
</h3>
|
|
363
|
+
<div class="users-list">
|
|
364
|
+
{#each $allUsers.slice(0, 3) as user}
|
|
365
|
+
<div class="user-item clickable" on:click={() => console.log('User clicked:', user)}>
|
|
366
|
+
<strong>{user.name}</strong> ({user.email})
|
|
367
|
+
</div>
|
|
368
|
+
{/each}
|
|
369
|
+
</div>
|
|
370
|
+
|
|
371
|
+
<h3 class="section-title">
|
|
372
|
+
<svg class="section-icon" viewBox="0 0 24 24">
|
|
373
|
+
<path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z"/>
|
|
374
|
+
</svg>
|
|
375
|
+
Posts
|
|
376
|
+
</h3>
|
|
377
|
+
<div class="posts-list">
|
|
378
|
+
{#each $allPosts.slice(0, 3) as post}
|
|
379
|
+
<div class="post-item clickable" on:click={() => console.log('Post clicked:', post)}>
|
|
380
|
+
<strong>{post.title}</strong>
|
|
381
|
+
<span class="post-status" class:published={post.published}>
|
|
382
|
+
{post.published ? 'Published' : 'Draft'}
|
|
383
|
+
</span>
|
|
384
|
+
</div>
|
|
385
|
+
{/each}
|
|
386
|
+
</div>
|
|
387
|
+
|
|
388
|
+
<h3 class="section-title">
|
|
389
|
+
<svg class="section-icon" viewBox="0 0 24 24">
|
|
390
|
+
<path d="M12 2C13.1 2 14 2.9 14 4C14 5.1 13.1 6 12 6C10.9 6 10 5.1 10 4C10 2.9 10.9 2 12 2ZM21 9V7L15 1H5C3.89 1 3 1.89 3 3V7H1V9H3V11H1V13H3V15H1V17H3V19C3 20.11 3.89 21 5 21H19C20.11 21 21 20.11 21 19V17H23V15H21V13H23V11H21V9H23V7H21V9Z"/>
|
|
391
|
+
</svg>
|
|
392
|
+
Profiles
|
|
393
|
+
</h3>
|
|
394
|
+
<div class="profiles-list">
|
|
395
|
+
{#each $allProfiles.slice(0, 3) as profile}
|
|
396
|
+
<div class="profile-item clickable" on:click={() => console.log('Profile clicked:', profile)}>
|
|
397
|
+
<strong>{profile.bio || 'No bio'}</strong>
|
|
398
|
+
</div>
|
|
399
|
+
{/each}
|
|
400
|
+
</div>
|
|
401
|
+
|
|
402
|
+
<div class="ide-test">
|
|
403
|
+
<h4>IDE Test</h4>
|
|
404
|
+
<p>Hover over the items above to see TypeScript intellisense in action!</p>
|
|
405
|
+
</div>
|
|
406
|
+
</div>
|
|
407
|
+
</div>
|
|
408
|
+
</div>
|
|
409
|
+
|
|
410
|
+
<!-- Posts Live Query Demo - 1:1 z React -->
|
|
411
|
+
<div class="posts-live-query-demo">
|
|
412
|
+
<div class="demo-card posts-card">
|
|
413
|
+
<div class="demo-header">
|
|
414
|
+
<svg class="demo-icon" viewBox="0 0 24 24">
|
|
415
|
+
<path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z"/>
|
|
416
|
+
</svg>
|
|
417
|
+
<h2>Posts Live Query Demo</h2>
|
|
418
|
+
</div>
|
|
419
|
+
|
|
420
|
+
<div class="demo-content">
|
|
421
|
+
<h3 class="section-title">
|
|
422
|
+
<svg class="section-icon" viewBox="0 0 24 24">
|
|
423
|
+
<path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/>
|
|
424
|
+
</svg>
|
|
425
|
+
Post Statistics
|
|
426
|
+
</h3>
|
|
427
|
+
<div class="stats-grid">
|
|
428
|
+
<div class="stat-item">
|
|
429
|
+
<span class="stat-label">Total Posts:</span>
|
|
430
|
+
<span class="stat-value">{$postStats.total}</span>
|
|
431
|
+
</div>
|
|
432
|
+
<div class="stat-item">
|
|
433
|
+
<span class="stat-label">Published:</span>
|
|
434
|
+
<span class="stat-value">{$postStats.published}</span>
|
|
435
|
+
</div>
|
|
436
|
+
<div class="stat-item">
|
|
437
|
+
<span class="stat-label">Total Likes:</span>
|
|
438
|
+
<span class="stat-value">{$postStats.totalLikes}</span>
|
|
439
|
+
</div>
|
|
440
|
+
</div>
|
|
441
|
+
|
|
442
|
+
<h3 class="section-title">
|
|
443
|
+
<svg class="section-icon" viewBox="0 0 24 24">
|
|
444
|
+
<path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/>
|
|
445
|
+
</svg>
|
|
446
|
+
All Posts
|
|
447
|
+
</h3>
|
|
448
|
+
<div class="posts-list">
|
|
449
|
+
{#each $allPosts.slice(0, 5) as post}
|
|
450
|
+
<div class="post-item">
|
|
451
|
+
<strong>{post.title}</strong>
|
|
452
|
+
<span class="post-status" class:published={post.published}>
|
|
453
|
+
{post.published ? 'Published' : 'Draft'}
|
|
454
|
+
</span>
|
|
455
|
+
<span class="post-likes">{post.likes || 0} likes</span>
|
|
456
|
+
</div>
|
|
457
|
+
{/each}
|
|
458
|
+
</div>
|
|
459
|
+
|
|
460
|
+
<div class="note-section">
|
|
461
|
+
<h4>
|
|
462
|
+
<svg class="note-icon" viewBox="0 0 24 24">
|
|
463
|
+
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
|
|
464
|
+
</svg>
|
|
465
|
+
Note
|
|
466
|
+
</h4>
|
|
467
|
+
<p>This demonstrates advanced live queries with posts, including statistics and filtering.</p>
|
|
468
|
+
</div>
|
|
469
|
+
</div>
|
|
470
|
+
</div>
|
|
471
|
+
</div>
|
|
472
|
+
</div>
|
|
473
|
+
{:else if $tabIndex === 1}
|
|
474
|
+
<!-- Cloud Sync Tab Content - 1:1 z React -->
|
|
475
|
+
<div class="tab-content">
|
|
476
|
+
<div class="cloud-sync-demo">
|
|
477
|
+
<div class="cloud-sync-card">
|
|
478
|
+
<h2>Cloud Sync Demo</h2>
|
|
479
|
+
<p class="cloud-sync-description">
|
|
480
|
+
<strong>Dexie Cloud Addon Integration:</strong> Cloud synchronization demo
|
|
481
|
+
</p>
|
|
482
|
+
|
|
483
|
+
<div class="cloud-sync-grid">
|
|
484
|
+
<div class="sync-status-section">
|
|
485
|
+
<h3 class="section-title">
|
|
486
|
+
<svg class="section-icon" viewBox="0 0 24 24">
|
|
487
|
+
<path d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z"/>
|
|
488
|
+
</svg>
|
|
489
|
+
Sync status
|
|
490
|
+
</h3>
|
|
491
|
+
<div class="status-card">
|
|
492
|
+
<p>
|
|
493
|
+
<strong>Enabled:</strong> {$syncStatus.enabled ? 'Yes' : 'No'}
|
|
494
|
+
</p>
|
|
495
|
+
<p>
|
|
496
|
+
<strong>Online:</strong> {$syncStatus.isOnline !== undefined ? ($syncStatus.isOnline ? 'Yes' : 'No') : 'Unknown'}
|
|
497
|
+
</p>
|
|
498
|
+
<p>
|
|
499
|
+
<strong>Last sync:</strong> {$syncStatus.lastSync ? new Date($syncStatus.lastSync).toLocaleString() : 'Never'}
|
|
500
|
+
</p>
|
|
501
|
+
</div>
|
|
502
|
+
</div>
|
|
503
|
+
|
|
504
|
+
<div class="sync-controls-section">
|
|
505
|
+
<h3 class="section-title">
|
|
506
|
+
<svg class="section-icon" viewBox="0 0 24 24">
|
|
507
|
+
<path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"/>
|
|
508
|
+
</svg>
|
|
509
|
+
Sync controls
|
|
510
|
+
</h3>
|
|
511
|
+
<div class="controls-buttons">
|
|
512
|
+
<button
|
|
513
|
+
class="sync-button manual"
|
|
514
|
+
on:click={() => alert('Sync manually')}
|
|
515
|
+
disabled={!$syncStatus.enabled}
|
|
516
|
+
>
|
|
517
|
+
Sync manually
|
|
518
|
+
</button>
|
|
519
|
+
|
|
520
|
+
<button
|
|
521
|
+
class="sync-button tables"
|
|
522
|
+
on:click={() => alert('Sync tables (users, posts)')}
|
|
523
|
+
disabled={!$syncStatus.enabled}
|
|
524
|
+
>
|
|
525
|
+
Sync tables (users, posts)
|
|
526
|
+
</button>
|
|
527
|
+
|
|
528
|
+
{#if !$syncStatus.enabled}
|
|
529
|
+
<button
|
|
530
|
+
class="sync-button enable"
|
|
531
|
+
on:click={() => alert('Enable cloud sync')}
|
|
532
|
+
>
|
|
533
|
+
Enable cloud sync
|
|
534
|
+
</button>
|
|
535
|
+
{:else}
|
|
536
|
+
<button
|
|
537
|
+
class="sync-button disable"
|
|
538
|
+
on:click={() => alert('Disable cloud sync')}
|
|
539
|
+
>
|
|
540
|
+
Disable cloud sync
|
|
541
|
+
</button>
|
|
542
|
+
{/if}
|
|
543
|
+
</div>
|
|
544
|
+
</div>
|
|
545
|
+
</div>
|
|
546
|
+
|
|
547
|
+
<div class="instructions-section">
|
|
548
|
+
<h4 class="instructions-title">
|
|
549
|
+
<svg class="instructions-icon" viewBox="0 0 24 24">
|
|
550
|
+
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
|
|
551
|
+
</svg>
|
|
552
|
+
Instructions:
|
|
553
|
+
</h4>
|
|
554
|
+
<ol class="instructions-list">
|
|
555
|
+
<li>
|
|
556
|
+
<strong>Install dexie-cloud-addon:</strong> <code>npm install dexie-cloud-addon</code>
|
|
557
|
+
</li>
|
|
558
|
+
<li>
|
|
559
|
+
<strong>Configure database URL</strong> in <code>demo-app/src/database/Database.ts</code>
|
|
560
|
+
</li>
|
|
561
|
+
<li>
|
|
562
|
+
<strong>Enable cloud sync</strong> using the button above
|
|
563
|
+
</li>
|
|
564
|
+
<li>
|
|
565
|
+
<strong>Test sync</strong> – add data and verify it synchronizes
|
|
566
|
+
</li>
|
|
567
|
+
</ol>
|
|
568
|
+
</div>
|
|
569
|
+
|
|
570
|
+
<div class="configuration-section">
|
|
571
|
+
<strong>Configuration:</strong> Cloud sync is configured in Database.ts with automatic sync every 30 seconds.
|
|
572
|
+
<br />
|
|
573
|
+
<strong>Offline Support:</strong> The app works offline and syncs when connection is restored.
|
|
574
|
+
<br />
|
|
575
|
+
<strong>Reactivity:</strong> All changes are automatically synchronized with the cloud!
|
|
576
|
+
</div>
|
|
577
|
+
</div>
|
|
578
|
+
</div>
|
|
579
|
+
</div>
|
|
580
|
+
{/if}
|
|
581
|
+
</main>
|
|
582
|
+
</div>
|
|
583
|
+
|
|
584
|
+
<style>
|
|
585
|
+
/* Global styles for full width */
|
|
586
|
+
:global(body), :global(html) {
|
|
587
|
+
margin: 0;
|
|
588
|
+
padding: 0;
|
|
589
|
+
width: 100%;
|
|
590
|
+
height: 100%;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
:global(#app) {
|
|
594
|
+
width: 100%;
|
|
595
|
+
height: 100%;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/* Material-UI App Bar */
|
|
599
|
+
.app-bar {
|
|
600
|
+
background-color: #1976d2;
|
|
601
|
+
color: white;
|
|
602
|
+
box-shadow: 0px 2px 4px -1px rgba(0,0,0,0.2), 0px 4px 5px 0px rgba(0,0,0,0.14), 0px 1px 10px 0px rgba(0,0,0,0.12);
|
|
603
|
+
z-index: 1000;
|
|
604
|
+
width: 100%;
|
|
605
|
+
position: static;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
.toolbar {
|
|
609
|
+
display: flex;
|
|
610
|
+
align-items: center;
|
|
611
|
+
padding: 0 16px;
|
|
612
|
+
height: 64px;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
.mobile-menu-button {
|
|
616
|
+
display: none;
|
|
617
|
+
background: none;
|
|
618
|
+
border: none;
|
|
619
|
+
color: white;
|
|
620
|
+
cursor: pointer;
|
|
621
|
+
padding: 8px;
|
|
622
|
+
margin-right: 16px;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
.menu-icon {
|
|
626
|
+
width: 24px;
|
|
627
|
+
height: 24px;
|
|
628
|
+
fill: currentColor;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
.title {
|
|
632
|
+
font-size: 1.25rem;
|
|
633
|
+
font-weight: 500;
|
|
634
|
+
margin: 0;
|
|
635
|
+
flex-grow: 1;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
.main-layout {
|
|
639
|
+
display: flex;
|
|
640
|
+
flex: 1;
|
|
641
|
+
width: 100%;
|
|
642
|
+
min-height: calc(100vh - 64px);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/* Material-UI Drawer */
|
|
646
|
+
.mobile-drawer {
|
|
647
|
+
position: fixed;
|
|
648
|
+
top: 0;
|
|
649
|
+
left: 0;
|
|
650
|
+
height: 100vh;
|
|
651
|
+
width: 240px;
|
|
652
|
+
background: white;
|
|
653
|
+
box-shadow: 0px 8px 10px -5px rgba(0,0,0,0.2), 0px 16px 24px 2px rgba(0,0,0,0.14), 0px 6px 30px 5px rgba(0,0,0,0.12);
|
|
654
|
+
z-index: 1001;
|
|
655
|
+
transform: translateX(-100%);
|
|
656
|
+
transition: transform 0.3s ease;
|
|
657
|
+
padding-top: 64px;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
.mobile-drawer.open {
|
|
661
|
+
transform: translateX(0);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
.desktop-drawer {
|
|
665
|
+
display: none;
|
|
666
|
+
width: 240px;
|
|
667
|
+
background: white;
|
|
668
|
+
box-shadow: 0px 8px 10px -5px rgba(0,0,0,0.2), 0px 16px 24px 2px rgba(0,0,0,0.14), 0px 6px 30px 5px rgba(0,0,0,0.12);
|
|
669
|
+
flex-shrink: 0;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
.drawer-content {
|
|
673
|
+
padding: 16px 0;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
.nav-list {
|
|
677
|
+
list-style: none;
|
|
678
|
+
margin: 0;
|
|
679
|
+
padding: 0;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
.nav-item {
|
|
683
|
+
display: block;
|
|
684
|
+
width: 100%;
|
|
685
|
+
padding: 12px 24px;
|
|
686
|
+
border: none;
|
|
687
|
+
background: none;
|
|
688
|
+
text-align: left;
|
|
689
|
+
cursor: pointer;
|
|
690
|
+
color: #666;
|
|
691
|
+
transition: background-color 0.2s;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
.nav-item:hover {
|
|
695
|
+
background-color: #f5f5f5;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
.nav-item.active {
|
|
699
|
+
background-color: #e3f2fd;
|
|
700
|
+
color: #1976d2;
|
|
701
|
+
font-weight: 500;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.main-content {
|
|
705
|
+
flex-grow: 1;
|
|
706
|
+
padding: 24px;
|
|
707
|
+
width: 100%;
|
|
708
|
+
max-width: 100%;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
.tab-content {
|
|
712
|
+
width: 100%;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/* Material-UI Paper for Main Info */
|
|
716
|
+
.main-info {
|
|
717
|
+
margin-bottom: 24px;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
.info-card {
|
|
721
|
+
background: white;
|
|
722
|
+
border: 1px solid #e0e0e0;
|
|
723
|
+
border-radius: 4px;
|
|
724
|
+
padding: 16px;
|
|
725
|
+
box-shadow: 0px 2px 1px -1px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 1px 3px 0px rgba(0,0,0,0.12);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
.info-header {
|
|
729
|
+
display: flex;
|
|
730
|
+
align-items: center;
|
|
731
|
+
margin-bottom: 16px;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
.info-icon {
|
|
735
|
+
width: 24px;
|
|
736
|
+
height: 24px;
|
|
737
|
+
margin-right: 8px;
|
|
738
|
+
fill: #1976d2;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
.info-header h2 {
|
|
742
|
+
margin: 0;
|
|
743
|
+
font-size: 1.25rem;
|
|
744
|
+
font-weight: 500;
|
|
745
|
+
color: #1976d2;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
.info-description {
|
|
749
|
+
font-size: 0.875rem;
|
|
750
|
+
color: rgba(0, 0, 0, 0.6);
|
|
751
|
+
margin-bottom: 16px;
|
|
752
|
+
line-height: 1.43;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
.info-features {
|
|
756
|
+
display: grid;
|
|
757
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
758
|
+
gap: 8px;
|
|
759
|
+
margin-bottom: 16px;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
.feature {
|
|
763
|
+
display: flex;
|
|
764
|
+
align-items: center;
|
|
765
|
+
gap: 8px;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
.feature-icon {
|
|
769
|
+
width: 16px;
|
|
770
|
+
height: 16px;
|
|
771
|
+
fill: #1976d2;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
.feature span {
|
|
775
|
+
font-size: 0.875rem;
|
|
776
|
+
color: rgba(0, 0, 0, 0.87);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
.info-button-section {
|
|
780
|
+
margin-top: 16px;
|
|
781
|
+
padding-top: 16px;
|
|
782
|
+
border-top: 1px solid #e0e0e0;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
.info-button {
|
|
786
|
+
display: inline-flex;
|
|
787
|
+
align-items: center;
|
|
788
|
+
padding: 6px 16px;
|
|
789
|
+
background: transparent;
|
|
790
|
+
color: #1976d2;
|
|
791
|
+
border: 1px solid #1976d2;
|
|
792
|
+
border-radius: 4px;
|
|
793
|
+
cursor: pointer;
|
|
794
|
+
font-size: 0.875rem;
|
|
795
|
+
font-weight: 500;
|
|
796
|
+
text-transform: uppercase;
|
|
797
|
+
transition: background-color 0.2s;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
.info-button:hover {
|
|
801
|
+
background-color: rgba(25, 118, 210, 0.04);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.button-icon {
|
|
805
|
+
width: 16px;
|
|
806
|
+
height: 16px;
|
|
807
|
+
margin-right: 8px;
|
|
808
|
+
fill: currentColor;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/* Admin Actions - 1:1 z React Material-UI */
|
|
812
|
+
.admin-section {
|
|
813
|
+
margin-bottom: 24px;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
.admin-title {
|
|
817
|
+
font-size: 1.5rem;
|
|
818
|
+
font-weight: 400;
|
|
819
|
+
margin: 0 0 16px 0;
|
|
820
|
+
color: rgba(0, 0, 0, 0.87);
|
|
821
|
+
line-height: 1.33;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
.actions-grid {
|
|
825
|
+
display: grid;
|
|
826
|
+
grid-template-columns: repeat(2, 1fr);
|
|
827
|
+
grid-template-rows: repeat(5, auto);
|
|
828
|
+
gap: 8px;
|
|
829
|
+
margin-bottom: 16px;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
.action-button {
|
|
833
|
+
display: flex;
|
|
834
|
+
align-items: center;
|
|
835
|
+
justify-content: center;
|
|
836
|
+
gap: 8px;
|
|
837
|
+
padding: 8px 16px;
|
|
838
|
+
border: 1px solid rgba(25, 118, 210, 0.5);
|
|
839
|
+
background: transparent;
|
|
840
|
+
border-radius: 4px;
|
|
841
|
+
cursor: pointer;
|
|
842
|
+
font-size: 0.75rem;
|
|
843
|
+
font-weight: 500;
|
|
844
|
+
color: #1976d2;
|
|
845
|
+
text-transform: uppercase;
|
|
846
|
+
transition: all 0.2s;
|
|
847
|
+
min-height: 36px;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
.action-button.outlined {
|
|
851
|
+
border: 1px solid rgba(25, 118, 210, 0.5);
|
|
852
|
+
background: transparent;
|
|
853
|
+
color: #1976d2;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
.action-button.outlined:hover {
|
|
857
|
+
background: rgba(25, 118, 210, 0.04);
|
|
858
|
+
border-color: #1976d2;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
.action-button.clear-button {
|
|
862
|
+
/* Clear All będzie w linii z innymi przyciskami */
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
.action-icon {
|
|
866
|
+
width: 18px;
|
|
867
|
+
height: 18px;
|
|
868
|
+
fill: currentColor;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
/* Users Section - 1:1 z React Material-UI */
|
|
872
|
+
.users-section {
|
|
873
|
+
margin-top: 24px;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
.users-title {
|
|
877
|
+
font-size: 1.25rem;
|
|
878
|
+
font-weight: 500;
|
|
879
|
+
margin: 0 0 8px 0;
|
|
880
|
+
color: rgba(0, 0, 0, 0.87);
|
|
881
|
+
line-height: 1.6;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
.users-stack {
|
|
885
|
+
display: flex;
|
|
886
|
+
flex-direction: column;
|
|
887
|
+
gap: 8px;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
.user-paper {
|
|
891
|
+
background: white;
|
|
892
|
+
border: 1px solid rgba(0, 0, 0, 0.12);
|
|
893
|
+
border-radius: 4px;
|
|
894
|
+
padding: 12px;
|
|
895
|
+
box-shadow: 0px 2px 1px -1px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 1px 3px 0px rgba(0,0,0,0.12);
|
|
896
|
+
font-size: 0.875rem;
|
|
897
|
+
line-height: 1.43;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/* Cloud Sync Demo - 1:1 z React */
|
|
901
|
+
.cloud-sync-demo {
|
|
902
|
+
margin: 24px 0;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
.cloud-sync-card {
|
|
906
|
+
border: 2px solid #2196f3;
|
|
907
|
+
padding: 20px;
|
|
908
|
+
margin: 20px 0;
|
|
909
|
+
border-radius: 8px;
|
|
910
|
+
background-color: #e3f2fd;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
.cloud-sync-card h2 {
|
|
914
|
+
margin: 0 0 16px 0;
|
|
915
|
+
font-size: 1.5rem;
|
|
916
|
+
font-weight: 500;
|
|
917
|
+
color: #1976d2;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
.cloud-sync-description {
|
|
921
|
+
color: #666;
|
|
922
|
+
margin-bottom: 20px;
|
|
923
|
+
font-size: 0.875rem;
|
|
924
|
+
line-height: 1.43;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
.cloud-sync-grid {
|
|
928
|
+
display: grid;
|
|
929
|
+
grid-template-columns: 1fr 1fr;
|
|
930
|
+
gap: 20px;
|
|
931
|
+
margin-bottom: 20px;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
.sync-status-section, .sync-controls-section {
|
|
935
|
+
display: flex;
|
|
936
|
+
flex-direction: column;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
.section-title {
|
|
940
|
+
display: flex;
|
|
941
|
+
align-items: center;
|
|
942
|
+
gap: 8px;
|
|
943
|
+
margin: 0 0 12px 0;
|
|
944
|
+
font-size: 1rem;
|
|
945
|
+
font-weight: 500;
|
|
946
|
+
color: #1976d2;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
.section-icon {
|
|
950
|
+
width: 20px;
|
|
951
|
+
height: 20px;
|
|
952
|
+
fill: #1976d2;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
.status-card {
|
|
956
|
+
background-color: white;
|
|
957
|
+
padding: 15px;
|
|
958
|
+
border-radius: 4px;
|
|
959
|
+
border: 1px solid #ddd;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
.status-card p {
|
|
963
|
+
margin: 0 0 8px 0;
|
|
964
|
+
font-size: 0.875rem;
|
|
965
|
+
line-height: 1.43;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
.status-card p:last-child {
|
|
969
|
+
margin-bottom: 0;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
.controls-buttons {
|
|
973
|
+
display: flex;
|
|
974
|
+
flex-direction: column;
|
|
975
|
+
gap: 10px;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
.sync-button {
|
|
979
|
+
padding: 10px 15px;
|
|
980
|
+
border: none;
|
|
981
|
+
border-radius: 4px;
|
|
982
|
+
cursor: pointer;
|
|
983
|
+
font-size: 0.875rem;
|
|
984
|
+
font-weight: 500;
|
|
985
|
+
transition: background-color 0.2s;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
.sync-button.manual {
|
|
989
|
+
background-color: #4caf50;
|
|
990
|
+
color: white;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
.sync-button.manual:disabled {
|
|
994
|
+
background-color: #ccc;
|
|
995
|
+
cursor: not-allowed;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
.sync-button.tables {
|
|
999
|
+
background-color: #ff9800;
|
|
1000
|
+
color: white;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
.sync-button.tables:disabled {
|
|
1004
|
+
background-color: #ccc;
|
|
1005
|
+
cursor: not-allowed;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
.sync-button.enable {
|
|
1009
|
+
background-color: #2196f3;
|
|
1010
|
+
color: white;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
.sync-button.disable {
|
|
1014
|
+
background-color: #f44336;
|
|
1015
|
+
color: white;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
.instructions-section {
|
|
1019
|
+
background-color: #fff3e0;
|
|
1020
|
+
padding: 15px;
|
|
1021
|
+
border-radius: 4px;
|
|
1022
|
+
border: 1px solid #ffb74d;
|
|
1023
|
+
margin-bottom: 15px;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
.instructions-title {
|
|
1027
|
+
display: flex;
|
|
1028
|
+
align-items: center;
|
|
1029
|
+
gap: 8px;
|
|
1030
|
+
margin: 0 0 16px 0;
|
|
1031
|
+
font-size: 1rem;
|
|
1032
|
+
font-weight: 500;
|
|
1033
|
+
color: #1976d2;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
.instructions-icon {
|
|
1037
|
+
width: 16px;
|
|
1038
|
+
height: 16px;
|
|
1039
|
+
fill: #1976d2;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
.instructions-list {
|
|
1043
|
+
margin: 10px 0;
|
|
1044
|
+
padding-left: 20px;
|
|
1045
|
+
font-size: 0.875rem;
|
|
1046
|
+
line-height: 1.43;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
.instructions-list li {
|
|
1050
|
+
margin-bottom: 8px;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
.instructions-list code {
|
|
1054
|
+
background-color: #f5f5f5;
|
|
1055
|
+
padding: 2px 4px;
|
|
1056
|
+
border-radius: 3px;
|
|
1057
|
+
font-family: 'Courier New', monospace;
|
|
1058
|
+
font-size: 0.8rem;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
.configuration-section {
|
|
1062
|
+
margin-top: 15px;
|
|
1063
|
+
font-size: 0.9em;
|
|
1064
|
+
color: #666;
|
|
1065
|
+
background-color: #e8f5e8;
|
|
1066
|
+
padding: 10px;
|
|
1067
|
+
border-radius: 4px;
|
|
1068
|
+
line-height: 1.43;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
/* Responsive Design */
|
|
1072
|
+
@media (max-width: 768px) {
|
|
1073
|
+
.cloud-sync-grid {
|
|
1074
|
+
grid-template-columns: 1fr;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
/* Live Query Demo */
|
|
1079
|
+
.live-query-demo {
|
|
1080
|
+
margin: 24px 0;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
.demo-header {
|
|
1084
|
+
display: flex;
|
|
1085
|
+
align-items: center;
|
|
1086
|
+
margin-bottom: 16px;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
.demo-icon {
|
|
1090
|
+
width: 24px;
|
|
1091
|
+
height: 24px;
|
|
1092
|
+
margin-right: 8px;
|
|
1093
|
+
fill: #1976d2;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
.demo-header h2 {
|
|
1097
|
+
margin: 0;
|
|
1098
|
+
font-size: 1.25rem;
|
|
1099
|
+
font-weight: 500;
|
|
1100
|
+
color: #1976d2;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
.demo-grid {
|
|
1104
|
+
display: grid;
|
|
1105
|
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
1106
|
+
gap: 16px;
|
|
1107
|
+
margin-top: 16px;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
.demo-section {
|
|
1111
|
+
display: flex;
|
|
1112
|
+
flex-direction: column;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
.section-card {
|
|
1116
|
+
background: white;
|
|
1117
|
+
border: 1px solid #e0e0e0;
|
|
1118
|
+
border-radius: 4px;
|
|
1119
|
+
padding: 16px;
|
|
1120
|
+
box-shadow: 0px 2px 1px -1px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 1px 3px 0px rgba(0,0,0,0.12);
|
|
1121
|
+
flex: 1;
|
|
1122
|
+
display: flex;
|
|
1123
|
+
flex-direction: column;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
.section-title {
|
|
1127
|
+
display: flex;
|
|
1128
|
+
align-items: center;
|
|
1129
|
+
gap: 8px;
|
|
1130
|
+
font-size: 1rem;
|
|
1131
|
+
font-weight: 500;
|
|
1132
|
+
margin: 0 0 12px 0;
|
|
1133
|
+
color: rgba(0, 0, 0, 0.87);
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
.stats-grid {
|
|
1137
|
+
display: flex;
|
|
1138
|
+
flex-direction: column;
|
|
1139
|
+
gap: 8px;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
.stat-item {
|
|
1143
|
+
display: flex;
|
|
1144
|
+
justify-content: space-between;
|
|
1145
|
+
padding: 4px 0;
|
|
1146
|
+
border-bottom: 1px solid #e0e0e0;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
.stat-label {
|
|
1150
|
+
font-weight: 500;
|
|
1151
|
+
color: rgba(0, 0, 0, 0.6);
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
.stat-value {
|
|
1155
|
+
color: #1976d2;
|
|
1156
|
+
font-weight: 500;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
.user-item, .post-item, .profile-item {
|
|
1160
|
+
padding: 8px 0;
|
|
1161
|
+
border-bottom: 1px solid #e0e0e0;
|
|
1162
|
+
font-size: 0.875rem;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
.user-item:last-child, .post-item:last-child, .profile-item:last-child {
|
|
1166
|
+
border-bottom: none;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
.clickable {
|
|
1170
|
+
cursor: pointer;
|
|
1171
|
+
transition: background-color 0.2s;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
.clickable:hover {
|
|
1175
|
+
background-color: rgba(25, 118, 210, 0.04);
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
.post-status {
|
|
1179
|
+
display: inline-block;
|
|
1180
|
+
padding: 2px 8px;
|
|
1181
|
+
border-radius: 12px;
|
|
1182
|
+
font-size: 0.75rem;
|
|
1183
|
+
font-weight: 500;
|
|
1184
|
+
background-color: #f44336;
|
|
1185
|
+
color: white;
|
|
1186
|
+
margin-left: 8px;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
.post-status.published {
|
|
1190
|
+
background-color: #4caf50;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
.post-likes {
|
|
1194
|
+
color: #666;
|
|
1195
|
+
font-size: 0.75rem;
|
|
1196
|
+
margin-left: 8px;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
/* TypeScript Demo - kolorowe tło jak w React */
|
|
1200
|
+
.typescript-demo {
|
|
1201
|
+
margin: 24px 0;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
.typescript-card {
|
|
1205
|
+
border: 2px solid #ff9800;
|
|
1206
|
+
background-color: #fff8e1;
|
|
1207
|
+
border-radius: 8px;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
.ide-test {
|
|
1211
|
+
margin-top: 16px;
|
|
1212
|
+
padding: 12px;
|
|
1213
|
+
background-color: rgba(255, 152, 0, 0.1);
|
|
1214
|
+
border-radius: 4px;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
.ide-test h4 {
|
|
1218
|
+
margin: 0 0 8px 0;
|
|
1219
|
+
font-size: 1rem;
|
|
1220
|
+
font-weight: 500;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
.ide-test p {
|
|
1224
|
+
margin: 0;
|
|
1225
|
+
font-size: 0.875rem;
|
|
1226
|
+
color: rgba(0, 0, 0, 0.6);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
/* Posts Live Query Demo - kolorowe tło jak w React */
|
|
1230
|
+
.posts-live-query-demo {
|
|
1231
|
+
margin: 24px 0;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
.posts-card {
|
|
1235
|
+
border: 2px solid #9c27b0;
|
|
1236
|
+
background-color: #faf5ff;
|
|
1237
|
+
border-radius: 8px;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
.note-section {
|
|
1241
|
+
margin-top: 16px;
|
|
1242
|
+
padding: 12px;
|
|
1243
|
+
background-color: rgba(156, 39, 176, 0.1);
|
|
1244
|
+
border-radius: 4px;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
.note-section h4 {
|
|
1248
|
+
display: flex;
|
|
1249
|
+
align-items: center;
|
|
1250
|
+
gap: 8px;
|
|
1251
|
+
margin: 0 0 8px 0;
|
|
1252
|
+
font-size: 1rem;
|
|
1253
|
+
font-weight: 500;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
.note-icon {
|
|
1257
|
+
width: 16px;
|
|
1258
|
+
height: 16px;
|
|
1259
|
+
fill: #9c27b0;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
.note-section p {
|
|
1263
|
+
margin: 0;
|
|
1264
|
+
font-size: 0.875rem;
|
|
1265
|
+
color: rgba(0, 0, 0, 0.6);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
/* Responsive Design - 1:1 z React Material-UI */
|
|
1269
|
+
@media (min-width: 600px) {
|
|
1270
|
+
.actions-grid {
|
|
1271
|
+
grid-template-columns: repeat(3, 1fr);
|
|
1272
|
+
grid-template-rows: repeat(3, auto);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
@media (min-width: 960px) {
|
|
1277
|
+
.mobile-menu-button {
|
|
1278
|
+
display: none;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
.desktop-drawer {
|
|
1282
|
+
display: block;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
.main-content {
|
|
1286
|
+
width: 100%;
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
.actions-grid {
|
|
1290
|
+
grid-template-columns: repeat(4, 1fr);
|
|
1291
|
+
grid-template-rows: repeat(3, auto);
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
.demo-grid {
|
|
1295
|
+
grid-template-columns: repeat(3, 1fr);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
@media (min-width: 1200px) {
|
|
1300
|
+
.actions-grid {
|
|
1301
|
+
grid-template-columns: repeat(5, 1fr);
|
|
1302
|
+
grid-template-rows: repeat(2, auto);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
</style>
|