Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
cc05848
add multi file support
knervous Sep 10, 2025
dce8f07
prebuild check for built dependencies
knervous Sep 10, 2025
4d800f3
option for standalone and @dev deps
knervous Sep 10, 2025
720e447
rm unused function
knervous Sep 10, 2025
2059917
try with preflight commands
knervous Sep 10, 2025
3731550
try public path
knervous Sep 10, 2025
eb5a0c0
output
knervous Sep 10, 2025
e245b98
monaco worker names
knervous Sep 10, 2025
100bcf1
update build with chunks
knervous Sep 10, 2025
6259faa
try base
knervous Sep 10, 2025
4b314ce
rename
knervous Sep 10, 2025
1051846
readd
knervous Sep 10, 2025
14e8605
upgrade monaco, use scrollelement to get closer to vscode, real lexer…
knervous Sep 11, 2025
f6c6115
scroll state memory persistence, support for fx/glsl/wgsl files, tab …
knervous Sep 11, 2025
a518dc3
link follow enabled with cmd/ctrl click and scroll sync
knervous Sep 11, 2025
54af9bb
add divider
knervous Sep 11, 2025
5f5bc60
touch support for scroll
knervous Sep 11, 2025
a3268ad
split monacoManager into separate services, turn text block into a ru…
knervous Sep 12, 2025
9abf07f
cleanup
knervous Sep 12, 2025
1ee51f3
npm export dirs working
knervous Sep 12, 2025
4f2855d
ata fixes, path fixes
knervous Sep 13, 2025
f816077
support for pinning versions and local package links
knervous Sep 14, 2025
de96d98
neuter package.json and downstream bjs ATA
knervous Sep 16, 2025
bc51b69
fix ensuring exports for v1 snippets, language change hydration
knervous Sep 17, 2025
dcc334c
create custom engine and compatibility entrypoints
knervous Sep 17, 2025
4e8d585
merge master and update for dispose lifecycle and caching workers
knervous Sep 17, 2025
6dc884a
merge in master, implement download esm service
knervous Sep 17, 2025
b056dca
esbuild bundle in download and fix rename file
knervous Sep 17, 2025
284bd5f
add local file revision tools, unify theme and style with dialogs
knervous Sep 19, 2025
1a6993d
local hash session support
knervous Sep 19, 2025
ea8d310
rm built pg bundle
knervous Sep 19, 2025
7412442
cleanup before merge request
knervous Sep 19, 2025
1f9d9e4
more cleanup
knervous Sep 19, 2025
8084c09
format and start fixing tests
knervous Sep 19, 2025
ed7ab33
selector for editor
knervous Sep 19, 2025
7ed2335
restore default PG code with comments, update test and safe b64 encod…
knervous Sep 19, 2025
36bd733
b64 safety
knervous Sep 19, 2025
c045b60
remove ts worker singleton wrapper
knervous Sep 20, 2025
11fec81
vercel
knervous Sep 20, 2025
907de03
change
knervous Sep 20, 2025
00948fa
change for deploy
knervous Sep 20, 2025
35049eb
change
knervous Sep 20, 2025
0e10882
schema
knervous Sep 20, 2025
38912b4
root
knervous Sep 20, 2025
5efd4bb
cors creds
knervous Sep 21, 2025
1f4ed13
clean up scrolling, event listeners, logic for create/duplicate
knervous Sep 21, 2025
ef77e4b
implement file explorer
knervous Sep 22, 2025
ecadbab
merge master
knervous Sep 23, 2025
53d1541
vscode icons + styling + merge upstream
knervous Sep 23, 2025
a886b8e
extra semi
knervous Sep 23, 2025
425522e
consolidate snippet type definitions, versioning, add v2 handling to …
knervous Sep 24, 2025
fa16cdc
likely cyclic dependency
knervous Sep 24, 2025
84139c7
add search activity panel
knervous Sep 24, 2025
de2829a
styling and shortcuts, formatting
knervous Sep 24, 2025
8e3ee54
key handler qualifier for search, styling in search pane, local npm m…
knervous Sep 25, 2025
dfe95b4
local resolution in runner
knervous Sep 25, 2025
b5110b0
skip WS file ambient module declarations for ts
knervous Sep 29, 2025
84c718f
Merge branch 'master' into pgv2
deltakosh Sep 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 38 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions packages/tools/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
"@svgr/webpack": "^7.0.0",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@types/uuid": "^10.0.0",
"@typescript/ata": "^0.9.8",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^7.1.0",
"es-module-lexer": "^1.7.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.4.0",
"mini-css-extract-plugin": "^2.4.3",
"monaco-editor": "0.27.0",
"monaco-editor-webpack-plugin": "^4.2.0",
"monaco-editor": "^0.53.0",
"monaco-editor-webpack-plugin": "^7.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-refresh": "^0.17.0",
Expand Down
71 changes: 0 additions & 71 deletions packages/tools/playground/public/zipContent/index.html

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/* eslint-disable jsdoc/require-jsdoc */
// activityBarComponent.tsx
import * as React from "react";
import type { GlobalState } from "../../globalState";
import HistoryIcon from "./icons/history.svg";
import FilesIcon from "./icons/files.svg";
import SearchIcon from "./icons/search.svg";
import { FileDialog } from "./fileDialog";
import { LocalSessionDialog } from "./localSessionDialog";
import { Utilities } from "../../tools/utilities";
import { Icon } from "./iconComponent";

type DialogKind = "create" | "rename" | "duplicate";
type DialogState = {
open: boolean;
type: DialogKind | null;
title: string;
initialValue: string;
targetPath?: string;
};

export type ActivityBarHandle = {
openCreateDialog: (suggestedName?: string) => void;
openRenameDialog: (targetPath: string, initialDisplay?: string) => void;
openDuplicateDialog: (targetPath: string, suggestedName?: string) => void;
toggleSessionDialog: () => void;
};

interface IActivityBarProps {
globalState: GlobalState;

// Monaco owns mutations
onConfirmFileDialog: (type: DialogKind, filename: string, targetPath?: string) => void;

// Lifted layout state
explorerOpen: boolean;
onToggleExplorer: () => void;

sessionOpen: boolean;
onToggleSession: () => void;

searchOpen: boolean;
onToggleSearch: () => void;
}

export const ActivityBar = React.forwardRef<ActivityBarHandle, IActivityBarProps>(function activityBar(
{ globalState, onConfirmFileDialog, explorerOpen, onToggleExplorer, sessionOpen, onToggleSession, searchOpen, onToggleSearch },
ref
) {
const [theme, setTheme] = React.useState<"dark" | "light">(() => (Utilities.ReadStringFromStore("theme", "Light") === "Dark" ? "dark" : "light"));

const [fileDialog, setFileDialog] = React.useState<DialogState>({
open: false,
type: null,
title: "",
initialValue: "",
});

// helpers
const toDisplay = (path: string) => path.replace(/^\/?src\//, "");
const toInternal = (displayPath: string) => (displayPath?.startsWith("/") ? displayPath.slice(1) : displayPath || "");
const defaultNewFileName = (): string => {
const isTS = globalState.language !== "JS";
const base = isTS ? "new.ts" : "new.js";
let idx = 0;
let candidate = base;
const files = globalState.files || {};
while (Object.prototype.hasOwnProperty.call(files, toInternal(candidate))) {
idx++;
const parts = base.split(".");
const ext = parts.pop();
candidate = `${parts.join(".")}${idx}.${ext}`;
}
return candidate;
};
const defaultDuplicateName = (path: string): string => {
const baseFull = path.replace(/\.(\w+)$/, "");
const ext = (path.match(/\.(\w+)$/) || ["", ""])[1];
let i = 1;
let candidate = `${baseFull}.copy${i}${ext ? "." + ext : ""}`;
const files = globalState.files || {};
while (Object.prototype.hasOwnProperty.call(files, candidate)) {
i++;
candidate = `${baseFull}.copy${i}${ext ? "." + ext : ""}`;
}
return toDisplay(candidate);
};

// imperative API
React.useImperativeHandle(ref, () => ({
openCreateDialog: (suggestedName?: string) => {
setFileDialog({ open: true, type: "create", title: "New file", initialValue: suggestedName ?? defaultNewFileName() });
},
openRenameDialog: (targetPath: string, initialDisplay?: string) => {
setFileDialog({
open: true,
type: "rename",
title: "Rename file",
initialValue: initialDisplay ?? toDisplay(targetPath),
targetPath,
});
},
openDuplicateDialog: (targetPath: string, suggestedName?: string) => {
setFileDialog({
open: true,
type: "duplicate",
title: "Duplicate file",
initialValue: suggestedName ?? defaultDuplicateName(targetPath),
targetPath,
});
},
toggleSessionDialog: () => onToggleSession(),
}));

// theme sync
React.useEffect(() => {
const updateTheme = () => {
setTheme(Utilities.ReadStringFromStore("theme", "Light") === "Dark" ? "dark" : "light");
};
globalState.onThemeChangedObservable.add(updateTheme);
return () => {
globalState.onThemeChangedObservable.removeCallback(updateTheme);
};
}, [globalState]);

// dialog handlers
const closeFileDialog = () => setFileDialog({ open: false, type: null, title: "", initialValue: "" });
const confirmFileDialog = (filename: string) => {
if (!fileDialog.type) {
return;
}
onConfirmFileDialog(fileDialog.type, filename, fileDialog.targetPath);
closeFileDialog();
};

return (
<div className={`pg-activity-bar-col pg-theme-${theme}`}>
{/* Vertical Activity Bar (far left) */}
<div className="pg-activity-bar">
<button className={`pg-activity-item ${explorerOpen ? "active" : ""}`} onClick={onToggleExplorer} title="Explorer">
<Icon size={20}>
<FilesIcon />
</Icon>
</button>
<button className={`pg-activity-item ${searchOpen ? "active" : ""}`} onClick={onToggleSearch} title="Search">
<Icon size={20}>
<SearchIcon />
</Icon>
</button>
<button className={`pg-activity-item ${sessionOpen ? "active" : ""}`} onClick={onToggleSession} title="Session">
<Icon size={24}>
<HistoryIcon />
</Icon>
</button>
</div>

{/* File Dialog */}
<FileDialog
globalState={globalState}
isOpen={fileDialog.open}
title={fileDialog.title}
initialValue={fileDialog.initialValue}
placeholder="Enter filename..."
submitLabel={fileDialog.type === "rename" ? "Rename" : fileDialog.type === "duplicate" ? "Duplicate" : "Create"}
onConfirm={confirmFileDialog}
onCancel={closeFileDialog}
/>

{/* Local Session Dialog */}
<LocalSessionDialog onCancel={onToggleSession} isOpen={sessionOpen} globalState={globalState} />
</div>
);
});
Loading
Loading