@tutti-os/browser-node 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +21 -0
- package/dist/assets/workspace-dock-website.d.ts +3 -0
- package/dist/assets/workspace-dock-website.png +0 -0
- package/dist/bridge/index.d.ts +15 -0
- package/dist/bridge/index.js +9 -0
- package/dist/bridge/index.js.map +1 -0
- package/dist/chunk-2GEY55PS.js +1179 -0
- package/dist/chunk-2GEY55PS.js.map +1 -0
- package/dist/chunk-IO5AJ2R5.js +111 -0
- package/dist/chunk-IO5AJ2R5.js.map +1 -0
- package/dist/chunk-IS2USG4D.js +93 -0
- package/dist/chunk-IS2USG4D.js.map +1 -0
- package/dist/chunk-LVVPDNEF.js +93 -0
- package/dist/chunk-LVVPDNEF.js.map +1 -0
- package/dist/chunk-UTXZLRPE.js +34 -0
- package/dist/chunk-UTXZLRPE.js.map +1 -0
- package/dist/electron-main/index.d.ts +158 -0
- package/dist/electron-main/index.js +1492 -0
- package/dist/electron-main/index.js.map +1 -0
- package/dist/electron-preload/index.d.ts +33 -0
- package/dist/electron-preload/index.js +140 -0
- package/dist/electron-preload/index.js.map +1 -0
- package/dist/i18n/index.d.ts +18 -0
- package/dist/i18n/index.js +13 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/index.d.ts +187 -0
- package/dist/index.js +165 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.d.ts +41 -0
- package/dist/react/index.js +11 -0
- package/dist/react/index.js.map +1 -0
- package/dist/types-Bmzz1Q84.d.ts +32 -0
- package/dist/workbench/index.d.ts +55 -0
- package/dist/workbench/index.js +194 -0
- package/dist/workbench/index.js.map +1 -0
- package/package.json +89 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createBrowserNodeI18nRuntime
|
|
3
|
+
} from "./chunk-IS2USG4D.js";
|
|
4
|
+
import {
|
|
5
|
+
resolveBrowserAddressInput,
|
|
6
|
+
resolveBrowserNavigationUrl
|
|
7
|
+
} from "./chunk-LVVPDNEF.js";
|
|
8
|
+
|
|
9
|
+
// src/core/runtimeStore.ts
|
|
10
|
+
var defaultBrowserNodeRuntimeState = {
|
|
11
|
+
canGoBack: false,
|
|
12
|
+
canGoForward: false,
|
|
13
|
+
error: null,
|
|
14
|
+
isAttachedToWindow: false,
|
|
15
|
+
isLoading: false,
|
|
16
|
+
isOccluded: false,
|
|
17
|
+
lifecycle: "cold",
|
|
18
|
+
title: null,
|
|
19
|
+
url: null
|
|
20
|
+
};
|
|
21
|
+
var chromiumErrorPageUrlPrefix = "chrome-error://";
|
|
22
|
+
function isChromiumErrorPageUrl(value) {
|
|
23
|
+
return value?.trim().startsWith(chromiumErrorPageUrlPrefix) === true;
|
|
24
|
+
}
|
|
25
|
+
function normalizePublishedBrowserValue(value) {
|
|
26
|
+
const trimmed = value?.trim() ?? "";
|
|
27
|
+
if (trimmed.length === 0 || trimmed === "about:blank" || isChromiumErrorPageUrl(trimmed)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return trimmed;
|
|
31
|
+
}
|
|
32
|
+
function shouldClearLoadError({
|
|
33
|
+
isLoading,
|
|
34
|
+
url
|
|
35
|
+
}) {
|
|
36
|
+
return isLoading && !isChromiumErrorPageUrl(url);
|
|
37
|
+
}
|
|
38
|
+
function createBrowserNodeRuntimeStore() {
|
|
39
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
40
|
+
let runtimeByNodeId = {};
|
|
41
|
+
const notify = () => {
|
|
42
|
+
for (const listener of listeners) {
|
|
43
|
+
listener();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
applyEvent(event) {
|
|
48
|
+
if (event.type === "open-url") {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (event.type === "closed") {
|
|
52
|
+
if (!runtimeByNodeId[event.nodeId]) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const next2 = { ...runtimeByNodeId };
|
|
56
|
+
delete next2[event.nodeId];
|
|
57
|
+
runtimeByNodeId = next2;
|
|
58
|
+
notify();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const previous = runtimeByNodeId[event.nodeId] ?? defaultBrowserNodeRuntimeState;
|
|
62
|
+
const next = event.type === "state" ? resolveNextState(previous, event) : {
|
|
63
|
+
...previous,
|
|
64
|
+
error: {
|
|
65
|
+
code: event.code,
|
|
66
|
+
diagnosticMessage: event.diagnosticMessage,
|
|
67
|
+
params: event.params
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
runtimeByNodeId = {
|
|
71
|
+
...runtimeByNodeId,
|
|
72
|
+
[event.nodeId]: next
|
|
73
|
+
};
|
|
74
|
+
notify();
|
|
75
|
+
},
|
|
76
|
+
clearAll() {
|
|
77
|
+
if (Object.keys(runtimeByNodeId).length === 0) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
runtimeByNodeId = {};
|
|
81
|
+
notify();
|
|
82
|
+
},
|
|
83
|
+
clearNode(nodeId) {
|
|
84
|
+
const normalized = nodeId.trim();
|
|
85
|
+
if (normalized.length === 0 || !runtimeByNodeId[normalized]) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const next = { ...runtimeByNodeId };
|
|
89
|
+
delete next[normalized];
|
|
90
|
+
runtimeByNodeId = next;
|
|
91
|
+
notify();
|
|
92
|
+
},
|
|
93
|
+
getNodeState(nodeId) {
|
|
94
|
+
return runtimeByNodeId[nodeId] ?? defaultBrowserNodeRuntimeState;
|
|
95
|
+
},
|
|
96
|
+
getSnapshot() {
|
|
97
|
+
return runtimeByNodeId;
|
|
98
|
+
},
|
|
99
|
+
subscribe(listener) {
|
|
100
|
+
listeners.add(listener);
|
|
101
|
+
return () => {
|
|
102
|
+
listeners.delete(listener);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function resolveNextState(previous, event) {
|
|
108
|
+
const nextUrl = normalizePublishedBrowserValue(event.url) ?? (event.lifecycle !== "cold" ? previous.url : null);
|
|
109
|
+
const nextTitle = normalizePublishedBrowserValue(event.title) ?? (event.lifecycle !== "cold" ? previous.title : null);
|
|
110
|
+
return {
|
|
111
|
+
...previous,
|
|
112
|
+
canGoBack: event.canGoBack,
|
|
113
|
+
canGoForward: event.canGoForward,
|
|
114
|
+
error: shouldClearLoadError({
|
|
115
|
+
isLoading: event.isLoading,
|
|
116
|
+
url: event.url
|
|
117
|
+
}) ? null : previous.error,
|
|
118
|
+
isAttachedToWindow: event.isAttachedToWindow ?? previous.isAttachedToWindow,
|
|
119
|
+
isLoading: event.isLoading,
|
|
120
|
+
isOccluded: event.isOccluded,
|
|
121
|
+
lifecycle: event.lifecycle,
|
|
122
|
+
title: nextTitle,
|
|
123
|
+
url: nextUrl
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/core/feature.ts
|
|
128
|
+
function createBrowserNodeFeature({
|
|
129
|
+
hostApi,
|
|
130
|
+
i18n,
|
|
131
|
+
reportDiagnostic,
|
|
132
|
+
resolveSearchUrl,
|
|
133
|
+
runtimeStore = createBrowserNodeRuntimeStore()
|
|
134
|
+
}) {
|
|
135
|
+
let listenerCount = 0;
|
|
136
|
+
let disconnect = null;
|
|
137
|
+
const connect = () => {
|
|
138
|
+
listenerCount += 1;
|
|
139
|
+
if (!disconnect) {
|
|
140
|
+
disconnect = hostApi.onEvent((event) => runtimeStore.applyEvent(event));
|
|
141
|
+
}
|
|
142
|
+
return () => {
|
|
143
|
+
listenerCount = Math.max(0, listenerCount - 1);
|
|
144
|
+
if (listenerCount === 0) {
|
|
145
|
+
disconnect?.();
|
|
146
|
+
disconnect = null;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
return {
|
|
151
|
+
connect,
|
|
152
|
+
hostApi,
|
|
153
|
+
i18n: createBrowserNodeI18nRuntime(i18n),
|
|
154
|
+
reportDiagnostic,
|
|
155
|
+
resolveAddressInput(rawInput) {
|
|
156
|
+
return resolveBrowserAddressInput(rawInput, { resolveSearchUrl });
|
|
157
|
+
},
|
|
158
|
+
runtimeStore
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
export {
|
|
162
|
+
createBrowserNodeFeature,
|
|
163
|
+
resolveBrowserNavigationUrl
|
|
164
|
+
};
|
|
165
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/runtimeStore.ts","../src/core/feature.ts"],"sourcesContent":["import type { BrowserNodeEvent, BrowserNodeRuntimeState } from \"./types.ts\";\n\nexport interface BrowserNodeRuntimeStore {\n applyEvent(event: BrowserNodeEvent): void;\n clearAll(): void;\n clearNode(nodeId: string): void;\n getNodeState(nodeId: string): BrowserNodeRuntimeState;\n getSnapshot(): Record<string, BrowserNodeRuntimeState | undefined>;\n subscribe(listener: () => void): () => void;\n}\n\nconst defaultBrowserNodeRuntimeState: BrowserNodeRuntimeState = {\n canGoBack: false,\n canGoForward: false,\n error: null,\n isAttachedToWindow: false,\n isLoading: false,\n isOccluded: false,\n lifecycle: \"cold\",\n title: null,\n url: null\n};\n\nconst chromiumErrorPageUrlPrefix = \"chrome-error://\";\n\nfunction isChromiumErrorPageUrl(value: string | null | undefined): boolean {\n return value?.trim().startsWith(chromiumErrorPageUrlPrefix) === true;\n}\n\nfunction normalizePublishedBrowserValue(\n value: string | null | undefined\n): string | null {\n const trimmed = value?.trim() ?? \"\";\n if (\n trimmed.length === 0 ||\n trimmed === \"about:blank\" ||\n isChromiumErrorPageUrl(trimmed)\n ) {\n return null;\n }\n return trimmed;\n}\n\nfunction shouldClearLoadError({\n isLoading,\n url\n}: {\n isLoading: boolean;\n url: string | null;\n}): boolean {\n return isLoading && !isChromiumErrorPageUrl(url);\n}\n\nexport function createBrowserNodeRuntimeStore(): BrowserNodeRuntimeStore {\n const listeners = new Set<() => void>();\n let runtimeByNodeId: Record<string, BrowserNodeRuntimeState | undefined> = {};\n\n const notify = () => {\n for (const listener of listeners) {\n listener();\n }\n };\n\n return {\n applyEvent(event) {\n if (event.type === \"open-url\") {\n return;\n }\n\n if (event.type === \"closed\") {\n if (!runtimeByNodeId[event.nodeId]) {\n return;\n }\n const next = { ...runtimeByNodeId };\n delete next[event.nodeId];\n runtimeByNodeId = next;\n notify();\n return;\n }\n\n const previous =\n runtimeByNodeId[event.nodeId] ?? defaultBrowserNodeRuntimeState;\n const next =\n event.type === \"state\"\n ? resolveNextState(previous, event)\n : {\n ...previous,\n error: {\n code: event.code,\n diagnosticMessage: event.diagnosticMessage,\n params: event.params\n }\n };\n\n runtimeByNodeId = {\n ...runtimeByNodeId,\n [event.nodeId]: next\n };\n notify();\n },\n clearAll() {\n if (Object.keys(runtimeByNodeId).length === 0) {\n return;\n }\n runtimeByNodeId = {};\n notify();\n },\n clearNode(nodeId) {\n const normalized = nodeId.trim();\n if (normalized.length === 0 || !runtimeByNodeId[normalized]) {\n return;\n }\n const next = { ...runtimeByNodeId };\n delete next[normalized];\n runtimeByNodeId = next;\n notify();\n },\n getNodeState(nodeId) {\n return runtimeByNodeId[nodeId] ?? defaultBrowserNodeRuntimeState;\n },\n getSnapshot() {\n return runtimeByNodeId;\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n }\n };\n}\n\nfunction resolveNextState(\n previous: BrowserNodeRuntimeState,\n event: Extract<BrowserNodeEvent, { type: \"state\" }>\n): BrowserNodeRuntimeState {\n const nextUrl =\n normalizePublishedBrowserValue(event.url) ??\n (event.lifecycle !== \"cold\" ? previous.url : null);\n const nextTitle =\n normalizePublishedBrowserValue(event.title) ??\n (event.lifecycle !== \"cold\" ? previous.title : null);\n\n return {\n ...previous,\n canGoBack: event.canGoBack,\n canGoForward: event.canGoForward,\n error: shouldClearLoadError({\n isLoading: event.isLoading,\n url: event.url\n })\n ? null\n : previous.error,\n isAttachedToWindow: event.isAttachedToWindow ?? previous.isAttachedToWindow,\n isLoading: event.isLoading,\n isOccluded: event.isOccluded,\n lifecycle: event.lifecycle,\n title: nextTitle,\n url: nextUrl\n };\n}\n","import type { I18nRuntime } from \"@tutti-os/ui-i18n-runtime\";\nimport { createBrowserNodeI18nRuntime } from \"../i18n/browserNodeI18n.ts\";\nimport type { BrowserNodeI18nRuntime } from \"../i18n/browserNodeI18n.ts\";\nimport type { BrowserNodeHostApi } from \"./types.ts\";\nimport {\n createBrowserNodeRuntimeStore,\n type BrowserNodeRuntimeStore\n} from \"./runtimeStore.ts\";\nimport {\n resolveBrowserAddressInput,\n type BrowserAddressInputResolution,\n type BrowserSearchUrlResolver\n} from \"./url.ts\";\n\nexport interface BrowserNodeFeature {\n hostApi: BrowserNodeHostApi;\n i18n: BrowserNodeI18nRuntime;\n reportDiagnostic?: BrowserNodeDiagnosticReporter;\n resolveAddressInput(rawInput: string): BrowserAddressInputResolution;\n runtimeStore: BrowserNodeRuntimeStore;\n connect(): () => void;\n}\n\nexport interface BrowserNodeDiagnosticPayload {\n details?: Record<string, unknown>;\n event: string;\n level?: \"debug\" | \"info\" | \"warn\" | \"error\";\n}\n\nexport type BrowserNodeDiagnosticReporter = (\n payload: BrowserNodeDiagnosticPayload\n) => void;\n\nexport interface CreateBrowserNodeFeatureInput {\n hostApi: BrowserNodeHostApi;\n i18n?: I18nRuntime<string>;\n reportDiagnostic?: BrowserNodeDiagnosticReporter;\n resolveSearchUrl?: BrowserSearchUrlResolver;\n runtimeStore?: BrowserNodeRuntimeStore;\n}\n\nexport function createBrowserNodeFeature({\n hostApi,\n i18n,\n reportDiagnostic,\n resolveSearchUrl,\n runtimeStore = createBrowserNodeRuntimeStore()\n}: CreateBrowserNodeFeatureInput): BrowserNodeFeature {\n let listenerCount = 0;\n let disconnect: (() => void) | null = null;\n\n const connect = () => {\n listenerCount += 1;\n if (!disconnect) {\n disconnect = hostApi.onEvent((event) => runtimeStore.applyEvent(event));\n }\n\n return () => {\n listenerCount = Math.max(0, listenerCount - 1);\n if (listenerCount === 0) {\n disconnect?.();\n disconnect = null;\n }\n };\n };\n\n return {\n connect,\n hostApi,\n i18n: createBrowserNodeI18nRuntime(i18n),\n reportDiagnostic,\n resolveAddressInput(rawInput) {\n return resolveBrowserAddressInput(rawInput, { resolveSearchUrl });\n },\n runtimeStore\n };\n}\n"],"mappings":"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","names":["next"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { JSX, ReactNode, HTMLAttributes } from 'react';
|
|
2
|
+
import { BrowserNodeFeature, BrowserNodeNavigationPolicy, BrowserNodeSessionMode } from '../index.js';
|
|
3
|
+
import '@tutti-os/ui-i18n-runtime';
|
|
4
|
+
import '../i18n/index.js';
|
|
5
|
+
|
|
6
|
+
interface BrowserNodeProps {
|
|
7
|
+
defaultUrl: string;
|
|
8
|
+
feature: BrowserNodeFeature;
|
|
9
|
+
navigationPolicy?: BrowserNodeNavigationPolicy | null;
|
|
10
|
+
nodeId: string;
|
|
11
|
+
onFocusRequest?: () => void;
|
|
12
|
+
onNavigated?: (url: string) => void;
|
|
13
|
+
profileId?: string | null;
|
|
14
|
+
sessionMode?: BrowserNodeSessionMode;
|
|
15
|
+
sessionPartition?: string | null;
|
|
16
|
+
showHeader?: boolean;
|
|
17
|
+
syncDefaultUrl?: boolean;
|
|
18
|
+
}
|
|
19
|
+
declare function BrowserNode({ defaultUrl, feature, navigationPolicy, nodeId, onFocusRequest, onNavigated, profileId, sessionMode, sessionPartition, showHeader, syncDefaultUrl }: BrowserNodeProps): JSX.Element;
|
|
20
|
+
declare function BrowserNodeHeader({ canGoBack, canGoForward, className, defaultActions, draftUrl, dragHandleProps, feature, isCold, isLoading, onCloseRequest, onDraftUrlChange, onFocusRequest, onGoBack, onGoForward, onOpenExternal, onReload, onSubmitUrl, withBorder }: {
|
|
21
|
+
canGoBack: boolean;
|
|
22
|
+
canGoForward: boolean;
|
|
23
|
+
className?: string;
|
|
24
|
+
defaultActions?: ReactNode;
|
|
25
|
+
draftUrl: string;
|
|
26
|
+
dragHandleProps?: HTMLAttributes<HTMLElement>;
|
|
27
|
+
feature: BrowserNodeFeature;
|
|
28
|
+
isCold?: boolean;
|
|
29
|
+
isLoading: boolean;
|
|
30
|
+
onCloseRequest?: () => void;
|
|
31
|
+
onDraftUrlChange: (nextUrl: string) => void;
|
|
32
|
+
onFocusRequest?: () => void;
|
|
33
|
+
onGoBack: () => void;
|
|
34
|
+
onGoForward: () => void;
|
|
35
|
+
onOpenExternal?: () => void;
|
|
36
|
+
onReload: () => void;
|
|
37
|
+
onSubmitUrl: () => void;
|
|
38
|
+
withBorder?: boolean;
|
|
39
|
+
}): JSX.Element;
|
|
40
|
+
|
|
41
|
+
export { BrowserNode, BrowserNodeHeader, type BrowserNodeProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
interface BrowserNodeBridgeError {
|
|
2
|
+
code: string;
|
|
3
|
+
message: string;
|
|
4
|
+
params?: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
type BrowserNodeBridgeResult<T> = {
|
|
7
|
+
ok: true;
|
|
8
|
+
value: T;
|
|
9
|
+
} | {
|
|
10
|
+
ok: false;
|
|
11
|
+
error: BrowserNodeBridgeError;
|
|
12
|
+
};
|
|
13
|
+
interface BrowserNodeBridgeCallPayload {
|
|
14
|
+
args: unknown;
|
|
15
|
+
method: string;
|
|
16
|
+
}
|
|
17
|
+
interface BrowserNodeBridgeMeta {
|
|
18
|
+
runtime: "electron";
|
|
19
|
+
version: string;
|
|
20
|
+
}
|
|
21
|
+
interface BrowserNodeBridgeMethodDescriptor {
|
|
22
|
+
readonly defaultErrorCode?: string;
|
|
23
|
+
readonly hostPatterns: readonly string[];
|
|
24
|
+
readonly name: string;
|
|
25
|
+
}
|
|
26
|
+
type BrowserNodeBridgeCallable = (args?: unknown) => Promise<BrowserNodeBridgeResult<unknown>>;
|
|
27
|
+
interface BrowserNodeBridgeApiTree {
|
|
28
|
+
meta: BrowserNodeBridgeMeta;
|
|
29
|
+
[key: string]: unknown;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type { BrowserNodeBridgeApiTree as B, BrowserNodeBridgeCallPayload as a, BrowserNodeBridgeCallable as b, BrowserNodeBridgeError as c, BrowserNodeBridgeMeta as d, BrowserNodeBridgeMethodDescriptor as e, BrowserNodeBridgeResult as f };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { WorkbenchFrame, WorkbenchHostExternalStateSource, WorkbenchHostDockEntry, WorkbenchHostNodeDefinition, WorkbenchContribution, WorkbenchHostLaunchRequest, WorkbenchHostLaunchResult } from '@tutti-os/workbench-surface';
|
|
3
|
+
import { BrowserNodeFeature } from '../index.js';
|
|
4
|
+
import '@tutti-os/ui-i18n-runtime';
|
|
5
|
+
import '../i18n/index.js';
|
|
6
|
+
|
|
7
|
+
interface BrowserNodeOpenUrlActivationPayload {
|
|
8
|
+
title?: string;
|
|
9
|
+
url: string;
|
|
10
|
+
}
|
|
11
|
+
interface BrowserNodeExternalState {
|
|
12
|
+
title?: string | null;
|
|
13
|
+
url?: string | null;
|
|
14
|
+
}
|
|
15
|
+
interface CreateBrowserNodeDefinitionInput {
|
|
16
|
+
defaultUrl: string;
|
|
17
|
+
dockIcon?: ReactNode;
|
|
18
|
+
feature: BrowserNodeFeature;
|
|
19
|
+
frame?: WorkbenchFrame;
|
|
20
|
+
onNavigated?: (input: {
|
|
21
|
+
nodeId: string;
|
|
22
|
+
url: string;
|
|
23
|
+
}) => void;
|
|
24
|
+
typeId?: string;
|
|
25
|
+
}
|
|
26
|
+
interface CreateBrowserDockEntryInput {
|
|
27
|
+
dockIcon?: ReactNode;
|
|
28
|
+
feature: BrowserNodeFeature;
|
|
29
|
+
id?: string;
|
|
30
|
+
order?: number;
|
|
31
|
+
sectionId?: string;
|
|
32
|
+
typeId?: string;
|
|
33
|
+
}
|
|
34
|
+
interface CreateBrowserWorkbenchLaunchHandlerInput {
|
|
35
|
+
browserInstancePrefix?: string;
|
|
36
|
+
typeId?: string;
|
|
37
|
+
}
|
|
38
|
+
interface CreateBrowserWorkbenchContributionInput {
|
|
39
|
+
contributionId?: string;
|
|
40
|
+
defaultUrl: string;
|
|
41
|
+
dockEntry?: Omit<CreateBrowserDockEntryInput, "feature">;
|
|
42
|
+
externalStateSource?: WorkbenchHostExternalStateSource<BrowserNodeExternalState | null, unknown>;
|
|
43
|
+
feature: BrowserNodeFeature;
|
|
44
|
+
launch?: CreateBrowserWorkbenchLaunchHandlerInput;
|
|
45
|
+
node?: Omit<CreateBrowserNodeDefinitionInput, "defaultUrl" | "feature">;
|
|
46
|
+
typeId?: string;
|
|
47
|
+
}
|
|
48
|
+
declare const defaultBrowserNodeTypeId = "browser";
|
|
49
|
+
declare function createBrowserNodeDefinition({ defaultUrl, feature, frame, onNavigated, typeId }: CreateBrowserNodeDefinitionInput): WorkbenchHostNodeDefinition<BrowserNodeExternalState>;
|
|
50
|
+
declare function createBrowserDockEntry(input: CreateBrowserDockEntryInput): WorkbenchHostDockEntry;
|
|
51
|
+
declare function createBrowserDockIconImage(src: string): ReactNode;
|
|
52
|
+
declare function createBrowserWorkbenchLaunchHandler({ browserInstancePrefix, typeId }?: CreateBrowserWorkbenchLaunchHandlerInput): (request: WorkbenchHostLaunchRequest) => WorkbenchHostLaunchResult | null;
|
|
53
|
+
declare function createBrowserWorkbenchContribution({ contributionId, defaultUrl, dockEntry, externalStateSource, feature, launch, node, typeId }: CreateBrowserWorkbenchContributionInput): WorkbenchContribution;
|
|
54
|
+
|
|
55
|
+
export { type BrowserNodeExternalState, type BrowserNodeOpenUrlActivationPayload, type CreateBrowserDockEntryInput, type CreateBrowserNodeDefinitionInput, type CreateBrowserWorkbenchContributionInput, type CreateBrowserWorkbenchLaunchHandlerInput, createBrowserDockEntry, createBrowserDockIconImage, createBrowserNodeDefinition, createBrowserWorkbenchContribution, createBrowserWorkbenchLaunchHandler, defaultBrowserNodeTypeId };
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BrowserNode,
|
|
3
|
+
BrowserNodeWorkbenchHeader
|
|
4
|
+
} from "../chunk-2GEY55PS.js";
|
|
5
|
+
import "../chunk-UTXZLRPE.js";
|
|
6
|
+
import "../chunk-LVVPDNEF.js";
|
|
7
|
+
|
|
8
|
+
// src/workbench/index.ts
|
|
9
|
+
import { createElement } from "react";
|
|
10
|
+
var defaultBrowserNodeFrame = {
|
|
11
|
+
height: 560,
|
|
12
|
+
width: 920,
|
|
13
|
+
x: 220,
|
|
14
|
+
y: 120
|
|
15
|
+
};
|
|
16
|
+
var defaultBrowserNodeTypeId = "browser";
|
|
17
|
+
function createBrowserNodeDefinition({
|
|
18
|
+
defaultUrl,
|
|
19
|
+
feature,
|
|
20
|
+
frame = defaultBrowserNodeFrame,
|
|
21
|
+
onNavigated,
|
|
22
|
+
typeId = defaultBrowserNodeTypeId
|
|
23
|
+
}) {
|
|
24
|
+
return {
|
|
25
|
+
frame,
|
|
26
|
+
instance: {
|
|
27
|
+
mode: "multi"
|
|
28
|
+
},
|
|
29
|
+
renderBody: (context) => createElement(BrowserNode, {
|
|
30
|
+
defaultUrl: resolveBrowserNodeInitialUrl({
|
|
31
|
+
activation: context.activation,
|
|
32
|
+
defaultUrl,
|
|
33
|
+
externalNodeState: context.externalNodeState
|
|
34
|
+
}),
|
|
35
|
+
feature,
|
|
36
|
+
nodeId: context.node.id,
|
|
37
|
+
onFocusRequest: context.isFocused ? void 0 : () => context.focus(),
|
|
38
|
+
onNavigated: onNavigated ? (url) => onNavigated({
|
|
39
|
+
nodeId: context.node.id,
|
|
40
|
+
url
|
|
41
|
+
}) : void 0,
|
|
42
|
+
showHeader: false,
|
|
43
|
+
syncDefaultUrl: true
|
|
44
|
+
}),
|
|
45
|
+
renderHeader: ({
|
|
46
|
+
defaultActions,
|
|
47
|
+
activation,
|
|
48
|
+
dragHandleProps,
|
|
49
|
+
externalNodeState,
|
|
50
|
+
isFocused,
|
|
51
|
+
node,
|
|
52
|
+
windowActions
|
|
53
|
+
}) => createElement(BrowserNodeWorkbenchHeader, {
|
|
54
|
+
defaultActions,
|
|
55
|
+
defaultUrl: resolveBrowserNodeInitialUrl({
|
|
56
|
+
activation,
|
|
57
|
+
defaultUrl,
|
|
58
|
+
externalNodeState
|
|
59
|
+
}),
|
|
60
|
+
dragHandleProps,
|
|
61
|
+
feature,
|
|
62
|
+
nodeId: node.id,
|
|
63
|
+
onCloseRequest: () => {
|
|
64
|
+
void feature.hostApi.close({ nodeId: node.id }).catch(() => void 0);
|
|
65
|
+
},
|
|
66
|
+
onFocusRequest: isFocused ? void 0 : () => windowActions.focus()
|
|
67
|
+
}),
|
|
68
|
+
title: feature.i18n.t("title"),
|
|
69
|
+
typeId,
|
|
70
|
+
window: {
|
|
71
|
+
closable: true,
|
|
72
|
+
defaultOpen: false,
|
|
73
|
+
minimizedDock: {
|
|
74
|
+
capturePreview: ({ node }) => feature.hostApi.capturePreview?.({ nodeId: node.id }) ?? null,
|
|
75
|
+
kind: "snapshot"
|
|
76
|
+
},
|
|
77
|
+
minimizable: true,
|
|
78
|
+
restoreOnLoad: true
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function createBrowserDockEntry(input) {
|
|
83
|
+
return {
|
|
84
|
+
capturePopupItemPreview: ({ node }) => input.feature.hostApi.capturePreview?.({ nodeId: node.id }) ?? null,
|
|
85
|
+
icon: input.dockIcon ?? null,
|
|
86
|
+
id: input.id ?? defaultBrowserNodeTypeId,
|
|
87
|
+
label: input.feature.i18n.t("dockLabel"),
|
|
88
|
+
launchBehavior: "enabled",
|
|
89
|
+
matchNode: (node) => node.data.typeId === (input.typeId ?? defaultBrowserNodeTypeId),
|
|
90
|
+
order: input.order,
|
|
91
|
+
resolvePopupItem: ({ node }) => {
|
|
92
|
+
const runtime = input.feature.runtimeStore.getNodeState(node.id);
|
|
93
|
+
return {
|
|
94
|
+
subtitle: runtime.url?.trim() || node.data.instanceId,
|
|
95
|
+
title: runtime.title?.trim() || node.title
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
sectionId: input.sectionId,
|
|
99
|
+
typeId: input.typeId ?? defaultBrowserNodeTypeId,
|
|
100
|
+
visibility: "always"
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function createBrowserDockIconImage(src) {
|
|
104
|
+
return createElement("img", {
|
|
105
|
+
alt: "",
|
|
106
|
+
"aria-hidden": "true",
|
|
107
|
+
"data-browser-node-dock-icon": "true",
|
|
108
|
+
draggable: false,
|
|
109
|
+
src
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function createBrowserWorkbenchLaunchHandler({
|
|
113
|
+
browserInstancePrefix,
|
|
114
|
+
typeId = defaultBrowserNodeTypeId
|
|
115
|
+
} = {}) {
|
|
116
|
+
let nextBrowserInstanceSequence = 1;
|
|
117
|
+
const instancePrefix = browserInstancePrefix ?? globalThis.crypto?.randomUUID?.() ?? typeId;
|
|
118
|
+
return (request) => {
|
|
119
|
+
if (request.typeId !== typeId) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
const instanceId = `${typeId}-${instancePrefix}-${nextBrowserInstanceSequence++}`;
|
|
123
|
+
return {
|
|
124
|
+
dockEntryId: request.dockEntryId ?? typeId,
|
|
125
|
+
framePolicy: "cascade",
|
|
126
|
+
instanceId,
|
|
127
|
+
typeId
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function createBrowserWorkbenchContribution({
|
|
132
|
+
contributionId,
|
|
133
|
+
defaultUrl,
|
|
134
|
+
dockEntry,
|
|
135
|
+
externalStateSource,
|
|
136
|
+
feature,
|
|
137
|
+
launch,
|
|
138
|
+
node,
|
|
139
|
+
typeId = defaultBrowserNodeTypeId
|
|
140
|
+
}) {
|
|
141
|
+
return {
|
|
142
|
+
dockEntries: [
|
|
143
|
+
createBrowserDockEntry({
|
|
144
|
+
...dockEntry,
|
|
145
|
+
feature,
|
|
146
|
+
typeId
|
|
147
|
+
})
|
|
148
|
+
],
|
|
149
|
+
externalStateSource,
|
|
150
|
+
id: contributionId ?? typeId,
|
|
151
|
+
nodes: [
|
|
152
|
+
createBrowserNodeDefinition({
|
|
153
|
+
...node,
|
|
154
|
+
defaultUrl,
|
|
155
|
+
feature,
|
|
156
|
+
typeId
|
|
157
|
+
})
|
|
158
|
+
],
|
|
159
|
+
onLaunchRequest: createBrowserWorkbenchLaunchHandler({
|
|
160
|
+
...launch,
|
|
161
|
+
typeId
|
|
162
|
+
})
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function resolveBrowserNodeInitialUrl({
|
|
166
|
+
activation,
|
|
167
|
+
defaultUrl,
|
|
168
|
+
externalNodeState
|
|
169
|
+
}) {
|
|
170
|
+
return readBrowserOpenUrlActivationPayload(activation)?.url ?? normalizeBrowserNodeInitialUrl(externalNodeState?.url) ?? defaultUrl;
|
|
171
|
+
}
|
|
172
|
+
function normalizeBrowserNodeInitialUrl(value) {
|
|
173
|
+
const trimmed = value?.trim() ?? "";
|
|
174
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
175
|
+
}
|
|
176
|
+
function readBrowserOpenUrlActivationPayload(activation) {
|
|
177
|
+
if (activation?.type !== "open-url" || !activation.payload || typeof activation.payload !== "object") {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
const typed = activation.payload;
|
|
181
|
+
return typeof typed.url === "string" ? {
|
|
182
|
+
title: typeof typed.title === "string" ? typed.title : void 0,
|
|
183
|
+
url: typed.url
|
|
184
|
+
} : null;
|
|
185
|
+
}
|
|
186
|
+
export {
|
|
187
|
+
createBrowserDockEntry,
|
|
188
|
+
createBrowserDockIconImage,
|
|
189
|
+
createBrowserNodeDefinition,
|
|
190
|
+
createBrowserWorkbenchContribution,
|
|
191
|
+
createBrowserWorkbenchLaunchHandler,
|
|
192
|
+
defaultBrowserNodeTypeId
|
|
193
|
+
};
|
|
194
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/workbench/index.ts"],"sourcesContent":["import { createElement, type ReactNode } from \"react\";\nimport type {\n WorkbenchContribution,\n WorkbenchHostActivation,\n WorkbenchHostDockEntry,\n WorkbenchHostExternalStateSource,\n WorkbenchFrame,\n WorkbenchHostLaunchRequest,\n WorkbenchHostLaunchResult,\n WorkbenchHostNodeDefinition\n} from \"@tutti-os/workbench-surface\";\nimport type { BrowserNodeFeature } from \"../core/feature.ts\";\nimport {\n BrowserNode,\n BrowserNodeWorkbenchHeader\n} from \"../react/BrowserNode.tsx\";\n\nexport interface BrowserNodeOpenUrlActivationPayload {\n title?: string;\n url: string;\n}\n\nexport interface BrowserNodeExternalState {\n title?: string | null;\n url?: string | null;\n}\n\nexport interface CreateBrowserNodeDefinitionInput {\n defaultUrl: string;\n dockIcon?: ReactNode;\n feature: BrowserNodeFeature;\n frame?: WorkbenchFrame;\n onNavigated?: (input: { nodeId: string; url: string }) => void;\n typeId?: string;\n}\n\nexport interface CreateBrowserDockEntryInput {\n dockIcon?: ReactNode;\n feature: BrowserNodeFeature;\n id?: string;\n order?: number;\n sectionId?: string;\n typeId?: string;\n}\n\nexport interface CreateBrowserWorkbenchLaunchHandlerInput {\n browserInstancePrefix?: string;\n typeId?: string;\n}\n\nexport interface CreateBrowserWorkbenchContributionInput {\n contributionId?: string;\n defaultUrl: string;\n dockEntry?: Omit<CreateBrowserDockEntryInput, \"feature\">;\n externalStateSource?: WorkbenchHostExternalStateSource<\n BrowserNodeExternalState | null,\n unknown\n >;\n feature: BrowserNodeFeature;\n launch?: CreateBrowserWorkbenchLaunchHandlerInput;\n node?: Omit<CreateBrowserNodeDefinitionInput, \"defaultUrl\" | \"feature\">;\n typeId?: string;\n}\n\nconst defaultBrowserNodeFrame: WorkbenchFrame = {\n height: 560,\n width: 920,\n x: 220,\n y: 120\n};\n\nexport const defaultBrowserNodeTypeId = \"browser\";\n\nexport function createBrowserNodeDefinition({\n defaultUrl,\n feature,\n frame = defaultBrowserNodeFrame,\n onNavigated,\n typeId = defaultBrowserNodeTypeId\n}: CreateBrowserNodeDefinitionInput): WorkbenchHostNodeDefinition<BrowserNodeExternalState> {\n return {\n frame,\n instance: {\n mode: \"multi\"\n },\n renderBody: (context) =>\n createElement(BrowserNode, {\n defaultUrl: resolveBrowserNodeInitialUrl({\n activation: context.activation,\n defaultUrl,\n externalNodeState: context.externalNodeState\n }),\n feature,\n nodeId: context.node.id,\n onFocusRequest: context.isFocused ? undefined : () => context.focus(),\n onNavigated: onNavigated\n ? (url) =>\n onNavigated({\n nodeId: context.node.id,\n url\n })\n : undefined,\n showHeader: false,\n syncDefaultUrl: true\n }),\n renderHeader: ({\n defaultActions,\n activation,\n dragHandleProps,\n externalNodeState,\n isFocused,\n node,\n windowActions\n }) =>\n createElement(BrowserNodeWorkbenchHeader, {\n defaultActions,\n defaultUrl: resolveBrowserNodeInitialUrl({\n activation,\n defaultUrl,\n externalNodeState\n }),\n dragHandleProps,\n feature,\n nodeId: node.id,\n onCloseRequest: () => {\n void feature.hostApi\n .close({ nodeId: node.id })\n .catch(() => undefined);\n },\n onFocusRequest: isFocused ? undefined : () => windowActions.focus()\n }),\n title: feature.i18n.t(\"title\"),\n typeId,\n window: {\n closable: true,\n defaultOpen: false,\n minimizedDock: {\n capturePreview: ({ node }) =>\n feature.hostApi.capturePreview?.({ nodeId: node.id }) ?? null,\n kind: \"snapshot\"\n },\n minimizable: true,\n restoreOnLoad: true\n }\n };\n}\n\nexport function createBrowserDockEntry(\n input: CreateBrowserDockEntryInput\n): WorkbenchHostDockEntry {\n return {\n capturePopupItemPreview: ({ node }) =>\n input.feature.hostApi.capturePreview?.({ nodeId: node.id }) ?? null,\n icon: input.dockIcon ?? null,\n id: input.id ?? defaultBrowserNodeTypeId,\n label: input.feature.i18n.t(\"dockLabel\"),\n launchBehavior: \"enabled\",\n matchNode: (node) =>\n node.data.typeId === (input.typeId ?? defaultBrowserNodeTypeId),\n order: input.order,\n resolvePopupItem: ({ node }) => {\n const runtime = input.feature.runtimeStore.getNodeState(node.id);\n return {\n subtitle: runtime.url?.trim() || node.data.instanceId,\n title: runtime.title?.trim() || node.title\n };\n },\n sectionId: input.sectionId,\n typeId: input.typeId ?? defaultBrowserNodeTypeId,\n visibility: \"always\"\n };\n}\n\nexport function createBrowserDockIconImage(src: string): ReactNode {\n return createElement(\"img\", {\n alt: \"\",\n \"aria-hidden\": \"true\",\n \"data-browser-node-dock-icon\": \"true\",\n draggable: false,\n src\n });\n}\n\nexport function createBrowserWorkbenchLaunchHandler({\n browserInstancePrefix,\n typeId = defaultBrowserNodeTypeId\n}: CreateBrowserWorkbenchLaunchHandlerInput = {}): (\n request: WorkbenchHostLaunchRequest\n) => WorkbenchHostLaunchResult | null {\n let nextBrowserInstanceSequence = 1;\n const instancePrefix =\n browserInstancePrefix ?? globalThis.crypto?.randomUUID?.() ?? typeId;\n\n return (request) => {\n if (request.typeId !== typeId) {\n return null;\n }\n\n const instanceId = `${typeId}-${instancePrefix}-${nextBrowserInstanceSequence++}`;\n return {\n dockEntryId: request.dockEntryId ?? typeId,\n framePolicy: \"cascade\",\n instanceId,\n typeId\n };\n };\n}\n\nexport function createBrowserWorkbenchContribution({\n contributionId,\n defaultUrl,\n dockEntry,\n externalStateSource,\n feature,\n launch,\n node,\n typeId = defaultBrowserNodeTypeId\n}: CreateBrowserWorkbenchContributionInput): WorkbenchContribution {\n return {\n dockEntries: [\n createBrowserDockEntry({\n ...dockEntry,\n feature,\n typeId\n })\n ],\n externalStateSource,\n id: contributionId ?? typeId,\n nodes: [\n createBrowserNodeDefinition({\n ...node,\n defaultUrl,\n feature,\n typeId\n })\n ],\n onLaunchRequest: createBrowserWorkbenchLaunchHandler({\n ...launch,\n typeId\n })\n };\n}\n\nfunction resolveBrowserNodeInitialUrl({\n activation,\n defaultUrl,\n externalNodeState\n}: {\n activation: WorkbenchHostActivation | null;\n defaultUrl: string;\n externalNodeState?: BrowserNodeExternalState | null;\n}): string {\n return (\n readBrowserOpenUrlActivationPayload(activation)?.url ??\n normalizeBrowserNodeInitialUrl(externalNodeState?.url) ??\n defaultUrl\n );\n}\n\nfunction normalizeBrowserNodeInitialUrl(\n value: string | null | undefined\n): string | null {\n const trimmed = value?.trim() ?? \"\";\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction readBrowserOpenUrlActivationPayload(\n activation: WorkbenchHostActivation | null\n): BrowserNodeOpenUrlActivationPayload | null {\n if (\n activation?.type !== \"open-url\" ||\n !activation.payload ||\n typeof activation.payload !== \"object\"\n ) {\n return null;\n }\n\n const typed =\n activation.payload as Partial<BrowserNodeOpenUrlActivationPayload>;\n return typeof typed.url === \"string\"\n ? {\n title: typeof typed.title === \"string\" ? typed.title : undefined,\n url: typed.url\n }\n : null;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tutti-os/browser-node",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./assets/workspace-dock-website.png": {
|
|
13
|
+
"types": "./dist/assets/workspace-dock-website.d.ts",
|
|
14
|
+
"default": "./dist/assets/workspace-dock-website.png"
|
|
15
|
+
},
|
|
16
|
+
"./bridge": {
|
|
17
|
+
"types": "./dist/bridge/index.d.ts",
|
|
18
|
+
"import": "./dist/bridge/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./electron-main": {
|
|
21
|
+
"types": "./dist/electron-main/index.d.ts",
|
|
22
|
+
"import": "./dist/electron-main/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./electron-preload": {
|
|
25
|
+
"types": "./dist/electron-preload/index.d.ts",
|
|
26
|
+
"import": "./dist/electron-preload/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./i18n": {
|
|
29
|
+
"types": "./dist/i18n/index.d.ts",
|
|
30
|
+
"import": "./dist/i18n/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./react": {
|
|
33
|
+
"types": "./dist/react/index.d.ts",
|
|
34
|
+
"import": "./dist/react/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./workbench": {
|
|
37
|
+
"types": "./dist/workbench/index.d.ts",
|
|
38
|
+
"import": "./dist/workbench/index.js"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist",
|
|
43
|
+
"README.md"
|
|
44
|
+
],
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/tutti-os/tutti.git",
|
|
48
|
+
"directory": "packages/browser/workbench-node"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@tutti-os/ui-i18n-runtime": "0.0.1",
|
|
52
|
+
"@tutti-os/ui-react-hooks": "0.0.1",
|
|
53
|
+
"@tutti-os/ui-system": "0.0.1",
|
|
54
|
+
"@tutti-os/workbench-surface": "0.0.1",
|
|
55
|
+
"ws": "^8.21.0"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/node": "^24.0.1",
|
|
59
|
+
"@types/react": "^19.1.6",
|
|
60
|
+
"@types/react-dom": "^19.1.5",
|
|
61
|
+
"@types/ws": "^8.18.1",
|
|
62
|
+
"electron": "^35.7.5",
|
|
63
|
+
"react": "^19.1.0",
|
|
64
|
+
"react-dom": "^19.1.0",
|
|
65
|
+
"typescript": "^5.8.3",
|
|
66
|
+
"@tutti-os/config-tsconfig": "0.0.0"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"electron": "^35.7.5",
|
|
70
|
+
"react": "^19.1.0",
|
|
71
|
+
"react-dom": "^19.1.0"
|
|
72
|
+
},
|
|
73
|
+
"peerDependenciesMeta": {
|
|
74
|
+
"electron": {
|
|
75
|
+
"optional": true
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"nextop": {
|
|
79
|
+
"tailwindSourceRoot": "src"
|
|
80
|
+
},
|
|
81
|
+
"publishConfig": {
|
|
82
|
+
"access": "public"
|
|
83
|
+
},
|
|
84
|
+
"scripts": {
|
|
85
|
+
"build": "tsup --config tsup.config.ts && node ../../../tools/scripts/copy-package-assets.mjs src/assets dist/assets",
|
|
86
|
+
"test": "node --test --experimental-strip-types ./src/**/*.test.ts",
|
|
87
|
+
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
88
|
+
}
|
|
89
|
+
}
|