@typespec/playground 0.14.1-dev.3 → 0.15.0-dev.4

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/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { i as createBrowserHost, n as registerMonacoLanguage } from "./services-CELCHECS.js";
1
+ import { i as createBrowserHost, n as registerMonacoLanguage } from "./services-CtYDGH-a.js";
2
2
  import { createUrlStateStorage } from "./state-storage.js";
3
3
  //#region src/monaco-worker.ts
4
4
  function registerMonacoDefaultWorkersForVite() {
@@ -1,10 +1,10 @@
1
- import { a as resolveVirtualPath, i as createBrowserHost, n as registerMonacoLanguage, o as debugGlobals, r as updateDiagnosticsForCodeFixes, s as printDebugInfo, t as getMonacoRange } from "../services-CELCHECS.js";
1
+ import { a as resolveVirtualPath, i as createBrowserHost, n as registerMonacoLanguage, o as debugGlobals, r as updateDiagnosticsForCodeFixes, s as printDebugInfo, t as getMonacoRange } from "../services-CtYDGH-a.js";
2
2
  import { createUrlStateStorage } from "../state-storage.js";
3
3
  import { getSourceLocation } from "@typespec/compiler";
4
- import { KeyCode, KeyMod, MarkerSeverity, Uri, editor } from "monaco-editor";
4
+ import { KeyCode, KeyMod, MarkerSeverity, Range, Uri, editor } from "monaco-editor";
5
5
  import { CompletionItemTag } from "vscode-languageserver";
6
6
  import { Fragment, createContext, memo, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
7
- import { Button, Card, Checkbox, DrawerBody, DrawerHeader, DrawerHeaderTitle, FluentProvider, Input, Label, Menu, MenuDivider, MenuItem, MenuList, MenuPopover, MenuTrigger, OverlayDrawer, Popover, PopoverSurface, PopoverTrigger, Radio, RadioGroup, SearchBox, Select, Subtitle2, Switch, Tab, TabList, Table, TableBody, TableCell, TableHeader, TableHeaderCell, TableRow, Text, Title3, Toast, ToastBody, ToastTitle, Toaster, Toolbar, ToolbarButton, Tooltip, mergeClasses, tokens, useId as useId$1, useToastController, webLightTheme } from "@fluentui/react-components";
7
+ import { Button, Card, Checkbox, DrawerBody, DrawerHeader, DrawerHeaderTitle, FluentProvider, Input, Label, Menu, MenuDivider, MenuItem, MenuList, MenuPopover, MenuTrigger, OverlayDrawer, Popover, PopoverSurface, PopoverTrigger, Radio, RadioGroup, SearchBox, Select, Spinner, Subtitle2, Switch, Tab, TabList, Table, TableBody, TableCell, TableHeader, TableHeaderCell, TableRow, Text, Title3, Toast, ToastBody, ToastTitle, Toaster, Toolbar, ToolbarButton, Tooltip, mergeClasses, tokens, useId as useId$1, useToastController, webLightTheme } from "@fluentui/react-components";
8
8
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
9
  import { $ } from "@typespec/compiler/typekit";
10
10
  import { Broom16Filled, Bug16Regular, Checkmark16Regular, ChevronDown16Regular, ChevronDownRegular, ChevronRightRegular, DataLineRegular, Dismiss24Regular, DocumentBulletList24Regular, DocumentRegular, ErrorCircle16Filled, FolderListRegular, FolderRegular, MoreHorizontal24Filled, Save16Regular, SettingsRegular, Warning16Filled } from "@fluentui/react-icons";
@@ -153,12 +153,9 @@ var FooterItem = ({ children, link, className }) => {
153
153
  children
154
154
  });
155
155
  };
156
- //#endregion
157
- //#region src/react/footer/footer-version-item.module.css
158
- var button = "_button_1c15n_4";
159
156
  var footer_version_item_module_default = {
160
157
  "version-item": "_version-item_1c15n_1",
161
- button
158
+ button: "_button_1c15n_4"
162
159
  };
163
160
  //#endregion
164
161
  //#region src/react/footer/footer-version-item.tsx
@@ -259,21 +256,19 @@ function Pane({ children, ...props }) {
259
256
  children
260
257
  });
261
258
  }
262
- var sash = "_sash_v2eo6_20";
263
- var pane = "_pane_v2eo6_70";
264
259
  var split_pane_module_default = {
265
260
  "split-pane": "_split-pane_v2eo6_1",
266
261
  "split-disabled": "_split-disabled_v2eo6_8",
267
262
  "split-pane-dragging": "_split-pane-dragging_v2eo6_12",
268
263
  "react-split-vertical": "_react-split-vertical_v2eo6_12",
269
264
  "react-split-horizontal": "_react-split-horizontal_v2eo6_16",
270
- sash,
265
+ sash: "_sash_v2eo6_20",
271
266
  "sash-disabled": "_sash-disabled_v2eo6_29",
272
267
  "sash-vertical": "_sash-vertical_v2eo6_33",
273
268
  "sash-horizontal": "_sash-horizontal_v2eo6_37",
274
269
  "sash-content": "_sash-content_v2eo6_41",
275
270
  "sash-content-dragging": "_sash-content-dragging_v2eo6_47",
276
- pane
271
+ pane: "_pane_v2eo6_70"
277
272
  };
278
273
  var SashContent = ({ className, children, dragging, ...others }) => {
279
274
  return /* @__PURE__ */ jsx("div", {
@@ -545,25 +540,18 @@ function useTreeControls({ onSetExpanded }) {
545
540
  rerender
546
541
  ]);
547
542
  }
548
- var tree = "_tree_16t0l_1";
549
- var focus = "_focus_16t0l_18";
550
- var active = "_active_16t0l_22";
551
- var caret = "_caret_16t0l_26";
552
- var icon = "_icon_16t0l_33";
553
- var label = "_label_16t0l_40";
554
- var column = "_column_16t0l_44";
555
543
  var tree_module_default = {
556
- tree,
544
+ tree: "_tree_16t0l_1",
557
545
  "tree-row": "_tree-row_16t0l_4",
558
- focus,
559
- active,
560
- caret,
561
- icon,
562
- label,
563
- column
546
+ focus: "_focus_16t0l_18",
547
+ active: "_active_16t0l_22",
548
+ caret: "_caret_16t0l_26",
549
+ icon: "_icon_16t0l_33",
550
+ label: "_label_16t0l_40",
551
+ column: "_column_16t0l_44"
564
552
  };
565
553
  var INDENT_SIZE = 8;
566
- function TreeViewRow({ id, row, active, focussed, activate, icon: Icon }) {
554
+ function TreeViewRow({ id, row, active, focussed, activate, icon: Icon, label: Label }) {
567
555
  const paddingLeft = row.depth * INDENT_SIZE;
568
556
  const onClick = useCallback(() => activate(row), [activate, row]);
569
557
  return /* @__PURE__ */ jsxs("div", {
@@ -588,7 +576,7 @@ function TreeViewRow({ id, row, active, focussed, activate, icon: Icon }) {
588
576
  /* @__PURE__ */ jsx("span", {
589
577
  className: "label",
590
578
  title: row.item.name,
591
- children: row.item.name
579
+ children: Label ? /* @__PURE__ */ jsx(Label, { node: row.item }) : row.item.name
592
580
  })
593
581
  ]
594
582
  });
@@ -601,7 +589,7 @@ var Caret = ({ row }) => {
601
589
  if (row.hasChildren) return row.expanded ? /* @__PURE__ */ jsx(ChevronDownRegular, { onClick: toggleExpand }) : /* @__PURE__ */ jsx(ChevronRightRegular, { onClick: toggleExpand });
602
590
  else return null;
603
591
  };
604
- function Tree({ tree, selected, onSelect, onSetExpanded, nodeIcon, selectionMode = "none" }) {
592
+ function Tree({ tree, selected, onSelect, onSetExpanded, nodeIcon, nodeLabel, selectionMode = "none" }) {
605
593
  const id = useId();
606
594
  const { expanded, toggleExpand, expand, collapse } = useTreeControls({ onSetExpanded });
607
595
  const [focusedIndex, setFocusedIndex] = useState(-1);
@@ -691,6 +679,7 @@ function Tree({ tree, selected, onSelect, onSetExpanded, nodeIcon, selectionMode
691
679
  return /* @__PURE__ */ jsx(TreeViewRow, {
692
680
  id: `${id}-${row.index}`,
693
681
  icon: nodeIcon,
682
+ label: nodeLabel,
694
683
  focussed: focusedIndex === row.index,
695
684
  row,
696
685
  active: selectionMode === "single" && row.id === selectedKey,
@@ -1245,6 +1234,26 @@ var DefaultFooter = () => {
1245
1234
  return /* @__PURE__ */ jsx(Footer, { children: /* @__PURE__ */ jsx(FooterVersionItem, {}) });
1246
1235
  };
1247
1236
  //#endregion
1237
+ //#region src/react/diff-utils.ts
1238
+ /**
1239
+ * Computes which lines in the new text are changed or inserted compared to the old text.
1240
+ * Uses a greedy forward-matching approach to handle insertions/deletions.
1241
+ */
1242
+ function getChangedLineNumbers(oldText, newText) {
1243
+ const oldLines = oldText.split("\n");
1244
+ const newLines = newText.split("\n");
1245
+ const matchedNewIndices = /* @__PURE__ */ new Set();
1246
+ let oi = 0;
1247
+ for (let ni = 0; ni < newLines.length; ni++) for (let j = oi; j < oldLines.length; j++) if (newLines[ni] === oldLines[j]) {
1248
+ matchedNewIndices.add(ni);
1249
+ oi = j + 1;
1250
+ break;
1251
+ }
1252
+ const changed = [];
1253
+ for (let ni = 0; ni < newLines.length; ni++) if (!matchedNewIndices.has(ni)) changed.push(ni + 1);
1254
+ return changed;
1255
+ }
1256
+ //#endregion
1248
1257
  //#region src/react/typespec-editor.tsx
1249
1258
  var TypeSpecEditor = ({ actions, options, ...other }) => {
1250
1259
  return /* @__PURE__ */ jsx(Editor, {
@@ -1259,34 +1268,52 @@ var TypeSpecEditor = ({ actions, options, ...other }) => {
1259
1268
  ...other
1260
1269
  });
1261
1270
  };
1262
- var OutputEditor = ({ filename, value, editorOptions }) => {
1271
+ var OutputEditor = ({ filename, value, changedLineNumbers, editorOptions }) => {
1263
1272
  const model = useMonacoModel(filename);
1273
+ const [editorInstance, setEditorInstance] = useState(null);
1274
+ const decorationCollectionRef = useRef(null);
1275
+ const onMount = useCallback(({ editor: ed }) => {
1276
+ decorationCollectionRef.current = ed.createDecorationsCollection();
1277
+ setEditorInstance(ed);
1278
+ }, []);
1279
+ useEffect(() => {
1280
+ if (filename === "") return;
1281
+ model.setValue(value);
1282
+ }, [
1283
+ filename,
1284
+ value,
1285
+ model
1286
+ ]);
1287
+ useEffect(() => {
1288
+ if (!editorInstance || !decorationCollectionRef.current) return;
1289
+ if (changedLineNumbers && changedLineNumbers.length > 0 && changedLineNumbers.length < 500) decorationCollectionRef.current.set(changedLineNumbers.map((line) => ({
1290
+ range: new Range(line, 1, line, 1),
1291
+ options: {
1292
+ isWholeLine: true,
1293
+ className: "playground-changed-line"
1294
+ }
1295
+ })));
1296
+ else decorationCollectionRef.current.clear();
1297
+ }, [changedLineNumbers, editorInstance]);
1264
1298
  if (filename === "") return null;
1265
- const options = {
1266
- ...editorOptions,
1267
- readOnly: true,
1268
- automaticLayout: true,
1269
- minimap: { enabled: false }
1270
- };
1271
- model.setValue(value);
1272
1299
  return /* @__PURE__ */ jsx(Editor, {
1273
1300
  model,
1274
- options
1301
+ options: {
1302
+ ...editorOptions,
1303
+ readOnly: true,
1304
+ automaticLayout: true,
1305
+ minimap: { enabled: false }
1306
+ },
1307
+ onMount
1275
1308
  });
1276
1309
  };
1277
- //#endregion
1278
- //#region src/react/settings/compiler-settings.module.css
1279
- var settings = "_settings_1yvpj_1";
1280
- var section = "_section_1yvpj_7";
1281
- var field = "_field_1yvpj_23";
1282
- var empty = "_empty_1yvpj_33";
1283
1310
  var compiler_settings_module_default = {
1284
- settings,
1285
- section,
1311
+ settings: "_settings_1yvpj_1",
1312
+ section: "_section_1yvpj_7",
1286
1313
  "section-title": "_section-title_1yvpj_19",
1287
- field,
1314
+ field: "_field_1yvpj_23",
1288
1315
  "section-subtitle": "_section-subtitle_1yvpj_29",
1289
- empty
1316
+ empty: "_empty_1yvpj_33"
1290
1317
  };
1291
1318
  var emitter_options_form_module_default = {
1292
1319
  form: "_form_w9o1o_1",
@@ -1789,7 +1816,7 @@ var file_output_module_default = {
1789
1816
  /**
1790
1817
  * Display a file output using different viewers.
1791
1818
  */
1792
- var FileOutput = ({ filename, content, viewers }) => {
1819
+ var FileOutput = ({ filename, content, viewers, changedLineNumbers }) => {
1793
1820
  const resolvedViewers = useMemo(() => ({
1794
1821
  [RawFileViewer.key]: RawFileViewer,
1795
1822
  ...viewers
@@ -1805,7 +1832,8 @@ var FileOutput = ({ filename, content, viewers }) => {
1805
1832
  if (keys.length === 0) return /* @__PURE__ */ jsx(Fragment$1, { children: "No viewers" });
1806
1833
  else if (keys.length === 1) return resolvedViewers[keys[0]].render({
1807
1834
  filename,
1808
- content
1835
+ content,
1836
+ changedLineNumbers
1809
1837
  });
1810
1838
  return /* @__PURE__ */ jsxs("div", {
1811
1839
  className: file_output_module_default["file-output"],
@@ -1822,16 +1850,18 @@ var FileOutput = ({ filename, content, viewers }) => {
1822
1850
  })
1823
1851
  }), selectedRender && selectedRender({
1824
1852
  filename,
1825
- content
1853
+ content,
1854
+ changedLineNumbers
1826
1855
  })]
1827
1856
  });
1828
1857
  };
1829
1858
  var RawFileViewer = {
1830
1859
  key: "raw",
1831
1860
  label: "File",
1832
- render: ({ filename, content }) => /* @__PURE__ */ jsx(OutputEditor, {
1861
+ render: ({ filename, content, changedLineNumbers }) => /* @__PURE__ */ jsx(OutputEditor, {
1833
1862
  filename,
1834
- value: content
1863
+ value: content,
1864
+ changedLineNumbers
1835
1865
  })
1836
1866
  };
1837
1867
  //#endregion
@@ -1843,10 +1873,19 @@ var FileNodeIcon = ({ node }) => {
1843
1873
  if (node.isDirectory) return /* @__PURE__ */ jsx(FolderRegular, {});
1844
1874
  return /* @__PURE__ */ jsx(DocumentRegular, {});
1845
1875
  };
1876
+ var FileNodeLabel = ({ node }) => {
1877
+ return /* @__PURE__ */ jsx("span", {
1878
+ style: node.changed ? {
1879
+ fontWeight: 600,
1880
+ color: "var(--colorPaletteGreenForeground1)"
1881
+ } : void 0,
1882
+ children: node.name
1883
+ });
1884
+ };
1846
1885
  /**
1847
1886
  * Builds a tree structure from a flat list of file paths.
1848
1887
  */
1849
- function buildTree(files) {
1888
+ function buildTree(files, changedFiles) {
1850
1889
  const root = {
1851
1890
  id: "__root__",
1852
1891
  name: "root",
@@ -1874,7 +1913,8 @@ function buildTree(files) {
1874
1913
  if (lastSlash === -1) root.children.push({
1875
1914
  id: file,
1876
1915
  name: file,
1877
- isDirectory: false
1916
+ isDirectory: false,
1917
+ changed: changedFiles?.has(file)
1878
1918
  });
1879
1919
  else {
1880
1920
  const dirPath = file.substring(0, lastSlash);
@@ -1882,7 +1922,8 @@ function buildTree(files) {
1882
1922
  ensureDir(dirPath).children.push({
1883
1923
  id: file,
1884
1924
  name: fileName,
1885
- isDirectory: false
1925
+ isDirectory: false,
1926
+ changed: changedFiles?.has(file)
1886
1927
  });
1887
1928
  }
1888
1929
  }
@@ -1898,8 +1939,8 @@ function buildTree(files) {
1898
1939
  sortChildren(root);
1899
1940
  return root;
1900
1941
  }
1901
- var FileTreeExplorer = ({ files, selected, onSelect }) => {
1902
- const tree = useMemo(() => buildTree(files), [files]);
1942
+ var FileTreeExplorer = ({ files, selected, onSelect, changedFiles }) => {
1943
+ const tree = useMemo(() => buildTree(files, changedFiles), [files, changedFiles]);
1903
1944
  return /* @__PURE__ */ jsx("div", {
1904
1945
  className: file_tree_module_default["file-tree"],
1905
1946
  children: /* @__PURE__ */ jsx(Tree, {
@@ -1907,18 +1948,15 @@ var FileTreeExplorer = ({ files, selected, onSelect }) => {
1907
1948
  selectionMode: "single",
1908
1949
  selected,
1909
1950
  onSelect,
1910
- nodeIcon: FileNodeIcon
1951
+ nodeIcon: FileNodeIcon,
1952
+ nodeLabel: FileNodeLabel
1911
1953
  })
1912
1954
  });
1913
1955
  };
1914
- //#endregion
1915
- //#region src/react/output-tabs/output-tabs.module.css
1916
- var tabs = "_tabs_1x6x2_1";
1917
- var tab = "_tab_1x6x2_1";
1918
1956
  var output_tabs_module_default = {
1919
- tabs,
1957
+ tabs: "_tabs_1x6x2_1",
1920
1958
  "tab-divider": "_tab-divider_1x6x2_7",
1921
- tab,
1959
+ tab: "_tab_1x6x2_1",
1922
1960
  "tab--selected": "_tab--selected_1x6x2_18"
1923
1961
  };
1924
1962
  //#endregion
@@ -1940,23 +1978,85 @@ var OutputTabs = ({ filenames, selected, onSelect }) => {
1940
1978
  });
1941
1979
  };
1942
1980
  //#endregion
1981
+ //#region src/react/output-view/use-file-changes.ts
1982
+ /**
1983
+ * Tracks which output files have changed between compilations.
1984
+ * Returns the set of changed file paths and a map of changed line numbers per file.
1985
+ */
1986
+ function useFileChanges(program, outputFiles, highlightChanges) {
1987
+ const [changedFiles, setChangedFiles] = useState(/* @__PURE__ */ new Set());
1988
+ const [changedLines, setChangedLines] = useState(/* @__PURE__ */ new Map());
1989
+ const prevContentsRef = useRef(/* @__PURE__ */ new Map());
1990
+ useEffect(() => {
1991
+ if (!highlightChanges) return;
1992
+ let cancelled = false;
1993
+ async function diffFiles() {
1994
+ const changed = /* @__PURE__ */ new Set();
1995
+ const lines = /* @__PURE__ */ new Map();
1996
+ const newContents = /* @__PURE__ */ new Map();
1997
+ const isEmitterSwitch = prevContentsRef.current.size > 0 && !outputFiles.some((f) => prevContentsRef.current.has(f));
1998
+ let hasAnyChange = false;
1999
+ for (const file of outputFiles) try {
2000
+ const contents = await program.host.readFile("./tsp-output/" + file);
2001
+ newContents.set(file, contents.text);
2002
+ if (!isEmitterSwitch) {
2003
+ const prev = prevContentsRef.current.get(file);
2004
+ if (prev === void 0 && prevContentsRef.current.size > 0) {
2005
+ changed.add(file);
2006
+ const lineCount = contents.text.split("\n").length;
2007
+ lines.set(file, Array.from({ length: lineCount }, (_, i) => i + 1));
2008
+ hasAnyChange = true;
2009
+ } else if (prev !== void 0 && prev !== contents.text) {
2010
+ changed.add(file);
2011
+ lines.set(file, getChangedLineNumbers(prev, contents.text));
2012
+ hasAnyChange = true;
2013
+ } else if (prev === void 0) hasAnyChange = true;
2014
+ } else hasAnyChange = true;
2015
+ } catch {}
2016
+ if (cancelled) return;
2017
+ if (hasAnyChange || prevContentsRef.current.size === 0) {
2018
+ prevContentsRef.current = newContents;
2019
+ setChangedFiles(changed);
2020
+ setChangedLines(lines);
2021
+ }
2022
+ }
2023
+ diffFiles();
2024
+ return () => {
2025
+ cancelled = true;
2026
+ };
2027
+ }, [
2028
+ program,
2029
+ outputFiles,
2030
+ highlightChanges
2031
+ ]);
2032
+ return useMemo(() => ({
2033
+ changedFiles,
2034
+ changedLines
2035
+ }), [changedFiles, changedLines]);
2036
+ }
2037
+ //#endregion
1943
2038
  //#region src/react/output-view/output-view.module.css
1944
2039
  var output_view_module_default = {
1945
- "output-view": "_output-view_eeqi3_1",
1946
- "file-viewer": "_file-viewer_eeqi3_6",
1947
- "output-content": "_output-content_eeqi3_12",
1948
- "file-viewer-content": "_file-viewer-content_eeqi3_16",
1949
- "file-viewer-content-with-breadcrumb": "_file-viewer-content-with-breadcrumb_eeqi3_21",
1950
- "type-graph-viewer": "_type-graph-viewer_eeqi3_32",
1951
- "viewer-tabs-container": "_viewer-tabs-container_eeqi3_37",
1952
- "viewer-error": "_viewer-error_eeqi3_41"
2040
+ "output-view": "_output-view_l4ok7_1",
2041
+ "file-viewer": "_file-viewer_l4ok7_6",
2042
+ "output-content": "_output-content_l4ok7_12",
2043
+ "file-viewer-content": "_file-viewer-content_l4ok7_16",
2044
+ "file-viewer-content-with-breadcrumb": "_file-viewer-content-with-breadcrumb_l4ok7_21",
2045
+ "type-graph-viewer": "_type-graph-viewer_l4ok7_32",
2046
+ "viewer-tabs-container": "_viewer-tabs-container_l4ok7_37",
2047
+ "viewer-error": "_viewer-error_l4ok7_41",
2048
+ "output-view-wrapper": "_output-view-wrapper_l4ok7_45",
2049
+ "output-compiling": "_output-compiling_l4ok7_50",
2050
+ "output-compiling-overlay": "_output-compiling-overlay_l4ok7_57",
2051
+ "output-stale-banner": "_output-stale-banner_l4ok7_64"
1953
2052
  };
1954
2053
  //#endregion
1955
2054
  //#region src/react/output-view/file-viewer.tsx
1956
- var FileViewerComponent = ({ program, outputFiles, fileViewers }) => {
2055
+ var FileViewerComponent = ({ program, outputFiles, fileViewers, highlightChanges }) => {
1957
2056
  const [filename, setFilename] = useState("");
1958
2057
  const [content, setContent] = useState("");
1959
- const showFileTree = useMemo(() => outputFiles.length > 1 && (outputFiles.some((f) => f.includes("/")) || outputFiles.length >= 3), [outputFiles]);
2058
+ const { changedFiles, changedLines } = useFileChanges(program, outputFiles, highlightChanges);
2059
+ const showFileTree = useMemo(() => outputFiles.some((f) => f.includes("/")) || outputFiles.length >= 3, [outputFiles]);
1960
2060
  const loadOutputFile = useCallback(async (path) => {
1961
2061
  setContent((await program.host.readFile("./tsp-output/" + path)).text);
1962
2062
  }, [program.host]);
@@ -1989,7 +2089,8 @@ var FileViewerComponent = ({ program, outputFiles, fileViewers }) => {
1989
2089
  children: /* @__PURE__ */ jsx(FileTreeExplorer, {
1990
2090
  files: outputFiles,
1991
2091
  selected: filename,
1992
- onSelect: handleFileSelection
2092
+ onSelect: handleFileSelection,
2093
+ changedFiles: highlightChanges ? changedFiles : void 0
1993
2094
  })
1994
2095
  }), /* @__PURE__ */ jsx(Pane, { children: /* @__PURE__ */ jsxs("div", {
1995
2096
  className: output_view_module_default["file-viewer-content-with-breadcrumb"],
@@ -1998,7 +2099,8 @@ var FileViewerComponent = ({ program, outputFiles, fileViewers }) => {
1998
2099
  children: /* @__PURE__ */ jsx(FileOutput, {
1999
2100
  filename,
2000
2101
  content,
2001
- viewers: fileViewers
2102
+ viewers: fileViewers,
2103
+ changedLineNumbers: highlightChanges ? changedLines.get(filename) : void 0
2002
2104
  })
2003
2105
  })]
2004
2106
  }) })]
@@ -2015,13 +2117,15 @@ var FileViewerComponent = ({ program, outputFiles, fileViewers }) => {
2015
2117
  children: /* @__PURE__ */ jsx(FileOutput, {
2016
2118
  filename,
2017
2119
  content,
2018
- viewers: fileViewers
2120
+ viewers: fileViewers,
2121
+ changedLineNumbers: highlightChanges ? changedLines.get(filename) : void 0
2019
2122
  })
2020
2123
  })]
2021
2124
  });
2022
2125
  };
2023
- function createFileViewer(fileViewers) {
2126
+ function createFileViewer(fileViewers, options) {
2024
2127
  const viewerMap = Object.fromEntries(fileViewers.map((x) => [x.key, x]));
2128
+ const highlightChanges = options?.highlightChanges ?? false;
2025
2129
  return {
2026
2130
  key: "file-output",
2027
2131
  label: "Output explorer",
@@ -2029,7 +2133,8 @@ function createFileViewer(fileViewers) {
2029
2133
  render: (props) => {
2030
2134
  return /* @__PURE__ */ jsx(FileViewerComponent, {
2031
2135
  ...props,
2032
- fileViewers: viewerMap
2136
+ fileViewers: viewerMap,
2137
+ highlightChanges
2033
2138
  });
2034
2139
  }
2035
2140
  };
@@ -2061,21 +2166,50 @@ var TypeGraphViewer = {
2061
2166
  };
2062
2167
  //#endregion
2063
2168
  //#region src/react/output-view/output-view.tsx
2064
- var OutputView = ({ compilationState, viewers, fileViewers, selectedViewer, onViewerChange, viewerState, onViewerStateChange }) => {
2065
- const resolvedViewers = useMemo(() => resolveViewers(viewers, fileViewers), [fileViewers, viewers]);
2066
- if (compilationState === void 0) return /* @__PURE__ */ jsx(Fragment$1, {});
2169
+ var OutputView = ({ compilationState, isCompiling, isOutputStale, viewers, fileViewers, highlightChanges, selectedViewer, onViewerChange, viewerState, onViewerStateChange }) => {
2170
+ const resolvedViewers = useMemo(() => resolveViewers(viewers, fileViewers, highlightChanges), [
2171
+ fileViewers,
2172
+ viewers,
2173
+ highlightChanges
2174
+ ]);
2175
+ if (compilationState === void 0) {
2176
+ if (isCompiling) return /* @__PURE__ */ jsx("div", {
2177
+ className: output_view_module_default["output-compiling"],
2178
+ children: /* @__PURE__ */ jsx(Spinner, {
2179
+ size: "small",
2180
+ label: "Compiling..."
2181
+ })
2182
+ });
2183
+ return /* @__PURE__ */ jsx(Fragment$1, {});
2184
+ }
2067
2185
  if ("internalCompilerError" in compilationState) return /* @__PURE__ */ jsx(Fragment$1, {});
2068
- return /* @__PURE__ */ jsx(OutputViewInternal, {
2069
- compilationResult: compilationState,
2070
- viewers: resolvedViewers,
2071
- selectedViewer,
2072
- onViewerChange,
2073
- viewerState,
2074
- onViewerStateChange
2186
+ return /* @__PURE__ */ jsxs("div", {
2187
+ className: output_view_module_default["output-view-wrapper"],
2188
+ children: [
2189
+ isOutputStale && /* @__PURE__ */ jsx("div", {
2190
+ className: output_view_module_default["output-stale-banner"],
2191
+ children: "Output is from last successful compilation"
2192
+ }),
2193
+ isCompiling && /* @__PURE__ */ jsx("div", {
2194
+ className: output_view_module_default["output-compiling-overlay"],
2195
+ children: /* @__PURE__ */ jsx(Spinner, {
2196
+ size: "tiny",
2197
+ label: "Compiling..."
2198
+ })
2199
+ }),
2200
+ /* @__PURE__ */ jsx(OutputViewInternal, {
2201
+ compilationResult: compilationState,
2202
+ viewers: resolvedViewers,
2203
+ selectedViewer,
2204
+ onViewerChange,
2205
+ viewerState,
2206
+ onViewerStateChange
2207
+ })
2208
+ ]
2075
2209
  });
2076
2210
  };
2077
- function resolveViewers(viewers, fileViewers) {
2078
- const fileViewer = createFileViewer(fileViewers ?? []);
2211
+ function resolveViewers(viewers, fileViewers, highlightChanges) {
2212
+ const fileViewer = createFileViewer(fileViewers ?? [], { highlightChanges });
2079
2213
  const output = { programViewers: {
2080
2214
  [fileViewer.key]: fileViewer,
2081
2215
  [TypeGraphViewer.key]: TypeGraphViewer
@@ -2426,6 +2560,9 @@ var Playground = (props) => {
2426
2560
  }, [host]);
2427
2561
  const typespecModel = useMonacoModel("inmemory://test/main.tsp", "typespec");
2428
2562
  const [compilationState, setCompilationState] = useState(void 0);
2563
+ const lastSuccessfulOutputRef = useRef([]);
2564
+ const [isCompiling, setIsCompiling] = useState(false);
2565
+ const [isOutputStale, setIsOutputStale] = useState(false);
2429
2566
  const { selectedEmitter, compilerOptions, selectedSampleName, selectedViewer, viewerState, content, onSelectedEmitterChange, onCompilerOptionsChange, onSelectedSampleNameChange, onSelectedViewerChange, onViewerStateChange, onContentChange } = usePlaygroundState({
2430
2567
  libraries: props.libraries,
2431
2568
  samples: props.samples,
@@ -2435,6 +2572,10 @@ var Playground = (props) => {
2435
2572
  defaultEmitter: props.defaultEmitter,
2436
2573
  defaultContent: props.defaultContent
2437
2574
  });
2575
+ useEffect(() => {
2576
+ lastSuccessfulOutputRef.current = [];
2577
+ setIsOutputStale(false);
2578
+ }, [selectedEmitter]);
2438
2579
  useEffect(() => {
2439
2580
  if (typespecModel.getValue() !== (content ?? "")) typespecModel.setValue(content ?? "");
2440
2581
  }, [content, typespecModel]);
@@ -2456,11 +2597,33 @@ var Playground = (props) => {
2456
2597
  selectedSampleName,
2457
2598
  props.samples
2458
2599
  ]);
2600
+ const compileIdRef = useRef(0);
2459
2601
  const doCompile = useCallback(async () => {
2460
2602
  const currentContent = typespecModel.getValue();
2461
2603
  const typespecCompiler = host.compiler;
2462
- const state = await compile(host, currentContent, selectedEmitter, compilerOptions);
2463
- setCompilationState(state);
2604
+ const compileId = ++compileIdRef.current;
2605
+ setIsCompiling(true);
2606
+ let state;
2607
+ try {
2608
+ state = await compile(host, currentContent, selectedEmitter, compilerOptions);
2609
+ } catch (error) {
2610
+ console.error("Compilation failed", error);
2611
+ return;
2612
+ } finally {
2613
+ setIsCompiling(false);
2614
+ }
2615
+ if (compileId !== compileIdRef.current) return;
2616
+ if ("program" in state && state.program.hasError() && state.outputFiles.length === 0 && lastSuccessfulOutputRef.current.length > 0) {
2617
+ setIsOutputStale(true);
2618
+ setCompilationState({
2619
+ ...state,
2620
+ outputFiles: lastSuccessfulOutputRef.current
2621
+ });
2622
+ } else {
2623
+ setIsOutputStale(false);
2624
+ if ("program" in state && state.outputFiles.length > 0) lastSuccessfulOutputRef.current = state.outputFiles;
2625
+ setCompilationState(state);
2626
+ }
2464
2627
  if ("program" in state) {
2465
2628
  const markers = state.program.diagnostics.map((diag) => ({
2466
2629
  ...getMonacoRange(typespecCompiler, diag.target),
@@ -2482,14 +2645,19 @@ var Playground = (props) => {
2482
2645
  compilerOptions,
2483
2646
  typespecModel
2484
2647
  ]);
2648
+ const currentEmitterOptions = selectedEmitter ? props.emitterOptions?.[selectedEmitter] : void 0;
2485
2649
  useEffect(() => {
2486
- const debouncer = debounce(() => doCompile(), 200);
2650
+ const debouncer = debounce(() => doCompile(), currentEmitterOptions?.debounce ?? 200);
2487
2651
  const disposable = typespecModel.onDidChangeContent(debouncer);
2488
2652
  return () => {
2489
2653
  debouncer.clear();
2490
2654
  disposable.dispose();
2491
2655
  };
2492
- }, [typespecModel, doCompile]);
2656
+ }, [
2657
+ typespecModel,
2658
+ doCompile,
2659
+ currentEmitterOptions?.debounce
2660
+ ]);
2493
2661
  useEffect(() => {
2494
2662
  doCompile();
2495
2663
  }, [doCompile]);
@@ -2587,9 +2755,12 @@ var Playground = (props) => {
2587
2755
  });
2588
2756
  const outputPanel = /* @__PURE__ */ jsx(OutputView, {
2589
2757
  compilationState,
2758
+ isCompiling,
2759
+ isOutputStale,
2590
2760
  editorOptions: props.editorOptions,
2591
2761
  viewers: props.viewers,
2592
2762
  fileViewers: selectedEmitter ? props.emitterViewers?.[selectedEmitter] : void 0,
2763
+ highlightChanges: currentEmitterOptions?.newChangeDiff,
2593
2764
  selectedViewer,
2594
2765
  onViewerChange: onSelectedViewerChange,
2595
2766
  viewerState,
@@ -1,7 +1,7 @@
1
1
  import { TypeSpecLanguageConfiguration, createSourceFile, getSourceFileKindFromExt, resolvePath } from "@typespec/compiler";
2
2
  import * as monaco from "monaco-editor";
3
3
  import * as lsp from "vscode-languageserver";
4
- import { DiagnosticSeverity, DocumentHighlightKind, FormattingOptions, Range } from "vscode-languageserver";
4
+ import { DiagnosticSeverity, DocumentHighlightKind, FormattingOptions, Range as Range$1 } from "vscode-languageserver";
5
5
  import { TextDocument } from "vscode-languageserver-textdocument";
6
6
  //#region src/react/debug.ts
7
7
  /**
@@ -304,7 +304,7 @@ function position(pos) {
304
304
  };
305
305
  }
306
306
  function range(range) {
307
- return Range.create({
307
+ return Range$1.create({
308
308
  line: range.startLineNumber - 1,
309
309
  character: range.startColumn - 1
310
310
  }, {
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Computes which lines in the new text are changed or inserted compared to the old text.
3
+ * Uses a greedy forward-matching approach to handle insertions/deletions.
4
+ */
5
+ export declare function getChangedLineNumbers(oldText: string, newText: string): number[];
6
+ //# sourceMappingURL=diff-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-utils.d.ts","sourceRoot":"","sources":["../../../src/react/diff-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CA0BhF"}
@@ -4,6 +4,8 @@ export interface FileOutputProps {
4
4
  readonly filename: string;
5
5
  readonly content: string;
6
6
  readonly viewers: Record<string, FileOutputViewer>;
7
+ /** Line numbers to highlight as changed (1-based). */
8
+ readonly changedLineNumbers?: number[];
7
9
  }
8
10
  /**
9
11
  * Display a file output using different viewers.
@@ -1 +1 @@
1
- {"version":3,"file":"file-output.d.ts","sourceRoot":"","sources":["../../../../src/react/file-output/file-output.tsx"],"names":[],"mappings":"AACA,OAAO,EAAkC,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CACpD;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,iBAAiB,CAAC,eAAe,CAyCzD,CAAC"}
1
+ {"version":3,"file":"file-output.d.ts","sourceRoot":"","sources":["../../../../src/react/file-output/file-output.tsx"],"names":[],"mappings":"AACA,OAAO,EAAkC,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACnD,sDAAsD;IACtD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CACxC;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,iBAAiB,CAAC,eAAe,CA8CzD,CAAC"}
@@ -3,6 +3,7 @@ export interface FileTreeExplorerProps {
3
3
  readonly files: string[];
4
4
  readonly selected: string;
5
5
  readonly onSelect: (file: string) => void;
6
+ readonly changedFiles?: Set<string>;
6
7
  }
7
8
  export declare const FileTreeExplorer: FunctionComponent<FileTreeExplorerProps>;
8
9
  //# sourceMappingURL=file-tree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-tree.d.ts","sourceRoot":"","sources":["../../../../src/react/file-tree/file-tree.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAKjE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AA8ED,eAAO,MAAM,gBAAgB,EAAE,iBAAiB,CAAC,qBAAqB,CAkBrE,CAAC"}
1
+ {"version":3,"file":"file-tree.d.ts","sourceRoot":"","sources":["../../../../src/react/file-tree/file-tree.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAKjE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACrC;AA6FD,eAAO,MAAM,gBAAgB,EAAE,iBAAiB,CAAC,qBAAqB,CAoBrE,CAAC"}
@@ -5,7 +5,7 @@ export type { DiagnosticListProps } from './diagnostic-list/diagnostic-list.js';
5
5
  export { Editor, useMonacoModel, type EditorProps } from './editor.js';
6
6
  export { Footer, FooterItem, FooterVersionItem, type FooterItemProps, type FooterProps, type FooterVersionItemProps, type VersionSelectorProps, type VersionSelectorVersion, } from './footer/index.js';
7
7
  export { Playground } from './playground.js';
8
- export type { PlaygroundProps, PlaygroundSaveData } from './playground.js';
8
+ export type { PlaygroundEmitterOptions, PlaygroundProps, PlaygroundSaveData, } from './playground.js';
9
9
  export { StandalonePlayground, createReactPlayground, createStandalonePlaygroundStateStorage, renderReactPlayground, } from './standalone.js';
10
10
  export type * from './types.js';
11
11
  export { usePlaygroundState, type PlaygroundState } from './use-playground-state.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AACtE,YAAY,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EACL,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,sCAAsC,EACtC,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AACzB,mBAAmB,YAAY,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AACtE,YAAY,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EACL,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EACV,wBAAwB,EACxB,eAAe,EACf,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,sCAAsC,EACtC,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AACzB,mBAAmB,YAAY,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC"}
@@ -1,3 +1,7 @@
1
1
  import { FileOutputViewer, ProgramViewer } from '../types.js';
2
- export declare function createFileViewer(fileViewers: FileOutputViewer[]): ProgramViewer;
2
+ export interface FileViewerOptions {
3
+ /** When true, highlights changed files in the tree and changed lines in the editor after recompilation. */
4
+ highlightChanges?: boolean;
5
+ }
6
+ export declare function createFileViewer(fileViewers: FileOutputViewer[], options?: FileViewerOptions): ProgramViewer;
3
7
  //# sourceMappingURL=file-viewer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-viewer.d.ts","sourceRoot":"","sources":["../../../../src/react/output-view/file-viewer.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAqB,aAAa,EAAE,MAAM,aAAa,CAAC;AAuFtF,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,gBAAgB,EAAE,GAAG,aAAa,CAU/E"}
1
+ {"version":3,"file":"file-viewer.d.ts","sourceRoot":"","sources":["../../../../src/react/output-view/file-viewer.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAqB,aAAa,EAAE,MAAM,aAAa,CAAC;AAsGtF,MAAM,WAAW,iBAAiB;IAChC,2GAA2G;IAC3G,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,gBAAgB,EAAE,EAC/B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,aAAa,CAiBf"}
@@ -3,12 +3,19 @@ import { PlaygroundEditorsOptions } from '../playground.js';
3
3
  import { CompilationState, FileOutputViewer, ProgramViewer } from '../types.js';
4
4
  export interface OutputViewProps {
5
5
  compilationState: CompilationState | undefined;
6
+ isCompiling?: boolean;
7
+ /** When true, the displayed output is from a previous successful compilation. */
8
+ isOutputStale?: boolean;
6
9
  editorOptions?: PlaygroundEditorsOptions;
7
10
  /**
8
11
  * List of custom viewers to display the output. It can be file viewers or program viewers.
9
12
  */
10
13
  viewers?: ProgramViewer[];
11
14
  fileViewers?: FileOutputViewer[];
15
+ /**
16
+ * When true, highlights changed files and lines after recompilation.
17
+ */
18
+ highlightChanges?: boolean;
12
19
  /**
13
20
  * The currently selected viewer key.
14
21
  */
@@ -1 +1 @@
1
- {"version":3,"file":"output-view.d.ts","sourceRoot":"","sources":["../../../../src/react/output-view/output-view.tsx"],"names":[],"mappings":"AACA,OAAO,EAAkC,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE/E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAiB,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMpG,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC/C,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC;;OAEG;IACH,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CAC5D;AAED,eAAO,MAAM,UAAU,EAAE,iBAAiB,CAAC,eAAe,CA8BzD,CAAC"}
1
+ {"version":3,"file":"output-view.d.ts","sourceRoot":"","sources":["../../../../src/react/output-view/output-view.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAkC,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE/E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAiB,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMpG,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iFAAiF;IACjF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC;;OAEG;IACH,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CAC5D;AAED,eAAO,MAAM,UAAU,EAAE,iBAAiB,CAAC,eAAe,CAoDzD,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { CompileResult } from '../types.js';
2
+ export interface FileChanges {
3
+ changedFiles: Set<string>;
4
+ changedLines: Map<string, number[]>;
5
+ }
6
+ /**
7
+ * Tracks which output files have changed between compilations.
8
+ * Returns the set of changed file paths and a map of changed line numbers per file.
9
+ */
10
+ export declare function useFileChanges(program: CompileResult["program"], outputFiles: string[], highlightChanges: boolean): FileChanges;
11
+ //# sourceMappingURL=use-file-changes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-file-changes.d.ts","sourceRoot":"","sources":["../../../../src/react/output-view/use-file-changes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,EACjC,WAAW,EAAE,MAAM,EAAE,EACrB,gBAAgB,EAAE,OAAO,GACxB,WAAW,CA8Db"}
@@ -4,6 +4,12 @@ import { CommandBarItem } from './responsive-command-bar/index.js';
4
4
  import { FileOutputViewer, ProgramViewer } from './types.js';
5
5
  import { PlaygroundState } from './use-playground-state.js';
6
6
  export type { PlaygroundState };
7
+ export interface PlaygroundEmitterOptions {
8
+ /** Compile debounce delay in milliseconds. Default is 200. */
9
+ debounce?: number;
10
+ /** When true, highlights changed files and lines after recompilation. */
11
+ newChangeDiff?: boolean;
12
+ }
7
13
  export interface PlaygroundProps {
8
14
  host: BrowserHost;
9
15
  /** Default content if leaving this unmanaged. */
@@ -30,6 +36,10 @@ export interface PlaygroundProps {
30
36
  viewers?: ProgramViewer[];
31
37
  /** Custom file viewers that enabled for certain emitters. Key of the map is emitter name */
32
38
  emitterViewers?: Record<string, FileOutputViewer[]>;
39
+ /**
40
+ * Per-emitter playground options. Key is the emitter name.
41
+ */
42
+ emitterOptions?: Record<string, PlaygroundEmitterOptions>;
33
43
  onSave?: (value: PlaygroundSaveData) => void;
34
44
  editorOptions?: PlaygroundEditorsOptions;
35
45
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"playground.d.ts","sourceRoot":"","sources":["../../../src/react/playground.tsx"],"names":[],"mappings":"AAGA,OAAO,sCAAsC,CAAC;AAG9C,OAAO,EAML,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAKf,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AASjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAoB,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpF,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAIrF,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,CAAC;IAElB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,kCAAkC;IAClC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAEtC,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAE3C,oCAAoC;IACpC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,yDAAyD;IACzD,sBAAsB,CAAC,EAAE,eAAe,CAAC;IACzC,6CAA6C;IAC7C,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAE3D;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAEvB,mDAAmD;IACnD,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IAEnC,kDAAkD;IAClD,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAE1B,4FAA4F;IAC5F,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAEpD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAE7C,aAAa,CAAC,EAAE,wBAAwB,CAAC;IAEzC;;OAEG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAEhB,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,eAAO,MAAM,UAAU,EAAE,iBAAiB,CAAC,eAAe,CAmRzD,CAAC"}
1
+ {"version":3,"file":"playground.d.ts","sourceRoot":"","sources":["../../../src/react/playground.tsx"],"names":[],"mappings":"AAGA,OAAO,sCAAsC,CAAC;AAG9C,OAAO,EAML,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAKf,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AASjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAoB,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpF,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAIrF,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,MAAM,WAAW,wBAAwB;IACvC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,CAAC;IAElB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,kCAAkC;IAClC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAEtC,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAE3C,oCAAoC;IACpC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,yDAAyD;IACzD,sBAAsB,CAAC,EAAE,eAAe,CAAC;IACzC,6CAA6C;IAC7C,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAE3D;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAEvB,mDAAmD;IACnD,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IAEnC,kDAAkD;IAClD,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAE1B,4FAA4F;IAC5F,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAEpD;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IAE1D,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAE7C,aAAa,CAAC,EAAE,wBAAwB,CAAC;IAEzC;;OAEG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAEhB,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,eAAO,MAAM,UAAU,EAAE,iBAAiB,CAAC,eAAe,CAyUzD,CAAC"}
@@ -32,5 +32,7 @@ export interface FileOutputViewer {
32
32
  export interface FileOutputViewerProps {
33
33
  readonly filename: string;
34
34
  readonly content: string;
35
+ /** Line numbers to highlight as changed (1-based). */
36
+ readonly changedLineNumbers?: number[];
35
37
  }
36
38
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/react/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,qBAAqB,EAAE,GAAG,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,kBAAkB,CAAC;AAElE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAErE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,oBAAoB;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3C,sCAAsC;IACtC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CACrE;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,GAAG,IAAI,CAAC;CACjE;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,SAAS,GAAG,IAAI,CAAC;CACrE;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/react/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,qBAAqB,EAAE,GAAG,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,kBAAkB,CAAC;AAElE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAErE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,oBAAoB;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3C,sCAAsC;IACtC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CACrE;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,GAAG,IAAI,CAAC;CACjE;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,SAAS,GAAG,IAAI,CAAC;CACrE;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CACxC"}
@@ -2,6 +2,7 @@ import { editor } from 'monaco-editor';
2
2
  import { FunctionComponent } from 'react';
3
3
  import { EditorProps } from './editor.js';
4
4
  import { PlaygroundEditorsOptions } from './playground.js';
5
+ export { getChangedLineNumbers } from './diff-utils.js';
5
6
  export interface TypeSpecEditorProps extends Omit<EditorProps, "options"> {
6
7
  options?: editor.IStandaloneEditorConstructionOptions;
7
8
  }
@@ -9,6 +10,7 @@ export declare const TypeSpecEditor: FunctionComponent<TypeSpecEditorProps>;
9
10
  export declare const OutputEditor: FunctionComponent<{
10
11
  filename: string;
11
12
  value: string;
13
+ changedLineNumbers?: number[];
12
14
  editorOptions?: PlaygroundEditorsOptions;
13
15
  }>;
14
16
  //# sourceMappingURL=typespec-editor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"typespec-editor.d.ts","sourceRoot":"","sources":["../../../src/react/typespec-editor.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAA0B,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC,oCAAoC,CAAC;CACvD;AAED,eAAO,MAAM,cAAc,EAAE,iBAAiB,CAAC,mBAAmB,CAejE,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,iBAAiB,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,wBAAwB,CAAC;CAC1C,CAeA,CAAC"}
1
+ {"version":3,"file":"typespec-editor.d.ts","sourceRoot":"","sources":["../../../src/react/typespec-editor.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAS,MAAM,eAAe,CAAC;AAC9C,OAAO,EAA4C,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AACzF,OAAO,EAA0B,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,8BAA8B,CAAC;AAGtC,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC,oCAAoC,CAAC;CACvD;AAED,eAAO,MAAM,cAAc,EAAE,iBAAiB,CAAC,mBAAmB,CAejE,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,iBAAiB,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,aAAa,CAAC,EAAE,wBAAwB,CAAC;CAC1C,CA8CA,CAAC"}
package/dist/style.css CHANGED
@@ -446,49 +446,76 @@
446
446
  ._tab--selected_1x6x2_18 {
447
447
  background-color: var(--colorNeutralBackground5) !important;
448
448
  }
449
- ._output-view_eeqi3_1 {
449
+ ._output-view_l4ok7_1 {
450
450
  display: flex;
451
451
  flex-direction: row;
452
452
  height: 100%;
453
453
  }
454
- ._file-viewer_eeqi3_6 {
454
+ ._file-viewer_l4ok7_6 {
455
455
  display: flex;
456
456
  flex-direction: column;
457
457
  height: 100%;
458
458
  }
459
459
 
460
- ._output-content_eeqi3_12 {
460
+ ._output-content_l4ok7_12 {
461
461
  flex: 1;
462
462
  min-width: 0;
463
463
  }
464
- ._file-viewer-content_eeqi3_16 {
464
+ ._file-viewer-content_l4ok7_16 {
465
465
  flex: 1;
466
466
  min-height: 0;
467
467
  }
468
468
 
469
- ._file-viewer-content-with-breadcrumb_eeqi3_21 {
469
+ ._file-viewer-content-with-breadcrumb_l4ok7_21 {
470
470
  display: flex;
471
471
  flex-direction: column;
472
472
  height: 100%;
473
473
  }
474
474
 
475
- ._file-viewer-content-with-breadcrumb_eeqi3_21 ._file-viewer-content_eeqi3_16 {
475
+ ._file-viewer-content-with-breadcrumb_l4ok7_21 ._file-viewer-content_l4ok7_16 {
476
476
  flex: 1;
477
477
  min-height: 0;
478
478
  }
479
479
 
480
- ._type-graph-viewer_eeqi3_32 {
480
+ ._type-graph-viewer_l4ok7_32 {
481
481
  height: 100%;
482
482
  overflow-y: auto;
483
483
  }
484
484
 
485
- ._viewer-tabs-container_eeqi3_37 {
485
+ ._viewer-tabs-container_l4ok7_37 {
486
486
  background-color: var(--colorNeutralBackground3);
487
487
  }
488
488
 
489
- ._viewer-error_eeqi3_41 {
489
+ ._viewer-error_l4ok7_41 {
490
490
  padding: 20px;
491
491
  }
492
+
493
+ ._output-view-wrapper_l4ok7_45 {
494
+ position: relative;
495
+ height: 100%;
496
+ }
497
+
498
+ ._output-compiling_l4ok7_50 {
499
+ display: flex;
500
+ align-items: center;
501
+ justify-content: center;
502
+ height: 100%;
503
+ }
504
+
505
+ ._output-compiling-overlay_l4ok7_57 {
506
+ position: absolute;
507
+ top: 8px;
508
+ right: 48px;
509
+ z-index: 10;
510
+ }
511
+
512
+ ._output-stale-banner_l4ok7_64 {
513
+ background-color: var(--colorPaletteYellowBackground2);
514
+ color: var(--colorNeutralForeground1);
515
+ padding: 4px 12px;
516
+ font-size: 12px;
517
+ text-align: center;
518
+ }
492
519
  ._layout_63onh_1 {
493
520
  display: flex;
494
521
  flex-direction: column;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typespec/playground",
3
- "version": "0.14.1-dev.3",
3
+ "version": "0.15.0-dev.4",
4
4
  "author": "Microsoft Corporation",
5
5
  "description": "TypeSpec playground UI components.",
6
6
  "homepage": "https://typespec.io",
@@ -59,53 +59,53 @@
59
59
  "!dist/test/**"
60
60
  ],
61
61
  "dependencies": {
62
- "@fluentui/react-components": "~9.73.3",
62
+ "@fluentui/react-components": "^9.73.7",
63
63
  "@fluentui/react-icons": "^2.0.323",
64
64
  "@typespec/bundler": "^0.5.2 || >= 0.5.3-dev.4",
65
- "@typespec/compiler": "^1.11.0 || >= 1.12.0-dev.2",
65
+ "@typespec/compiler": "^1.11.0 || >= 1.12.0-dev.4",
66
66
  "@typespec/html-program-viewer": "^0.81.0 || >= 0.82.0-dev.3",
67
67
  "@typespec/http": "^1.11.0 || >= 1.12.0-dev.2",
68
68
  "@typespec/openapi": "^1.11.0 || >= 1.12.0-dev.2",
69
- "@typespec/openapi3": "^1.11.0 || >= 1.12.0-dev.2",
69
+ "@typespec/openapi3": "^1.11.0 || >= 1.12.0-dev.3",
70
70
  "@typespec/protobuf": "^0.81.0 || >= 0.82.0-dev.1",
71
71
  "@typespec/rest": "^0.81.0 || >= 0.82.0-dev.2",
72
72
  "@typespec/versioning": "^0.81.0 || >= 0.82.0-dev.2",
73
73
  "clsx": "^2.1.1",
74
- "debounce": "~3.0.0",
74
+ "debounce": "^3.0.0",
75
75
  "lzutf8": "0.6.3",
76
- "monaco-editor": "~0.55.1",
77
- "react": "~19.2.4",
78
- "react-dom": "~19.2.4",
76
+ "monaco-editor": "^0.55.1",
77
+ "react": "^19.2.4",
78
+ "react-dom": "^19.2.4",
79
79
  "react-error-boundary": "^6.1.1",
80
- "swagger-ui-dist": "^5.32.0",
81
- "vscode-languageserver": "~9.0.1",
82
- "vscode-languageserver-textdocument": "~1.0.12",
83
- "yaml": "~2.8.2"
80
+ "swagger-ui-dist": "^5.32.2",
81
+ "vscode-languageserver": "^9.0.1",
82
+ "vscode-languageserver-textdocument": "^1.0.12",
83
+ "yaml": "^2.8.3"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@babel/core": "^7.29.0",
87
- "@playwright/test": "^1.58.2",
88
- "@storybook/cli": "^10.3.3",
89
- "@storybook/react-vite": "^10.3.3",
87
+ "@playwright/test": "^1.59.1",
88
+ "@storybook/cli": "^10.3.5",
89
+ "@storybook/react-vite": "^10.3.5",
90
90
  "@testing-library/dom": "^10.4.1",
91
91
  "@testing-library/jest-dom": "^6.9.1",
92
92
  "@testing-library/react": "^16.3.2",
93
- "@types/debounce": "~1.2.4",
94
- "@types/node": "~25.5.0",
95
- "@types/react": "~19.2.14",
96
- "@types/react-dom": "~19.2.3",
97
- "@types/swagger-ui-dist": "~3.30.6",
93
+ "@types/debounce": "^1.2.4",
94
+ "@types/node": "^25.5.2",
95
+ "@types/react": "^19.2.14",
96
+ "@types/react-dom": "^19.2.3",
97
+ "@types/swagger-ui-dist": "^3.30.6",
98
98
  "@typespec/bundler": "^0.5.2 || >= 0.5.3-dev.4",
99
- "@vitejs/plugin-react": "~6.0.1",
100
- "cross-env": "~10.1.0",
101
- "es-module-shims": "~2.8.0",
102
- "rimraf": "~6.1.3",
103
- "storybook": "^10.3.3",
99
+ "@vitejs/plugin-react": "^6.0.1",
100
+ "cross-env": "^10.1.0",
101
+ "es-module-shims": "^2.8.0",
102
+ "rimraf": "^6.1.3",
103
+ "storybook": "^10.3.5",
104
104
  "typescript": "~6.0.2",
105
- "vite": "^8.0.1",
105
+ "vite": "^8.0.7",
106
106
  "vite-plugin-checker": "^0.12.0",
107
107
  "vite-plugin-dts": "4.5.4",
108
- "vitest": "^4.1.0",
108
+ "vitest": "^4.1.3",
109
109
  "@typespec/react-components": "^0.57.0"
110
110
  },
111
111
  "scripts": {