Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 3 additions & 6 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,10 @@ jobs:
name: "Run Linters and Typechecking"
runs-on: "depot-ubuntu-24.04-small"
steps:
- uses: "actions/checkout@v4"
- uses: "authzed/action-spicedb@v1"
- uses: "actions/checkout@v6"
- uses: "actions/setup-node@v6"
with:
version: "latest"
- uses: "actions/setup-node@v4"
with:
node-version: 22
node-version: 24
cache-dependency-path: "yarn.lock"
cache: "yarn"
- uses: "bahmutov/npm-install@v1"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
contents: "write"
packages: "write"
steps:
- uses: "actions/checkout@v4"
- uses: "actions/checkout@v6"
with:
lfs: "true"
submodules: "recursive"
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ jobs:
name: "Run Tests"
runs-on: "depot-ubuntu-24.04-small"
steps:
- uses: "actions/checkout@v4"
- uses: "actions/checkout@v6"
with:
submodules: true
- uses: "authzed/action-spicedb@v1"
with:
version: "latest"
- uses: "actions/setup-node@v4"
- uses: "actions/setup-node@v6"
with:
node-version: 22
node-version: 24
cache-dependency-path: "yarn.lock"
cache: "yarn"
- uses: "bahmutov/npm-install@v1"
Expand Down
5 changes: 3 additions & 2 deletions .oxfmtrc.jsonc
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"ignorePatterns": ["src/spicedb-common/protodefs", "examples", "public"],
"experimentalSortImports": {
"sortImports": {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer experimental :D

// This is for `import "foo.css"` type stuff
"sortSideEffects": true,
"groups": [
["side-effect"],
["builtin"],
["external", "type-external"],
["internal", "type-internal"],
Expand Down
2 changes: 1 addition & 1 deletion .oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// "restriction": "error"
},
"plugins": ["eslint", "import", "oxc", "promise", "react", "typescript", "unicorn"],
"ignorePatterns": ["dist", "src/spicedb-common/protodefs", "public"],
"ignorePatterns": ["dist", "src/spicedb-common/protodefs", "public", "src/components/ui"],
"rules": {
// TODO: fix this and get rid of it
"react/only-export-components": [
Expand Down
66 changes: 30 additions & 36 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,28 @@
},
"dependencies": {
"@authzed/spicedb-parser-js": "^1.0.5",
"@aws-sdk/client-s3": "^3.0.0",
"@aws-sdk/client-s3": "^3.997.0",
"@bufbuild/protobuf": "^2.4.0",
"@dagrejs/dagre": "^2.0.4",
"@fontsource/roboto": "^5.1.1",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.2.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@glideapps/glide-data-grid": "^6.0.3",
"@glideapps/glide-data-grid-cells": "^6.0.3",
"@material-ui/core": "^4.12.4",
"@material-ui/icons": "^4.11.3",
"@material-ui/lab": "^4.0.0-alpha.61",
"@monaco-editor/react": "^4.3.1",
"@posthog/react": "^1.5.2",
"@radix-ui/react-alert-dialog": "^1.1.11",
"@radix-ui/react-select": "^2.2.2",
"@radix-ui/react-slot": "^1.2.0",
"@radix-ui/react-tabs": "^1.1.9",
"@tailwindcss/vite": "^4.1.5",
"@tanstack/react-pacer": "^0.17.4",
"@tanstack/react-router": "^1.119.0",
"@tanstack/react-router-devtools": "^1.119.1",
"@monaco-editor/react": "^4.7.0",
"@posthog/react": "^1.8.0",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@tailwindcss/vite": "^4.2.1",
"@tanstack/react-pacer": "^0.20.0",
"@tanstack/react-router": "^1.163.2",
"@tanstack/react-router-devtools": "^1.163.2",
"@vercel/node": "^5.2.0",
"@xyflow/react": "^12.10.0",
"ajv": "6.12.6",
"@xyflow/react": "^12.10.1",
"ajv": "8.18.0",
"ansi-to-html": "^0.7.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
Expand All @@ -51,61 +48,58 @@
"file-saver": "^2.0.5",
"file-select-dialog": "^1.5.4",
"line-column": "^1.0.2",
"lucide-react": "^0.503.0",
"marked": "^4.0.10",
"monaco-editor": "~0.40.0",
"lucide-react": "^0.575.0",
"monaco-editor": "~0.55.1",
"next-themes": "^0.4.6",
"parsimmon": "^1.18.1",
"posthog-js": "^1.304.0",
"posthog-js": "^1.353.1",
"radix-ui": "^1.4.3",
"react": "^18.3.1",
"react-cookie": "^4.1.1",
"react-cookie": "^8.0.1",
"react-dom": "^18.3.1",
"react-joyride": "^2.5.3",
"react-reflex": "^4.0.9",
"react-reflex": "^4.2.7",
"react-responsive-carousel": "^3.2.23",
"sjcl": "^1.0.8",
"sonner": "^2.0.7",
"string-to-color": "^2.2.2",
"string.prototype.replaceall": "^1.0.6",
"styled-components": "^6.1.14",
"tailwind-merge": "^3.2.0",
"tailwindcss": "^4.1.5",
"tailwind-merge": "^3.5.0",
"tailwindcss": "^4.2.1",
"typeface-roboto-mono": "^1.1.13",
"use-deep-compare": "^1.1.0",
"use-deep-compare-effect": "^1.8.1",
"visjs-network": "^4.24.11",
"yaml": "^2.0.1",
"zod": "^4.2.1"
"zod": "^4.3.6"
},
"devDependencies": {
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/d3-scale-chromatic": "^3.0.0",
"@types/dagre": "^0.7.53",
"@types/file-saver": "^2.0.5",
"@types/jest": "^29.5.0",
"@types/line-column": "^1.0.0",
"@types/node": "^22.15.3",
"@types/node": "^25.3.0",
"@types/parsimmon": "^1.10.6",
"@types/react": "^18.3.1",
"@types/react-copy-to-clipboard": "^5.0.4",
"@types/react-dom": "^18.3.1",
"@types/sjcl": "^1.0.30",
"@types/styled-components": "^5.1.26",
"@types/use-deep-compare-effect": "^1.5.1",
"@types/uuid": "^9.0.1",
"@vitejs/plugin-react": "^4.3.4",
"@types/uuid": "^11.0.0",
"@vitejs/plugin-react": "^5.1.4",
"cypress": "^12.9.0",
"cypress-wait-until": "^1.7.2",
"globals": "^15.14.0",
"oxfmt": "^0.28.0",
"oxlint": "^1.48.0",
"oxlint-tsgolint": "^0.14.0",
"oxfmt": "^0.35.0",
"oxlint": "^1.50.0",
"oxlint-tsgolint": "^0.15.0",
"tw-animate-css": "^1.2.8",
"typescript": "~5.7.3",
"vite": "^6.0.7",
"vite-plugin-svgr": "^4.3.0",
"typescript": "~5.9.3",
"vite": "^7.3.1",
"vite-plugin-svgr": "^4.5.0",
"vitest": "^2.1.8"
},
"browserslist": {
Expand Down
29 changes: 16 additions & 13 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import "react-reflex/styles.css";
import "typeface-roboto-mono/index.css"; // Import the Roboto Mono font.
import "./App.css";

import { PostHogProvider } from "@posthog/react";
import {
Outlet,
Expand All @@ -12,9 +8,13 @@ import {
} from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
import posthog from "posthog-js";
import { CookiesProvider } from "react-cookie";
import "react-reflex/styles.css";
import "typeface-roboto-mono/index.css"; // Import the Roboto Mono font.

import { ThemeProvider } from "@/components/ThemeProvider";

import "./App.css";
import { EmbeddedPlayground } from "./components/EmbeddedPlayground";
import { FullPlayground } from "./components/FullPlayground";
import { InlinePlayground } from "./components/InlinePlayground";
Expand Down Expand Up @@ -71,15 +71,18 @@ function App() {
return (
<>
<Toaster />
<PostHogProvider client={posthog}>
<ThemeProvider>
<PlaygroundUIThemed {...PLAYGROUND_UI_COLORS} forceDarkMode={isEmbeddedPlayground}>
<ConfirmDialogProvider>
<RouterProvider router={router} />
</ConfirmDialogProvider>
</PlaygroundUIThemed>
</ThemeProvider>
</PostHogProvider>
{/* @ts-ignore-error react-cookie's types are screwy; CI and (local and vercel) disagree about whether there's an error or not. */}
<CookiesProvider>
<PostHogProvider client={posthog}>
<ThemeProvider>
<PlaygroundUIThemed {...PLAYGROUND_UI_COLORS} forceDarkMode={isEmbeddedPlayground}>
<ConfirmDialogProvider>
<RouterProvider router={router} />
</ConfirmDialogProvider>
</PlaygroundUIThemed>
</ThemeProvider>
</PostHogProvider>
</CookiesProvider>
</>
);
}
Expand Down
109 changes: 61 additions & 48 deletions src/components/EditorDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import "react-reflex/styles.css";

import { TextRange } from "@authzed/spicedb-parser-js";
import Editor, { DiffEditor, useMonaco } from "@monaco-editor/react";
import { Editor, DiffEditor, useMonaco } from "@monaco-editor/react";
import { useDebouncedCallback } from "@tanstack/react-pacer/debouncer";
import { useNavigate, useLocation } from "@tanstack/react-router";
import lineColumn from "line-column";
import * as monaco from "monaco-editor";
import { useEffect, useMemo, useRef, useState } from "react";
import { flushSync } from "react-dom";
import "react-reflex/styles.css";

import { useMediaQuery } from "@/hooks/use-media-query";

Expand Down Expand Up @@ -428,55 +427,69 @@ export function EditorDisplay(props: EditorDisplayProps) {
props.services.problemService.stateKey,
]);

const Component = props.diff ? DiffEditor : Editor;
const extraProps = props.diff
? {
original: props.diff,
modified: currentItem?.editableContents,
language: languageName,
}
: {};

return (
<div>
{monacoReady && currentItem && (
<div className="w-full h-full">
<Component
key={`${currentItem.id}-${props.diff ? "diff" : ""}`}
height={
props.dimensions ? `${props.dimensions.height}px` : (props.defaultHeight ?? "40vh")
}
width={
props.dimensions ? `${props.dimensions.width}px` : (props.defaultWidth ?? "60vw")
}
defaultLanguage={languageName}
value={currentItem.editableContents}
theme={themeName}
onChange={handleEditorChange}
// TODO: this is weirdly typed because we're conditionally rendering
// a diff editor or a code editor and typescript doesn't know about that.
// It'd be better to separate this into two different components that
// reuse their internals.
// @ts-expect-error the mount handler is a no-op if the component is in diff mode
onMount={handleEditorMounted}
options={{
readOnly: props.isReadOnly || !!props.diff,
scrollbar: {
handleMouseWheel:
props.disableScrolling !== true && props.disableMouseWheelScrolling !== true,
vertical: props.disableScrolling ? "hidden" : undefined,
},
"semanticHighlighting.enabled": true,
fixedOverflowWidgets: true,
minimap: {
enabled: props.hideMinimap !== true,
},
fontSize: props.fontSize,
scrollBeyondLastLine:
props.scrollBeyondLastLine ?? (props.disableScrolling === true ? false : true),
}}
{...extraProps}
/>
{props.diff ? (
<DiffEditor
height={
props.dimensions ? `${props.dimensions.height}px` : (props.defaultHeight ?? "40vh")
}
width={
props.dimensions ? `${props.dimensions.width}px` : (props.defaultWidth ?? "60vw")
}
theme={themeName}
options={{
readOnly: props.isReadOnly || !!props.diff,
scrollbar: {
handleMouseWheel:
props.disableScrolling !== true && props.disableMouseWheelScrolling !== true,
vertical: props.disableScrolling ? "hidden" : undefined,
},
fixedOverflowWidgets: true,
minimap: {
enabled: props.hideMinimap !== true,
},
fontSize: props.fontSize,
scrollBeyondLastLine:
props.scrollBeyondLastLine ?? (props.disableScrolling === true ? false : true),
}}
original={props.diff}
modified={currentItem?.editableContents}
language={languageName}
/>
) : (
<Editor
height={
props.dimensions ? `${props.dimensions.height}px` : (props.defaultHeight ?? "40vh")
}
width={
props.dimensions ? `${props.dimensions.width}px` : (props.defaultWidth ?? "60vw")
}
defaultLanguage={languageName}
value={currentItem.editableContents}
theme={themeName}
onChange={handleEditorChange}
onMount={handleEditorMounted}
options={{
readOnly: props.isReadOnly || !!props.diff,
scrollbar: {
handleMouseWheel:
props.disableScrolling !== true && props.disableMouseWheelScrolling !== true,
vertical: props.disableScrolling ? "hidden" : undefined,
},
"semanticHighlighting.enabled": true,
fixedOverflowWidgets: true,
minimap: {
enabled: props.hideMinimap !== true,
},
fontSize: props.fontSize,
scrollBeyondLastLine:
props.scrollBeyondLastLine ?? (props.disableScrolling === true ? false : true),
}}
/>
)}
</div>
)}
</div>
Expand Down
Loading