@happyvertical/smrt-svelte 0.37.8 → 0.37.10
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/AGENTS.md +22 -86
- package/README.md +14 -10
- package/dist/components/workspace/MIGRATION.md +55 -0
- package/dist/components/workspace/README.md +22 -25
- package/dist/components/workspace/__tests__/AdminShell.test.js +55 -0
- package/dist/components/workspace/__tests__/admin-shell-hotkeys.test.js +34 -0
- package/dist/components/workspace/__tests__/admin-shell-settings.test.js +25 -0
- package/dist/components/workspace/__tests__/admin-shell-state.test.js +110 -0
- package/dist/components/workspace/__tests__/index.test.js +15 -24
- package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts +2 -1
- package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts.map +1 -1
- package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.js +1 -1
- package/dist/components/workspace/admin-shell/ActivityBadge.svelte +25 -0
- package/dist/components/workspace/admin-shell/ActivityBadge.svelte.d.ts +9 -0
- package/dist/components/workspace/admin-shell/ActivityBadge.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ActivityItem.svelte +85 -0
- package/dist/components/workspace/admin-shell/ActivityItem.svelte.d.ts +8 -0
- package/dist/components/workspace/admin-shell/ActivityItem.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ActivityList.svelte +41 -0
- package/dist/components/workspace/admin-shell/ActivityList.svelte.d.ts +10 -0
- package/dist/components/workspace/admin-shell/ActivityList.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ActivityToasts.svelte +140 -0
- package/dist/components/workspace/admin-shell/ActivityToasts.svelte.d.ts +16 -0
- package/dist/components/workspace/admin-shell/ActivityToasts.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/AdminShell.svelte +691 -0
- package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts +24 -0
- package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/AppScopePanel.svelte +94 -0
- package/dist/components/workspace/admin-shell/AppScopePanel.svelte.d.ts +14 -0
- package/dist/components/workspace/admin-shell/AppScopePanel.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/HotkeyInput.svelte +74 -0
- package/dist/components/workspace/admin-shell/HotkeyInput.svelte.d.ts +11 -0
- package/dist/components/workspace/admin-shell/HotkeyInput.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShellCorner.svelte +25 -0
- package/dist/components/workspace/admin-shell/ShellCorner.svelte.d.ts +9 -0
- package/dist/components/workspace/admin-shell/ShellCorner.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShellDockTool.svelte +19 -0
- package/dist/components/workspace/admin-shell/ShellDockTool.svelte.d.ts +7 -0
- package/dist/components/workspace/admin-shell/ShellDockTool.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte +146 -0
- package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts +4 -0
- package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte +81 -0
- package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte.d.ts +7 -0
- package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/SystemScopePanel.svelte +118 -0
- package/dist/components/workspace/admin-shell/SystemScopePanel.svelte.d.ts +9 -0
- package/dist/components/workspace/admin-shell/SystemScopePanel.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/SystemStatusChips.svelte +71 -0
- package/dist/components/workspace/admin-shell/SystemStatusChips.svelte.d.ts +8 -0
- package/dist/components/workspace/admin-shell/SystemStatusChips.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/TenantNav.svelte +101 -0
- package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts +10 -0
- package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/context.d.ts +6 -0
- package/dist/components/workspace/admin-shell/context.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/context.js +16 -0
- package/dist/components/workspace/admin-shell/hotkeys.d.ts +14 -0
- package/dist/components/workspace/admin-shell/hotkeys.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/hotkeys.js +62 -0
- package/dist/components/workspace/admin-shell/settings.d.ts +14 -0
- package/dist/components/workspace/admin-shell/settings.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/settings.js +139 -0
- package/dist/components/workspace/admin-shell/state.svelte.d.ts +47 -0
- package/dist/components/workspace/admin-shell/state.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/state.svelte.js +252 -0
- package/dist/components/workspace/admin-shell/types.d.ts +137 -0
- package/dist/components/workspace/admin-shell/types.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/types.js +13 -0
- package/dist/components/workspace/index.d.ts +25 -11
- package/dist/components/workspace/index.d.ts.map +1 -1
- package/dist/components/workspace/index.js +24 -10
- package/dist/i18n/strings.workspace.d.ts +30 -0
- package/dist/i18n/strings.workspace.d.ts.map +1 -1
- package/dist/i18n/strings.workspace.js +31 -0
- package/dist/internal/logger.d.ts +13 -6
- package/dist/internal/logger.d.ts.map +1 -1
- package/dist/internal/logger.js +33 -8
- package/dist/internal/logger.test.js +54 -0
- package/dist/web/__tests__/harness.svelte +25 -0
- package/dist/web/__tests__/harness.svelte.d.ts +15 -0
- package/dist/web/__tests__/harness.svelte.d.ts.map +1 -0
- package/dist/web/__tests__/live-collection.svelte.test.js +184 -0
- package/dist/web/index.d.ts +13 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +12 -0
- package/dist/web/live-collection.svelte.d.ts +132 -0
- package/dist/web/live-collection.svelte.d.ts.map +1 -0
- package/dist/web/live-collection.svelte.js +173 -0
- package/package.json +13 -4
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
3
|
+
import { Badge } from '@happyvertical/smrt-ui/ui';
|
|
4
|
+
import { M } from '../../../i18n/strings.workspace.js';
|
|
5
|
+
import type { ShellStatusChip } from './types.js';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
chips: ShellStatusChip[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { chips }: Props = $props();
|
|
12
|
+
const { t } = useI18n();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<div
|
|
16
|
+
class="smrt-system-status-chips"
|
|
17
|
+
aria-label={t(M['ui.system_status_chips.system_status'])}
|
|
18
|
+
>
|
|
19
|
+
{#each chips as chip (chip.id)}
|
|
20
|
+
{#if chip.href}
|
|
21
|
+
<a href={chip.href} data-tone={chip.tone ?? 'neutral'}>
|
|
22
|
+
<span>{chip.label}</span>
|
|
23
|
+
{#if chip.value !== undefined}
|
|
24
|
+
<Badge size="sm" variant={chip.tone === 'error' ? 'error' : 'default'}>
|
|
25
|
+
{chip.value}
|
|
26
|
+
</Badge>
|
|
27
|
+
{/if}
|
|
28
|
+
</a>
|
|
29
|
+
{:else}
|
|
30
|
+
<span class="smrt-system-status-chips__chip" data-tone={chip.tone ?? 'neutral'}>
|
|
31
|
+
<span>{chip.label}</span>
|
|
32
|
+
{#if chip.value !== undefined}
|
|
33
|
+
<Badge size="sm" variant={chip.tone === 'error' ? 'error' : 'default'}>
|
|
34
|
+
{chip.value}
|
|
35
|
+
</Badge>
|
|
36
|
+
{/if}
|
|
37
|
+
</span>
|
|
38
|
+
{/if}
|
|
39
|
+
{/each}
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<style>
|
|
43
|
+
.smrt-system-status-chips {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-wrap: wrap;
|
|
46
|
+
gap: var(--smrt-spacing-2);
|
|
47
|
+
align-items: center;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.smrt-system-status-chips a,
|
|
51
|
+
.smrt-system-status-chips__chip {
|
|
52
|
+
display: inline-flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
gap: var(--smrt-spacing-2);
|
|
55
|
+
min-inline-size: 0;
|
|
56
|
+
color: var(--smrt-color-on-surface);
|
|
57
|
+
text-decoration: none;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.smrt-system-status-chips [data-tone='success'] {
|
|
61
|
+
color: var(--smrt-color-success);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.smrt-system-status-chips [data-tone='warning'] {
|
|
65
|
+
color: var(--smrt-color-warning);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.smrt-system-status-chips [data-tone='error'] {
|
|
69
|
+
color: var(--smrt-color-error);
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ShellStatusChip } from './types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
chips: ShellStatusChip[];
|
|
4
|
+
}
|
|
5
|
+
declare const SystemStatusChips: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type SystemStatusChips = ReturnType<typeof SystemStatusChips>;
|
|
7
|
+
export default SystemStatusChips;
|
|
8
|
+
//# sourceMappingURL=SystemStatusChips.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SystemStatusChips.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/SystemStatusChips.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,UAAU,KAAK;IACb,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAwCD,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
3
|
+
import { M } from '../../../i18n/strings.workspace.js';
|
|
4
|
+
import type { ShellNavItem } from './types.js';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
items: ShellNavItem[];
|
|
8
|
+
currentHref?: string;
|
|
9
|
+
onNavigate?: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { items, currentHref = '', onNavigate }: Props = $props();
|
|
13
|
+
const { t } = useI18n();
|
|
14
|
+
|
|
15
|
+
function isActive(item: ShellNavItem): boolean {
|
|
16
|
+
return item.href === currentHref || currentHref.startsWith(`${item.href}/`);
|
|
17
|
+
}
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<nav
|
|
21
|
+
class="smrt-tenant-nav"
|
|
22
|
+
aria-label={t(M['ui.tenant_nav.tenant_navigation'])}
|
|
23
|
+
>
|
|
24
|
+
{#each items as item (item.href)}
|
|
25
|
+
<div class="smrt-tenant-nav__section">
|
|
26
|
+
<a
|
|
27
|
+
href={item.href}
|
|
28
|
+
aria-current={isActive(item) ? 'page' : undefined}
|
|
29
|
+
onclick={onNavigate}
|
|
30
|
+
>
|
|
31
|
+
{#if item.icon}
|
|
32
|
+
<span aria-hidden="true">{item.icon}</span>
|
|
33
|
+
{/if}
|
|
34
|
+
<strong>{item.label}</strong>
|
|
35
|
+
{#if item.badge !== null && item.badge !== undefined}
|
|
36
|
+
<small>{item.badge}</small>
|
|
37
|
+
{/if}
|
|
38
|
+
</a>
|
|
39
|
+
{#if item.children?.length}
|
|
40
|
+
<div class="smrt-tenant-nav__children">
|
|
41
|
+
{#each item.children as child (child.href)}
|
|
42
|
+
<a
|
|
43
|
+
href={child.href}
|
|
44
|
+
aria-current={isActive(child) ? 'page' : undefined}
|
|
45
|
+
onclick={onNavigate}
|
|
46
|
+
>
|
|
47
|
+
{#if child.icon}
|
|
48
|
+
<span aria-hidden="true">{child.icon}</span>
|
|
49
|
+
{/if}
|
|
50
|
+
<span>{child.label}</span>
|
|
51
|
+
{#if child.badge !== null && child.badge !== undefined}
|
|
52
|
+
<small>{child.badge}</small>
|
|
53
|
+
{/if}
|
|
54
|
+
</a>
|
|
55
|
+
{/each}
|
|
56
|
+
</div>
|
|
57
|
+
{/if}
|
|
58
|
+
</div>
|
|
59
|
+
{/each}
|
|
60
|
+
</nav>
|
|
61
|
+
|
|
62
|
+
<style>
|
|
63
|
+
.smrt-tenant-nav,
|
|
64
|
+
.smrt-tenant-nav__section,
|
|
65
|
+
.smrt-tenant-nav__children {
|
|
66
|
+
display: grid;
|
|
67
|
+
gap: var(--smrt-spacing-1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.smrt-tenant-nav a {
|
|
71
|
+
display: grid;
|
|
72
|
+
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
73
|
+
align-items: center;
|
|
74
|
+
gap: var(--smrt-spacing-2);
|
|
75
|
+
min-inline-size: 0;
|
|
76
|
+
padding: var(--smrt-spacing-2) var(--smrt-spacing-3);
|
|
77
|
+
border-radius: var(--smrt-radius-medium);
|
|
78
|
+
color: var(--smrt-color-on-surface);
|
|
79
|
+
text-decoration: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.smrt-tenant-nav a:hover,
|
|
83
|
+
.smrt-tenant-nav a[aria-current='page'] {
|
|
84
|
+
background: var(--smrt-color-surface-container-high);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.smrt-tenant-nav strong,
|
|
88
|
+
.smrt-tenant-nav span {
|
|
89
|
+
overflow: hidden;
|
|
90
|
+
text-overflow: ellipsis;
|
|
91
|
+
white-space: nowrap;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.smrt-tenant-nav small {
|
|
95
|
+
color: var(--smrt-color-on-surface-variant);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.smrt-tenant-nav__children {
|
|
99
|
+
padding-inline-start: var(--smrt-spacing-4);
|
|
100
|
+
}
|
|
101
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ShellNavItem } from './types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
items: ShellNavItem[];
|
|
4
|
+
currentHref?: string;
|
|
5
|
+
onNavigate?: () => void;
|
|
6
|
+
}
|
|
7
|
+
declare const TenantNav: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type TenantNav = ReturnType<typeof TenantNav>;
|
|
9
|
+
export default TenantNav;
|
|
10
|
+
//# sourceMappingURL=TenantNav.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TenantNav.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/TenantNav.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,UAAU,KAAK;IACb,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAkDD,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ShellState } from './state.svelte.js';
|
|
2
|
+
export declare const ADMIN_SHELL_CONTEXT: unique symbol;
|
|
3
|
+
export declare function setAdminShell(shell: ShellState): ShellState;
|
|
4
|
+
export declare function useAdminShell(): ShellState;
|
|
5
|
+
export declare function tryUseAdminShell(): ShellState | null;
|
|
6
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,eAAO,MAAM,mBAAmB,eAA6B,CAAC;AAE9D,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAG3D;AAED,wBAAgB,aAAa,IAAI,UAAU,CAQ1C;AAED,wBAAgB,gBAAgB,IAAI,UAAU,GAAG,IAAI,CAEpD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getContext, setContext } from 'svelte';
|
|
2
|
+
export const ADMIN_SHELL_CONTEXT = Symbol('smrt-admin-shell');
|
|
3
|
+
export function setAdminShell(shell) {
|
|
4
|
+
setContext(ADMIN_SHELL_CONTEXT, shell);
|
|
5
|
+
return shell;
|
|
6
|
+
}
|
|
7
|
+
export function useAdminShell() {
|
|
8
|
+
const shell = getContext(ADMIN_SHELL_CONTEXT);
|
|
9
|
+
if (!shell) {
|
|
10
|
+
throw new Error('[useAdminShell] No AdminShell state found on Svelte context.');
|
|
11
|
+
}
|
|
12
|
+
return shell;
|
|
13
|
+
}
|
|
14
|
+
export function tryUseAdminShell() {
|
|
15
|
+
return getContext(ADMIN_SHELL_CONTEXT) ?? null;
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PanelEdge, ShellHotkeyBinding, ShellPanelConfig, ShellSettingsDelta } from './types.js';
|
|
2
|
+
export type ShellHotkeyAction = {
|
|
3
|
+
type: 'toggle-panel';
|
|
4
|
+
edge: PanelEdge;
|
|
5
|
+
} | {
|
|
6
|
+
type: 'show-shortcuts';
|
|
7
|
+
};
|
|
8
|
+
export declare function shellActionFromKeyboardEvent(event: KeyboardEvent, panels: Record<PanelEdge, ShellPanelConfig>, settings?: ShellSettingsDelta): ShellHotkeyAction | null;
|
|
9
|
+
export declare function shouldIgnoreShellHotkey(event: KeyboardEvent, settings?: ShellSettingsDelta): boolean;
|
|
10
|
+
export declare function hotkeyMatchesEvent(binding: ShellHotkeyBinding, event: KeyboardEvent): boolean;
|
|
11
|
+
export declare function isShortcutsEvent(event: KeyboardEvent): boolean;
|
|
12
|
+
export declare function isEditableTarget(target: EventTarget | null): boolean;
|
|
13
|
+
export declare function formatHotkeyBinding(binding: ShellHotkeyBinding | null | undefined): string;
|
|
14
|
+
//# sourceMappingURL=hotkeys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotkeys.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/hotkeys.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAE/B,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,gBAAgB,CAAC,EAC3C,QAAQ,GAAE,kBAAuB,GAChC,iBAAiB,GAAG,IAAI,CAY1B;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,aAAa,EACpB,QAAQ,GAAE,kBAAuB,GAChC,OAAO,CAWT;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,kBAAkB,EAC3B,KAAK,EAAE,aAAa,GACnB,OAAO,CAQT;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAE9D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAMpE;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,GAC7C,MAAM,CAUR"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { resolveHotkey } from './settings.js';
|
|
2
|
+
import { PANEL_EDGES } from './types.js';
|
|
3
|
+
export function shellActionFromKeyboardEvent(event, panels, settings = {}) {
|
|
4
|
+
if (shouldIgnoreShellHotkey(event, settings))
|
|
5
|
+
return null;
|
|
6
|
+
if (isShortcutsEvent(event))
|
|
7
|
+
return { type: 'show-shortcuts' };
|
|
8
|
+
for (const edge of PANEL_EDGES) {
|
|
9
|
+
const binding = resolveHotkey(edge, panels[edge], settings);
|
|
10
|
+
if (binding && hotkeyMatchesEvent(binding, event)) {
|
|
11
|
+
return { type: 'toggle-panel', edge };
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
export function shouldIgnoreShellHotkey(event, settings = {}) {
|
|
17
|
+
if (settings.hotkeysEnabled === false)
|
|
18
|
+
return true;
|
|
19
|
+
if (event.isComposing)
|
|
20
|
+
return true;
|
|
21
|
+
// An editable control always wins: never hijack a keystroke destined for a
|
|
22
|
+
// field — including `?`, which is otherwise the shortcuts trigger. This must
|
|
23
|
+
// precede the modifier branch below, since `?` carries Shift.
|
|
24
|
+
if (isEditableTarget(event.target))
|
|
25
|
+
return true;
|
|
26
|
+
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
27
|
+
return !isShortcutsEvent(event);
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
export function hotkeyMatchesEvent(binding, event) {
|
|
32
|
+
return (binding.code === event.code &&
|
|
33
|
+
Boolean(binding.altKey) === event.altKey &&
|
|
34
|
+
Boolean(binding.ctrlKey) === event.ctrlKey &&
|
|
35
|
+
Boolean(binding.metaKey) === event.metaKey &&
|
|
36
|
+
Boolean(binding.shiftKey) === event.shiftKey);
|
|
37
|
+
}
|
|
38
|
+
export function isShortcutsEvent(event) {
|
|
39
|
+
return event.key === '?' || (event.code === 'Slash' && event.shiftKey);
|
|
40
|
+
}
|
|
41
|
+
export function isEditableTarget(target) {
|
|
42
|
+
if (!(target instanceof HTMLElement))
|
|
43
|
+
return false;
|
|
44
|
+
const tag = target.tagName.toLowerCase();
|
|
45
|
+
if (tag === 'input' || tag === 'textarea' || tag === 'select')
|
|
46
|
+
return true;
|
|
47
|
+
if (target.isContentEditable)
|
|
48
|
+
return true;
|
|
49
|
+
return Boolean(target.closest('[contenteditable="true"]'));
|
|
50
|
+
}
|
|
51
|
+
export function formatHotkeyBinding(binding) {
|
|
52
|
+
if (!binding)
|
|
53
|
+
return 'Off';
|
|
54
|
+
const parts = [
|
|
55
|
+
binding.ctrlKey ? 'Ctrl' : '',
|
|
56
|
+
binding.altKey ? 'Alt' : '',
|
|
57
|
+
binding.shiftKey ? 'Shift' : '',
|
|
58
|
+
binding.metaKey ? 'Meta' : '',
|
|
59
|
+
binding.code.replace(/^Key/, '').replace(/^Digit/, ''),
|
|
60
|
+
].filter(Boolean);
|
|
61
|
+
return parts.join('+');
|
|
62
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PanelEdge, PanelState, ResolvedShellConfig, ShellHotkeyBinding, ShellPanelConfig, ShellPanelDefaults, ShellSettingsAdapter, ShellSettingsDelta } from './types.js';
|
|
2
|
+
export declare const DEFAULT_SHELL_KEYMAP: Record<PanelEdge, ShellHotkeyBinding>;
|
|
3
|
+
export declare function resolveShellConfig(appDefaults?: ShellPanelDefaults): ResolvedShellConfig;
|
|
4
|
+
export declare function resolveInitialPanelState(edge: PanelEdge, config: ShellPanelConfig, settings?: ShellSettingsDelta): PanelState;
|
|
5
|
+
export declare function resolveHotkey(edge: PanelEdge, config: ShellPanelConfig, settings?: ShellSettingsDelta): ShellHotkeyBinding | null;
|
|
6
|
+
export declare function mergeShellSettingsDelta(base: ShellSettingsDelta, next: ShellSettingsDelta): ShellSettingsDelta;
|
|
7
|
+
export declare function pruneShellSettingsDelta(delta: ShellSettingsDelta): ShellSettingsDelta;
|
|
8
|
+
export declare class LocalStorageShellSettingsAdapter implements ShellSettingsAdapter {
|
|
9
|
+
private readonly key;
|
|
10
|
+
constructor(key: string);
|
|
11
|
+
read(): ShellSettingsDelta | null;
|
|
12
|
+
write(delta: ShellSettingsDelta): void;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,SAAS,EAAE,kBAAkB,CAKtE,CAAC;AA6CF,wBAAgB,kBAAkB,CAChC,WAAW,GAAE,kBAAuB,GACnC,mBAAmB,CA2BrB;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,gBAAgB,EACxB,QAAQ,GAAE,kBAAuB,GAChC,UAAU,CAGZ;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,gBAAgB,EACxB,QAAQ,GAAE,kBAAuB,GAChC,kBAAkB,GAAG,IAAI,CAM3B;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,kBAAkB,GACvB,kBAAkB,CAapB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,kBAAkB,GACxB,kBAAkB,CAepB;AAED,qBAAa,gCAAiC,YAAW,oBAAoB;IAC/D,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,MAAM;IAExC,IAAI,IAAI,kBAAkB,GAAG,IAAI;IAWjC,KAAK,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;CAOvC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { EDGE_SCOPES, PANEL_EDGES } from './types.js';
|
|
2
|
+
export const DEFAULT_SHELL_KEYMAP = {
|
|
3
|
+
top: { code: 'KeyW' },
|
|
4
|
+
left: { code: 'KeyA' },
|
|
5
|
+
bottom: { code: 'KeyS' },
|
|
6
|
+
right: { code: 'KeyD' },
|
|
7
|
+
};
|
|
8
|
+
const DEFAULT_PANEL_CONFIG = {
|
|
9
|
+
top: {
|
|
10
|
+
edge: 'top',
|
|
11
|
+
scope: 'app',
|
|
12
|
+
label: 'App',
|
|
13
|
+
initial: 'collapsed',
|
|
14
|
+
presentation: 'overlay',
|
|
15
|
+
hotkey: DEFAULT_SHELL_KEYMAP.top,
|
|
16
|
+
collapsedSize: '3.5rem',
|
|
17
|
+
expandedSize: '18rem',
|
|
18
|
+
},
|
|
19
|
+
left: {
|
|
20
|
+
edge: 'left',
|
|
21
|
+
scope: 'tenant',
|
|
22
|
+
label: 'Tenant',
|
|
23
|
+
initial: 'collapsed',
|
|
24
|
+
presentation: 'push',
|
|
25
|
+
hotkey: DEFAULT_SHELL_KEYMAP.left,
|
|
26
|
+
collapsedSize: '4.25rem',
|
|
27
|
+
expandedSize: '16rem',
|
|
28
|
+
},
|
|
29
|
+
right: {
|
|
30
|
+
edge: 'right',
|
|
31
|
+
scope: 'focus',
|
|
32
|
+
label: 'Focus',
|
|
33
|
+
initial: 'collapsed',
|
|
34
|
+
presentation: 'push',
|
|
35
|
+
hotkey: DEFAULT_SHELL_KEYMAP.right,
|
|
36
|
+
collapsedSize: '4.25rem',
|
|
37
|
+
expandedSize: '20rem',
|
|
38
|
+
},
|
|
39
|
+
bottom: {
|
|
40
|
+
edge: 'bottom',
|
|
41
|
+
scope: 'system',
|
|
42
|
+
label: 'System',
|
|
43
|
+
initial: 'collapsed',
|
|
44
|
+
presentation: 'overlay',
|
|
45
|
+
hotkey: DEFAULT_SHELL_KEYMAP.bottom,
|
|
46
|
+
collapsedSize: '2.75rem',
|
|
47
|
+
expandedSize: '18rem',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
export function resolveShellConfig(appDefaults = {}) {
|
|
51
|
+
const panels = Object.fromEntries(PANEL_EDGES.map((edge) => {
|
|
52
|
+
const override = appDefaults[edge];
|
|
53
|
+
if (override === false) {
|
|
54
|
+
return [
|
|
55
|
+
edge,
|
|
56
|
+
{
|
|
57
|
+
...DEFAULT_PANEL_CONFIG[edge],
|
|
58
|
+
initial: 'hidden',
|
|
59
|
+
hotkey: null,
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
return [
|
|
64
|
+
edge,
|
|
65
|
+
{
|
|
66
|
+
...DEFAULT_PANEL_CONFIG[edge],
|
|
67
|
+
...override,
|
|
68
|
+
edge,
|
|
69
|
+
scope: override?.scope ?? EDGE_SCOPES[edge],
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
}));
|
|
73
|
+
return { panels };
|
|
74
|
+
}
|
|
75
|
+
export function resolveInitialPanelState(edge, config, settings = {}) {
|
|
76
|
+
if (config.initial === 'hidden')
|
|
77
|
+
return 'hidden';
|
|
78
|
+
return settings.panels?.[edge] ?? config.initial;
|
|
79
|
+
}
|
|
80
|
+
export function resolveHotkey(edge, config, settings = {}) {
|
|
81
|
+
if (config.initial === 'hidden')
|
|
82
|
+
return null;
|
|
83
|
+
if (settings.keymap && edge in settings.keymap) {
|
|
84
|
+
return settings.keymap[edge] ?? null;
|
|
85
|
+
}
|
|
86
|
+
return config.hotkey;
|
|
87
|
+
}
|
|
88
|
+
export function mergeShellSettingsDelta(base, next) {
|
|
89
|
+
return {
|
|
90
|
+
...base,
|
|
91
|
+
...next,
|
|
92
|
+
keymap: base.keymap || next.keymap
|
|
93
|
+
? { ...(base.keymap ?? {}), ...(next.keymap ?? {}) }
|
|
94
|
+
: undefined,
|
|
95
|
+
panels: base.panels || next.panels
|
|
96
|
+
? { ...(base.panels ?? {}), ...(next.panels ?? {}) }
|
|
97
|
+
: undefined,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export function pruneShellSettingsDelta(delta) {
|
|
101
|
+
const pruned = {};
|
|
102
|
+
if (delta.hotkeysEnabled !== undefined) {
|
|
103
|
+
pruned.hotkeysEnabled = delta.hotkeysEnabled;
|
|
104
|
+
}
|
|
105
|
+
if (delta.activeFocusToolId !== undefined) {
|
|
106
|
+
pruned.activeFocusToolId = delta.activeFocusToolId;
|
|
107
|
+
}
|
|
108
|
+
if (delta.keymap && Object.keys(delta.keymap).length > 0) {
|
|
109
|
+
pruned.keymap = delta.keymap;
|
|
110
|
+
}
|
|
111
|
+
if (delta.panels && Object.keys(delta.panels).length > 0) {
|
|
112
|
+
pruned.panels = delta.panels;
|
|
113
|
+
}
|
|
114
|
+
return pruned;
|
|
115
|
+
}
|
|
116
|
+
export class LocalStorageShellSettingsAdapter {
|
|
117
|
+
key;
|
|
118
|
+
constructor(key) {
|
|
119
|
+
this.key = key;
|
|
120
|
+
}
|
|
121
|
+
read() {
|
|
122
|
+
if (typeof window === 'undefined')
|
|
123
|
+
return null;
|
|
124
|
+
try {
|
|
125
|
+
const raw = window.localStorage.getItem(this.key);
|
|
126
|
+
if (!raw)
|
|
127
|
+
return null;
|
|
128
|
+
return JSON.parse(raw);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
write(delta) {
|
|
135
|
+
if (typeof window === 'undefined')
|
|
136
|
+
return;
|
|
137
|
+
window.localStorage.setItem(this.key, JSON.stringify(pruneShellSettingsDelta(delta)));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { PanelEdge, PanelState, ResolvedShellConfig, ShellActivity, ShellActivityBadge, ShellActivityEvent, ShellActivityFilter, ShellFocusTool, ShellPanelDefaults, ShellScope, ShellSettingsAdapter, ShellSettingsDelta, ShellStateSnapshot, VisiblePanelState } from './types.js';
|
|
2
|
+
type ActivityListener = (event: ShellActivityEvent) => void;
|
|
3
|
+
export interface ShellStateOptions {
|
|
4
|
+
config?: ShellPanelDefaults;
|
|
5
|
+
settings?: ShellSettingsDelta;
|
|
6
|
+
settingsAdapter?: ShellSettingsAdapter;
|
|
7
|
+
storageKey?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class ShellState {
|
|
10
|
+
readonly config: ResolvedShellConfig;
|
|
11
|
+
readonly adapter: ShellSettingsAdapter | null;
|
|
12
|
+
settings: ShellSettingsDelta;
|
|
13
|
+
panels: Record<PanelEdge, PanelState>;
|
|
14
|
+
focusTools: ShellFocusTool[];
|
|
15
|
+
activeFocusToolId: string | null;
|
|
16
|
+
activities: ShellActivity[];
|
|
17
|
+
private activityListeners;
|
|
18
|
+
constructor(options?: ShellStateOptions);
|
|
19
|
+
hydrate(): Promise<void>;
|
|
20
|
+
snapshot(): ShellStateSnapshot;
|
|
21
|
+
applySettings(delta: ShellSettingsDelta, options?: {
|
|
22
|
+
persist?: boolean;
|
|
23
|
+
}): void;
|
|
24
|
+
setHotkeysEnabled(enabled: boolean): void;
|
|
25
|
+
setHotkey(edge: PanelEdge, code: string | null): void;
|
|
26
|
+
setPanel(edge: PanelEdge, state: VisiblePanelState): void;
|
|
27
|
+
togglePanel(edge: PanelEdge): void;
|
|
28
|
+
expandPanel(edge: PanelEdge): void;
|
|
29
|
+
collapsePanel(edge: PanelEdge): void;
|
|
30
|
+
closeTopmostExpanded(): boolean;
|
|
31
|
+
registerFocusTool(tool: ShellFocusTool): () => void;
|
|
32
|
+
unregisterFocusTool(id: string): void;
|
|
33
|
+
openFocusTool(id: string): void;
|
|
34
|
+
upsertActivity(activity: ShellActivity): void;
|
|
35
|
+
updateActivity(id: string, patch: Partial<Omit<ShellActivity, 'id'>>): void;
|
|
36
|
+
removeActivity(id: string): void;
|
|
37
|
+
watchActivities(listener: ActivityListener): () => void;
|
|
38
|
+
listActivities(filter?: ShellActivityFilter): ShellActivity[];
|
|
39
|
+
activityBadge(edge: PanelEdge): ShellActivityBadge;
|
|
40
|
+
homeEdgeForScope(scope: ShellScope): PanelEdge;
|
|
41
|
+
private closeExclusivePeers;
|
|
42
|
+
private persistSettings;
|
|
43
|
+
private emitActivity;
|
|
44
|
+
}
|
|
45
|
+
export declare function createShellState(options?: ShellStateOptions): ShellState;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=state.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/state.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAGpB,KAAK,gBAAgB,GAAG,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,UAAU;IACrB,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAE9C,QAAQ,qBAAkC;IAC1C,MAAM,gCAKH;IACH,UAAU,mBAAgC;IAC1C,iBAAiB,gBAA+B;IAChD,UAAU,kBAA+B;IAEzC,OAAO,CAAC,iBAAiB,CAA+B;gBAE5C,OAAO,GAAE,iBAAsB;IAUrC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B,QAAQ,IAAI,kBAAkB;IAY9B,aAAa,CACX,KAAK,EAAE,kBAAkB,EACzB,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAO,GAClC,IAAI;IAcP,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIzC,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAQrD,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAazD,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAQlC,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAIlC,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAIpC,oBAAoB,IAAI,OAAO;IAU/B,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,IAAI;IASnD,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAOrC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAU/B,cAAc,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAuB7C,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI;IAW3E,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAOhC,eAAe,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,IAAI;IAKvD,cAAc,CAAC,MAAM,GAAE,mBAAwB,GAAG,aAAa,EAAE;IASjE,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,kBAAkB;IAsBlD,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS;IAW9C,OAAO,CAAC,mBAAmB;YAmBb,eAAe;IAI7B,OAAO,CAAC,YAAY;CAGrB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,CAE5E"}
|