@nuraly/lumenjs 0.1.2 → 0.1.4
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/README.md +76 -235
- package/dist/auth/config.d.ts +23 -0
- package/dist/auth/config.js +115 -0
- package/dist/auth/guard.d.ts +12 -0
- package/dist/auth/guard.js +28 -0
- package/dist/auth/index.d.ts +3 -0
- package/dist/auth/index.js +1 -0
- package/dist/auth/middleware.d.ts +23 -0
- package/dist/auth/middleware.js +89 -0
- package/dist/auth/native-auth.d.ts +73 -0
- package/dist/auth/native-auth.js +293 -0
- package/dist/auth/oidc-client.d.ts +17 -0
- package/dist/auth/oidc-client.js +123 -0
- package/dist/auth/providers/google.d.ts +23 -0
- package/dist/auth/providers/google.js +25 -0
- package/dist/auth/providers/index.d.ts +2 -0
- package/dist/auth/providers/index.js +1 -0
- package/dist/auth/routes/login.d.ts +8 -0
- package/dist/auth/routes/login.js +98 -0
- package/dist/auth/routes/logout.d.ts +4 -0
- package/dist/auth/routes/logout.js +79 -0
- package/dist/auth/routes/oidc-callback.d.ts +3 -0
- package/dist/auth/routes/oidc-callback.js +70 -0
- package/dist/auth/routes/password.d.ts +5 -0
- package/dist/auth/routes/password.js +149 -0
- package/dist/auth/routes/signup.d.ts +3 -0
- package/dist/auth/routes/signup.js +81 -0
- package/dist/auth/routes/token.d.ts +4 -0
- package/dist/auth/routes/token.js +70 -0
- package/dist/auth/routes/utils.d.ts +7 -0
- package/dist/auth/routes/utils.js +35 -0
- package/dist/auth/routes/verify.d.ts +3 -0
- package/dist/auth/routes/verify.js +26 -0
- package/dist/auth/routes.d.ts +8 -0
- package/dist/auth/routes.js +110 -0
- package/dist/auth/session.d.ts +8 -0
- package/dist/auth/session.js +54 -0
- package/dist/auth/token.d.ts +33 -0
- package/dist/auth/token.js +90 -0
- package/dist/auth/types.d.ts +156 -0
- package/dist/auth/types.js +2 -0
- package/dist/build/build-client.d.ts +15 -0
- package/dist/build/build-client.js +45 -0
- package/dist/build/build-prerender.d.ts +11 -0
- package/dist/build/build-prerender.js +159 -0
- package/dist/build/build-server.d.ts +17 -0
- package/dist/build/build-server.js +98 -0
- package/dist/build/build.js +52 -120
- package/dist/build/scan.d.ts +19 -0
- package/dist/build/scan.js +77 -6
- package/dist/build/serve-api.js +8 -2
- package/dist/build/serve-loaders.d.ts +4 -2
- package/dist/build/serve-loaders.js +128 -10
- package/dist/build/serve-ssr.js +38 -11
- package/dist/build/serve-static.js +3 -3
- package/dist/build/serve.js +229 -14
- package/dist/cli.js +37 -6
- package/dist/communication/encryption.d.ts +35 -0
- package/dist/communication/encryption.js +90 -0
- package/dist/communication/handlers/context.d.ts +27 -0
- package/dist/communication/handlers/context.js +1 -0
- package/dist/communication/handlers/conversation.d.ts +24 -0
- package/dist/communication/handlers/conversation.js +113 -0
- package/dist/communication/handlers/file-upload.d.ts +17 -0
- package/dist/communication/handlers/file-upload.js +62 -0
- package/dist/communication/handlers/messaging.d.ts +30 -0
- package/dist/communication/handlers/messaging.js +237 -0
- package/dist/communication/handlers/presence.d.ts +15 -0
- package/dist/communication/handlers/presence.js +76 -0
- package/dist/communication/handlers.d.ts +5 -0
- package/dist/communication/handlers.js +5 -0
- package/dist/communication/index.d.ts +9 -0
- package/dist/communication/index.js +7 -0
- package/dist/communication/link-preview.d.ts +18 -0
- package/dist/communication/link-preview.js +115 -0
- package/dist/communication/schema.d.ts +10 -0
- package/dist/communication/schema.js +101 -0
- package/dist/communication/server.d.ts +86 -0
- package/dist/communication/server.js +212 -0
- package/dist/communication/signaling.d.ts +43 -0
- package/dist/communication/signaling.js +271 -0
- package/dist/communication/store.d.ts +71 -0
- package/dist/communication/store.js +289 -0
- package/dist/communication/types.d.ts +454 -0
- package/dist/communication/types.js +1 -0
- package/dist/create.d.ts +1 -0
- package/dist/create.js +55 -0
- package/dist/db/auto-migrate.d.ts +3 -0
- package/dist/db/auto-migrate.js +100 -0
- package/dist/db/client.d.ts +3 -0
- package/dist/db/client.js +18 -0
- package/dist/db/context.d.ts +2 -0
- package/dist/db/context.js +9 -0
- package/dist/db/index.d.ts +23 -0
- package/dist/db/index.js +258 -0
- package/dist/db/seed.d.ts +12 -0
- package/dist/db/seed.js +88 -0
- package/dist/db/table.d.ts +10 -0
- package/dist/db/table.js +12 -0
- package/dist/dev-server/config.d.ts +14 -0
- package/dist/dev-server/config.js +26 -9
- package/dist/dev-server/index-html.d.ts +3 -0
- package/dist/dev-server/index-html.js +18 -6
- package/dist/dev-server/nuralyui-aliases.d.ts +0 -4
- package/dist/dev-server/nuralyui-aliases.js +115 -94
- package/dist/dev-server/plugins/vite-plugin-api-routes.js +29 -5
- package/dist/dev-server/plugins/vite-plugin-auth.d.ts +6 -0
- package/dist/dev-server/plugins/vite-plugin-auth.js +223 -0
- package/dist/dev-server/plugins/vite-plugin-auto-define.d.ts +16 -0
- package/dist/dev-server/plugins/vite-plugin-auto-define.js +111 -0
- package/dist/dev-server/plugins/vite-plugin-communication.d.ts +6 -0
- package/dist/dev-server/plugins/vite-plugin-communication.js +205 -0
- package/dist/dev-server/plugins/vite-plugin-editor-api.d.ts +6 -0
- package/dist/dev-server/plugins/vite-plugin-editor-api.js +318 -0
- package/dist/dev-server/plugins/vite-plugin-i18n.js +69 -2
- package/dist/dev-server/plugins/vite-plugin-lit-dedup.d.ts +6 -0
- package/dist/dev-server/plugins/vite-plugin-lit-dedup.js +78 -34
- package/dist/dev-server/plugins/vite-plugin-lit-hmr.js +44 -2
- package/dist/dev-server/plugins/vite-plugin-llms.d.ts +2 -0
- package/dist/dev-server/plugins/vite-plugin-llms.js +92 -0
- package/dist/dev-server/plugins/vite-plugin-loaders.d.ts +0 -1
- package/dist/dev-server/plugins/vite-plugin-loaders.js +311 -42
- package/dist/dev-server/plugins/vite-plugin-routes.js +18 -6
- package/dist/dev-server/plugins/vite-plugin-socketio.d.ts +2 -0
- package/dist/dev-server/plugins/vite-plugin-socketio.js +51 -0
- package/dist/dev-server/plugins/vite-plugin-source-annotator.d.ts +2 -0
- package/dist/dev-server/plugins/vite-plugin-source-annotator.js +26 -3
- package/dist/dev-server/plugins/vite-plugin-storage.d.ts +10 -0
- package/dist/dev-server/plugins/vite-plugin-storage.js +126 -0
- package/dist/dev-server/plugins/vite-plugin-virtual-modules.js +111 -2
- package/dist/dev-server/server.js +128 -12
- package/dist/dev-server/ssr-render.d.ts +2 -1
- package/dist/dev-server/ssr-render.js +107 -48
- package/dist/editor/ai/backend.d.ts +20 -0
- package/dist/editor/ai/backend.js +104 -0
- package/dist/editor/ai/claude-code-client.d.ts +20 -0
- package/dist/editor/ai/claude-code-client.js +145 -0
- package/dist/editor/ai/opencode-client.d.ts +14 -0
- package/dist/editor/ai/opencode-client.js +125 -0
- package/dist/editor/ai/snapshot-store.d.ts +22 -0
- package/dist/editor/ai/snapshot-store.js +35 -0
- package/dist/editor/ai/types.d.ts +30 -0
- package/dist/editor/ai/types.js +136 -0
- package/dist/editor/ai-chat-panel.d.ts +13 -0
- package/dist/editor/ai-chat-panel.js +587 -0
- package/dist/editor/ai-markdown.d.ts +10 -0
- package/dist/editor/ai-markdown.js +70 -0
- package/dist/editor/ai-project-panel.d.ts +11 -0
- package/dist/editor/ai-project-panel.js +332 -0
- package/dist/editor/ast-modification.d.ts +11 -0
- package/dist/editor/ast-modification.js +1 -0
- package/dist/editor/ast-service.d.ts +30 -0
- package/dist/editor/ast-service.js +180 -0
- package/dist/editor/css-rules.d.ts +54 -0
- package/dist/editor/css-rules.js +423 -0
- package/dist/editor/editor-api-client.d.ts +51 -0
- package/dist/editor/editor-api-client.js +162 -0
- package/dist/editor/editor-bridge.d.ts +1 -0
- package/dist/editor/editor-bridge.js +17 -8
- package/dist/editor/editor-toolbar.d.ts +14 -0
- package/dist/editor/editor-toolbar.js +115 -0
- package/dist/editor/file-editor.d.ts +9 -0
- package/dist/editor/file-editor.js +236 -0
- package/dist/editor/file-service.d.ts +16 -0
- package/dist/editor/file-service.js +52 -0
- package/dist/editor/i18n-key-gen.d.ts +1 -0
- package/dist/editor/i18n-key-gen.js +7 -0
- package/dist/editor/inline-text-edit.d.ts +5 -0
- package/dist/editor/inline-text-edit.js +173 -92
- package/dist/editor/overlay-events.d.ts +5 -0
- package/dist/editor/overlay-events.js +364 -0
- package/dist/editor/overlay-hmr.d.ts +2 -0
- package/dist/editor/overlay-hmr.js +75 -0
- package/dist/editor/overlay-selection.d.ts +29 -0
- package/dist/editor/overlay-selection.js +148 -0
- package/dist/editor/overlay-utils.d.ts +12 -0
- package/dist/editor/overlay-utils.js +59 -0
- package/dist/editor/properties-panel-persist.d.ts +14 -0
- package/dist/editor/properties-panel-persist.js +70 -0
- package/dist/editor/properties-panel-rows.d.ts +10 -0
- package/dist/editor/properties-panel-rows.js +349 -0
- package/dist/editor/properties-panel-styles.d.ts +4 -0
- package/dist/editor/properties-panel-styles.js +174 -0
- package/dist/editor/properties-panel.d.ts +4 -0
- package/dist/editor/properties-panel.js +148 -0
- package/dist/editor/property-registry.d.ts +16 -0
- package/dist/editor/property-registry.js +303 -0
- package/dist/editor/standalone-file-panel.d.ts +0 -0
- package/dist/editor/standalone-file-panel.js +1 -0
- package/dist/editor/standalone-overlay-dom.d.ts +0 -0
- package/dist/editor/standalone-overlay-dom.js +1 -0
- package/dist/editor/standalone-overlay-styles.d.ts +0 -0
- package/dist/editor/standalone-overlay-styles.js +1 -0
- package/dist/editor/standalone-overlay.d.ts +1 -0
- package/dist/editor/standalone-overlay.js +76 -0
- package/dist/editor/syntax-highlighter.d.ts +4 -0
- package/dist/editor/syntax-highlighter.js +81 -0
- package/dist/editor/text-toolbar.d.ts +11 -0
- package/dist/editor/text-toolbar.js +327 -0
- package/dist/editor/toolbar-styles.d.ts +4 -0
- package/dist/editor/toolbar-styles.js +198 -0
- package/dist/email/index.d.ts +32 -0
- package/dist/email/index.js +154 -0
- package/dist/email/providers/resend.d.ts +2 -0
- package/dist/email/providers/resend.js +24 -0
- package/dist/email/providers/sendgrid.d.ts +2 -0
- package/dist/email/providers/sendgrid.js +31 -0
- package/dist/email/providers/smtp.d.ts +13 -0
- package/dist/email/providers/smtp.js +125 -0
- package/dist/email/template-engine.d.ts +18 -0
- package/dist/email/template-engine.js +116 -0
- package/dist/email/templates/base.d.ts +9 -0
- package/dist/email/templates/base.js +65 -0
- package/dist/email/templates/password-reset.d.ts +5 -0
- package/dist/email/templates/password-reset.js +15 -0
- package/dist/email/templates/verify-email.d.ts +5 -0
- package/dist/email/templates/verify-email.js +15 -0
- package/dist/email/templates/welcome.d.ts +5 -0
- package/dist/email/templates/welcome.js +13 -0
- package/dist/email/types.d.ts +49 -0
- package/dist/email/types.js +1 -0
- package/dist/llms/generate.d.ts +46 -0
- package/dist/llms/generate.js +185 -0
- package/dist/permissions/guard.d.ts +28 -0
- package/dist/permissions/guard.js +30 -0
- package/dist/permissions/index.d.ts +6 -0
- package/dist/permissions/index.js +3 -0
- package/dist/permissions/service.d.ts +80 -0
- package/dist/permissions/service.js +210 -0
- package/dist/permissions/tables.d.ts +5 -0
- package/dist/permissions/tables.js +68 -0
- package/dist/permissions/types.d.ts +33 -0
- package/dist/permissions/types.js +1 -0
- package/dist/runtime/app-shell.js +163 -0
- package/dist/runtime/auth.d.ts +10 -0
- package/dist/runtime/auth.js +30 -0
- package/dist/runtime/communication.d.ts +137 -0
- package/dist/runtime/communication.js +228 -0
- package/dist/runtime/error-boundary.d.ts +23 -0
- package/dist/runtime/error-boundary.js +120 -0
- package/dist/runtime/i18n.d.ts +6 -1
- package/dist/runtime/i18n.js +42 -21
- package/dist/runtime/router-data.d.ts +5 -0
- package/dist/runtime/router-data.js +121 -16
- package/dist/runtime/router-hydration.js +25 -0
- package/dist/runtime/router.d.ts +21 -1
- package/dist/runtime/router.js +221 -39
- package/dist/runtime/socket-client.d.ts +2 -0
- package/dist/runtime/socket-client.js +30 -0
- package/dist/runtime/webrtc.d.ts +47 -0
- package/dist/runtime/webrtc.js +178 -0
- package/dist/shared/graceful-shutdown.d.ts +8 -0
- package/dist/shared/graceful-shutdown.js +36 -0
- package/dist/shared/health.d.ts +8 -0
- package/dist/shared/health.js +25 -0
- package/dist/shared/llms-txt.d.ts +31 -0
- package/dist/shared/llms-txt.js +85 -0
- package/dist/shared/logger.d.ts +32 -0
- package/dist/shared/logger.js +93 -0
- package/dist/shared/meta.d.ts +27 -0
- package/dist/shared/meta.js +71 -0
- package/dist/shared/middleware-runner.d.ts +9 -0
- package/dist/shared/middleware-runner.js +29 -0
- package/dist/shared/rate-limit.d.ts +18 -0
- package/dist/shared/rate-limit.js +71 -0
- package/dist/shared/request-id.d.ts +5 -0
- package/dist/shared/request-id.js +18 -0
- package/dist/shared/route-matching.js +16 -1
- package/dist/shared/security-headers.d.ts +18 -0
- package/dist/shared/security-headers.js +38 -0
- package/dist/shared/socket-io-setup.d.ts +11 -0
- package/dist/shared/socket-io-setup.js +51 -0
- package/dist/shared/types.d.ts +16 -0
- package/dist/shared/utils.d.ts +37 -7
- package/dist/shared/utils.js +175 -26
- package/dist/storage/adapters/local.d.ts +44 -0
- package/dist/storage/adapters/local.js +85 -0
- package/dist/storage/adapters/s3.d.ts +32 -0
- package/dist/storage/adapters/s3.js +116 -0
- package/dist/storage/adapters/types.d.ts +53 -0
- package/dist/storage/adapters/types.js +1 -0
- package/dist/storage/index.d.ts +76 -0
- package/dist/storage/index.js +83 -0
- package/package.json +20 -1
- package/templates/blog/api/posts.ts +6 -0
- package/templates/blog/data/migrations/001_init.sql +13 -0
- package/templates/blog/lumenjs.config.ts +3 -0
- package/templates/blog/package.json +14 -0
- package/templates/blog/pages/_layout.ts +25 -0
- package/templates/blog/pages/index.ts +65 -0
- package/templates/blog/pages/posts/[slug].ts +60 -0
- package/templates/blog/pages/tag/[tag].ts +44 -0
- package/templates/dashboard/api/stats.ts +10 -0
- package/templates/dashboard/data/migrations/001_init.sql +13 -0
- package/templates/dashboard/lumenjs.config.ts +3 -0
- package/templates/dashboard/package.json +14 -0
- package/templates/dashboard/pages/_layout.ts +25 -0
- package/templates/dashboard/pages/index.ts +72 -0
- package/templates/dashboard/pages/settings/index.ts +29 -0
- package/templates/default/lumenjs.config.ts +3 -0
- package/templates/default/package.json +14 -0
- package/templates/default/pages/index.ts +24 -0
- package/templates/social/api/posts/[id].ts +14 -0
- package/templates/social/api/posts.ts +11 -0
- package/templates/social/api/profile/[username].ts +10 -0
- package/templates/social/api/upload.ts +19 -0
- package/templates/social/data/migrations/001_init.sql +78 -0
- package/templates/social/data/migrations/002_add_image_url.sql +1 -0
- package/templates/social/data/migrations/003_auth.sql +7 -0
- package/templates/social/docs/architecture.md +76 -0
- package/templates/social/docs/components.md +100 -0
- package/templates/social/docs/data.md +89 -0
- package/templates/social/docs/pages.md +96 -0
- package/templates/social/docs/theming.md +52 -0
- package/templates/social/lib/media.ts +130 -0
- package/templates/social/lumenjs.auth.ts +21 -0
- package/templates/social/lumenjs.config.ts +3 -0
- package/templates/social/package.json +5 -0
- package/templates/social/pages/_layout.ts +239 -0
- package/templates/social/pages/apps/[id].ts +173 -0
- package/templates/social/pages/apps/index.ts +116 -0
- package/templates/social/pages/auth/login.ts +92 -0
- package/templates/social/pages/bookmarks.ts +57 -0
- package/templates/social/pages/explore.ts +73 -0
- package/templates/social/pages/index.ts +351 -0
- package/templates/social/pages/messages.ts +298 -0
- package/templates/social/pages/new.ts +77 -0
- package/templates/social/pages/notifications.ts +73 -0
- package/templates/social/pages/post/[id].ts +124 -0
- package/templates/social/pages/profile/[username].ts +100 -0
- package/templates/social/pages/settings/accessibility.ts +153 -0
- package/templates/social/pages/settings/account.ts +260 -0
- package/templates/social/pages/settings/help.ts +141 -0
- package/templates/social/pages/settings/language.ts +103 -0
- package/templates/social/pages/settings/privacy.ts +183 -0
- package/templates/social/pages/settings/security.ts +133 -0
- package/templates/social/pages/settings.ts +185 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
|
|
3
|
+
const svg = {
|
|
4
|
+
search: html`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>`,
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export async function loader() {
|
|
8
|
+
return {
|
|
9
|
+
featured: [
|
|
10
|
+
{ id: 'poll', name: 'Polls', desc: 'Create polls and surveys for your community', color: '#7c3aed', icon: 'bar-chart' },
|
|
11
|
+
{ id: 'calendar', name: 'Calendar', desc: 'Track events, meetings, and deadlines', color: '#3b49df', icon: 'calendar' },
|
|
12
|
+
{ id: 'notes', name: 'Quick Notes', desc: 'Markdown notes that sync across devices', color: '#22c55e', icon: 'file-text' },
|
|
13
|
+
],
|
|
14
|
+
categories: ['Productivity', 'Entertainment', 'Finance', 'Social', 'Developer Tools', 'Health'],
|
|
15
|
+
apps: [
|
|
16
|
+
{ id: 'poll', name: 'Poll Creator', desc: 'Create polls and surveys for your feed', category: 'Social', color: '#7c3aed' },
|
|
17
|
+
{ id: 'calendar', name: 'Mini Calendar', desc: 'Track events and meetings', category: 'Productivity', color: '#3b49df' },
|
|
18
|
+
{ id: 'notes', name: 'Quick Notes', desc: 'Markdown notes with cloud sync', category: 'Productivity', color: '#22c55e' },
|
|
19
|
+
{ id: 'timer', name: 'Focus Timer', desc: 'Pomodoro timer for deep work', category: 'Productivity', color: '#ef4444' },
|
|
20
|
+
{ id: 'weather', name: 'Weather', desc: 'Local weather and forecasts', category: 'Entertainment', color: '#f59e0b' },
|
|
21
|
+
{ id: 'stocks', name: 'Stock Tracker', desc: 'Watch your portfolio in real-time', category: 'Finance', color: '#10b981' },
|
|
22
|
+
{ id: 'news', name: 'News Feed', desc: 'Curated tech news from top sources', category: 'Entertainment', color: '#6366f1' },
|
|
23
|
+
{ id: 'tasks', name: 'Task Board', desc: 'Kanban-style task management', category: 'Productivity', color: '#8b5cf6' },
|
|
24
|
+
{ id: 'translate', name: 'Translator', desc: 'Translate text between languages', category: 'Developer Tools', color: '#06b6d4' },
|
|
25
|
+
{ id: 'code', name: 'Code Snippets', desc: 'Save and share code snippets', category: 'Developer Tools', color: '#0f172a' },
|
|
26
|
+
{ id: 'fitness', name: 'Step Counter', desc: 'Track daily steps and activity', category: 'Health', color: '#ec4899' },
|
|
27
|
+
{ id: 'budget', name: 'Budget Tracker', desc: 'Track expenses and income', category: 'Finance', color: '#14b8a6' },
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class PageApps extends LitElement {
|
|
33
|
+
static properties = { loaderData: { type: Object }, _category: { state: true } };
|
|
34
|
+
loaderData: any = {};
|
|
35
|
+
_category: string = '';
|
|
36
|
+
|
|
37
|
+
static styles = css`
|
|
38
|
+
:host { display: block; }
|
|
39
|
+
.card { background: var(--bg); border-radius: 6px; border: 1px solid var(--border); overflow: hidden; margin-bottom: 12px; }
|
|
40
|
+
h2 { font-size: 20px; font-weight: 700; padding: 16px 20px 8px; margin: 0; }
|
|
41
|
+
|
|
42
|
+
.search-wrap { padding: 0 20px 16px; position: relative; }
|
|
43
|
+
.search-icon { position: absolute; left: 32px; top: 50%; transform: translateY(-50%); color: var(--text-secondary); display: flex; }
|
|
44
|
+
.search { width: 100%; padding: 10px 12px 10px 36px; border: 1px solid var(--border); border-radius: 9999px; font-size: 14px; outline: none; background: var(--input-bg); }
|
|
45
|
+
.search:focus { border-color: var(--accent); background: var(--bg); }
|
|
46
|
+
|
|
47
|
+
.featured { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; padding: 0 20px 16px; }
|
|
48
|
+
.feat-card { border: 1px solid var(--border); border-radius: 12px; padding: 16px; cursor: pointer; text-decoration: none; color: inherit; transition: box-shadow 0.15s; }
|
|
49
|
+
.feat-card:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
|
|
50
|
+
.feat-icon { width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 18px; font-weight: 700; }
|
|
51
|
+
.feat-name { font-size: 15px; font-weight: 700; margin-top: 10px; }
|
|
52
|
+
.feat-desc { font-size: 12px; color: var(--text-secondary); margin-top: 4px; line-height: 1.3; }
|
|
53
|
+
|
|
54
|
+
.categories { display: flex; gap: 6px; padding: 0 20px 12px; overflow-x: auto; scrollbar-width: none; }
|
|
55
|
+
.categories::-webkit-scrollbar { display: none; }
|
|
56
|
+
.cat-btn { padding: 6px 14px; border-radius: 9999px; border: 1px solid var(--border); background: var(--bg); font-size: 13px; color: var(--text-secondary); cursor: pointer; white-space: nowrap; font-weight: 500; }
|
|
57
|
+
.cat-btn:hover { border-color: var(--accent); color: var(--accent); }
|
|
58
|
+
.cat-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); }
|
|
59
|
+
|
|
60
|
+
.app-list { padding: 0 20px 8px; }
|
|
61
|
+
.app-item { display: flex; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border-light); align-items: center; }
|
|
62
|
+
.app-item:last-child { border-bottom: none; }
|
|
63
|
+
.app-icon { width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 16px; font-weight: 700; flex-shrink: 0; }
|
|
64
|
+
.app-info { flex: 1; min-width: 0; }
|
|
65
|
+
.app-name { font-size: 14px; font-weight: 700; }
|
|
66
|
+
.app-desc { font-size: 12px; color: var(--text-secondary); margin-top: 1px; }
|
|
67
|
+
.app-cat { font-size: 11px; color: var(--text-tertiary); margin-top: 2px; }
|
|
68
|
+
.open-btn { padding: 5px 14px; border-radius: 9999px; border: 1px solid var(--accent); color: var(--accent); background: var(--bg); font-size: 12px; font-weight: 600; cursor: pointer; text-decoration: none; }
|
|
69
|
+
.open-btn:hover { background: rgba(124,58,237,0.1); }
|
|
70
|
+
|
|
71
|
+
@media (max-width: 640px) { .featured { grid-template-columns: 1fr; } }
|
|
72
|
+
`;
|
|
73
|
+
|
|
74
|
+
render() {
|
|
75
|
+
const { featured, categories, apps } = this.loaderData;
|
|
76
|
+
const filtered = this._category ? apps?.filter((a: any) => a.category === this._category) : apps;
|
|
77
|
+
return html`
|
|
78
|
+
<div class="card">
|
|
79
|
+
<h2>Apps</h2>
|
|
80
|
+
<div class="search-wrap">
|
|
81
|
+
<span class="search-icon">${svg.search}</span>
|
|
82
|
+
<input class="search" type="text" placeholder="Search apps...">
|
|
83
|
+
</div>
|
|
84
|
+
<h2 style="font-size:16px;padding-top:0">Featured</h2>
|
|
85
|
+
<div class="featured">
|
|
86
|
+
${(featured || []).map((f: any) => html`
|
|
87
|
+
<a class="feat-card" href="/apps/${f.id}">
|
|
88
|
+
<div class="feat-icon" style="background:${f.color}">${f.name.charAt(0)}</div>
|
|
89
|
+
<div class="feat-name">${f.name}</div>
|
|
90
|
+
<div class="feat-desc">${f.desc}</div>
|
|
91
|
+
</a>
|
|
92
|
+
`)}
|
|
93
|
+
</div>
|
|
94
|
+
<div class="categories">
|
|
95
|
+
<button class="cat-btn ${this._category === '' ? 'active' : ''}" @click=${() => this._category = ''}>All</button>
|
|
96
|
+
${(categories || []).map((c: string) => html`
|
|
97
|
+
<button class="cat-btn ${this._category === c ? 'active' : ''}" @click=${() => this._category = c}>${c}</button>
|
|
98
|
+
`)}
|
|
99
|
+
</div>
|
|
100
|
+
<div class="app-list">
|
|
101
|
+
${(filtered || []).map((a: any) => html`
|
|
102
|
+
<div class="app-item">
|
|
103
|
+
<div class="app-icon" style="background:${a.color}">${a.name.charAt(0)}</div>
|
|
104
|
+
<div class="app-info">
|
|
105
|
+
<div class="app-name">${a.name}</div>
|
|
106
|
+
<div class="app-desc">${a.desc}</div>
|
|
107
|
+
<div class="app-cat">${a.category}</div>
|
|
108
|
+
</div>
|
|
109
|
+
<a class="open-btn" href="/apps/${a.id}">Open</a>
|
|
110
|
+
</div>
|
|
111
|
+
`)}
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
|
|
3
|
+
// Google 'G' logo SVG (official colors)
|
|
4
|
+
const googleLogo = html`<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
|
|
5
|
+
<path d="M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844a4.14 4.14 0 01-1.796 2.716v2.259h2.908c1.702-1.567 2.684-3.875 2.684-6.615z" fill="#4285F4"/>
|
|
6
|
+
<path d="M9 18c2.43 0 4.467-.806 5.956-2.18l-2.908-2.259c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332A8.997 8.997 0 009 18z" fill="#34A853"/>
|
|
7
|
+
<path d="M3.964 10.71A5.41 5.41 0 013.682 9c0-.593.102-1.17.282-1.71V4.958H.957A8.996 8.996 0 000 9c0 1.452.348 2.827.957 4.042l3.007-2.332z" fill="#FBBC05"/>
|
|
8
|
+
<path d="M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0A8.997 8.997 0 00.957 4.958L3.964 6.29C4.672 4.163 6.656 3.58 9 3.58z" fill="#EA4335"/>
|
|
9
|
+
</svg>`;
|
|
10
|
+
|
|
11
|
+
export async function loader({ query }: any) {
|
|
12
|
+
return {
|
|
13
|
+
error: query?.error ?? null,
|
|
14
|
+
returnTo: query?.returnTo ?? '/',
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class PageAuthLogin extends LitElement {
|
|
19
|
+
static properties = { loaderData: { type: Object } };
|
|
20
|
+
loaderData: any = {};
|
|
21
|
+
|
|
22
|
+
static styles = css`
|
|
23
|
+
:host { display: flex; align-items: center; justify-content: center; min-height: 80vh; padding: 24px 16px; }
|
|
24
|
+
|
|
25
|
+
.card {
|
|
26
|
+
width: 100%; max-width: 380px;
|
|
27
|
+
background: var(--bg); border: 1px solid var(--border);
|
|
28
|
+
border-radius: 16px; padding: 40px 32px;
|
|
29
|
+
text-align: center;
|
|
30
|
+
box-shadow: 0 4px 24px rgba(0,0,0,0.06);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.logo {
|
|
34
|
+
width: 52px; height: 52px; border-radius: 50%;
|
|
35
|
+
background: var(--accent); color: #fff;
|
|
36
|
+
font-size: 24px; font-weight: 900;
|
|
37
|
+
display: flex; align-items: center; justify-content: center;
|
|
38
|
+
margin: 0 auto 20px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
h1 { font-size: 22px; font-weight: 800; margin: 0 0 6px; color: var(--text); }
|
|
42
|
+
p { font-size: 14px; color: var(--text-secondary); margin: 0 0 28px; }
|
|
43
|
+
|
|
44
|
+
.error {
|
|
45
|
+
background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px;
|
|
46
|
+
color: #dc2626; font-size: 13px; padding: 10px 14px;
|
|
47
|
+
margin-bottom: 20px; text-align: left;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.google-btn {
|
|
51
|
+
display: flex; align-items: center; justify-content: center; gap: 10px;
|
|
52
|
+
width: 100%; padding: 11px 20px;
|
|
53
|
+
background: var(--bg); color: var(--text);
|
|
54
|
+
border: 1px solid var(--border); border-radius: 8px;
|
|
55
|
+
font-size: 14px; font-weight: 600;
|
|
56
|
+
text-decoration: none; cursor: pointer;
|
|
57
|
+
transition: background 0.15s, border-color 0.15s;
|
|
58
|
+
}
|
|
59
|
+
.google-btn:hover { background: var(--bg-secondary); border-color: var(--accent); }
|
|
60
|
+
|
|
61
|
+
.divider { display: flex; align-items: center; gap: 12px; margin: 20px 0; color: var(--text-tertiary); font-size: 12px; }
|
|
62
|
+
.divider::before, .divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }
|
|
63
|
+
|
|
64
|
+
.terms { font-size: 12px; color: var(--text-tertiary); margin-top: 20px; line-height: 1.5; }
|
|
65
|
+
`;
|
|
66
|
+
|
|
67
|
+
render() {
|
|
68
|
+
const { error, returnTo } = this.loaderData;
|
|
69
|
+
const loginUrl = `/__nk_auth/login/google?returnTo=${encodeURIComponent(returnTo ?? '/')}`;
|
|
70
|
+
const errorMsg = error === 'access_denied' ? 'Access was denied. Please try again.'
|
|
71
|
+
: error === 'state_mismatch' ? 'Login session expired. Please try again.'
|
|
72
|
+
: error ? 'Authentication failed. Please try again.'
|
|
73
|
+
: null;
|
|
74
|
+
|
|
75
|
+
return html`
|
|
76
|
+
<div class="card">
|
|
77
|
+
<div class="logo">N</div>
|
|
78
|
+
<h1>Sign in</h1>
|
|
79
|
+
<p>Welcome back — sign in to continue</p>
|
|
80
|
+
|
|
81
|
+
${errorMsg ? html`<div class="error">${errorMsg}</div>` : ''}
|
|
82
|
+
|
|
83
|
+
<a class="google-btn" href="${loginUrl}">
|
|
84
|
+
${googleLogo}
|
|
85
|
+
Continue with Google
|
|
86
|
+
</a>
|
|
87
|
+
|
|
88
|
+
<p class="terms">By signing in you agree to our Terms of Service and Privacy Policy.</p>
|
|
89
|
+
</div>
|
|
90
|
+
`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
|
|
3
|
+
const svg = {
|
|
4
|
+
bookmark: html`<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M19 21l-7-5-7 5V5a2 2 0 012-2h10a2 2 0 012 2z"/></svg>`,
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export async function loader() {
|
|
8
|
+
return {
|
|
9
|
+
bookmarks: [
|
|
10
|
+
{ id: 1, username: 'aymen', display_name: 'Aymen Labidi', initials: 'AL', color: '#7c3aed', title: 'Why file-based routing changes everything', saved: '2 hours ago' },
|
|
11
|
+
{ id: 7, username: 'emma_data', display_name: 'Emma Williams', initials: 'EW', color: '#3572a5', title: 'Polars vs Pandas: a practical comparison', saved: '1 day ago' },
|
|
12
|
+
{ id: 4, username: 'mike_ops', display_name: 'Mike Johnson', initials: 'MJ', color: '#22c55e', title: 'Migrating CI/CD to GitHub Actions: a retrospective', saved: '3 days ago' },
|
|
13
|
+
],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class PageBookmarks extends LitElement {
|
|
18
|
+
static properties = { loaderData: { type: Object } };
|
|
19
|
+
loaderData: any = {};
|
|
20
|
+
|
|
21
|
+
static styles = css`
|
|
22
|
+
:host { display: block; }
|
|
23
|
+
.card { background: var(--bg); border-radius: 6px; border: 1px solid var(--border); overflow: hidden; }
|
|
24
|
+
h2 { font-size: 20px; font-weight: 700; padding: 16px 20px; margin: 0; border-bottom: 1px solid var(--border-light); }
|
|
25
|
+
.item { display: flex; gap: 10px; padding: 12px 20px; border-bottom: 1px solid var(--border-light); cursor: pointer; }
|
|
26
|
+
.item:hover { background: var(--bg-hover); }
|
|
27
|
+
.item:last-child { border-bottom: none; }
|
|
28
|
+
.item-icon { width: 36px; height: 36px; border-radius: 8px; background: var(--bg-secondary); display: flex; align-items: center; justify-content: center; color: var(--accent); flex-shrink: 0; }
|
|
29
|
+
.item-body { flex: 1; }
|
|
30
|
+
.item-title { font-size: 15px; font-weight: 600; }
|
|
31
|
+
.item-title a { color: var(--text); text-decoration: none; }
|
|
32
|
+
.item-title a:hover { color: var(--accent); }
|
|
33
|
+
.item-meta { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
|
|
34
|
+
.empty { padding: 48px 20px; text-align: center; color: var(--text-secondary); font-size: 14px; }
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
render() {
|
|
38
|
+
const bookmarks = this.loaderData.bookmarks || [];
|
|
39
|
+
return html`
|
|
40
|
+
<div class="card">
|
|
41
|
+
<h2>Bookmarks</h2>
|
|
42
|
+
${bookmarks.length === 0
|
|
43
|
+
? html`<div class="empty">No bookmarks yet</div>`
|
|
44
|
+
: bookmarks.map((b: any) => html`
|
|
45
|
+
<div class="item">
|
|
46
|
+
<div class="item-icon">${svg.bookmark}</div>
|
|
47
|
+
<div class="item-body">
|
|
48
|
+
<div class="item-title"><a href="/post/${b.id}">${b.title}</a></div>
|
|
49
|
+
<div class="item-meta">${b.display_name} · Saved ${b.saved}</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
`)
|
|
53
|
+
}
|
|
54
|
+
</div>
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
|
|
3
|
+
export async function loader() {
|
|
4
|
+
return {
|
|
5
|
+
tags: [
|
|
6
|
+
{ name: 'webcomponents', count: 1250, color: '#3b49df' },
|
|
7
|
+
{ name: 'typescript', count: 3400, color: '#3178c6' },
|
|
8
|
+
{ name: 'devops', count: 890, color: '#e44d26' },
|
|
9
|
+
{ name: 'machinelearning', count: 2100, color: '#f7df1e' },
|
|
10
|
+
{ name: 'opensource', count: 1800, color: '#22c55e' },
|
|
11
|
+
{ name: 'css', count: 4200, color: '#a855f7' },
|
|
12
|
+
{ name: 'python', count: 5100, color: '#3572a5' },
|
|
13
|
+
{ name: 'beginners', count: 6300, color: '#ef4444' },
|
|
14
|
+
],
|
|
15
|
+
topPosts: [
|
|
16
|
+
{ id: 9, display_name: 'Aymen Labidi', title: 'Building a commit message generator with Claude', likes: 112, comments: 18, time: '4 days ago' },
|
|
17
|
+
{ id: 7, display_name: 'Emma Williams', title: 'Polars vs Pandas: a practical comparison', likes: 93, comments: 15, time: '3 days ago' },
|
|
18
|
+
{ id: 5, display_name: 'Aymen Labidi', title: 'TypeScript\'s type system is secretly a language', likes: 85, comments: 12, time: '2 days ago' },
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class PageExplore extends LitElement {
|
|
24
|
+
static properties = { loaderData: { type: Object } };
|
|
25
|
+
loaderData: any = {};
|
|
26
|
+
|
|
27
|
+
static styles = css`
|
|
28
|
+
:host { display: block; }
|
|
29
|
+
.card { background: var(--bg); border-radius: 6px; border: 1px solid var(--border); padding: 20px; margin-bottom: 12px; }
|
|
30
|
+
h2 { font-size: 20px; font-weight: 700; margin: 0 0 16px; }
|
|
31
|
+
|
|
32
|
+
.tags-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; }
|
|
33
|
+
.tag-card { border: 1px solid var(--border); border-radius: 6px; padding: 12px 16px; cursor: pointer; transition: all 0.15s; }
|
|
34
|
+
.tag-card:hover { border-color: #d0d0d0; box-shadow: 0 2px 4px rgba(0,0,0,0.04); }
|
|
35
|
+
.tag-top { width: 100%; height: 6px; border-radius: 3px; margin-bottom: 8px; }
|
|
36
|
+
.tag-name { font-size: 16px; font-weight: 600; }
|
|
37
|
+
.tag-count { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
|
|
38
|
+
|
|
39
|
+
.top-post { padding: 10px 0; border-bottom: 1px solid var(--border-light); }
|
|
40
|
+
.top-post:last-child { border-bottom: none; }
|
|
41
|
+
.top-title { font-size: 15px; font-weight: 600; }
|
|
42
|
+
.top-title a { color: var(--text); text-decoration: none; }
|
|
43
|
+
.top-title a:hover { color: var(--accent); }
|
|
44
|
+
.top-meta { font-size: 12px; color: var(--text-secondary); margin-top: 4px; }
|
|
45
|
+
`;
|
|
46
|
+
|
|
47
|
+
render() {
|
|
48
|
+
const { tags, topPosts } = this.loaderData;
|
|
49
|
+
return html`
|
|
50
|
+
<div class="card">
|
|
51
|
+
<h2>Popular Tags</h2>
|
|
52
|
+
<div class="tags-grid">
|
|
53
|
+
${(tags || []).map((t: any) => html`
|
|
54
|
+
<div class="tag-card">
|
|
55
|
+
<div class="tag-top" style="background:${t.color}"></div>
|
|
56
|
+
<div class="tag-name">#${t.name}</div>
|
|
57
|
+
<div class="tag-count">${t.count.toLocaleString()} posts published</div>
|
|
58
|
+
</div>
|
|
59
|
+
`)}
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="card">
|
|
63
|
+
<h2>Top Posts This Week</h2>
|
|
64
|
+
${(topPosts || []).map((p: any) => html`
|
|
65
|
+
<div class="top-post">
|
|
66
|
+
<div class="top-title"><a href="/post/${p.id}">${p.title}</a></div>
|
|
67
|
+
<div class="top-meta">${p.display_name} · ${p.likes} reactions · ${p.comments} comments · ${p.time}</div>
|
|
68
|
+
</div>
|
|
69
|
+
`)}
|
|
70
|
+
</div>
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
}
|