sh3-core 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/Shell.svelte +283 -0
- package/dist/Shell.svelte.d.ts +5 -0
- package/dist/api.d.ts +28 -0
- package/dist/api.js +50 -0
- package/dist/app/admin/ApiKeysView.svelte +169 -0
- package/dist/app/admin/ApiKeysView.svelte.d.ts +3 -0
- package/dist/app/admin/AuthSettingsView.svelte +105 -0
- package/dist/app/admin/AuthSettingsView.svelte.d.ts +3 -0
- package/dist/app/admin/SystemView.svelte +73 -0
- package/dist/app/admin/SystemView.svelte.d.ts +3 -0
- package/dist/app/admin/UsersView.svelte +188 -0
- package/dist/app/admin/UsersView.svelte.d.ts +3 -0
- package/dist/app/admin/adminApp.d.ts +7 -0
- package/dist/app/admin/adminApp.js +25 -0
- package/dist/app/admin/adminShard.svelte.d.ts +4 -0
- package/dist/app/admin/adminShard.svelte.js +62 -0
- package/dist/app/store/InstalledView.svelte +246 -0
- package/dist/app/store/InstalledView.svelte.d.ts +3 -0
- package/dist/app/store/StoreView.svelte +522 -0
- package/dist/app/store/StoreView.svelte.d.ts +3 -0
- package/dist/app/store/storeApp.d.ts +10 -0
- package/dist/app/store/storeApp.js +26 -0
- package/dist/app/store/storeShard.svelte.d.ts +38 -0
- package/dist/app/store/storeShard.svelte.js +218 -0
- package/dist/apps/lifecycle.d.ts +42 -0
- package/dist/apps/lifecycle.js +184 -0
- package/dist/apps/registry.svelte.d.ts +40 -0
- package/dist/apps/registry.svelte.js +59 -0
- package/dist/apps/terminal/manifest.d.ts +8 -0
- package/dist/apps/terminal/manifest.js +13 -0
- package/dist/apps/terminal/terminal-app.d.ts +7 -0
- package/dist/apps/terminal/terminal-app.js +14 -0
- package/dist/apps/types.d.ts +93 -0
- package/dist/apps/types.js +10 -0
- package/dist/artifact.d.ts +32 -0
- package/dist/artifact.js +1 -0
- package/dist/assets/SH3.png +0 -0
- package/dist/assets/icons.svg +1126 -0
- package/dist/assets.d.ts +13 -0
- package/dist/auth/GuestBanner.svelte +134 -0
- package/dist/auth/GuestBanner.svelte.d.ts +3 -0
- package/dist/auth/SignInWall.svelte +203 -0
- package/dist/auth/SignInWall.svelte.d.ts +7 -0
- package/dist/auth/auth.svelte.d.ts +69 -0
- package/dist/auth/auth.svelte.js +165 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.js +1 -0
- package/dist/auth/types.d.ts +41 -0
- package/dist/auth/types.js +6 -0
- package/dist/build.d.ts +49 -0
- package/dist/build.js +236 -0
- package/dist/contract.d.ts +20 -0
- package/dist/contract.js +28 -0
- package/dist/createShell.d.ts +24 -0
- package/dist/createShell.js +131 -0
- package/dist/documents/backends.d.ts +17 -0
- package/dist/documents/backends.js +156 -0
- package/dist/documents/config.d.ts +7 -0
- package/dist/documents/config.js +27 -0
- package/dist/documents/handle.d.ts +6 -0
- package/dist/documents/handle.js +154 -0
- package/dist/documents/http-backend.d.ts +22 -0
- package/dist/documents/http-backend.js +78 -0
- package/dist/documents/index.d.ts +6 -0
- package/dist/documents/index.js +8 -0
- package/dist/documents/notifications.d.ts +9 -0
- package/dist/documents/notifications.js +39 -0
- package/dist/documents/types.d.ts +97 -0
- package/dist/documents/types.js +12 -0
- package/dist/env/client.d.ts +44 -0
- package/dist/env/client.js +106 -0
- package/dist/env/index.d.ts +2 -0
- package/dist/env/index.js +1 -0
- package/dist/env/types.d.ts +12 -0
- package/dist/env/types.js +8 -0
- package/dist/host-entry.d.ts +13 -0
- package/dist/host-entry.js +17 -0
- package/dist/host.d.ts +15 -0
- package/dist/host.js +86 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +14 -0
- package/dist/layout/DragPreview.svelte +63 -0
- package/dist/layout/DragPreview.svelte.d.ts +3 -0
- package/dist/layout/LayoutRenderer.svelte +262 -0
- package/dist/layout/LayoutRenderer.svelte.d.ts +6 -0
- package/dist/layout/SlotContainer.svelte +140 -0
- package/dist/layout/SlotContainer.svelte.d.ts +8 -0
- package/dist/layout/SlotDropZone.svelte +122 -0
- package/dist/layout/SlotDropZone.svelte.d.ts +8 -0
- package/dist/layout/drag.svelte.d.ts +45 -0
- package/dist/layout/drag.svelte.js +200 -0
- package/dist/layout/inspection.d.ts +72 -0
- package/dist/layout/inspection.js +209 -0
- package/dist/layout/ops.d.ts +100 -0
- package/dist/layout/ops.js +310 -0
- package/dist/layout/slotHostPool.svelte.d.ts +36 -0
- package/dist/layout/slotHostPool.svelte.js +229 -0
- package/dist/layout/store.svelte.d.ts +39 -0
- package/dist/layout/store.svelte.js +153 -0
- package/dist/layout/tree-walk.d.ts +15 -0
- package/dist/layout/tree-walk.js +33 -0
- package/dist/layout/types.d.ts +108 -0
- package/dist/layout/types.js +25 -0
- package/dist/migrations/shell-rename.d.ts +16 -0
- package/dist/migrations/shell-rename.js +48 -0
- package/dist/overlays/ModalFrame.svelte +87 -0
- package/dist/overlays/ModalFrame.svelte.d.ts +10 -0
- package/dist/overlays/PopupFrame.svelte +85 -0
- package/dist/overlays/PopupFrame.svelte.d.ts +10 -0
- package/dist/overlays/ToastItem.svelte +77 -0
- package/dist/overlays/ToastItem.svelte.d.ts +9 -0
- package/dist/overlays/focusTrap.d.ts +1 -0
- package/dist/overlays/focusTrap.js +64 -0
- package/dist/overlays/modal.d.ts +9 -0
- package/dist/overlays/modal.js +141 -0
- package/dist/overlays/popup.d.ts +9 -0
- package/dist/overlays/popup.js +108 -0
- package/dist/overlays/roots.d.ts +4 -0
- package/dist/overlays/roots.js +31 -0
- package/dist/overlays/toast.d.ts +6 -0
- package/dist/overlays/toast.js +93 -0
- package/dist/overlays/types.d.ts +31 -0
- package/dist/overlays/types.js +15 -0
- package/dist/platform/index.d.ts +10 -0
- package/dist/platform/index.js +33 -0
- package/dist/platform/tauri-backend.d.ts +15 -0
- package/dist/platform/tauri-backend.js +58 -0
- package/dist/primitives/.gitkeep +0 -0
- package/dist/primitives/ResizableSplitter.svelte +333 -0
- package/dist/primitives/ResizableSplitter.svelte.d.ts +35 -0
- package/dist/primitives/TabbedPanel.svelte +305 -0
- package/dist/primitives/TabbedPanel.svelte.d.ts +50 -0
- package/dist/primitives/base.css +42 -0
- package/dist/registry/client.d.ts +74 -0
- package/dist/registry/client.js +117 -0
- package/dist/registry/index.d.ts +13 -0
- package/dist/registry/index.js +14 -0
- package/dist/registry/installer.d.ts +53 -0
- package/dist/registry/installer.js +168 -0
- package/dist/registry/integrity.d.ts +32 -0
- package/dist/registry/integrity.js +92 -0
- package/dist/registry/loader.d.ts +50 -0
- package/dist/registry/loader.js +145 -0
- package/dist/registry/schema.d.ts +47 -0
- package/dist/registry/schema.js +185 -0
- package/dist/registry/storage.d.ts +37 -0
- package/dist/registry/storage.js +101 -0
- package/dist/registry/types.d.ts +262 -0
- package/dist/registry/types.js +14 -0
- package/dist/server-shard/types.d.ts +67 -0
- package/dist/server-shard/types.js +13 -0
- package/dist/sh3core-shard/ShellHome.svelte +192 -0
- package/dist/sh3core-shard/ShellHome.svelte.d.ts +3 -0
- package/dist/sh3core-shard/ShellTitle.svelte +171 -0
- package/dist/sh3core-shard/ShellTitle.svelte.d.ts +3 -0
- package/dist/sh3core-shard/sh3coreShard.svelte.d.ts +2 -0
- package/dist/sh3core-shard/sh3coreShard.svelte.js +53 -0
- package/dist/shards/activate.svelte.d.ts +52 -0
- package/dist/shards/activate.svelte.js +186 -0
- package/dist/shards/registry.d.ts +4 -0
- package/dist/shards/registry.js +28 -0
- package/dist/shards/types.d.ts +207 -0
- package/dist/shards/types.js +20 -0
- package/dist/shell-shard/InputLine.svelte +133 -0
- package/dist/shell-shard/InputLine.svelte.d.ts +11 -0
- package/dist/shell-shard/ScrollbackView.svelte +47 -0
- package/dist/shell-shard/ScrollbackView.svelte.d.ts +7 -0
- package/dist/shell-shard/Terminal.svelte +122 -0
- package/dist/shell-shard/Terminal.svelte.d.ts +8 -0
- package/dist/shell-shard/entries/PromptEntry.svelte +25 -0
- package/dist/shell-shard/entries/PromptEntry.svelte.d.ts +7 -0
- package/dist/shell-shard/entries/RichEntry.svelte +19 -0
- package/dist/shell-shard/entries/RichEntry.svelte.d.ts +8 -0
- package/dist/shell-shard/entries/StatusEntry.svelte +22 -0
- package/dist/shell-shard/entries/StatusEntry.svelte.d.ts +7 -0
- package/dist/shell-shard/entries/TextEntry.svelte +25 -0
- package/dist/shell-shard/entries/TextEntry.svelte.d.ts +7 -0
- package/dist/shell-shard/manifest.d.ts +2 -0
- package/dist/shell-shard/manifest.js +11 -0
- package/dist/shell-shard/protocol.d.ts +90 -0
- package/dist/shell-shard/protocol.js +11 -0
- package/dist/shell-shard/registry.d.ts +69 -0
- package/dist/shell-shard/registry.js +47 -0
- package/dist/shell-shard/rich/AppCard.svelte +25 -0
- package/dist/shell-shard/rich/AppCard.svelte.d.ts +10 -0
- package/dist/shell-shard/rich/AppsTable.svelte +29 -0
- package/dist/shell-shard/rich/AppsTable.svelte.d.ts +12 -0
- package/dist/shell-shard/rich/EnvTable.svelte +27 -0
- package/dist/shell-shard/rich/EnvTable.svelte.d.ts +8 -0
- package/dist/shell-shard/rich/HelpTable.svelte +29 -0
- package/dist/shell-shard/rich/HelpTable.svelte.d.ts +12 -0
- package/dist/shell-shard/rich/HistoryList.svelte +37 -0
- package/dist/shell-shard/rich/HistoryList.svelte.d.ts +9 -0
- package/dist/shell-shard/rich/ShardsTable.svelte +28 -0
- package/dist/shell-shard/rich/ShardsTable.svelte.d.ts +12 -0
- package/dist/shell-shard/rich/ViewsTable.svelte +31 -0
- package/dist/shell-shard/rich/ViewsTable.svelte.d.ts +13 -0
- package/dist/shell-shard/rich/ZoneTree.svelte +19 -0
- package/dist/shell-shard/rich/ZoneTree.svelte.d.ts +8 -0
- package/dist/shell-shard/rich/ZonesTable.svelte +27 -0
- package/dist/shell-shard/rich/ZonesTable.svelte.d.ts +11 -0
- package/dist/shell-shard/scrollback.svelte.d.ts +36 -0
- package/dist/shell-shard/scrollback.svelte.js +43 -0
- package/dist/shell-shard/session-client.svelte.d.ts +23 -0
- package/dist/shell-shard/session-client.svelte.js +120 -0
- package/dist/shell-shard/shellShard.svelte.d.ts +2 -0
- package/dist/shell-shard/shellShard.svelte.js +139 -0
- package/dist/shell-shard/verbs/apps.d.ts +3 -0
- package/dist/shell-shard/verbs/apps.js +50 -0
- package/dist/shell-shard/verbs/clear.d.ts +2 -0
- package/dist/shell-shard/verbs/clear.js +7 -0
- package/dist/shell-shard/verbs/help.d.ts +2 -0
- package/dist/shell-shard/verbs/help.js +21 -0
- package/dist/shell-shard/verbs/history.d.ts +2 -0
- package/dist/shell-shard/verbs/history.js +20 -0
- package/dist/shell-shard/verbs/index.d.ts +2 -0
- package/dist/shell-shard/verbs/index.js +29 -0
- package/dist/shell-shard/verbs/session.d.ts +5 -0
- package/dist/shell-shard/verbs/session.js +65 -0
- package/dist/shell-shard/verbs/shards.d.ts +2 -0
- package/dist/shell-shard/verbs/shards.js +14 -0
- package/dist/shell-shard/verbs/views.d.ts +4 -0
- package/dist/shell-shard/verbs/views.js +90 -0
- package/dist/shell-shard/verbs/zones.d.ts +3 -0
- package/dist/shell-shard/verbs/zones.js +38 -0
- package/dist/shellRuntime.svelte.d.ts +27 -0
- package/dist/shellRuntime.svelte.js +27 -0
- package/dist/state/backends.d.ts +26 -0
- package/dist/state/backends.js +99 -0
- package/dist/state/manage.d.ts +14 -0
- package/dist/state/manage.js +40 -0
- package/dist/state/types.d.ts +55 -0
- package/dist/state/types.js +17 -0
- package/dist/state/zones.svelte.d.ts +53 -0
- package/dist/state/zones.svelte.js +141 -0
- package/dist/theme.d.ts +28 -0
- package/dist/theme.js +92 -0
- package/dist/tokens.css +102 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +2 -0
- package/package.json +60 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { registerShard, registerApp, bootstrap, __setBackend, setLocalOwner } from './host';
|
|
2
|
+
export type { BootstrapConfig } from './host';
|
|
3
|
+
export { __setTenantId, __setDocumentBackend } from './host';
|
|
4
|
+
export type { Backend } from './state/types';
|
|
5
|
+
export type { DocumentBackend } from './documents/types';
|
|
6
|
+
export { HttpDocumentBackend } from './documents/http-backend';
|
|
7
|
+
export { __setEnvServerUrl } from './env/index';
|
|
8
|
+
export { installPackage, uninstallPackage, listInstalledPackages, loadInstalledPackages, } from './registry/index';
|
|
9
|
+
export type { InstalledPackage, InstallResult, PackageMeta } from './registry/types';
|
|
10
|
+
export { initFromBoot, login, logout, register, setLocalOwner as setLocalOwnerAuth } from './auth/index';
|
|
11
|
+
export type { AuthUser, AuthSession, BootConfig, GlobalSettings } from './auth/types';
|
|
12
|
+
export { createShell } from './createShell';
|
|
13
|
+
export type { ShellConfig } from './createShell';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Host-process entry for the `sh3-core` package.
|
|
3
|
+
*
|
|
4
|
+
* This file is what `import ... from 'sh3-core/host'` resolves to. Only code that
|
|
5
|
+
* boots an SH3 shell (a main.ts that mounts Shell and registers shards/apps)
|
|
6
|
+
* should touch this path. Shards and apps must not import from here.
|
|
7
|
+
*/
|
|
8
|
+
export { registerShard, registerApp, bootstrap, __setBackend, setLocalOwner } from './host';
|
|
9
|
+
export { __setTenantId, __setDocumentBackend } from './host';
|
|
10
|
+
export { HttpDocumentBackend } from './documents/http-backend';
|
|
11
|
+
export { __setEnvServerUrl } from './env/index';
|
|
12
|
+
// Install API (host-only).
|
|
13
|
+
export { installPackage, uninstallPackage, listInstalledPackages, loadInstalledPackages, } from './registry/index';
|
|
14
|
+
// Auth (host-only — session lifecycle, boot initialization).
|
|
15
|
+
export { initFromBoot, login, logout, register, setLocalOwner as setLocalOwnerAuth } from './auth/index';
|
|
16
|
+
// Shell boot factory.
|
|
17
|
+
export { createShell } from './createShell';
|
package/dist/host.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { registerShard as registerShardInternal } from './shards/activate.svelte';
|
|
2
|
+
import { registerApp } from './apps/registry.svelte';
|
|
3
|
+
import { __setBackend } from './state/zones.svelte';
|
|
4
|
+
import { setLocalOwner } from './auth/index';
|
|
5
|
+
export { __setBackend };
|
|
6
|
+
export { setLocalOwner };
|
|
7
|
+
export { __setTenantId, __setDocumentBackend } from './documents/config';
|
|
8
|
+
export declare function registerShard(shard: Parameters<typeof registerShardInternal>[0]): void;
|
|
9
|
+
export { registerApp };
|
|
10
|
+
export interface BootstrapConfig {
|
|
11
|
+
/** Framework shard IDs to skip registration for */
|
|
12
|
+
excludeShards?: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare function bootstrap(config?: BootstrapConfig): Promise<void>;
|
|
15
|
+
export { installPackage, listInstalledPackages } from './registry/installer';
|
package/dist/host.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Host surface — functions `main.ts` (and only main.ts) calls.
|
|
3
|
+
*
|
|
4
|
+
* Registration APIs (`registerShard`, `registerApp`) are data-only and
|
|
5
|
+
* safe to call at any time; a future runtime loader uses them identically
|
|
6
|
+
* to hot-install registration at runtime.
|
|
7
|
+
*
|
|
8
|
+
* `bootstrap()` runs the post-registration boot sequence: it registers
|
|
9
|
+
* framework-owned shards and apps (filtering any the host excludes via
|
|
10
|
+
* BootstrapConfig), walks the registered-shards map and activates every
|
|
11
|
+
* self-starting shard, then reads the last-app user-zone entry and
|
|
12
|
+
* either launches that app or leaves the shell on home.
|
|
13
|
+
*
|
|
14
|
+
* This file is intentionally NOT re-exported through `api.ts`. The
|
|
15
|
+
* import-hygiene rule is: shards and apps import from `api.ts`, the host
|
|
16
|
+
* imports from `host.ts`.
|
|
17
|
+
*/
|
|
18
|
+
import { registerShard as registerShardInternal, activateShard, registeredShards, } from './shards/activate.svelte';
|
|
19
|
+
import { registerApp, registeredApps } from './apps/registry.svelte';
|
|
20
|
+
import { launchApp, readLastApp } from './apps/lifecycle';
|
|
21
|
+
import { sh3coreShard } from './sh3core-shard/sh3coreShard.svelte';
|
|
22
|
+
import { shellShard } from './shell-shard/shellShard.svelte';
|
|
23
|
+
import { storeShard } from './app/store/storeShard.svelte';
|
|
24
|
+
import { __setBackend, backends } from './state/zones.svelte';
|
|
25
|
+
import { loadInstalledPackages } from './registry/installer';
|
|
26
|
+
import { setLocalOwner } from './auth/index';
|
|
27
|
+
import { storeApp } from './app/store/storeApp';
|
|
28
|
+
import { adminShard } from './app/admin/adminShard.svelte';
|
|
29
|
+
import { adminApp } from './app/admin/adminApp';
|
|
30
|
+
import { terminalApp } from './apps/terminal/terminal-app';
|
|
31
|
+
import { runShellRenameMigration, } from './migrations/shell-rename';
|
|
32
|
+
export { __setBackend };
|
|
33
|
+
export { setLocalOwner };
|
|
34
|
+
export { __setTenantId, __setDocumentBackend } from './documents/config';
|
|
35
|
+
export function registerShard(shard) {
|
|
36
|
+
registerShardInternal(shard);
|
|
37
|
+
}
|
|
38
|
+
export { registerApp };
|
|
39
|
+
/**
|
|
40
|
+
* Adapter from the workspace-zone backend to the minimal KV shape the
|
|
41
|
+
* `__shell__` → `__sh3core__` migration needs. Kept local to host.ts so
|
|
42
|
+
* the migration module stays backend-agnostic.
|
|
43
|
+
*/
|
|
44
|
+
function createWorkspaceZoneAdapter() {
|
|
45
|
+
const backend = backends.workspace;
|
|
46
|
+
return {
|
|
47
|
+
keys: () => backend.list(),
|
|
48
|
+
read: (key) => backend.read(key),
|
|
49
|
+
write: (key, value) => backend.write(key, value),
|
|
50
|
+
delete: (key) => backend.delete(key),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export async function bootstrap(config) {
|
|
54
|
+
// Run before anything touches the workspace zone so renamed keys are
|
|
55
|
+
// already in place when shards activate.
|
|
56
|
+
if (typeof globalThis.localStorage !== 'undefined') {
|
|
57
|
+
runShellRenameMigration(createWorkspaceZoneAdapter(), globalThis.localStorage);
|
|
58
|
+
}
|
|
59
|
+
const exShards = new Set(config === null || config === void 0 ? void 0 : config.excludeShards);
|
|
60
|
+
// 1. Framework-owned shards
|
|
61
|
+
const frameworkShards = [sh3coreShard, shellShard, storeShard, adminShard];
|
|
62
|
+
for (const shard of frameworkShards) {
|
|
63
|
+
if (!exShards.has(shard.manifest.id)) {
|
|
64
|
+
registerShardInternal(shard);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// 2. Framework-shipped apps
|
|
68
|
+
const frameworkApps = [storeApp, adminApp, terminalApp];
|
|
69
|
+
for (const app of frameworkApps) {
|
|
70
|
+
registerApp(app);
|
|
71
|
+
}
|
|
72
|
+
// 3. Load any packages installed in a previous session from IndexedDB
|
|
73
|
+
await loadInstalledPackages();
|
|
74
|
+
// 4. Activate every self-starting shard
|
|
75
|
+
for (const [id, shard] of registeredShards) {
|
|
76
|
+
if (shard.autostart) {
|
|
77
|
+
await activateShard(id);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// 5. Read the last-active app from the user zone
|
|
81
|
+
const lastId = readLastApp();
|
|
82
|
+
if (lastId && registeredApps.has(lastId)) {
|
|
83
|
+
await launchApp(lastId);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export { installPackage, listInstalledPackages } from './registry/installer';
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Main public entry for the `sh3-core` package.
|
|
3
|
+
*
|
|
4
|
+
* This file is what `import ... from 'sh3-core'` resolves to. It re-exports the
|
|
5
|
+
* phase 8 public surface (api.ts) plus the Shell host component. Shard and
|
|
6
|
+
* app authors import from here.
|
|
7
|
+
*
|
|
8
|
+
* Host-process functions (registerShard, registerApp, bootstrap) are
|
|
9
|
+
* deliberately NOT exported here — they live at `sh3-core/host` because shards
|
|
10
|
+
* and apps must not register each other. See host-entry.ts.
|
|
11
|
+
*/
|
|
12
|
+
export * from './api';
|
|
13
|
+
export { default as Shell } from './Shell.svelte';
|
|
14
|
+
export * from './shell-shard/protocol';
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/*
|
|
3
|
+
* DragPreview — the ghost tab rendered on overlay layer 2 during a
|
|
4
|
+
* drag-reorganize gesture.
|
|
5
|
+
*
|
|
6
|
+
* The composition root mounts this component once into the drag-
|
|
7
|
+
* preview layer root. It reads `dragState` and renders itself only
|
|
8
|
+
* while `phase === 'dragging'`. Position tracks `dragState.pointerX`
|
|
9
|
+
* / `pointerY` minus the drag source's initial grab offset, so the
|
|
10
|
+
* ghost appears "held" at the same point on the tab where the user
|
|
11
|
+
* started dragging.
|
|
12
|
+
*
|
|
13
|
+
* Pointer events are disabled on the ghost itself — it must not
|
|
14
|
+
* intercept elementsFromPoint checks used by drop zones.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { dragState } from './drag.svelte';
|
|
18
|
+
|
|
19
|
+
const visible = $derived(dragState.phase === 'dragging' && !!dragState.source);
|
|
20
|
+
const left = $derived(
|
|
21
|
+
dragState.source ? dragState.pointerX - dragState.source.offsetX : 0,
|
|
22
|
+
);
|
|
23
|
+
const top = $derived(
|
|
24
|
+
dragState.source ? dragState.pointerY - dragState.source.offsetY : 0,
|
|
25
|
+
);
|
|
26
|
+
const width = $derived(dragState.source?.startRect.width ?? 0);
|
|
27
|
+
const height = $derived(dragState.source?.startRect.height ?? 0);
|
|
28
|
+
const label = $derived(dragState.source?.entry.label ?? '');
|
|
29
|
+
const icon = $derived(dragState.source?.entry.icon);
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
{#if visible}
|
|
33
|
+
<div
|
|
34
|
+
class="drag-preview"
|
|
35
|
+
style="left: {left}px; top: {top}px; width: {width}px; height: {height}px;"
|
|
36
|
+
>
|
|
37
|
+
{#if icon}<span class="drag-preview-icon">{icon}</span>{/if}
|
|
38
|
+
<span class="drag-preview-label">{label}</span>
|
|
39
|
+
</div>
|
|
40
|
+
{/if}
|
|
41
|
+
|
|
42
|
+
<style>
|
|
43
|
+
.drag-preview {
|
|
44
|
+
position: absolute;
|
|
45
|
+
display: inline-flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
gap: var(--shell-pad-sm);
|
|
48
|
+
padding: var(--shell-pad-sm) var(--shell-pad-md);
|
|
49
|
+
background: var(--shell-grad-bg-elevated, var(--shell-bg-elevated));
|
|
50
|
+
color: var(--shell-fg);
|
|
51
|
+
border: 1px solid var(--shell-accent);
|
|
52
|
+
border-radius: var(--shell-radius-sm);
|
|
53
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
|
|
54
|
+
font-size: 12px;
|
|
55
|
+
font-family: var(--shell-font-ui);
|
|
56
|
+
pointer-events: none;
|
|
57
|
+
opacity: 0.9;
|
|
58
|
+
/* The layer root inherits its z-index from --shell-z-layer-2 via
|
|
59
|
+
Shell.svelte; we don't set z-index here. */
|
|
60
|
+
}
|
|
61
|
+
.drag-preview-icon { font-size: 11px; }
|
|
62
|
+
.drag-preview-label { white-space: nowrap; }
|
|
63
|
+
</style>
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/*
|
|
3
|
+
* LayoutRenderer — recursive walker for a LayoutNode tree.
|
|
4
|
+
*
|
|
5
|
+
* Dispatches on the node kind:
|
|
6
|
+
* split → <ResizableSplitter> with one recursive <Self> per pane
|
|
7
|
+
* tabs → <TabbedPanel> with one <SlotContainer> per tab, a
|
|
8
|
+
* SlotDropZone overlay, and a drag controller wired to
|
|
9
|
+
* the drag engine
|
|
10
|
+
* slot → <SlotContainer> wrapped in a SlotDropZone
|
|
11
|
+
*
|
|
12
|
+
* Props: only `path` — a list of child indices from the root. The
|
|
13
|
+
* node itself is resolved as a $derived from `layoutStore.root` by
|
|
14
|
+
* walking the path. This is how we sidestep Svelte 5's
|
|
15
|
+
* `ownership_invalid_mutation` warning for a recursive component:
|
|
16
|
+
* - Passing `node` as a prop would make every mutation (e.g.
|
|
17
|
+
* `node.activeTab = i`) a write to a child-received prop, which
|
|
18
|
+
* the ownership tracker flags regardless of whether the
|
|
19
|
+
* underlying $state lives in a component or in a module.
|
|
20
|
+
* - Passing only `path` and deriving `node` locally means
|
|
21
|
+
* mutations go through a $derived of module state — no prop is
|
|
22
|
+
* involved, no ownership warning fires.
|
|
23
|
+
*
|
|
24
|
+
* `path` is a plain array, not reactive state, so there is no
|
|
25
|
+
* ownership concern on it. Each recursive call builds a new child
|
|
26
|
+
* path via `[...path, i]`.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import type { TabsNode, LayoutNode } from './types';
|
|
30
|
+
import ResizableSplitter from '../primitives/ResizableSplitter.svelte';
|
|
31
|
+
import TabbedPanel, { type TabDragController } from '../primitives/TabbedPanel.svelte';
|
|
32
|
+
import SlotContainer from './SlotContainer.svelte';
|
|
33
|
+
import SlotDropZone from './SlotDropZone.svelte';
|
|
34
|
+
import Self from './LayoutRenderer.svelte';
|
|
35
|
+
import { layoutStore } from './store.svelte';
|
|
36
|
+
import { nodeAtPath } from './ops';
|
|
37
|
+
import { isSlotClosable, isSlotDirty } from './slotHostPool.svelte';
|
|
38
|
+
import { closeTab } from './inspection';
|
|
39
|
+
import {
|
|
40
|
+
dragState,
|
|
41
|
+
beginTabDrag,
|
|
42
|
+
setDropTarget,
|
|
43
|
+
clearDropTarget,
|
|
44
|
+
suppressNextClick,
|
|
45
|
+
} from './drag.svelte';
|
|
46
|
+
|
|
47
|
+
let { path = [] }: { path?: number[] } = $props();
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Resolve the current node by walking `layoutStore.root` along the
|
|
51
|
+
* path. $derived tracks the reads so Svelte re-runs this when the
|
|
52
|
+
* layout mutates. If the path becomes invalid mid-mutation (a
|
|
53
|
+
* cleanup pass can collapse nodes out from under a recursive
|
|
54
|
+
* renderer), we render null.
|
|
55
|
+
*/
|
|
56
|
+
const node = $derived(nodeAtPath(layoutStore.root, path));
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Build a TabDragController bound to the current tabs node.
|
|
60
|
+
* Rebuilt whenever `node` changes identity (mutation can replace
|
|
61
|
+
* the node at this path with a new one during cleanup).
|
|
62
|
+
*/
|
|
63
|
+
function makeController(tabsNode: TabsNode): TabDragController {
|
|
64
|
+
return {
|
|
65
|
+
get isDragging() {
|
|
66
|
+
return dragState.phase === 'dragging';
|
|
67
|
+
},
|
|
68
|
+
onPointerDown(index, event, element) {
|
|
69
|
+
const entry = tabsNode.tabs[index];
|
|
70
|
+
if (!entry) return;
|
|
71
|
+
beginTabDrag(entry.slotId, entry, event, element);
|
|
72
|
+
},
|
|
73
|
+
onStripHover(stripRect, pointerX, pointerY, tabRects) {
|
|
74
|
+
if (pointerY < stripRect.top || pointerY > stripRect.bottom) {
|
|
75
|
+
clearDropTarget((t) => t.kind === 'strip' && t.tabsNode === tabsNode);
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
let insertIndex = tabRects.length;
|
|
79
|
+
for (let i = 0; i < tabRects.length; i++) {
|
|
80
|
+
const r = tabRects[i];
|
|
81
|
+
const mid = r.left + r.width / 2;
|
|
82
|
+
if (pointerX < mid) {
|
|
83
|
+
insertIndex = i;
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Normalize for same-strip reorder so the engine's commit
|
|
88
|
+
// doesn't double-count the removal shift: if the source tab
|
|
89
|
+
// lives in this strip at index < insertIndex, subtract one.
|
|
90
|
+
const source = dragState.source;
|
|
91
|
+
if (source) {
|
|
92
|
+
const srcIdx = tabsNode.tabs.findIndex((t) => t.slotId === source.slotId);
|
|
93
|
+
if (srcIdx >= 0 && srcIdx < insertIndex) insertIndex -= 1;
|
|
94
|
+
}
|
|
95
|
+
setDropTarget({ kind: 'strip', tabsNode, insertIndex });
|
|
96
|
+
return insertIndex;
|
|
97
|
+
},
|
|
98
|
+
onStripLeave() {
|
|
99
|
+
clearDropTarget((t) => t.kind === 'strip' && t.tabsNode === tabsNode);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Narrowing helpers — Svelte templates can't narrow a $derived
|
|
105
|
+
// across block boundaries, so we re-cast inside each branch below.
|
|
106
|
+
// These getters are just there to make the template readable.
|
|
107
|
+
function asSplit(n: LayoutNode) {
|
|
108
|
+
return n.type === 'split' ? n : null;
|
|
109
|
+
}
|
|
110
|
+
function asTabs(n: LayoutNode) {
|
|
111
|
+
return n.type === 'tabs' ? n : null;
|
|
112
|
+
}
|
|
113
|
+
function asSlot(n: LayoutNode) {
|
|
114
|
+
return n.type === 'slot' ? n : null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Build per-tab closable flags from reactive pool state. */
|
|
118
|
+
function tabClosable(tabs: import('./types').TabEntry[]): (boolean | undefined)[] {
|
|
119
|
+
return tabs.map((t) => isSlotClosable(t.slotId) || undefined);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Build per-tab dirty flags for TabbedPanel from live pool state. */
|
|
123
|
+
function tabDirty(tabs: import('./types').TabEntry[]): (boolean | undefined)[] {
|
|
124
|
+
return tabs.map((t) => isSlotDirty(t.slotId) || undefined);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Handle close button click from TabbedPanel. */
|
|
128
|
+
function handleTabClose(tabs: import('./types').TabEntry[], index: number) {
|
|
129
|
+
const entry = tabs[index];
|
|
130
|
+
if (entry) closeTab(entry.slotId);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Svelte action: mount a custom empty renderer into the element. */
|
|
134
|
+
function mountEmptyRenderer(node: HTMLElement, renderer: (el: HTMLElement) => void) {
|
|
135
|
+
renderer(node);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Drop handler for empty persistent tab groups. The whole area acts as
|
|
140
|
+
* a single "insert as first tab" target — no quadrant splits.
|
|
141
|
+
*/
|
|
142
|
+
function onEmptyTabsDrop(_e: PointerEvent, tabsNode: import('./types').TabsNode) {
|
|
143
|
+
if (dragState.phase !== 'dragging') return;
|
|
144
|
+
setDropTarget({ kind: 'strip', tabsNode, insertIndex: 0 });
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function onEmptyTabsLeave() {
|
|
148
|
+
clearDropTarget((t) => t.kind === 'strip' && t.insertIndex === 0);
|
|
149
|
+
}
|
|
150
|
+
</script>
|
|
151
|
+
|
|
152
|
+
{#if node}
|
|
153
|
+
{#if node.type === 'split'}
|
|
154
|
+
{@const split = asSplit(node)!}
|
|
155
|
+
<ResizableSplitter
|
|
156
|
+
direction={split.direction}
|
|
157
|
+
sizes={split.sizes}
|
|
158
|
+
pinned={split.pinned}
|
|
159
|
+
collapsed={split.collapsed}
|
|
160
|
+
count={split.children.length}
|
|
161
|
+
pane={splitPane}
|
|
162
|
+
onResize={(i, v) => (split.sizes[i] = v)}
|
|
163
|
+
onCollapseToggle={(i, v) => {
|
|
164
|
+
if (!split.collapsed) split.collapsed = split.children.map(() => false);
|
|
165
|
+
split.collapsed[i] = v;
|
|
166
|
+
}}
|
|
167
|
+
/>
|
|
168
|
+
{#snippet splitPane(i: number)}
|
|
169
|
+
<Self path={[...path, i]} />
|
|
170
|
+
{/snippet}
|
|
171
|
+
{:else if node.type === 'tabs'}
|
|
172
|
+
{@const tabs = asTabs(node)}
|
|
173
|
+
{#if tabs && tabs.tabs.length > 0}
|
|
174
|
+
{@const controller = makeController(tabs)}
|
|
175
|
+
<TabbedPanel
|
|
176
|
+
labels={tabs.tabs.map((t) => t.label)}
|
|
177
|
+
icons={tabs.tabs.map((t) => t.icon)}
|
|
178
|
+
activeTab={tabs.activeTab}
|
|
179
|
+
onActiveChange={(i) => (tabs.activeTab = i)}
|
|
180
|
+
body={tabBody}
|
|
181
|
+
dragController={controller}
|
|
182
|
+
clickGuard={suppressNextClick}
|
|
183
|
+
closable={tabClosable(tabs.tabs)}
|
|
184
|
+
dirty={tabDirty(tabs.tabs)}
|
|
185
|
+
onClose={(i) => handleTabClose(tabs.tabs, i)}
|
|
186
|
+
/>
|
|
187
|
+
{#snippet tabBody(i: number)}
|
|
188
|
+
{@const entry = tabs.tabs[i]}
|
|
189
|
+
{#if entry}
|
|
190
|
+
<div class="tab-slot-wrapper">
|
|
191
|
+
<SlotContainer node={{ type: 'slot', slotId: entry.slotId, viewId: entry.viewId }} label={entry.label} />
|
|
192
|
+
<SlotDropZone path={path} />
|
|
193
|
+
</div>
|
|
194
|
+
{/if}
|
|
195
|
+
{/snippet}
|
|
196
|
+
{:else if tabs?.persistent}
|
|
197
|
+
<div class="empty-tabs-placeholder">
|
|
198
|
+
{#if tabs.emptyRenderer}
|
|
199
|
+
<div class="empty-tabs-custom" use:mountEmptyRenderer={tabs.emptyRenderer}></div>
|
|
200
|
+
{:else}
|
|
201
|
+
<div class="empty-tabs-default">
|
|
202
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
203
|
+
<div
|
|
204
|
+
class="empty-tabs-drop"
|
|
205
|
+
onpointermove={(e) => onEmptyTabsDrop(e, tabs)}
|
|
206
|
+
onpointerleave={onEmptyTabsLeave}
|
|
207
|
+
></div>
|
|
208
|
+
</div>
|
|
209
|
+
{/if}
|
|
210
|
+
</div>
|
|
211
|
+
{/if}
|
|
212
|
+
{:else}
|
|
213
|
+
{@const slot = asSlot(node)!}
|
|
214
|
+
<div class="leaf-slot-wrapper">
|
|
215
|
+
<SlotContainer node={slot} />
|
|
216
|
+
<SlotDropZone path={path} />
|
|
217
|
+
</div>
|
|
218
|
+
{/if}
|
|
219
|
+
{/if}
|
|
220
|
+
|
|
221
|
+
<style>
|
|
222
|
+
.tab-slot-wrapper,
|
|
223
|
+
.leaf-slot-wrapper {
|
|
224
|
+
position: absolute;
|
|
225
|
+
inset: 0;
|
|
226
|
+
min-width: 0;
|
|
227
|
+
min-height: 0;
|
|
228
|
+
}
|
|
229
|
+
.empty-tabs-placeholder {
|
|
230
|
+
width: 100%;
|
|
231
|
+
height: 100%;
|
|
232
|
+
min-width: 0;
|
|
233
|
+
min-height: 0;
|
|
234
|
+
position: relative;
|
|
235
|
+
}
|
|
236
|
+
.empty-tabs-default {
|
|
237
|
+
position: absolute;
|
|
238
|
+
inset: 0;
|
|
239
|
+
display: flex;
|
|
240
|
+
flex-direction: column;
|
|
241
|
+
align-items: center;
|
|
242
|
+
justify-content: center;
|
|
243
|
+
color: var(--shell-fg-muted);
|
|
244
|
+
font-size: 12px;
|
|
245
|
+
background:
|
|
246
|
+
repeating-linear-gradient(
|
|
247
|
+
45deg,
|
|
248
|
+
var(--shell-bg) 0 10px,
|
|
249
|
+
var(--shell-bg-elevated) 10px 20px
|
|
250
|
+
);
|
|
251
|
+
border: 1px dashed var(--shell-border-strong);
|
|
252
|
+
}
|
|
253
|
+
.empty-tabs-custom {
|
|
254
|
+
position: absolute;
|
|
255
|
+
inset: 0;
|
|
256
|
+
}
|
|
257
|
+
.empty-tabs-drop {
|
|
258
|
+
position: absolute;
|
|
259
|
+
inset: 0;
|
|
260
|
+
pointer-events: auto;
|
|
261
|
+
}
|
|
262
|
+
</style>
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/*
|
|
3
|
+
* SlotContainer — the leaf of the layout tree and the hand-off point
|
|
4
|
+
* between the framework and shard-contributed views.
|
|
5
|
+
*
|
|
6
|
+
* Phase 6 change: the mounted view no longer lives inside this
|
|
7
|
+
* component's own DOM. Instead, the slot host is owned by the
|
|
8
|
+
* `slotHostPool` module and SlotContainer merely attaches (and later
|
|
9
|
+
* releases) the pooled host to its own wrapper. This is what makes
|
|
10
|
+
* drag-to-reorganize survive: when a tab moves, the old SlotContainer
|
|
11
|
+
* tears down and a new one mounts, but the pooled host (and the view
|
|
12
|
+
* mounted into it) is re-parented to the new wrapper without being
|
|
13
|
+
* destroyed. See slotHostPool.ts for the refcount / deferred-destroy
|
|
14
|
+
* details.
|
|
15
|
+
*
|
|
16
|
+
* Responsibilities:
|
|
17
|
+
* 1. Acquire the pooled host for `node.slotId` on mount and append
|
|
18
|
+
* it to the wrapper.
|
|
19
|
+
* 2. Release the pooled host on unmount. The pool decides whether
|
|
20
|
+
* that's a genuine destroy or the first half of a re-parent.
|
|
21
|
+
* 3. If no factory is registered for the viewId (empty slot or the
|
|
22
|
+
* shard providing it hasn't activated yet), render a placeholder
|
|
23
|
+
* in the wrapper alongside the empty host. A local ResizeObserver
|
|
24
|
+
* feeds the placeholder's dimensions readout.
|
|
25
|
+
*
|
|
26
|
+
* The view's own onResize delivery is NOT SlotContainer's job — the
|
|
27
|
+
* pool owns a ResizeObserver on each host that outlives this component
|
|
28
|
+
* across re-parents. See slotHostPool.ts.
|
|
29
|
+
*
|
|
30
|
+
* Note on the placeholder: the pool creates a host even when there is
|
|
31
|
+
* no factory, so the placeholder is layered *on top* of the empty
|
|
32
|
+
* host. That keeps the acquire/release path uniform — phase 7's
|
|
33
|
+
* "factory registered after layout render" case will just replace the
|
|
34
|
+
* host's contents without rewriting SlotContainer.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import type { SlotNode } from './types';
|
|
38
|
+
import { getView } from '../shards/registry';
|
|
39
|
+
import { acquireSlotHost, releaseSlotHost } from './slotHostPool.svelte';
|
|
40
|
+
|
|
41
|
+
let { node, label = '' }: { node: SlotNode; label?: string } = $props();
|
|
42
|
+
|
|
43
|
+
let wrapper: HTMLDivElement | undefined = $state();
|
|
44
|
+
let width = $state(0);
|
|
45
|
+
let height = $state(0);
|
|
46
|
+
// Whether a factory is registered — drives the placeholder. The pool
|
|
47
|
+
// owns the actual mount call; we mirror the registry lookup here just
|
|
48
|
+
// to decide whether to show the "no factory" hint.
|
|
49
|
+
const hasFactory = $derived(node.viewId ? !!getView(node.viewId) : false);
|
|
50
|
+
|
|
51
|
+
$effect(() => {
|
|
52
|
+
if (!wrapper) return;
|
|
53
|
+
|
|
54
|
+
const host = acquireSlotHost(node.slotId, node.viewId, label || node.viewId || node.slotId);
|
|
55
|
+
wrapper.appendChild(host);
|
|
56
|
+
|
|
57
|
+
// Local observer exists only to drive the placeholder's dims text;
|
|
58
|
+
// the view's own onResize is delivered by the pool.
|
|
59
|
+
const ro = new ResizeObserver((entries) => {
|
|
60
|
+
for (const entry of entries) {
|
|
61
|
+
const box = entry.contentRect;
|
|
62
|
+
width = Math.round(box.width);
|
|
63
|
+
height = Math.round(box.height);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
ro.observe(wrapper);
|
|
67
|
+
|
|
68
|
+
return () => {
|
|
69
|
+
ro.disconnect();
|
|
70
|
+
releaseSlotHost(node.slotId);
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<div
|
|
76
|
+
class="slot"
|
|
77
|
+
data-slot-id={node.slotId}
|
|
78
|
+
data-view-id={node.viewId ?? ''}
|
|
79
|
+
bind:this={wrapper}
|
|
80
|
+
>
|
|
81
|
+
{#if !hasFactory}
|
|
82
|
+
<div class="slot-placeholder">
|
|
83
|
+
<div class="slot-id">{node.slotId}</div>
|
|
84
|
+
<div class="slot-meta">
|
|
85
|
+
{#if node.viewId}
|
|
86
|
+
no factory for <code>{node.viewId}</code>
|
|
87
|
+
{:else}
|
|
88
|
+
<em>empty slot</em>
|
|
89
|
+
{/if}
|
|
90
|
+
</div>
|
|
91
|
+
<div class="slot-dims">{width} × {height}</div>
|
|
92
|
+
</div>
|
|
93
|
+
{/if}
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<style>
|
|
97
|
+
.slot {
|
|
98
|
+
position: relative;
|
|
99
|
+
width: 100%;
|
|
100
|
+
height: 100%;
|
|
101
|
+
min-width: 0;
|
|
102
|
+
min-height: 0;
|
|
103
|
+
overflow: hidden;
|
|
104
|
+
}
|
|
105
|
+
.slot-placeholder {
|
|
106
|
+
position: absolute;
|
|
107
|
+
inset: 0;
|
|
108
|
+
display: flex;
|
|
109
|
+
flex-direction: column;
|
|
110
|
+
align-items: center;
|
|
111
|
+
justify-content: center;
|
|
112
|
+
gap: var(--shell-pad-sm);
|
|
113
|
+
color: var(--shell-fg-muted);
|
|
114
|
+
font-size: 12px;
|
|
115
|
+
text-align: center;
|
|
116
|
+
padding: var(--shell-pad-md);
|
|
117
|
+
background:
|
|
118
|
+
repeating-linear-gradient(
|
|
119
|
+
45deg,
|
|
120
|
+
var(--shell-bg) 0 10px,
|
|
121
|
+
var(--shell-bg-elevated) 10px 20px
|
|
122
|
+
);
|
|
123
|
+
border: 1px dashed var(--shell-border-strong);
|
|
124
|
+
pointer-events: none;
|
|
125
|
+
}
|
|
126
|
+
.slot-id {
|
|
127
|
+
color: var(--shell-fg);
|
|
128
|
+
font-family: var(--shell-font-mono);
|
|
129
|
+
font-size: 13px;
|
|
130
|
+
}
|
|
131
|
+
.slot-meta code {
|
|
132
|
+
font-family: var(--shell-font-mono);
|
|
133
|
+
color: var(--shell-accent);
|
|
134
|
+
}
|
|
135
|
+
.slot-dims {
|
|
136
|
+
font-family: var(--shell-font-mono);
|
|
137
|
+
color: var(--shell-fg-subtle);
|
|
138
|
+
font-size: 11px;
|
|
139
|
+
}
|
|
140
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SlotNode } from './types';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
node: SlotNode;
|
|
4
|
+
label?: string;
|
|
5
|
+
};
|
|
6
|
+
declare const SlotContainer: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type SlotContainer = ReturnType<typeof SlotContainer>;
|
|
8
|
+
export default SlotContainer;
|