From e6752a666bb1d8f54533280b1c51b5b4cfd638cd Mon Sep 17 00:00:00 2001 From: Akita Noek Date: Wed, 26 Jun 2024 15:55:59 -0600 Subject: [PATCH] Repaired internal goban test page, WIP initial progress on examples pages --- examples/examples.css | 82 +++++ examples/main.tsx | 809 ++++++++++++++++++++++++++++++++++++++++++ package.json | 3 + test/index.html | 62 +--- tsconfig.json | 2 +- webpack.config.js | 9 +- yarn.lock | 45 ++- 7 files changed, 947 insertions(+), 65 deletions(-) create mode 100644 examples/examples.css create mode 100644 examples/main.tsx diff --git a/examples/examples.css b/examples/examples.css new file mode 100644 index 00000000..69a562f4 --- /dev/null +++ b/examples/examples.css @@ -0,0 +1,82 @@ +html, body { + margin: 0; + background-color: #333; + color: #aaa; +} +.Goban { + margin-left: 1rem; + margin-top: 1rem; + position: relative; + display: inline-block; +} + +.StoneLayer, .ShadowLayer, .PenLayer { + position: absolute; + left: 0; + right: 0; +} + +.ShadowLayer { + z-index: 5; +} +.StoneLayer { + z-index: 10; +} +.PenLayer { + z-index: 20; +} + +.inline-block { + display: inline-block; +} + +.setting span { + display: inline-block; + min-width: 7rem; +} + +.move-tree-container { + display: inline-block; + background-color: gray; + height: 20rem; + width: 30rem; + margin: 1rem; + resize: both; + overflow: scroll; +} + +svg text { + font-family: Verdana, Arial, sans-serif; + text-anchor: middle; + font-weight: bold; + user-select: none; +} + +a { + color: hsl(200, 100%, 50%); +} + +.Main { + display: flex; + flex-direction: row; + width: 100vw; + height: 100vh; +} + +.LeftNav { + flex-basis: 10rem; + flex-grow: 0; + flex-shrink: 0; + display: flex; + flex-direction: column; + +} + +.Main-content { + flex-grow: 1; + +} + +.font-mono { + font-family: monospace; +} \ No newline at end of file diff --git a/examples/main.tsx b/examples/main.tsx new file mode 100644 index 00000000..faf24018 --- /dev/null +++ b/examples/main.tsx @@ -0,0 +1,809 @@ +/* + * Copyright (C) Online-Go.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as React from "react"; +import * as ReactDOM from "react-dom/client"; +import { + Route, + Routes, + BrowserRouter, + Link, + //Navigate, + //useNavigate, +} from "react-router-dom"; + +import { EventEmitter } from "eventemitter3"; +import { + GobanConfig, + ColoredCircle, + GobanCanvas, + CanvasRendererGobanConfig, + SVGRenderer, + SVGRendererGobanConfig, + THEMES, + Goban, +} from "../src"; + +import { MoveTreePenMarks } from "../src/engine/MoveTree"; + +let stored_config: GobanConfig = {}; +try { + stored_config = JSON.parse(localStorage.getItem("config") || "{}"); +} catch (e) {} + +Goban.setCallbacks({ + getSelectedThemes: () => ({ + board: "Kaya", + //board: "Anime", + + white: "Plain", + black: "Plain", + //white: "Glass", + //black: "Glass", + //white: "Worn Glass", + //black: "Worn Glass", + //white: "Night", + //black: "Night", + //white: "Shell", + //black: "Slate", + //white: "Anime", + //black: "Anime", + //white: "Custom", + //black: "Custom", + }), + + customWhiteStoneUrl: () => { + return "https://cdn.online-go.com/goban/anime_white.svg"; + }, + customBlackStoneUrl: () => { + return "https://cdn.online-go.com/goban/anime_black.svg"; + }, +}); + +const base_config: GobanConfig = Object.assign( + { + interactive: true, + mode: "puzzle", + //"player_id": 0, + //"server_socket": null, + square_size: 25, + original_sgf: ` + (;FF[4] + CA[UTF-8] + GM[1] + GN[ai japanese hc 9] + PC[https://online-go.com/review/290167] + PB[Black] + PW[White] + BR[3p] + WR[3p] + TM[0]OT[0 none] + RE[?] + SZ[19] + KM[6.5] + RU[Japanese] + + ;B[sh] + ;W[sk] + ;B[sn] + ;W[sp] + ) + `, + draw_top_labels: true, + draw_left_labels: true, + draw_right_labels: true, + draw_bottom_labels: true, + bounds: { + left: 0, + right: 18, + top: 0, + bottom: 18, + }, + }, + stored_config, +); + +Goban.setCallbacks({ + //getCoordinateDisplaySystem: () => "1-1", + getCoordinateDisplaySystem: () => "A1", + getCDNReleaseBase: () => "", +}); + +function save() { + localStorage.setItem("config", JSON.stringify(base_config)); +} + +function clear() { + localStorage.remove("config"); +} +(window as any)["clear"] = clear; +/* + "getPuzzlePlacementSetting": () => { + return {"mode": "play"}; + }, + */ + +const fiddler = new EventEmitter(); + +function GobanTestPage(): JSX.Element { + const [_update, _setUpdate] = React.useState(1); + const [svg_or_canvas, setSVGOrCanvas] = React.useState("svg"); + function forceUpdate() { + _setUpdate(_update + 1); + } + function redraw() { + save(); + forceUpdate(); + fiddler.emit("redraw"); + } + + return ( +
+
+
+
+ {svg_or_canvas} mode:{" "} + +
+ +
+ Square size: + { + let ss = Math.max(1, parseInt(ev.target.value)); + //console.log(ss); + if (!ss) { + ss = 1; + } + base_config.square_size = ss; + forceUpdate(); + fiddler.emit("setSquareSize", ss); + }} + /> +
+ +
+ Top labels: + { + base_config.draw_top_labels = ev.target.checked; + redraw(); + }} + /> +
+ +
+ Left labels: + { + base_config.draw_left_labels = ev.target.checked; + redraw(); + }} + /> +
+
+ Right labels: + { + base_config.draw_right_labels = ev.target.checked; + redraw(); + }} + /> +
+
+ Bottom labels: + { + base_config.draw_bottom_labels = ev.target.checked; + redraw(); + }} + /> +
+
+
+
+ Top bounds: + { + if (base_config.bounds) { + base_config.bounds.top = parseInt(ev.target.value); + } + redraw(); + }} + /> +
+
+ Left bounds: + { + if (base_config.bounds) { + base_config.bounds.left = parseInt(ev.target.value); + } + redraw(); + }} + /> +
+
+ Right bounds: + { + if (base_config.bounds) { + base_config.bounds.right = parseInt(ev.target.value); + } + redraw(); + }} + /> +
+
+ Bottom bounds: + { + if (base_config.bounds) { + base_config.bounds.bottom = parseInt(ev.target.value); + } + redraw(); + }} + /> +
+
+
+ + {/*false && */} + {Array.from( + Array( + // 20 + 0, + ), + ).map((_, idx) => + svg_or_canvas === "svg" ? ( + + ) : ( + + ), + )} + {true && (svg_or_canvas === "svg" ? : )} +
+ ); +} + +interface ReactGobanProps {} + +function ReactGoban( + ctor: { new (x: CanvasRendererGobanConfig | SVGRendererGobanConfig): GobanClass }, + props: ReactGobanProps, +): JSX.Element { + const [elapsed, setElapsed] = React.useState(0); + const container = React.useRef(null); + const move_tree_container = React.useRef(null); + let goban: Goban; + + React.useEffect(() => { + const config: CanvasRendererGobanConfig | SVGRendererGobanConfig = Object.assign( + {}, + base_config, + { + board_div: container.current || undefined, + move_tree_container: move_tree_container.current || undefined, + }, + ); + + goban = new ctor(config); + + goban.showMessage("loading", { foo: "bar" }, 1000); + + const heatmap: number[][] = []; + for (let i = 0; i < 19; i++) { + heatmap[i] = []; + for (let j = 0; j < 19; j++) { + heatmap[i][j] = 0.0; + } + } + + fiddler.on("setSquareSize", (ss) => { + const start = Date.now(); + goban.setSquareSize(ss); + const end = Date.now(); + console.log("SSS time: ", end - start); + }); + + fiddler.on("redraw", () => { + const start = Date.now(); + goban.draw_top_labels = !!base_config.draw_top_labels; + goban.draw_left_labels = !!base_config.draw_left_labels; + goban.draw_right_labels = !!base_config.draw_right_labels; + goban.draw_bottom_labels = !!base_config.draw_bottom_labels; + goban.config.draw_top_labels = !!base_config.draw_top_labels; + goban.config.draw_left_labels = !!base_config.draw_left_labels; + goban.config.draw_right_labels = !!base_config.draw_right_labels; + goban.config.draw_bottom_labels = !!base_config.draw_bottom_labels; + if (base_config.bounds) { + goban.setBounds(base_config.bounds); + } + goban.redraw(true); + const end = Date.now(); + console.log("Redraw time: ", end - start); + }); + + let i = 0; + const start = Date.now(); + //const NUM_MOVES = 300; + const NUM_MOVES = 20; + const interval = setInterval(() => { + i++; + if (i >= NUM_MOVES) { + if (i === NUM_MOVES) { + const end = Date.now(); + console.log("Done in ", end - start); + setElapsed(end - start); + + // setup iso branch + const cur = goban.engine.cur_move; + goban.engine.place(18, 16); + goban.engine.place(18, 17); + goban.engine.place(17, 16); + goban.engine.place(17, 17); + + goban.engine.place(18, 2); + goban.engine.place(18, 1); + + goban.engine.jumpTo(cur); + goban.engine.place(17, 16); + goban.engine.place(17, 17); + goban.engine.place(18, 16); + goban.engine.place(18, 17); + + goban.engine.place(18, 1); + goban.engine.place(18, 2); + + /* test stuff for various features */ + { + heatmap[18][18] = 1.0; + heatmap[18][17] = 0.5; + heatmap[18][16] = 0.1; + goban.setHeatmap(heatmap, true); + + // blue move + const circle: ColoredCircle = { + //move: branch.moves[0], + move: { x: 16, y: 17 }, + color: "rgba(0,0,0,0)", + }; + const circle2: ColoredCircle = { + //move: branch.moves[0], + move: { x: 17, y: 17 }, + color: "rgba(0,0,0,0)", + }; + + goban.setMark(16, 17, "blue_move", true); + goban.setMark(17, 17, "blue_move", true); + circle.border_width = 0.2; + circle.border_color = "rgb(0, 130, 255)"; + circle.color = "rgba(0, 130, 255, 0.7)"; + circle2.border_width = 0.2; + circle2.border_color = "rgb(0, 130, 255)"; + circle2.color = "rgba(0, 130, 255, 0.7)"; + goban.setColoredCircles([circle, circle2], false); + } + + // Shapes & labels + goban.setMark(15, 16, "triangle", true); + goban.setMark(15, 15, "square", true); + goban.setMark(15, 14, "circle", true); + goban.setMark(15, 13, "cross", true); + goban.setMark(15, 12, "top", true); + goban.setSubscriptMark(15, 12, "sub", true); + goban.setSubscriptMark(16, 12, "sub", true); + goban.setMark(15, 11, "A", true); + + // pen marks + const marks: MoveTreePenMarks = []; + + { + const points: number[] = []; + for (let i = 0; i < 50; ++i) { + points.push(4 + i / 10); + points.push(9 + Math.sin(i) * 19); + } + + marks.push({ + color: "#ff8800", + points, + }); + } + { + const points: number[] = []; + for (let i = 0; i < 50; ++i) { + points.push(9 + i / 10); + points.push(20 + Math.sin(i) * 19); + } + + marks.push({ + color: "#3388ff", + points, + }); + } + + //goban.drawPenMarks(marks); + } + clearInterval(interval); + return; + } + const x = Math.floor(i / 19); + const y = Math.floor(i % 19); + goban.engine.place(x, y); + if (i === 3) { + /* + goban.setMark(x, y, "blue_move", true); + + const circle: ColoredCircle = { + //move: branch.moves[0], + move: { x, y }, + color: "rgba(0,0,0,0)", + }; + + // blue move + goban.setMark(x, y, "blue_move", true); + circle.border_width = 0.5; + circle.border_color = "rgb(0, 130, 255)"; + circle.color = "rgba(0, 130, 255, 0.7)"; + goban.setColoredCircles([circle], false); + */ + } + //goban.redraw(true); + }, 1); + + return () => { + goban.destroy(); + }; + }, [container]); + + return ( + + + + {elapsed > 0 &&
Elapsed: {elapsed}ms
} +
+
+
+
+
+
+ + ); +} + +function StoneSamples(): JSX.Element { + const div = React.useRef(null); + + React.useEffect(() => { + if (!div.current) { + console.log("no current"); + return; + } + + { + const white_theme = "Shell"; + const black_theme = "Slate"; + //const white_theme = "Glass"; + //const black_theme = "Glass"; + //const white_theme = "Worn Glass"; + //const black_theme = "Worn Glass"; + //const white_theme = "Night"; + //const black_theme = "Night"; + //const white_theme = "Plain"; + //const black_theme = "Plain"; + const radius = 80; + const cx = radius; + const cy = radius; + const size = radius * 2; + + const foo = document.createElement("div"); + + (div.current as any)?.appendChild(foo); + + { + const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + svg.setAttribute("width", size.toFixed(0)); + svg.setAttribute("height", size.toFixed(0)); + const theme = new THEMES["black"][black_theme](); + const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); + svg.appendChild(defs); + + const black_stones = theme.preRenderBlackSVG(defs, radius, 123, () => {}); + + const g = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svg.appendChild(g); + //for (let i = 0; i < black_stones.length; i++) { + for (let i = 0; i < 1; i++) { + theme.placeBlackStoneSVG( + g, + undefined, + black_stones[i], + cx + i * radius * 2, + cy, + radius, + ); + } + + foo.appendChild(svg); + } + + { + const theme = new THEMES["white"][white_theme](); + const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); + const white_stones = theme.preRenderWhiteSVG(defs, radius, 123, () => {}); + + const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + svg.setAttribute("width", (white_stones.length * size).toFixed(0)); + svg.setAttribute("height", size.toFixed(0)); + svg.appendChild(defs); + + const g = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svg.appendChild(g); + for (let i = 0; i < white_stones.length; i++) { + //for (let i = 0; i < 1; i++) { + theme.placeWhiteStoneSVG( + g, + undefined, + white_stones[i], + cx + i * radius * 2, + cy, + radius, + ); + } + + foo.appendChild(svg); + } + } + + { + const radius = 20; + const cx = radius; + const cy = radius; + const size = radius * 2; + + for (const black_theme in THEMES["black"]) { + const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + svg.setAttribute("width", size.toFixed(0)); + svg.setAttribute("height", size.toFixed(0)); + const theme = new THEMES["black"][black_theme](); + const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); + svg.appendChild(defs); + + const black_stones = theme.preRenderBlackSVG(defs, radius, 123, () => {}); + + const g = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svg.appendChild(g); + //for (let i = 0; i < black_stones.length; i++) { + for (let i = 0; i < 1; i++) { + theme.placeBlackStoneSVG( + g, + undefined, + black_stones[i], + cx + i * radius * 2, + cy, + radius, + ); + } + + const label = document.createElement("label"); + label.textContent = black_theme; + label.setAttribute( + "style", + "display: inline-block; width: 100px; margin-right: 1rem; text-align: right;", + ); + const d = document.createElement("span"); + d.appendChild(label); + d.appendChild(svg); + + (div.current as any)?.appendChild(d); + } + + const br = document.createElement("br"); + (div.current as any)?.appendChild(br); + + for (const white_theme in THEMES["white"]) { + const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + svg.setAttribute("width", size.toFixed(0)); + svg.setAttribute("height", size.toFixed(0)); + const theme = new THEMES["white"][white_theme](); + const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); + svg.appendChild(defs); + + const white_stones = theme.preRenderWhiteSVG(defs, radius, 123, () => {}); + + const g = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svg.appendChild(g); + //for (let i = 0; i < white_stones.length; i++) { + for (let i = 0; i < 1; i++) { + theme.placeWhiteStoneSVG( + g, + undefined, + white_stones[i], + cx + i * radius * 2, + cy, + radius, + ); + } + + const label = document.createElement("label"); + label.textContent = white_theme; + label.setAttribute( + "style", + "display: inline-block; width: 100px; margin-right: 1rem; text-align: right;", + ); + const d = document.createElement("span"); + d.appendChild(label); + d.appendChild(svg); + + (div.current as any)?.appendChild(d); + } + } + }, [div]); + + return
; +} + +function ReactGobanCanvas(props: ReactGobanProps): JSX.Element { + return ReactGoban(GobanCanvas, props); +} + +function ReactGobanSVG(props: ReactGobanProps): JSX.Element { + return ReactGoban(SVGRenderer, props); +} + +function Main(props: { children: any }): JSX.Element { + return
{props.children}
; +} + +//import { LiveProvider, LiveEditor, LivePreview, LiveError } from "react-live"; + +const scope = { + Goban: SVGRenderer, +}; + +const code = ` +new Goban({ + board_div: goban_container +}); +`; + +function Examples(): JSX.Element { + /* + return ( +
+ +
+ + + +
+
+
+
+ ); + */ + return ( +
+ +
+ ); +} + +function CodeExample({ + source, + scope, +}: { + source: string; + scope: { [key: string]: any }; +}): JSX.Element { + const [output, setOutput] = React.useState(null); + const goban_container = React.useRef(null); + + React.useEffect(() => { + if (!goban_container.current) { + return; + } + + try { + const context = { ...scope, goban_container: goban_container.current }; + + setOutput( + Function( + ...Object.keys(context), + '"use strict"; ' + source, + )(...Object.values(context)), + ); + } catch (e) { + console.error(e); + } + }, [source, scope, goban_container]); + + return ( +
+
{code}
+
+
{output}
+
+ ); +} + +export function LeftNav(): JSX.Element { + return ( +
+ Home + Examples + Test page +
+ ); +} + +export const routes = ( + <> + +
+ +
+ + } /> + } /> + } /> + +
+
+
+ +); + +const react_root = ReactDOM.createRoot(document.getElementById("test-content") as Element); +//react_root.render(); +//react_root.render({routes}); +react_root.render(routes); diff --git a/package.json b/package.json index be7de037..1c81a944 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,8 @@ "prettier-eslint": "^16.1.2", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-router": "^6.23.1", + "react-router-dom": "^6.23.1", "svg-inline-loader": "0.8.2", "thread-loader": "^3.0.4", "ts-jest": "^29.1.4", @@ -86,6 +88,7 @@ "typedoc": "^0.25.13", "typedoc-plugin-missing-exports": "^2.3.0", "typescript": "=5.5.2", + "stylus": "^0.63.0", "utf-8-validate": "^6.0.3", "webpack": "^5.89.0", "webpack-cli": "^5.1.4", diff --git a/test/index.html b/test/index.html index 759cc122..a53567d4 100644 --- a/test/index.html +++ b/test/index.html @@ -7,68 +7,10 @@ > - - +
- + diff --git a/tsconfig.json b/tsconfig.json index b4b65227..5bd30e8d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -34,7 +34,7 @@ "jsx": "react" }, "files": ["src/index.ts", "src/engine/index.ts", "jest.config.ts"], - "include": ["test/**/*.ts", "scripts/**/*.ts"], + "include": ["test/**/*.ts", "scripts/**/*.ts", "examples/**/*.tsx"], "ts-node": { "require": ["tsconfig-paths/register"] } diff --git a/webpack.config.js b/webpack.config.js index 7c626f4b..ca7fa19f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -117,6 +117,7 @@ module.exports = (env, argv) => { target: "web", entry: { goban: "./src/index.ts", + examples: "./examples/main.tsx", }, output: { @@ -167,9 +168,13 @@ module.exports = (env, argv) => { static: [ path.join(__dirname, "assets"), path.join(__dirname, "test"), - path.join(__dirname, "lib"), + path.join(__dirname, "build"), + path.join(__dirname, "examples"), + path.join(__dirname, "src"), ], - + historyApiFallback: { + index: "index.html", + }, devMiddleware: { index: true, mimeTypes: { phtml: "text/html" }, diff --git a/yarn.lock b/yarn.lock index 5d2e126e..99b04684 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adobe/css-tools@~4.3.3": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.3.tgz#90749bde8b89cd41764224f5aac29cd4138f75ff" + integrity sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ== + "@ampproject/remapping@^2.2.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -1087,6 +1092,11 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== +"@remix-run/router@1.17.0": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.17.0.tgz#fbb0add487478ef42247d5942e7a5d8a2e20095f" + integrity sha512-2D6XaHEVvkCn682XBnipbJjgZUU7xjLtA4dGJRBVUKpEaDYOZMENZoZjAOSb7qirxt5RupjzZxz4fK2FO+EFPw== + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -3655,7 +3665,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^7.1.3, glob@^7.1.4: +glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -5713,6 +5723,21 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== +react-router-dom@^6.23.1: + version "6.24.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.24.0.tgz#ec49dc38c49bb9bd25b310a8ae849268d3085e1d" + integrity sha512-960sKuau6/yEwS8e+NVEidYQb1hNjAYM327gjEyXlc6r3Skf2vtwuJ2l7lssdegD2YjoKG5l8MsVyeTDlVeY8g== + dependencies: + "@remix-run/router" "1.17.0" + react-router "6.24.0" + +react-router@6.24.0, react-router@^6.23.1: + version "6.24.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.24.0.tgz#aa46648f26b6525e07f908ad3e1ad2e68d131155" + integrity sha512-sQrgJ5bXk7vbcC4BxQxeNa5UmboFm35we1AFK0VvQaz9g0LzxEIuLOhHIoZ8rnu9BO21ishGeL9no1WB76W/eg== + dependencies: + "@remix-run/router" "1.17.0" + react@^18.2.0: version "18.3.1" resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" @@ -5900,6 +5925,11 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sax@~1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0" + integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA== + saxes@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" @@ -6166,7 +6196,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.7.4: +source-map@^0.7.3, source-map@^0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== @@ -6353,6 +6383,17 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +stylus@^0.63.0: + version "0.63.0" + resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.63.0.tgz#511e8d56f2005b09010fbc1f62561c7b6f72a490" + integrity sha512-OMlgrTCPzE/ibtRMoeLVhOY0RcNuNWh0rhAVqeKnk/QwcuUKQbnqhZ1kg2vzD8VU/6h3FoPTq4RJPHgLBvX6Bw== + dependencies: + "@adobe/css-tools" "~4.3.3" + debug "^4.3.2" + glob "^7.1.6" + sax "~1.3.0" + source-map "^0.7.3" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"