@elench/shell 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # @elench/shell
2
+
3
+ `@elench/shell` is the shared Elench desktop shell. Product code supplies
4
+ sections, sidebar entries, tab descriptors, tab renderers, and inspector/status
5
+ content. The package owns the activity rail, sidebar, tab rail, main pane,
6
+ inspector placement, status bar, persistence, and shell actions.
7
+
8
+ The core contract is strict: domain content can only render inside an open tab.
9
+ The shell never calls a product renderer with a null tab.
@@ -0,0 +1,28 @@
1
+ export {
2
+ ShellApp,
3
+ ShellEmptyState,
4
+ ShellField,
5
+ ShellMetric,
6
+ ShellPage,
7
+ ShellSidebar,
8
+ ShellSidebarItem,
9
+ ShellSidebarSection,
10
+ defineShellApp,
11
+ defineShellSection,
12
+ defineShellTab,
13
+ useShellController,
14
+ } from "./shell.js";
15
+ export type {
16
+ DefineShellSectionInput,
17
+ ShellActionMeta,
18
+ ShellAppDefinition,
19
+ ShellAppProps,
20
+ ShellController,
21
+ ShellRenderContext,
22
+ ShellSectionDefinition,
23
+ ShellSidebarContext,
24
+ ShellTab,
25
+ ShellTabTarget,
26
+ ShellTabTone,
27
+ } from "./shell.js";
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,eAAe,EACf,UAAU,EACV,WAAW,EACX,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,uBAAuB,EACvB,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,QAAQ,EACR,cAAc,EACd,YAAY,EACb,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { ShellApp, ShellEmptyState, ShellField, ShellMetric, ShellPage, ShellSidebar, ShellSidebarItem, ShellSidebarSection, defineShellApp, defineShellSection, defineShellTab, useShellController } from "./shell.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,eAAe,EACf,UAAU,EACV,WAAW,EACX,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EACnB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,147 @@
1
+ import { type CSSProperties, type ReactNode } from "react";
2
+ export type ShellTabTone =
3
+ | "neutral"
4
+ | "success"
5
+ | "warning"
6
+ | "danger"
7
+ | "info";
8
+ export type ShellTabTarget = {
9
+ kind: string;
10
+ [key: string]: string | number | boolean | null | undefined;
11
+ };
12
+ export type ShellTab<TTarget extends ShellTabTarget = ShellTabTarget> = {
13
+ id: string;
14
+ sectionId: string;
15
+ title: string;
16
+ description?: string;
17
+ tone?: ShellTabTone;
18
+ preview?: boolean;
19
+ target: TTarget;
20
+ };
21
+ export type ShellActionMeta = {
22
+ preview?: boolean;
23
+ source?: string;
24
+ };
25
+ export type ShellController = {
26
+ activeSectionId: string;
27
+ activeTab: ShellTab | null;
28
+ closeAllTabs: (meta?: ShellActionMeta) => void;
29
+ closeOtherTabs: (tabId: string, meta?: ShellActionMeta) => void;
30
+ closeTab: (tabId: string, meta?: ShellActionMeta) => void;
31
+ isOpen: (tabId: string) => boolean;
32
+ isSelected: (tabId: string) => boolean;
33
+ openTab: (tab: ShellTab, meta?: ShellActionMeta) => void;
34
+ pinTab: (tabId: string, meta?: ShellActionMeta) => void;
35
+ selectSection: (sectionId: string, meta?: ShellActionMeta) => void;
36
+ selectTab: (tabId: string, meta?: ShellActionMeta) => void;
37
+ tabs: ShellTab[];
38
+ tabsForActiveSection: ShellTab[];
39
+ tabsForSection: (sectionId: string) => ShellTab[];
40
+ };
41
+ export type ShellSidebarContext = ShellController & {
42
+ section: ShellSectionDefinition;
43
+ };
44
+ export type ShellRenderContext<TTab extends ShellTab = ShellTab> =
45
+ ShellController & {
46
+ section: ShellSectionDefinition;
47
+ tab: TTab;
48
+ };
49
+ export type DefineShellSectionInput = {
50
+ id: string;
51
+ label: string;
52
+ icon: ReactNode;
53
+ renderSidebar: (ctx: ShellSidebarContext) => ReactNode;
54
+ renderTab: (ctx: ShellRenderContext) => ReactNode;
55
+ renderInspector?: (ctx: ShellRenderContext) => ReactNode;
56
+ renderStatus?: (ctx: ShellController) => ReactNode;
57
+ };
58
+ export type ShellSectionDefinition = DefineShellSectionInput;
59
+ export type ShellAppDefinition = {
60
+ id: string;
61
+ title: string;
62
+ sections: ShellSectionDefinition[];
63
+ storageNamespace: string;
64
+ };
65
+ export type ShellAppProps = {
66
+ app: ShellAppDefinition;
67
+ initialSectionId?: string;
68
+ };
69
+ export declare function defineShellApp(
70
+ app: ShellAppDefinition,
71
+ ): ShellAppDefinition;
72
+ export declare function defineShellSection(
73
+ section: DefineShellSectionInput,
74
+ ): ShellSectionDefinition;
75
+ export declare function defineShellTab<TTarget extends ShellTabTarget>(
76
+ tab: ShellTab<TTarget>,
77
+ ): ShellTab<TTarget>;
78
+ export declare function useShellController(): ShellController;
79
+ export declare function ShellApp({
80
+ app,
81
+ initialSectionId,
82
+ }: ShellAppProps): import("react/jsx-runtime").JSX.Element;
83
+ export declare function ShellSidebar({
84
+ children,
85
+ title,
86
+ }: {
87
+ children: ReactNode;
88
+ title: string;
89
+ }): import("react/jsx-runtime").JSX.Element;
90
+ export declare function ShellSidebarSection({
91
+ children,
92
+ title,
93
+ }: {
94
+ children: ReactNode;
95
+ title: string;
96
+ }): import("react/jsx-runtime").JSX.Element;
97
+ export declare function ShellSidebarItem({
98
+ active,
99
+ children,
100
+ description,
101
+ icon,
102
+ onClick,
103
+ tone,
104
+ }: {
105
+ active?: boolean;
106
+ children: ReactNode;
107
+ description?: string;
108
+ icon?: ReactNode;
109
+ onClick: () => void;
110
+ tone?: ShellTabTone;
111
+ }): import("react/jsx-runtime").JSX.Element;
112
+ export declare function ShellPage({
113
+ actions,
114
+ children,
115
+ description,
116
+ eyebrow,
117
+ title,
118
+ }: {
119
+ actions?: ReactNode;
120
+ children: ReactNode;
121
+ description?: string;
122
+ eyebrow?: string | null;
123
+ title: string;
124
+ }): import("react/jsx-runtime").JSX.Element;
125
+ export declare function ShellMetric({
126
+ title,
127
+ value,
128
+ }: {
129
+ title: string;
130
+ value: ReactNode;
131
+ }): import("react/jsx-runtime").JSX.Element;
132
+ export declare function ShellField({
133
+ label,
134
+ value,
135
+ }: {
136
+ label: string;
137
+ value: ReactNode;
138
+ }): import("react/jsx-runtime").JSX.Element;
139
+ export declare function ShellEmptyState({
140
+ description,
141
+ title,
142
+ }: {
143
+ description?: string;
144
+ title: string;
145
+ }): import("react/jsx-runtime").JSX.Element;
146
+ export declare function createInsetStyle(value: number): CSSProperties;
147
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../src/shell.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AAUf,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,SAAS,GACT,SAAS,GACT,QAAQ,GACR,MAAM,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,QAAQ,CAAC,OAAO,SAAS,cAAc,GAAG,cAAc,IAAI;IACtE,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,CAAC,IAAI,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IAChE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IAC1D,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,OAAO,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IACzD,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IACxD,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IACnE,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3D,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,oBAAoB,EAAE,QAAQ,EAAE,CAAC;IACjC,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG;IAClD,OAAO,EAAE,sBAAsB,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,kBAAkB,CAAC,IAAI,SAAS,QAAQ,GAAG,QAAQ,IAC7D,eAAe,GAAG;IAChB,OAAO,EAAE,sBAAsB,CAAC;IAChC,GAAG,EAAE,IAAI,CAAC;CACX,CAAC;AAEJ,MAAM,MAAM,uBAAuB,GAAG;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,aAAa,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,SAAS,CAAC;IACvD,SAAS,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,SAAS,CAAC;IAClD,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,SAAS,CAAC;IACzD,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,SAAS,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAE7D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,kBAAkB,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAmBF,wBAAgB,cAAc,CAAC,GAAG,EAAE,kBAAkB,GAAG,kBAAkB,CAW1E;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,uBAAuB,GAC/B,sBAAsB,CAExB;AAED,wBAAgB,cAAc,CAAC,OAAO,SAAS,cAAc,EAC3D,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,GACrB,QAAQ,CAAC,OAAO,CAAC,CAEnB;AAED,wBAAgB,kBAAkB,IAAI,eAAe,CAEpD;AAED,wBAAgB,QAAQ,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,EAAE,aAAa,2CA4NhE;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAK,EACN,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,2CAOA;AAED,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,KAAK,EACN,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,2CAOA;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,QAAQ,EACR,WAAW,EACX,IAAI,EACJ,OAAO,EACP,IAAI,EACL,EAAE;IACD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,2CAqBA;AAED,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,QAAQ,EACR,WAAW,EACX,OAAO,EACP,KAAK,EACN,EAAE;IACD,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf,2CAcA;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,KAAK,EACN,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;CAClB,2CAOA;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACN,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;CAClB,2CAOA;AAED,wBAAgB,eAAe,CAAC,EAC9B,WAAW,EACX,KAAK,EACN,EAAE;IACD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf,2CAOA;AAqTD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAE7D"}
package/dist/shell.js ADDED
@@ -0,0 +1,339 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
4
+ import { ChevronRightIcon, PanelLeftCloseIcon, PanelLeftOpenIcon, PanelRightCloseIcon, PanelRightOpenIcon, XIcon } from "lucide-react";
5
+ const ShellContext = createContext(null);
6
+ export function defineShellApp(app) {
7
+ assertUnique(app.sections.map((section) => section.id), "Shell sections must have unique ids");
8
+ if (app.sections.length === 0) {
9
+ throw new Error("Shell apps must define at least one section.");
10
+ }
11
+ return app;
12
+ }
13
+ export function defineShellSection(section) {
14
+ return section;
15
+ }
16
+ export function defineShellTab(tab) {
17
+ return tab;
18
+ }
19
+ export function useShellController() {
20
+ return useShell();
21
+ }
22
+ export function ShellApp({ app, initialSectionId }) {
23
+ const defaultSectionId = resolveSectionId(app, initialSectionId);
24
+ const storageKey = `${app.storageNamespace}:elench-shell:v1`;
25
+ const initialState = useMemo(() => loadPersistedState(storageKey, app, defaultSectionId), [app, defaultSectionId, storageKey]);
26
+ const [activeSectionId, setActiveSectionId] = useState(initialState.activeSectionId);
27
+ const [activeTabIdBySection, setActiveTabIdBySection] = useState(initialState.activeTabIdBySection);
28
+ const [tabs, setTabs] = useState(initialState.tabs);
29
+ const [leftSidebarOpen, setLeftSidebarOpen] = useState(true);
30
+ const [rightInspectorOpen, setRightInspectorOpen] = useState(true);
31
+ const sectionsById = useMemo(() => new Map(app.sections.map((section) => [section.id, section])), [app.sections]);
32
+ const activeSection = sectionsById.get(activeSectionId) ?? app.sections[0];
33
+ const tabsForActiveSection = tabs.filter((tab) => tab.sectionId === activeSection.id);
34
+ const activeTabId = activeTabIdBySection[activeSection.id] ?? null;
35
+ const activeTab = tabsForActiveSection.find((tab) => tab.id === activeTabId) ?? null;
36
+ useEffect(() => {
37
+ persistState(storageKey, {
38
+ activeSectionId,
39
+ activeTabIdBySection,
40
+ tabs
41
+ });
42
+ }, [activeSectionId, activeTabIdBySection, storageKey, tabs]);
43
+ const tabsForSection = useCallback((sectionId) => tabs.filter((tab) => tab.sectionId === sectionId), [tabs]);
44
+ const selectSection = useCallback((sectionId) => {
45
+ if (!sectionsById.has(sectionId)) {
46
+ throw new Error(`Unknown shell section: ${sectionId}`);
47
+ }
48
+ setActiveSectionId(sectionId);
49
+ }, [sectionsById]);
50
+ const selectTab = useCallback((tabId) => {
51
+ const tab = tabs.find((candidate) => candidate.id === tabId);
52
+ if (!tab) {
53
+ throw new Error(`Unknown shell tab: ${tabId}`);
54
+ }
55
+ setActiveSectionId(tab.sectionId);
56
+ setActiveTabIdBySection((current) => ({
57
+ ...current,
58
+ [tab.sectionId]: tab.id
59
+ }));
60
+ }, [tabs]);
61
+ const openTab = useCallback((tab, meta) => {
62
+ setTabs((current) => {
63
+ const preview = meta?.preview === true;
64
+ const nextTab = preview ? { ...tab, preview: true } : tab;
65
+ const existing = current.some((candidate) => candidate.id === tab.id);
66
+ const withoutReplacedPreview = preview && !existing
67
+ ? current.filter((candidate) => !(candidate.sectionId === tab.sectionId && candidate.preview))
68
+ : current;
69
+ return existing
70
+ ? withoutReplacedPreview.map((candidate) => candidate.id === tab.id ? nextTab : candidate)
71
+ : [...withoutReplacedPreview, nextTab];
72
+ });
73
+ setActiveSectionId(tab.sectionId);
74
+ setActiveTabIdBySection((current) => ({
75
+ ...current,
76
+ [tab.sectionId]: tab.id
77
+ }));
78
+ }, []);
79
+ const pinTab = useCallback((tabId) => {
80
+ setTabs((current) => current.map((tab) => tab.id === tabId && tab.preview ? { ...tab, preview: false } : tab));
81
+ }, []);
82
+ const closeTab = useCallback((tabId) => {
83
+ setTabs((currentTabs) => {
84
+ const closingIndex = currentTabs.findIndex((tab) => tab.id === tabId);
85
+ if (closingIndex === -1)
86
+ return currentTabs;
87
+ const closingTab = currentTabs[closingIndex];
88
+ const nextTabs = currentTabs.filter((tab) => tab.id !== tabId);
89
+ setActiveTabIdBySection((currentActive) => {
90
+ if (currentActive[closingTab.sectionId] !== tabId) {
91
+ return currentActive;
92
+ }
93
+ const sameSection = nextTabs.filter((tab) => tab.sectionId === closingTab.sectionId);
94
+ const sameSectionOriginalIndex = currentTabs
95
+ .filter((tab) => tab.sectionId === closingTab.sectionId)
96
+ .findIndex((tab) => tab.id === tabId);
97
+ const nextActive = sameSection[Math.min(sameSectionOriginalIndex, sameSection.length - 1)] ?? null;
98
+ return {
99
+ ...currentActive,
100
+ [closingTab.sectionId]: nextActive?.id ?? null
101
+ };
102
+ });
103
+ return nextTabs;
104
+ });
105
+ }, []);
106
+ const closeOtherTabs = useCallback((tabId) => {
107
+ setTabs((current) => {
108
+ const tab = current.find((candidate) => candidate.id === tabId);
109
+ if (!tab)
110
+ return current;
111
+ setActiveSectionId(tab.sectionId);
112
+ setActiveTabIdBySection((active) => ({
113
+ ...active,
114
+ [tab.sectionId]: tab.id
115
+ }));
116
+ return [tab];
117
+ });
118
+ }, []);
119
+ const closeAllTabs = useCallback(() => {
120
+ setTabs([]);
121
+ setActiveTabIdBySection({});
122
+ }, []);
123
+ const controller = useMemo(() => ({
124
+ activeSectionId: activeSection.id,
125
+ activeTab,
126
+ closeAllTabs,
127
+ closeOtherTabs,
128
+ closeTab,
129
+ isOpen: (tabId) => tabs.some((tab) => tab.id === tabId),
130
+ isSelected: (tabId) => activeTab?.id === tabId,
131
+ openTab,
132
+ pinTab,
133
+ selectSection,
134
+ selectTab,
135
+ tabs,
136
+ tabsForActiveSection,
137
+ tabsForSection
138
+ }), [
139
+ activeSection.id,
140
+ activeTab,
141
+ closeAllTabs,
142
+ closeOtherTabs,
143
+ closeTab,
144
+ openTab,
145
+ pinTab,
146
+ selectSection,
147
+ selectTab,
148
+ tabs,
149
+ tabsForActiveSection,
150
+ tabsForSection
151
+ ]);
152
+ const value = useMemo(() => ({
153
+ ...controller,
154
+ app,
155
+ activeSection,
156
+ leftSidebarOpen,
157
+ rightInspectorOpen,
158
+ setLeftSidebarOpen,
159
+ setRightInspectorOpen
160
+ }), [
161
+ activeSection,
162
+ app,
163
+ controller,
164
+ leftSidebarOpen,
165
+ rightInspectorOpen
166
+ ]);
167
+ return (_jsx(ShellContext.Provider, { value: value, children: _jsxs("div", { className: "elench-shell", "data-left-sidebar": leftSidebarOpen ? "open" : "closed", "data-right-inspector": rightInspectorOpen ? "open" : "closed", children: [_jsx(TopBar, {}), _jsx(ActivityRail, {}), leftSidebarOpen ? _jsx(LeftSidebar, {}) : null, _jsx(MainPane, {}), rightInspectorOpen ? _jsx(RightInspector, {}) : null, _jsx(StatusBar, {})] }) }));
168
+ }
169
+ export function ShellSidebar({ children, title }) {
170
+ return (_jsxs("div", { className: "elench-shell-sidebar-frame", children: [_jsx("div", { className: "elench-shell-sidebar-title", children: title }), _jsx("div", { className: "elench-shell-sidebar-content", children: children })] }));
171
+ }
172
+ export function ShellSidebarSection({ children, title }) {
173
+ return (_jsxs("section", { className: "elench-shell-sidebar-section", children: [_jsx("h2", { children: title }), _jsx("div", { children: children })] }));
174
+ }
175
+ export function ShellSidebarItem({ active, children, description, icon, onClick, tone }) {
176
+ return (_jsxs("button", { "aria-selected": active ? "true" : "false", className: "elench-shell-sidebar-item", "data-tone": tone ?? "neutral", onClick: onClick, role: "tab", type: "button", children: [icon ? _jsx("span", { className: "elench-shell-sidebar-item-icon", children: icon }) : null, _jsxs("span", { className: "elench-shell-sidebar-item-text", children: [_jsx("span", { className: "elench-shell-sidebar-item-title", children: children }), description ? (_jsx("span", { className: "elench-shell-sidebar-item-description", children: description })) : null] })] }));
177
+ }
178
+ export function ShellPage({ actions, children, description, eyebrow, title }) {
179
+ return (_jsxs("div", { className: "elench-shell-page", children: [_jsxs("header", { className: "elench-shell-page-header", children: [_jsxs("div", { children: [eyebrow ? _jsx("div", { className: "elench-shell-page-eyebrow", children: eyebrow }) : null, _jsx("h1", { children: title }), description ? _jsx("p", { children: description }) : null] }), actions ? _jsx("div", { className: "elench-shell-page-actions", children: actions }) : null] }), children] }));
180
+ }
181
+ export function ShellMetric({ title, value }) {
182
+ return (_jsxs("div", { className: "elench-shell-metric", children: [_jsx("div", { children: title }), _jsx("strong", { children: value })] }));
183
+ }
184
+ export function ShellField({ label, value }) {
185
+ return (_jsxs("div", { className: "elench-shell-field", children: [_jsx("span", { children: label }), _jsx("strong", { children: value })] }));
186
+ }
187
+ export function ShellEmptyState({ description, title }) {
188
+ return (_jsxs("div", { className: "elench-shell-empty-state", children: [_jsx("strong", { children: title }), description ? _jsx("p", { children: description }) : null] }));
189
+ }
190
+ function TopBar() {
191
+ const { app, leftSidebarOpen, rightInspectorOpen, setLeftSidebarOpen, setRightInspectorOpen } = useShell();
192
+ return (_jsxs("header", { className: "elench-shell-topbar", children: [_jsx("div", { className: "elench-shell-topbar-title", children: app.title }), _jsxs("div", { className: "elench-shell-topbar-actions", children: [_jsx("button", { "aria-label": leftSidebarOpen ? "Close sidebar" : "Open sidebar", onClick: () => setLeftSidebarOpen(!leftSidebarOpen), type: "button", children: leftSidebarOpen ? _jsx(PanelLeftCloseIcon, {}) : _jsx(PanelLeftOpenIcon, {}) }), _jsx("button", { "aria-label": rightInspectorOpen ? "Close inspector" : "Open inspector", onClick: () => setRightInspectorOpen(!rightInspectorOpen), type: "button", children: rightInspectorOpen ? _jsx(PanelRightCloseIcon, {}) : _jsx(PanelRightOpenIcon, {}) })] })] }));
193
+ }
194
+ function ActivityRail() {
195
+ const { activeSectionId, app, selectSection } = useShell();
196
+ return (_jsx("nav", { "aria-label": "Activity rail", className: "elench-shell-activity-rail", children: app.sections.map((section) => (_jsx("button", { "aria-label": section.label, "aria-pressed": activeSectionId === section.id, className: "elench-shell-activity-button", onClick: () => selectSection(section.id, { source: "activity_rail" }), title: section.label, type: "button", children: section.icon }, section.id))) }));
197
+ }
198
+ function LeftSidebar() {
199
+ const shell = useShell();
200
+ const sidebarContext = {
201
+ ...toController(shell),
202
+ section: shell.activeSection
203
+ };
204
+ return (_jsx("aside", { "aria-label": "Sidebar", className: "elench-shell-sidebar", children: shell.activeSection.renderSidebar(sidebarContext) }));
205
+ }
206
+ function MainPane() {
207
+ const shell = useShell();
208
+ const activeTab = shell.activeTab;
209
+ return (_jsxs("main", { className: "elench-shell-main", children: [_jsx(TabRail, {}), _jsx("section", { className: "elench-shell-workspace", "data-testid": "shell-workspace", children: activeTab ? (shell.activeSection.renderTab({
210
+ ...toController(shell),
211
+ section: shell.activeSection,
212
+ tab: activeTab
213
+ })) : (_jsx("div", { "aria-label": "No open tab", className: "elench-shell-blank-main" })) })] }));
214
+ }
215
+ function TabRail() {
216
+ const { activeTab, closeTab, pinTab, selectTab, tabsForActiveSection } = useShell();
217
+ return (_jsx("div", { "aria-label": "Main tabs", className: "elench-shell-tab-rail", role: "tablist", children: tabsForActiveSection.map((tab) => (_jsxs("div", { "aria-selected": activeTab?.id === tab.id ? "true" : "false", className: "elench-shell-main-tab", "data-preview": tab.preview ? "true" : "false", "data-tone": tab.tone ?? "neutral", role: "tab", children: [_jsx("button", { className: "elench-shell-main-tab-select", onClick: () => selectTab(tab.id, { source: "tab_rail" }), type: "button", children: _jsx("span", { children: tab.title }) }), tab.preview ? (_jsx("button", { "aria-label": `Pin ${tab.title}`, className: "elench-shell-main-tab-icon", onClick: () => pinTab(tab.id, { source: "tab_rail" }), type: "button", children: _jsx(ChevronRightIcon, {}) })) : null, _jsx("button", { "aria-label": `Close ${tab.title}`, className: "elench-shell-main-tab-icon", onClick: () => closeTab(tab.id, { source: "tab_rail" }), type: "button", children: _jsx(XIcon, {}) })] }, tab.id))) }));
218
+ }
219
+ function RightInspector() {
220
+ const shell = useShell();
221
+ const activeTab = shell.activeTab;
222
+ return (_jsx("aside", { "aria-label": "Inspector", className: "elench-shell-inspector", children: activeTab && shell.activeSection.renderInspector ? (shell.activeSection.renderInspector({
223
+ ...toController(shell),
224
+ section: shell.activeSection,
225
+ tab: activeTab
226
+ })) : (_jsx(ShellEmptyState, { title: "No tab selected", description: "Open a tab to inspect its details." })) }));
227
+ }
228
+ function StatusBar() {
229
+ const shell = useShell();
230
+ return (_jsxs("footer", { className: "elench-shell-statusbar", children: [_jsx("span", { children: shell.activeSection.label }), _jsxs("span", { children: [shell.tabs.length, " open tabs"] }), _jsx("div", { className: "elench-shell-statusbar-slot", children: shell.activeSection.renderStatus?.(toController(shell)) })] }));
231
+ }
232
+ function useShell() {
233
+ const context = useContext(ShellContext);
234
+ if (!context) {
235
+ throw new Error("Shell hooks must be used within ShellApp.");
236
+ }
237
+ return context;
238
+ }
239
+ function toController(shell) {
240
+ return {
241
+ activeSectionId: shell.activeSectionId,
242
+ activeTab: shell.activeTab,
243
+ closeAllTabs: shell.closeAllTabs,
244
+ closeOtherTabs: shell.closeOtherTabs,
245
+ closeTab: shell.closeTab,
246
+ isOpen: shell.isOpen,
247
+ isSelected: shell.isSelected,
248
+ openTab: shell.openTab,
249
+ pinTab: shell.pinTab,
250
+ selectSection: shell.selectSection,
251
+ selectTab: shell.selectTab,
252
+ tabs: shell.tabs,
253
+ tabsForActiveSection: shell.tabsForActiveSection,
254
+ tabsForSection: shell.tabsForSection
255
+ };
256
+ }
257
+ function loadPersistedState(storageKey, app, fallbackSectionId) {
258
+ if (typeof window === "undefined") {
259
+ return emptyState(fallbackSectionId);
260
+ }
261
+ try {
262
+ const raw = window.localStorage.getItem(storageKey);
263
+ if (!raw)
264
+ return emptyState(fallbackSectionId);
265
+ const parsed = JSON.parse(raw);
266
+ const validSections = new Set(app.sections.map((section) => section.id));
267
+ const tabs = Array.isArray(parsed.tabs)
268
+ ? parsed.tabs.filter((tab) => isValidTab(tab, validSections))
269
+ : [];
270
+ const tabIds = new Set(tabs.map((tab) => tab.id));
271
+ const activeTabIdBySection = sanitizeActiveTabs(parsed.activeTabIdBySection, validSections, tabIds);
272
+ const activeSectionId = typeof parsed.activeSectionId === "string" &&
273
+ validSections.has(parsed.activeSectionId)
274
+ ? parsed.activeSectionId
275
+ : fallbackSectionId;
276
+ return {
277
+ activeSectionId,
278
+ activeTabIdBySection,
279
+ tabs
280
+ };
281
+ }
282
+ catch {
283
+ return emptyState(fallbackSectionId);
284
+ }
285
+ }
286
+ function persistState(storageKey, state) {
287
+ if (typeof window === "undefined")
288
+ return;
289
+ window.localStorage.setItem(storageKey, JSON.stringify(state));
290
+ }
291
+ function emptyState(activeSectionId) {
292
+ return {
293
+ activeSectionId,
294
+ activeTabIdBySection: {},
295
+ tabs: []
296
+ };
297
+ }
298
+ function resolveSectionId(app, initialSectionId) {
299
+ if (initialSectionId &&
300
+ app.sections.some((section) => section.id === initialSectionId)) {
301
+ return initialSectionId;
302
+ }
303
+ return app.sections[0].id;
304
+ }
305
+ function isValidTab(value, validSections) {
306
+ if (typeof value !== "object" || value == null)
307
+ return false;
308
+ const tab = value;
309
+ return (typeof tab.id === "string" &&
310
+ typeof tab.sectionId === "string" &&
311
+ validSections.has(tab.sectionId) &&
312
+ typeof tab.title === "string" &&
313
+ typeof tab.target === "object" &&
314
+ tab.target != null &&
315
+ typeof tab.target.kind === "string");
316
+ }
317
+ function sanitizeActiveTabs(value, validSections, tabIds) {
318
+ if (typeof value !== "object" || value == null)
319
+ return {};
320
+ const candidate = value;
321
+ const result = {};
322
+ for (const [sectionId, tabId] of Object.entries(candidate)) {
323
+ if (!validSections.has(sectionId))
324
+ continue;
325
+ if (typeof tabId === "string" && tabIds.has(tabId)) {
326
+ result[sectionId] = tabId;
327
+ }
328
+ }
329
+ return result;
330
+ }
331
+ function assertUnique(values, message) {
332
+ if (new Set(values).size !== values.length) {
333
+ throw new Error(message);
334
+ }
335
+ }
336
+ export function createInsetStyle(value) {
337
+ return { "--elench-shell-inset": `${value}px` };
338
+ }
339
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,475 @@
1
+ .elench-shell {
2
+ --elench-shell-topbar-height: 36px;
3
+ --elench-shell-status-height: 28px;
4
+ --elench-shell-rail-width: 46px;
5
+ --elench-shell-sidebar-width: 292px;
6
+ --elench-shell-inspector-width: 292px;
7
+ display: grid;
8
+ grid-template-areas:
9
+ "topbar topbar topbar topbar"
10
+ "rail sidebar main inspector"
11
+ "status status status status";
12
+ grid-template-columns:
13
+ var(--elench-shell-rail-width)
14
+ var(--elench-shell-sidebar-width)
15
+ minmax(0, 1fr)
16
+ var(--elench-shell-inspector-width);
17
+ grid-template-rows: var(--elench-shell-topbar-height) minmax(0, 1fr) var(
18
+ --elench-shell-status-height
19
+ );
20
+ width: 100vw;
21
+ height: 100vh;
22
+ min-height: 0;
23
+ overflow: hidden;
24
+ background: var(--bg-primary, #0a1120);
25
+ color: var(--fg, #e5edf7);
26
+ }
27
+
28
+ .elench-shell[data-left-sidebar="closed"] {
29
+ grid-template-areas:
30
+ "topbar topbar topbar"
31
+ "rail main inspector"
32
+ "status status status";
33
+ grid-template-columns:
34
+ var(--elench-shell-rail-width)
35
+ minmax(0, 1fr)
36
+ var(--elench-shell-inspector-width);
37
+ }
38
+
39
+ .elench-shell[data-right-inspector="closed"] {
40
+ grid-template-areas:
41
+ "topbar topbar topbar"
42
+ "rail sidebar main"
43
+ "status status status";
44
+ grid-template-columns:
45
+ var(--elench-shell-rail-width)
46
+ var(--elench-shell-sidebar-width)
47
+ minmax(0, 1fr);
48
+ }
49
+
50
+ .elench-shell[data-left-sidebar="closed"][data-right-inspector="closed"] {
51
+ grid-template-areas:
52
+ "topbar topbar"
53
+ "rail main"
54
+ "status status";
55
+ grid-template-columns: var(--elench-shell-rail-width) minmax(0, 1fr);
56
+ }
57
+
58
+ .elench-shell button {
59
+ font: inherit;
60
+ }
61
+
62
+ .elench-shell-topbar {
63
+ grid-area: topbar;
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: space-between;
67
+ border-bottom: 1px solid var(--border, #1e2d44);
68
+ background: var(--bg-secondary, #0f172a);
69
+ padding: 0 8px 0 12px;
70
+ }
71
+
72
+ .elench-shell-topbar-title {
73
+ min-width: 0;
74
+ overflow: hidden;
75
+ color: var(--fg-secondary, #a8b5c7);
76
+ font-size: 12px;
77
+ font-weight: 650;
78
+ text-overflow: ellipsis;
79
+ white-space: nowrap;
80
+ }
81
+
82
+ .elench-shell-topbar-actions {
83
+ display: flex;
84
+ align-items: center;
85
+ gap: 2px;
86
+ }
87
+
88
+ .elench-shell-topbar-actions button,
89
+ .elench-shell-activity-button,
90
+ .elench-shell-main-tab-icon {
91
+ display: inline-flex;
92
+ width: 28px;
93
+ height: 28px;
94
+ align-items: center;
95
+ justify-content: center;
96
+ border: 0;
97
+ border-radius: 6px;
98
+ background: transparent;
99
+ color: var(--fg-tertiary, #73839b);
100
+ cursor: pointer;
101
+ }
102
+
103
+ .elench-shell-topbar-actions button:hover,
104
+ .elench-shell-activity-button:hover,
105
+ .elench-shell-main-tab-icon:hover {
106
+ background: var(--bg-hover, #1e3050);
107
+ color: var(--fg, #e5edf7);
108
+ }
109
+
110
+ .elench-shell-topbar svg,
111
+ .elench-shell-activity-button svg,
112
+ .elench-shell-main-tab-icon svg {
113
+ width: 16px;
114
+ height: 16px;
115
+ }
116
+
117
+ .elench-shell-activity-rail {
118
+ grid-area: rail;
119
+ display: flex;
120
+ min-height: 0;
121
+ flex-direction: column;
122
+ align-items: center;
123
+ gap: 4px;
124
+ border-right: 1px solid var(--border, #1e2d44);
125
+ background: var(--bg-secondary, #0f172a);
126
+ padding: 8px 5px;
127
+ }
128
+
129
+ .elench-shell-activity-button {
130
+ width: 34px;
131
+ height: 34px;
132
+ position: relative;
133
+ }
134
+
135
+ .elench-shell-activity-button[aria-pressed="true"] {
136
+ background: var(--bg-active, #1a2d4a);
137
+ color: var(--fg, #e5edf7);
138
+ }
139
+
140
+ .elench-shell-activity-button[aria-pressed="true"]::before {
141
+ position: absolute;
142
+ left: -5px;
143
+ width: 2px;
144
+ height: 18px;
145
+ border-radius: 999px;
146
+ background: var(--primary, #3b82f6);
147
+ content: "";
148
+ }
149
+
150
+ .elench-shell-sidebar {
151
+ grid-area: sidebar;
152
+ min-width: 0;
153
+ min-height: 0;
154
+ overflow: hidden;
155
+ border-right: 1px solid var(--border, #1e2d44);
156
+ background: var(--bg-surface, #0f172a);
157
+ }
158
+
159
+ .elench-shell-sidebar-frame {
160
+ display: flex;
161
+ height: 100%;
162
+ min-height: 0;
163
+ flex-direction: column;
164
+ }
165
+
166
+ .elench-shell-sidebar-title {
167
+ flex: 0 0 auto;
168
+ border-bottom: 1px solid var(--border, #1e2d44);
169
+ color: var(--fg-secondary, #a8b5c7);
170
+ font-size: 11px;
171
+ font-weight: 700;
172
+ letter-spacing: 0.08em;
173
+ padding: 10px 12px;
174
+ text-transform: uppercase;
175
+ }
176
+
177
+ .elench-shell-sidebar-content {
178
+ min-height: 0;
179
+ flex: 1;
180
+ overflow: auto;
181
+ padding: 8px;
182
+ }
183
+
184
+ .elench-shell-sidebar-section {
185
+ margin: 0 0 12px;
186
+ }
187
+
188
+ .elench-shell-sidebar-section h2 {
189
+ color: var(--fg-tertiary, #73839b);
190
+ font-size: 11px;
191
+ font-weight: 650;
192
+ margin: 0 0 6px;
193
+ padding: 0 4px;
194
+ }
195
+
196
+ .elench-shell-sidebar-item {
197
+ display: flex;
198
+ width: 100%;
199
+ min-height: 42px;
200
+ align-items: center;
201
+ gap: 8px;
202
+ border: 1px solid transparent;
203
+ border-radius: 6px;
204
+ background: transparent;
205
+ color: var(--fg-secondary, #a8b5c7);
206
+ cursor: pointer;
207
+ padding: 7px 8px;
208
+ text-align: left;
209
+ }
210
+
211
+ .elench-shell-sidebar-item:hover {
212
+ background: var(--bg-hover, #1e3050);
213
+ color: var(--fg, #e5edf7);
214
+ }
215
+
216
+ .elench-shell-sidebar-item[aria-selected="true"] {
217
+ border-color: var(--border-strong, #2a3f5f);
218
+ background: var(--bg-active, #1a2d4a);
219
+ color: var(--fg, #e5edf7);
220
+ }
221
+
222
+ .elench-shell-sidebar-item-icon {
223
+ display: inline-flex;
224
+ flex: 0 0 auto;
225
+ color: var(--fg-tertiary, #73839b);
226
+ }
227
+
228
+ .elench-shell-sidebar-item-icon svg {
229
+ width: 16px;
230
+ height: 16px;
231
+ }
232
+
233
+ .elench-shell-sidebar-item-text {
234
+ display: grid;
235
+ min-width: 0;
236
+ gap: 2px;
237
+ }
238
+
239
+ .elench-shell-sidebar-item-title,
240
+ .elench-shell-main-tab-select span {
241
+ overflow: hidden;
242
+ text-overflow: ellipsis;
243
+ white-space: nowrap;
244
+ }
245
+
246
+ .elench-shell-sidebar-item-title {
247
+ font-size: 12.5px;
248
+ font-weight: 600;
249
+ }
250
+
251
+ .elench-shell-sidebar-item-description {
252
+ overflow: hidden;
253
+ color: var(--fg-tertiary, #73839b);
254
+ font-size: 11.5px;
255
+ text-overflow: ellipsis;
256
+ white-space: nowrap;
257
+ }
258
+
259
+ .elench-shell-main {
260
+ grid-area: main;
261
+ display: grid;
262
+ min-width: 0;
263
+ min-height: 0;
264
+ grid-template-rows: 34px minmax(0, 1fr);
265
+ background: var(--bg-primary, #0a1120);
266
+ }
267
+
268
+ .elench-shell-tab-rail {
269
+ display: flex;
270
+ min-width: 0;
271
+ align-items: end;
272
+ overflow-x: auto;
273
+ border-bottom: 1px solid var(--border, #1e2d44);
274
+ background: var(--bg-secondary, #0f172a);
275
+ padding: 3px 6px 0;
276
+ }
277
+
278
+ .elench-shell-main-tab {
279
+ display: flex;
280
+ min-width: 132px;
281
+ max-width: 220px;
282
+ height: 31px;
283
+ align-items: center;
284
+ border: 1px solid transparent;
285
+ border-bottom: 0;
286
+ border-radius: 6px 6px 0 0;
287
+ color: var(--fg-tertiary, #73839b);
288
+ }
289
+
290
+ .elench-shell-main-tab[aria-selected="true"] {
291
+ border-color: var(--border, #1e2d44);
292
+ background: var(--bg-surface, #0f172a);
293
+ color: var(--fg, #e5edf7);
294
+ }
295
+
296
+ .elench-shell-main-tab[data-preview="true"] .elench-shell-main-tab-select {
297
+ font-style: italic;
298
+ }
299
+
300
+ .elench-shell-main-tab-select {
301
+ min-width: 0;
302
+ flex: 1;
303
+ border: 0;
304
+ background: transparent;
305
+ color: inherit;
306
+ cursor: pointer;
307
+ padding: 0 8px;
308
+ text-align: left;
309
+ }
310
+
311
+ .elench-shell-workspace {
312
+ min-width: 0;
313
+ min-height: 0;
314
+ overflow: auto;
315
+ background: var(--bg-surface, #0f172a);
316
+ }
317
+
318
+ .elench-shell-blank-main {
319
+ height: 100%;
320
+ min-height: 0;
321
+ }
322
+
323
+ .elench-shell-inspector {
324
+ grid-area: inspector;
325
+ min-width: 0;
326
+ min-height: 0;
327
+ overflow: auto;
328
+ border-left: 1px solid var(--border, #1e2d44);
329
+ background: var(--bg-surface, #0f172a);
330
+ padding: 10px;
331
+ }
332
+
333
+ .elench-shell-statusbar {
334
+ grid-area: status;
335
+ display: flex;
336
+ min-width: 0;
337
+ align-items: center;
338
+ gap: 12px;
339
+ border-top: 1px solid var(--border, #1e2d44);
340
+ background: var(--bg-secondary, #0f172a);
341
+ color: var(--fg-tertiary, #73839b);
342
+ font-size: 11.5px;
343
+ padding: 0 10px;
344
+ }
345
+
346
+ .elench-shell-statusbar-slot {
347
+ min-width: 0;
348
+ flex: 1;
349
+ overflow: hidden;
350
+ text-overflow: ellipsis;
351
+ white-space: nowrap;
352
+ }
353
+
354
+ .elench-shell-page {
355
+ max-width: 1160px;
356
+ margin: 0 auto;
357
+ padding: 24px;
358
+ }
359
+
360
+ .elench-shell-page-header {
361
+ display: flex;
362
+ align-items: flex-start;
363
+ justify-content: space-between;
364
+ gap: 16px;
365
+ margin-bottom: 20px;
366
+ }
367
+
368
+ .elench-shell-page-eyebrow {
369
+ color: var(--fg-tertiary, #73839b);
370
+ font-size: 11px;
371
+ font-weight: 700;
372
+ letter-spacing: 0.08em;
373
+ margin-bottom: 4px;
374
+ text-transform: uppercase;
375
+ }
376
+
377
+ .elench-shell-page h1 {
378
+ color: var(--fg, #e5edf7);
379
+ font-size: 22px;
380
+ line-height: 1.2;
381
+ margin: 0;
382
+ }
383
+
384
+ .elench-shell-page p {
385
+ color: var(--fg-tertiary, #73839b);
386
+ font-size: 13px;
387
+ line-height: 1.6;
388
+ margin: 6px 0 0;
389
+ }
390
+
391
+ .elench-shell-page-actions {
392
+ flex: 0 0 auto;
393
+ }
394
+
395
+ .elench-shell-metric,
396
+ .elench-shell-field {
397
+ border: 1px solid var(--border, #1e2d44);
398
+ border-radius: 8px;
399
+ background: var(--bg-card, #162236);
400
+ }
401
+
402
+ .elench-shell-metric {
403
+ padding: 12px;
404
+ }
405
+
406
+ .elench-shell-metric div,
407
+ .elench-shell-field span {
408
+ color: var(--fg-tertiary, #73839b);
409
+ font-size: 11.5px;
410
+ }
411
+
412
+ .elench-shell-metric strong {
413
+ display: block;
414
+ color: var(--fg, #e5edf7);
415
+ font-size: 22px;
416
+ margin-top: 6px;
417
+ }
418
+
419
+ .elench-shell-field {
420
+ display: grid;
421
+ gap: 4px;
422
+ padding: 9px;
423
+ }
424
+
425
+ .elench-shell-field strong {
426
+ min-width: 0;
427
+ overflow: hidden;
428
+ color: var(--fg, #e5edf7);
429
+ font-size: 12px;
430
+ font-weight: 550;
431
+ text-overflow: ellipsis;
432
+ white-space: nowrap;
433
+ }
434
+
435
+ .elench-shell-empty-state {
436
+ display: grid;
437
+ min-height: 120px;
438
+ align-content: center;
439
+ justify-items: center;
440
+ border: 1px dashed var(--border, #1e2d44);
441
+ border-radius: 8px;
442
+ color: var(--fg-tertiary, #73839b);
443
+ padding: 18px;
444
+ text-align: center;
445
+ }
446
+
447
+ .elench-shell-empty-state strong {
448
+ color: var(--fg-secondary, #a8b5c7);
449
+ font-size: 13px;
450
+ }
451
+
452
+ .elench-shell-empty-state p {
453
+ max-width: 34ch;
454
+ font-size: 12px;
455
+ line-height: 1.5;
456
+ margin: 6px 0 0;
457
+ }
458
+
459
+ @media (max-width: 900px) {
460
+ .elench-shell,
461
+ .elench-shell[data-left-sidebar="closed"],
462
+ .elench-shell[data-right-inspector="closed"],
463
+ .elench-shell[data-left-sidebar="closed"][data-right-inspector="closed"] {
464
+ grid-template-areas:
465
+ "topbar topbar"
466
+ "rail main"
467
+ "status status";
468
+ grid-template-columns: var(--elench-shell-rail-width) minmax(0, 1fr);
469
+ }
470
+
471
+ .elench-shell-sidebar,
472
+ .elench-shell-inspector {
473
+ display: none;
474
+ }
475
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@elench/shell",
3
+ "version": "0.1.1",
4
+ "description": "A strict desktop application shell for Elench products.",
5
+ "type": "module",
6
+ "private": false,
7
+ "sideEffects": [
8
+ "./dist/styles.css"
9
+ ],
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js"
18
+ },
19
+ "./styles.css": "./dist/styles.css"
20
+ },
21
+ "scripts": {
22
+ "build": "rm -rf dist && tsc -p tsconfig.json && cp src/styles.css dist/styles.css",
23
+ "typecheck": "tsc -p tsconfig.json --noEmit",
24
+ "test": "vitest run --config vitest.config.ts"
25
+ },
26
+ "peerDependencies": {
27
+ "react": "^19.0.0",
28
+ "react-dom": "^19.0.0"
29
+ },
30
+ "dependencies": {
31
+ "lucide-react": "^1.8.0"
32
+ },
33
+ "devDependencies": {
34
+ "@testing-library/jest-dom": "^6.9.1",
35
+ "@testing-library/react": "^16.3.2",
36
+ "@testing-library/user-event": "^14.6.1",
37
+ "@vitejs/plugin-react": "^6.0.1",
38
+ "jsdom": "^29.0.2",
39
+ "typescript": "^5",
40
+ "vitest": "^4.1.4"
41
+ }
42
+ }