+
+
+
Topos Prototype
+
+
This is Topos, an experimental live coding platform.
+
Have fun, press Enter/Space to get started!
+
+
+
+
+
+
+
+
+ -
+ 1
+
+ -
+ 2
+
+ -
+ 3
+
+ -
+ 4
+
+ -
+ 5
+
+ -
+ 6
+
+ -
+ 7
+
+ -
+ 8
+
+ -
+ 9
+
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..b4e0111
--- /dev/null
+++ b/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "topos",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "preview": "vite preview"
+ },
+ "devDependencies": {
+ "typescript": "^5.0.2",
+ "vite": "^4.4.5"
+ },
+ "dependencies": {
+ "@codemirror/lang-javascript": "^6.1.9",
+ "@replit/codemirror-vim": "^6.0.14",
+ "autoprefixer": "^10.4.14",
+ "codemirror": "^6.0.1",
+ "postcss": "^8.4.27",
+ "tailwindcss": "^3.3.3",
+ "zzfx": "^1.2.0"
+ }
+}
diff --git a/postcss.config.js b/postcss.config.js
new file mode 100644
index 0000000..2e7af2b
--- /dev/null
+++ b/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/src/API.ts b/src/API.ts
new file mode 100644
index 0000000..ef3671d
--- /dev/null
+++ b/src/API.ts
@@ -0,0 +1,124 @@
+import { Editor } from "./main";
+import { tryEvaluate } from "./Evaluator";
+import { ZZFX, zzfx } from "zzfx";
+
+
+export class UserAPI {
+
+ variables: { [key: string]: any } = {}
+ globalGain: GainNode
+ audioNodes: AudioNode[] = []
+
+ constructor(public app: Editor) {
+ this.globalGain = this.app.audioContext.createGain()
+ // Give default parameters to the reverb
+
+ this.globalGain.gain.value = 0.2;
+ this.globalGain.connect(this.app.audioContext.destination)
+ }
+
+ private registerNode
(node: T): T{
+ this.audioNodes.push(node)
+ return node
+ }
+
+ killAll() {
+ this.audioNodes.forEach(node => {
+ node.disconnect()
+ })
+ }
+
+ var(name: string, value: any) {
+ this.variables[name] = value
+ }
+ get(name: string) { return this.variables[name] }
+
+ pick(array: T[]): T { return array[Math.floor(Math.random() * array.length)] }
+
+ almostNever() { return Math.random() > 0.9 }
+ sometimes() { return Math.random() > 0.5 }
+ rarely() { return Math.random() > 0.75 }
+ often() { return Math.random() > 0.25 }
+ almostAlways() { return Math.random() > 0.1 }
+ randInt(min: number, max: number) { return Math.floor(Math.random() * (max - min + 1)) + min }
+
+ // Iterators
+ get i() { return this.app.universes[this.app.selected_universe].global.evaluations }
+ e(index:number) { return this.app.universes[this.app.selected_universe].locals[index].evaluations }
+
+
+ // Script launcher: can launch any number of scripts
+ script(...args: number[]): void {
+ args.forEach(arg => { tryEvaluate(this.app, this.app.universes[this.app.selected_universe].locals[arg]) })
+ }
+
+ // Small ZZFX interface for playing with this synth
+ zzfx(...thing: number[]) {
+ zzfx(...thing);
+ }
+
+ on(beat: number = 1, pulse: number = 1): boolean {
+ return this.app.clock.time_position.beat === beat && this.app.clock.time_position.pulse === pulse
+ }
+
+ pulse(pulse: number) {
+ return this.app.clock.time_position.pulse === pulse
+ }
+
+ modPulse(pulse: number) {
+ return this.app.clock.time_position.pulse % pulse === 0
+ }
+
+ mute() {
+ this.globalGain.gain.value = 0
+ }
+
+ volume(volume: number) {
+ this.globalGain.gain.value = volume
+ }
+ vol = this.volume
+
+
+ beep(
+ frequency: number = 400, duration: number = 0.2,
+ type: OscillatorType = "sine", filter: BiquadFilterType = "lowpass",
+ cutoff: number = 10000, resonance: number = 1,
+ ) {
+ const oscillator = this.registerNode(this.app.audioContext.createOscillator());
+ const gainNode = this.registerNode(this.app.audioContext.createGain());
+ const limiterNode = this.registerNode(this.app.audioContext.createDynamicsCompressor());
+ const filterNode = this.registerNode(this.app.audioContext.createBiquadFilter());
+ // All this for the limiter
+ limiterNode.threshold.setValueAtTime(-5.0, this.app.audioContext.currentTime);
+ limiterNode.knee.setValueAtTime(0, this.app.audioContext.currentTime);
+ limiterNode.ratio.setValueAtTime(20.0, this.app.audioContext.currentTime);
+ limiterNode.attack.setValueAtTime(0.001, this.app.audioContext.currentTime);
+ limiterNode.release.setValueAtTime(0.05, this.app.audioContext.currentTime);
+
+
+ // Filter
+ filterNode.type = filter;
+ filterNode.frequency.value = cutoff;
+ filterNode.Q.value = resonance;
+
+
+ oscillator.type = type;
+ oscillator.frequency.value = frequency || 400;
+ gainNode.gain.value = 0.25;
+ oscillator
+ .connect(filterNode)
+ .connect(gainNode)
+ .connect(limiterNode)
+ .connect(this.globalGain)
+ oscillator.start();
+ gainNode.gain.exponentialRampToValueAtTime(0.00001, this.app.audioContext.currentTime + duration);
+ oscillator.stop(this.app.audioContext.currentTime + duration);
+ // Clean everything after a node has been played
+ oscillator.onended = () => {
+ oscillator.disconnect();
+ gainNode.disconnect();
+ filterNode.disconnect();
+ limiterNode.disconnect();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/AppSettings.ts b/src/AppSettings.ts
new file mode 100644
index 0000000..c12654f
--- /dev/null
+++ b/src/AppSettings.ts
@@ -0,0 +1,94 @@
+export type Universes = { [key: string]: Universe }
+
+export interface Universe {
+ global: File
+ locals: { [key: number]: File }
+ init: File
+}
+
+export interface File {
+ candidate: string
+ committed: string
+ evaluations: number
+}
+
+export interface Settings {
+ vimMode: boolean
+ theme: string
+ font: string
+ universes: Universes
+}
+
+export const template_universe = {
+ global: { candidate: "", committed: "", evaluations: 0 },
+ locals: {
+ 1: { candidate: "", committed: "", evaluations: 0},
+ 2: { candidate: "", committed: "", evaluations: 0},
+ 3: { candidate: "", committed: "", evaluations: 0},
+ 4: { candidate: "", committed: "", evaluations: 0},
+ 5: { candidate: "", committed: "", evaluations: 0},
+ 6: { candidate: "", committed: "", evaluations: 0},
+ 7: { candidate: "", committed: "", evaluations: 0},
+ 8: { candidate: "", committed: "", evaluations: 0},
+ 9: { candidate: "", committed: "", evaluations: 0},
+ },
+ init: { candidate: "", committed: "", evaluations: 0 }
+}
+
+export const template_universes = {
+ "Default": {
+ global: { candidate: "", committed: "", evaluations: 0 },
+ locals: {
+ 1: { candidate: "", committed: "", evaluations: 0},
+ 2: { candidate: "", committed: "", evaluations: 0},
+ 3: { candidate: "", committed: "", evaluations: 0},
+ 4: { candidate: "", committed: "", evaluations: 0},
+ 5: { candidate: "", committed: "", evaluations: 0},
+ 6: { candidate: "", committed: "", evaluations: 0},
+ 7: { candidate: "", committed: "", evaluations: 0},
+ 8: { candidate: "", committed: "", evaluations: 0},
+ 9: { candidate: "", committed: "", evaluations: 0},
+ },
+ init: { candidate: "", committed: "", evaluations: 0 }
+ }
+}
+
+
+export class AppSettings {
+
+ public vimMode: boolean = false
+ public theme: string = "materialDark"
+ public font: string = "SpaceMono"
+ public universes: Universes
+
+ constructor() {
+
+ const settingsFromStorage = JSON.parse(localStorage.getItem('topos') || "{}");
+
+ if (settingsFromStorage && Object.keys(settingsFromStorage).length !== 0) {
+ // let settings = JSON.parse(localStorage.getItem("topos") as string)
+ this.vimMode = settingsFromStorage.vimMode
+ this.theme = settingsFromStorage.theme
+ this.font = settingsFromStorage.font
+ this.universes = settingsFromStorage.universes
+ } else {
+ this.universes = template_universes
+ }
+
+ }
+
+
+ get data(): Settings {
+ return {
+ vimMode: this.vimMode,
+ theme: this.theme,
+ font: this.font,
+ universes: this.universes
+ }
+ }
+
+ saveApplicationToLocalStorage(universes: Universes): void{
+ this.universes = universes;
+ localStorage.setItem('topos', JSON.stringify(this.data))
+ }
+}
\ No newline at end of file
diff --git a/src/Clock.ts b/src/Clock.ts
new file mode 100644
index 0000000..7a4e6a8
--- /dev/null
+++ b/src/Clock.ts
@@ -0,0 +1,57 @@
+// @ts-ignore
+import { TransportNode } from './TransportNode';
+
+import { Editor } from './main';
+
+export interface TimePosition {
+ bar: number
+ beat: number
+ pulse: number
+}
+
+export class Clock {
+
+ evaluations: number
+ transportNode: TransportNode
+ bpm: number
+ time_signature: number[]
+ time_position: TimePosition
+ ppqn: number
+
+ constructor(public app: Editor, ctx: AudioContext) {
+ this.time_position = { bar: 0, beat: 0, pulse: 0 }
+ this.bpm = 120;
+ this.time_signature = [4, 4];
+ this.ppqn = 48;
+ this.evaluations = 0;
+ ctx.audioWorklet.addModule('src/TransportProcessor.js').then((e) => {
+ this.transportNode = new TransportNode(ctx, {}, this.app);
+ this.transportNode.connect(ctx.destination);
+ return e
+ })
+ .catch((e) => {
+ console.log('Error loading TransportProcessor.js:', e);
+ })
+ }
+
+ start(): void {
+ // Check if the clock is already running
+ if (this.transportNode?.state === 'running') {
+ console.log('Already started')
+ } else {
+ this.app.audioContext.resume()
+ this.transportNode?.start();
+ }
+ }
+
+ pause(): void {
+ this.transportNode?.pause();
+ }
+
+ stop(): void {
+ this.transportNode?.stop();
+ }
+
+ // Public methods
+ public toString(): string { return `` }
+}
\ No newline at end of file
diff --git a/src/EditorSetup.ts b/src/EditorSetup.ts
new file mode 100644
index 0000000..879602c
--- /dev/null
+++ b/src/EditorSetup.ts
@@ -0,0 +1,113 @@
+import { javascript } from "@codemirror/lang-javascript"
+import {
+ keymap,
+ highlightSpecialChars,
+ drawSelection,
+ highlightActiveLine,
+ dropCursor,
+ rectangularSelection,
+ lineNumbers,
+ crosshairCursor,
+ highlightActiveLineGutter
+} from "@codemirror/view"
+import {
+ Extension,
+ EditorState
+} from "@codemirror/state"
+import {
+ defaultHighlightStyle,
+ syntaxHighlighting,
+ indentOnInput,
+ bracketMatching,
+ foldKeymap
+} from "@codemirror/language"
+import {
+ defaultKeymap,
+ historyKeymap,
+ history,
+} from "@codemirror/commands"
+import {
+ searchKeymap,
+ highlightSelectionMatches
+} from "@codemirror/search"
+import {
+ autocompletion,
+ completionKeymap,
+ closeBrackets,
+ closeBracketsKeymap
+} from "@codemirror/autocomplete"
+import {
+ lintKeymap
+} from "@codemirror/lint"
+
+import { materialDark } from "./themes/materialDark"
+
+// (The superfluous function calls around the list of extensions work
+// around current limitations in tree-shaking software.)
+
+/// This is an extension value that just pulls together a number of
+/// extensions that you might want in a basic editor. It is meant as a
+/// convenient helper to quickly set up CodeMirror without installing
+/// and importing a lot of separate packages.
+///
+/// Specifically, it includes...
+///
+/// - [the default command bindings](#commands.defaultKeymap)
+/// - [line numbers](#view.lineNumbers)
+/// - [special character highlighting](#view.highlightSpecialChars)
+/// - [the undo history](#commands.history)
+/// - [a fold gutter](#language.foldGutter)
+/// - [custom selection drawing](#view.drawSelection)
+/// - [drop cursor](#view.dropCursor)
+/// - [multiple selections](#state.EditorState^allowMultipleSelections)
+/// - [reindentation on input](#language.indentOnInput)
+/// - [the default highlight style](#language.defaultHighlightStyle) (as fallback)
+/// - [bracket matching](#language.bracketMatching)
+/// - [bracket closing](#autocomplete.closeBrackets)
+/// - [autocompletion](#autocomplete.autocompletion)
+/// - [rectangular selection](#view.rectangularSelection) and [crosshair cursor](#view.crosshairCursor)
+/// - [active line highlighting](#view.highlightActiveLine)
+/// - [active line gutter highlighting](#view.highlightActiveLineGutter)
+/// - [selection match highlighting](#search.highlightSelectionMatches)
+/// - [search](#search.searchKeymap)
+/// - [linting](#lint.lintKeymap)
+///
+/// (You'll probably want to add some language package to your setup
+/// too.)
+///
+/// This extension does not allow customization. The idea is that,
+/// once you decide you want to configure your editor more precisely,
+/// you take this package's source (which is just a bunch of imports
+/// and an array literal), copy it into your own code, and adjust it
+/// as desired.
+
+export const editorSetup: Extension = (() => [
+ materialDark,
+ lineNumbers(),
+ javascript(),
+ highlightActiveLineGutter(),
+ highlightSpecialChars(),
+ history(),
+ // foldGutter(),
+ drawSelection(),
+ dropCursor(),
+ EditorState.allowMultipleSelections.of(true),
+ indentOnInput(),
+ syntaxHighlighting(defaultHighlightStyle, {fallback: true}),
+ bracketMatching(),
+ closeBrackets(),
+ autocompletion(),
+ rectangularSelection(),
+ crosshairCursor(),
+ highlightActiveLine(),
+ highlightSelectionMatches(),
+ keymap.of([
+ ...closeBracketsKeymap,
+ ...defaultKeymap,
+ ...searchKeymap,
+ ...historyKeymap,
+ ...foldKeymap,
+ ...completionKeymap,
+ ...lintKeymap
+ ])
+])()
\ No newline at end of file
diff --git a/src/Evaluator.ts b/src/Evaluator.ts
new file mode 100644
index 0000000..4eb0e28
--- /dev/null
+++ b/src/Evaluator.ts
@@ -0,0 +1,31 @@
+import type { Editor } from './main';
+import type { File } from './AppSettings';
+
+/* This mode of evaluation can only work if the whole buffer is evaluated at once */
+export const tryEvaluate = (application: Editor, code: File): void => {
+ let isValidCode: boolean;
+ try {
+ Function(`with (this) {try{${code.candidate}} catch (e) {console.log(e)}};`).call(application.api)
+ code.evaluations++;
+ isValidCode = true;
+ } catch (error) {
+ Function(`with (this) {try{${code.committed}} catch (e) {console.log(e)}};`).call(application.api)
+ code.evaluations++;
+ isValidCode = false;
+ }
+
+ if (isValidCode) {
+ code.committed = code.candidate;
+ } else {
+ evaluate(application, code);
+ }
+}
+
+export const evaluate = (application: Editor, code: File): void => {
+ Function(`with (this) {try{${code.committed}} catch (e) {console.log(e)}};`).call(application.api)
+ code.evaluations++;
+}
+
+export const evaluateCommand = (application: Editor, command: string): void => {
+ Function(`with (this) {try{${command}} catch (e) {console.log(e)}};`).call(application.api)
+}
\ No newline at end of file
diff --git a/src/Time.ts b/src/Time.ts
new file mode 100644
index 0000000..336aaa2
--- /dev/null
+++ b/src/Time.ts
@@ -0,0 +1,11 @@
+class Ligne {
+
+ public start: number
+ public end: number
+
+ constructor(start: number, end: number)) {
+ this.start = start
+ this.end = end
+ }
+
+}
\ No newline at end of file
diff --git a/src/TransportNode.js b/src/TransportNode.js
new file mode 100644
index 0000000..38d14d9
--- /dev/null
+++ b/src/TransportNode.js
@@ -0,0 +1,49 @@
+import { evaluate, tryEvaluate, evaluateCommand } from "./Evaluator";
+
+export class TransportNode extends AudioWorkletNode {
+
+ constructor(context, options, application) {
+ super(context, "transport", options);
+ this.app = application
+ this.port.addEventListener("message", this.handleMessage);
+ this.port.start();
+ /** @type {HTMLSpanElement} */
+ this.$clock = document.getElementById("clockviewer");
+ this.offset_time = 0;
+ }
+ /** @type {(this: MessagePort, ev: MessageEvent) => any} */
+ handleMessage = (message) => {
+ if (message.data === "bang") {
+ let info = this.convertTimeToBarsBeats(this.context.currentTime);
+ this.$clock.innerHTML = `${info.bar} / ${info.beat} / ${info.ppqn}`
+ this.app.clock.time_position = { bar: info.bar, beat: info.beat, pulse: info.ppqn }
+ tryEvaluate( this.app, this.app.global_buffer );
+ }
+ };
+
+ start() {
+ this.port.postMessage("start");
+ }
+
+ pause() {
+ this.port.postMessage("pause");
+ }
+
+ convertTimeToBarsBeats(currentTime) {
+ // Calculate the duration of one beat in seconds
+ const beatDuration = 60 / this.app.clock.bpm;
+
+ // Calculate the beat number
+ const beatNumber = (currentTime - this.offset_time) / beatDuration;
+
+ // Calculate the bar and beat numbers
+ const beatsPerBar = this.app.clock.time_signature[0];
+ const barNumber = Math.floor(beatNumber / beatsPerBar) + 1; // Adding 1 to make it 1-indexed
+ const beatWithinBar = Math.floor(beatNumber % beatsPerBar) + 1; // Adding 1 to make it 1-indexed
+
+ // Calculate the PPQN position
+ const ppqnPosition = Math.floor((beatNumber % 1) * this.app.clock.ppqn);
+ return { bar: barNumber, beat: beatWithinBar, ppqn: ppqnPosition };
+}
+
+}
\ No newline at end of file
diff --git a/src/TransportProcessor.js b/src/TransportProcessor.js
new file mode 100644
index 0000000..026eea9
--- /dev/null
+++ b/src/TransportProcessor.js
@@ -0,0 +1,37 @@
+class TransportProcessor extends AudioWorkletProcessor {
+
+ constructor(options) {
+ super(options);
+ this.port.addEventListener("message", this.handleMessage);
+ this.port.start();
+ this.interval = 0.001;
+ this.origin = currentTime;
+ this.next = this.origin + this.interval;
+ }
+
+ handleMessage = (message) => {
+ if (message.data === "start") {
+ this.origin = currentTime;
+ this.next = this.origin + this.interval;
+ } else if (message.data === "pause") {
+ this.next = Infinity;
+ } else if (message.data === "stop") {
+ this.origin = currentTime;
+ this.next = Infinity;
+ }
+ };
+
+ process(inputs, outputs, parameters) {
+ if (currentTime >= this.next) {
+ while (this.next < currentTime)
+ this.next += this.interval;
+ this.port.postMessage("bang");
+ }
+ return true;
+ }
+}
+
+registerProcessor(
+ "transport",
+ TransportProcessor
+);
\ No newline at end of file
diff --git a/src/highlightSelection.ts b/src/highlightSelection.ts
new file mode 100644
index 0000000..eae44d3
--- /dev/null
+++ b/src/highlightSelection.ts
@@ -0,0 +1,114 @@
+import { Decoration, DecorationSet } from "@codemirror/view"
+import { StateField, StateEffect, ChangeDesc } from "@codemirror/state"
+import { EditorView } from "@codemirror/view"
+import { invertedEffects } from "@codemirror/commands"
+import { Extension } from "@codemirror/state"
+
+
+function mapRange(range: {from: number, to: number}, change: ChangeDesc) {
+ let from = change.mapPos(range.from), to = change.mapPos(range.to)
+ return from < to ? {from, to} : undefined
+}
+
+const addHighlight = StateEffect.define<{from: number, to: number}>({
+ map: mapRange
+})
+
+const removeHighlight = StateEffect.define<{from: number, to: number}>({
+ map: mapRange
+})
+
+const highlight = Decoration.mark({
+ attributes: {style: `background-color: #ffad42`}
+})
+
+const highlightedRanges = StateField.define({
+ create() {
+ return Decoration.none
+ },
+ update(ranges, tr) {
+ ranges = ranges.map(tr.changes)
+ for (let e of tr.effects) {
+ if (e.is(addHighlight))
+ ranges = addRange(ranges, e.value)
+ else if (e.is(removeHighlight))
+ ranges = cutRange(ranges, e.value)
+ }
+ return ranges
+ },
+ provide: field => EditorView.decorations.from(field)
+})
+
+function cutRange(ranges: DecorationSet, r: {from: number, to: number}) {
+ let leftover: any[] = []
+ ranges.between(r.from, r.to, (from, to, deco) => {
+ if (from < r.from) leftover.push(deco.range(from, r.from))
+ if (to > r.to) leftover.push(deco.range(r.to, to))
+ })
+ return ranges.update({
+ filterFrom: r.from,
+ filterTo: r.to,
+ filter: () => false,
+ add: leftover
+ })
+}
+
+function addRange(ranges: DecorationSet, r: {from: number, to: number}) {
+ ranges.between(r.from, r.to, (from, to) => {
+ if (from < r.from) r = {from, to: r.to}
+ if (to > r.to) r = {from: r.from, to}
+ })
+ return ranges.update({
+ filterFrom: r.from,
+ filterTo: r.to,
+ filter: () => false,
+ add: [highlight.range(r.from, r.to)]
+ })
+}
+
+
+const invertHighlight = invertedEffects.of(tr => {
+ let found = []
+ for (let e of tr.effects) {
+ if (e.is(addHighlight)) found.push(removeHighlight.of(e.value))
+ else if (e.is(removeHighlight)) found.push(addHighlight.of(e.value))
+ }
+ let ranges = tr.startState.field(highlightedRanges)
+ tr.changes.iterChangedRanges((chFrom, chTo) => {
+ ranges.between(chFrom, chTo, (rFrom, rTo) => {
+ if (rFrom >= chFrom || rTo <= chTo) {
+ let from = Math.max(chFrom, rFrom), to = Math.min(chTo, rTo)
+ if (from < to) found.push(addHighlight.of({from, to}))
+ }
+ })
+ })
+ return found
+})
+
+export function highlightSelection(view: EditorView) {
+ view.dispatch({
+ effects: view.state.selection.ranges.filter(r => !r.empty)
+ .map(r => addHighlight.of(r))
+ })
+ return true
+}
+
+export function unhighlightSelection(view: EditorView) {
+ let highlighted = view.state.field(highlightedRanges)
+ let effects: any[] = []
+ for (let sel of view.state.selection.ranges) {
+ highlighted.between(sel.from, sel.to, (rFrom, rTo) => {
+ let from = Math.max(sel.from, rFrom), to = Math.min(sel.to, rTo)
+ if (from < to) effects.push(removeHighlight.of({from, to}))
+ })
+ }
+ view.dispatch({effects})
+ return true
+}
+
+export function rangeHighlighting(): Extension {
+ return [
+ highlightedRanges,
+ invertHighlight,
+ ]
+}
\ No newline at end of file
diff --git a/src/main.ts b/src/main.ts
new file mode 100644
index 0000000..33ddb91
--- /dev/null
+++ b/src/main.ts
@@ -0,0 +1,452 @@
+import './style.css'
+import { EditorView } from "codemirror";
+import { editorSetup } from './EditorSetup';
+import { EditorState, Compartment } from "@codemirror/state";
+import { javascript } from "@codemirror/lang-javascript";
+import { Clock } from './Clock'
+import { vim } from "@replit/codemirror-vim";
+import { AppSettings } from './AppSettings';
+import { ViewUpdate } from '@codemirror/view';
+import {
+ highlightSelection,
+ unhighlightSelection,
+ rangeHighlighting
+} from "./highlightSelection";
+import { UserAPI } from './API';
+import { Extension } from '@codemirror/state';
+import { Universes, File, template_universe } from './AppSettings';
+import { tryEvaluate } from './Evaluator';
+
+
+
+export class Editor {
+
+ // Data structures for editor text management
+ universes: Universes
+ selected_universe: string
+ local_index: number = 1
+ editor_mode: 'global' | 'local' | 'init' = 'local'
+
+ settings = new AppSettings()
+ editorExtensions: Extension[] = []
+ userPlugins: Extension[] = []
+ state: EditorState
+ api: UserAPI
+
+ // Audio stuff
+ audioContext: AudioContext
+ view: EditorView
+ clock: Clock
+
+ // Transport elements
+ play_button: HTMLButtonElement = document.getElementById('play-button') as HTMLButtonElement
+ pause_button: HTMLButtonElement = document.getElementById('pause-button') as HTMLButtonElement
+ clear_button: HTMLButtonElement = document.getElementById('clear-button') as HTMLButtonElement
+
+ // Script selection elements
+ local_button: HTMLButtonElement = document.getElementById('local-button') as HTMLButtonElement
+ global_button: HTMLButtonElement = document.getElementById('global-button') as HTMLButtonElement
+ init_button: HTMLButtonElement = document.getElementById('init-button') as HTMLButtonElement
+ universe_viewer: HTMLDivElement = document.getElementById('universe-viewer') as HTMLDivElement
+
+ // Buffer modal
+ buffer_modal: HTMLDivElement = document.getElementById('modal-buffers') as HTMLDivElement
+ buffer_search: HTMLInputElement = document.getElementById('buffer-search') as HTMLInputElement
+ settings_modal: HTMLDivElement = document.getElementById('modal-settings') as HTMLDivElement
+
+ // Local script tabs
+ local_script_tabs: HTMLDivElement = document.getElementById('local-script-tabs') as HTMLDivElement
+
+ constructor() {
+
+
+
+ // ================================================================================
+ // Loading the universe from local storage
+ // ================================================================================
+
+ this.selected_universe = "Default";
+ this.universe_viewer.innerHTML = `Topos: ${this.selected_universe}`
+ this.universes = this.settings.universes
+
+ // ================================================================================
+ // Audio context and clock
+ // ================================================================================
+
+ this.audioContext = new AudioContext({ sampleRate: 44100, latencyHint: 0.000001});
+ this.clock = new Clock(this, this.audioContext);
+
+ // ================================================================================
+ // User API
+ // ================================================================================
+
+ this.api = new UserAPI(this);
+
+ // ================================================================================
+ // CodeMirror Management
+ // ================================================================================
+
+ this.editorExtensions = [
+ editorSetup,
+ rangeHighlighting(),
+ javascript(),
+ EditorView.updateListener.of((v:ViewUpdate) => {
+ // This is the event listener for the editor
+ }),
+ ...this.userPlugins
+ ]
+
+ let dynamicPlugins = new Compartment;
+ this.state = EditorState.create({
+ extensions: [
+ ...this.editorExtensions,
+ EditorView.lineWrapping,
+ dynamicPlugins.of(this.userPlugins)
+ ],
+ doc: this.universes[this.selected_universe].locals[this.local_index].candidate
+ })
+
+ this.view = new EditorView({
+ parent: document.getElementById('editor') as HTMLElement,
+ state: this.state
+ });
+
+ // ================================================================================
+ // Application event listeners
+ // ================================================================================
+
+ document.addEventListener('keydown', (event: KeyboardEvent) => {
+
+ // TAB should do nothing
+ if (event.key === 'Tab') {
+ event.preventDefault();
+ }
+
+ // Ctrl + Shift + V: Vim Mode
+ if ((event.key === 'v' || event.key === 'V') && event.ctrlKey && event.shiftKey) {
+ this.settings.vimMode = !this.settings.vimMode
+ event.preventDefault();
+ this.userPlugins = this.settings.vimMode ? [] : [vim()]
+ this.view.dispatch({
+ effects: dynamicPlugins.reconfigure(this.userPlugins)
+ })
+ }
+
+ // Ctrl + Enter or Return: Evaluate the hovered code block
+ if ((event.key === 'Enter' || event.key === 'Return') && event.ctrlKey) {
+ event.preventDefault();
+ const code = this.getCodeBlock();
+ this.currentFile.candidate = this.view.state.doc.toString()
+ tryEvaluate(this, this.currentFile)
+ }
+
+ // Shift + Enter or Ctrl + E: evaluate the line
+ if ((event.key === 'Enter' && event.shiftKey) || (event.key === 'e' && event.ctrlKey)) {
+ event.preventDefault(); // Prevents the addition of a new line
+ this.currentFile.candidate = this.view.state.doc.toString()
+ const code = this.getSelectedLines();
+ }
+
+ // This is the modal to switch between universes
+ if (event.metaKey && event.key === "b") {
+ this.openBuffersModal()
+ }
+
+ // This is the modal that opens up the settings
+ if (event.shiftKey && event.key === "Escape") {
+ this.openSettingsModal()
+ }
+
+
+ });
+
+ // ================================================================================
+ // Interface buttons
+ // ================================================================================
+
+ let tabs = document.querySelectorAll('[id^="tab-"]');
+ // Iterate over the tabs with an index
+ for (let i = 0; i < tabs.length; i++) {
+ tabs[i].addEventListener('click', (event) => {
+
+ // Updating the CSS accordingly
+ tabs[i].classList.add('bg-orange-300')
+ for (let j = 0; j < tabs.length; j++) {
+ if (j != i) tabs[j].classList.remove('bg-orange-300')
+ }
+ this.currentFile.candidate = this.view.state.doc.toString()
+
+ let tab = event.target as HTMLElement
+ let tab_id = tab.id.split('-')[1]
+ this.local_index = parseInt(tab_id)
+ this.updateEditorView()
+ })
+ }
+
+ this.play_button.addEventListener('click', () => {
+ this.play_button.children[0].classList.add('fill-orange-300')
+ this.pause_button.children[0].classList.remove('fill-orange-300')
+ this.clock.start()
+ })
+
+ this.clear_button.addEventListener('click', () => {
+ // Reset the current universe to a template
+ if (confirm('Do you want to reset the current universe?')) {
+ this.universes[this.selected_universe] = template_universe
+ this.updateEditorView()
+ }
+ });
+
+ this.pause_button.addEventListener('click', () => {
+ // Change the color of the button
+ this.play_button.children[0].classList.remove('fill-orange-300')
+ this.pause_button.children[0].classList.add('fill-orange-300')
+ this.clock.pause()
+ })
+
+ this.local_button.addEventListener('click', () => this.changeModeFromInterface('local'))
+ this.global_button.addEventListener('click', () => this.changeModeFromInterface('global'))
+ this.init_button.addEventListener('click', () => this.changeModeFromInterface('init'))
+
+ this.buffer_search.addEventListener('keydown', (event) => {
+ if (event.key === "Enter") {
+ let query = this.buffer_search.value
+ if (query.length > 2 && query.length < 20) {
+ this.loadUniverse(query)
+ this.buffer_search.value = ""
+ this.closeBuffersModal()
+ }
+ }
+ })
+ }
+
+ get global_buffer() {
+ return this.universes[this.selected_universe.toString()].global
+ }
+
+ get init_buffer() {
+ return this.universes[this.selected_universe.toString()].init
+ }
+
+ changeModeFromInterface(mode: 'global' | 'local' | 'init') {
+
+ const interface_buttons = [this.local_button, this.global_button, this.init_button]
+
+ let changeColor = (button: HTMLElement) => {
+ interface_buttons.forEach(button => {
+ // Get the child svg element of each button
+ let svg = button.children[0] as HTMLElement
+ if (svg.classList.contains('text-orange-300')) {
+ svg.classList.remove('text-orange-300')
+ svg.classList.add('text-white')
+ }
+ })
+ button.children[0].classList.add('text-orange-300')
+ }
+
+ if (mode === this.editor_mode) return
+ switch (mode) {
+ case 'local':
+ if (this.local_script_tabs.classList.contains('hidden')) {
+ this.local_script_tabs.classList.remove('hidden')
+ }
+ this.currentFile.candidate = this.view.state.doc.toString()
+ changeColor(this.local_button)
+ this.editor_mode = 'local';
+ break;
+ case 'global':
+ if (!this.local_script_tabs.classList.contains('hidden')) {
+ this.local_script_tabs.classList.add('hidden')
+ }
+ this.currentFile.candidate = this.view.state.doc.toString()
+ changeColor(this.global_button)
+ this.editor_mode = 'global';
+ break;
+ case 'init':
+ if (!this.local_script_tabs.classList.contains('hidden')) {
+ this.local_script_tabs.classList.add('hidden')
+ }
+ this.currentFile.candidate = this.view.state.doc.toString()
+ changeColor(this.init_button)
+ this.editor_mode = 'init';
+ break;
+ }
+ this.updateEditorView();
+ }
+
+ updateEditorView():void {
+ // Remove everything from the editor
+ this.view.dispatch({
+ changes: {
+ from: 0,
+ to: this.view.state.doc.toString().length,
+ insert:''
+ }
+ })
+
+ // Insert something
+ this.view.dispatch({
+ changes: {
+ from: 0,
+ insert: this.currentFile.candidate
+ }
+ });
+ }
+
+ get currentFile(): File {
+ switch (this.editor_mode) {
+ case 'global': return this.global_buffer;
+ case 'local': return this.universes[this.selected_universe].locals[this.local_index];
+ case 'init': return this.init_buffer;
+ }
+ }
+
+ loadUniverse(universeName: string) {
+ this.currentFile.candidate = this.view.state.doc.toString()
+ let editor = this;
+
+ function whichBuffer(editor: Editor): File {
+ switch (editor.editor_mode) {
+ case 'global': return editor.global_buffer
+ case 'local': return editor.universes[
+ editor.selected_universe].locals[editor.local_index]
+ case 'init': return editor.init_buffer
+ }
+ }
+
+ let selectedUniverse = universeName.trim()
+ if (this.universes[selectedUniverse] === undefined) {
+ this.universes[selectedUniverse] = template_universe
+ }
+ this.selected_universe = selectedUniverse
+ this.universe_viewer.innerHTML = `Topos: ${selectedUniverse}`
+ this.global_buffer = this.universes[this.selected_universe.toString()].global
+ this.init_buffer = this.universes[this.selected_universe.toString()].init
+ // We should also update the editor accordingly
+ this.view.dispatch({
+ changes: { from: 0, to: this.view.state.doc.toString().length, insert:'' }
+ })
+ this.view.dispatch({
+ changes: { from: 0, insert: this.currentFile.candidate }
+ });
+ }
+
+ getCodeBlock(): string {
+ // Capture the position of the cursor
+ let cursor = this.view.state.selection.main.head
+ const state = this.view.state;
+ const { head } = state.selection.main;
+ const currentLine = state.doc.lineAt(head);
+ let startLine = currentLine;
+ while (startLine.number > 1 && !/^\s*$/.test(state.doc.line(startLine.number - 1).text)) {
+ startLine = state.doc.line(startLine.number - 1);
+ }
+ let endLine = currentLine;
+ while (
+ endLine.number < state.doc.lines && !/^\s*$/.test(state.doc.line(endLine.number + 1).text)) {
+ endLine = state.doc.line(endLine.number + 1);
+ }
+
+ this.view.dispatch({selection: {anchor: 0 + startLine.from, head: endLine.to}});
+ highlightSelection(this.view);
+
+ setTimeout(() => {
+ unhighlightSelection(this.view)
+ this.view.dispatch({selection: {anchor: cursor, head: cursor}});
+ }, 200);
+
+ let result_string = state.doc.sliceString(startLine.from, endLine.to);
+ result_string = result_string.split('\n').map((line, index, lines) => {
+ const trimmedLine = line.trim();
+ if (index === lines.length - 1 || /^\s/.test(lines[index + 1]) || trimmedLine.startsWith('@')) {
+ return line;
+ } else {
+ return line + ';\\';
+ }
+ }).join('\n');
+ return result_string
+ }
+
+ getSelectedLines = (): string => {
+ const state = this.view.state;
+ const { from, to } = state.selection.main;
+ const fromLine = state.doc.lineAt(from);
+ const toLine = state.doc.lineAt(to);
+ this.view.dispatch({selection: {anchor: 0 + fromLine.from, head: toLine.to}});
+ // Release the selection and get the cursor back to its original position
+
+ // Blink the text!
+ highlightSelection(this.view);
+
+ setTimeout(() => {
+ unhighlightSelection(this.view)
+ this.view.dispatch({selection: {anchor: from, head: from}});
+ }, 200);
+ return state.doc.sliceString(fromLine.from, toLine.to);
+ }
+
+ openSettingsModal() {
+ // If the modal is hidden, unhide it and hide the editor
+ if (document.getElementById('modal-settings')!.classList.contains('invisible')) {
+ document.getElementById('editor')!.classList.add('invisible')
+ document.getElementById('modal-settings')!.classList.remove('invisible')
+ } else {
+ this.closeSettingsModal();
+ }
+ }
+
+ closeSettingsModal() {
+ document.getElementById('editor')!.classList.remove('invisible')
+ document.getElementById('modal-settings')!.classList.add('invisible')
+ }
+
+ openBuffersModal() {
+ // If the modal is hidden, unhide it and hide the editor
+ if (document.getElementById('modal-buffers')!.classList.contains('invisible')) {
+ document.getElementById('editor')!.classList.add('invisible')
+ document.getElementById('modal-buffers')!.classList.remove('invisible')
+ document.getElementById('buffer-search')!.focus()
+ } else {
+ this.closeBuffersModal();
+ }
+ }
+
+ closeBuffersModal() {
+ // @ts-ignore
+ document.getElementById('buffer-search')!.value = ''
+ document.getElementById('editor')!.classList.remove('invisible')
+ document.getElementById('modal-buffers')!.classList.add('invisible')
+ document.getElementById('modal')!.classList.add('invisible')
+ }
+}
+
+const app = new Editor()
+
+function startClock() {
+ document.getElementById('editor')!.classList.remove('invisible')
+ document.getElementById('modal')!.classList.add('hidden')
+ document.getElementById('start-button')!.removeEventListener('click', startClock);
+ document.removeEventListener('keydown', startOnEnter)
+ app.clock.start()
+ app.view.focus()
+ // Change the play button svg color to orange
+ document.getElementById('pause-button')!.children[0].classList.remove('fill-orange-300')
+ document.getElementById('play-button')!.children[0].classList.add('fill-orange-300')
+}
+
+function startOnEnter(e: KeyboardEvent) {
+ if (e.code === 'Enter' || e.code === "Space") startClock()
+}
+
+document.addEventListener('keydown', startOnEnter)
+document.getElementById('start-button')!.addEventListener(
+ 'click', startClock);
+
+// When the user leaves the page, all the universes should be saved in the localStorage
+window.addEventListener('beforeunload', () => {
+ // Iterate over all local files and set the candidate to the committed
+ app.currentFile.candidate = app.view.state.doc.toString()
+ app.currentFile.committed = app.view.state.doc.toString()
+ app.settings.saveApplicationToLocalStorage(app.universes)
+ return null;
+});
\ No newline at end of file
diff --git a/src/output.css b/src/output.css
new file mode 100644
index 0000000..714c984
--- /dev/null
+++ b/src/output.css
@@ -0,0 +1,1405 @@
+/*
+! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com
+*/
+
+/*
+1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
+2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
+*/
+
+*,
+::before,
+::after {
+ box-sizing: border-box;
+ /* 1 */
+ border-width: 0;
+ /* 2 */
+ border-style: solid;
+ /* 2 */
+ border-color: #e5e7eb;
+ /* 2 */
+}
+
+::before,
+::after {
+ --tw-content: '';
+}
+
+/*
+1. Use a consistent sensible line-height in all browsers.
+2. Prevent adjustments of font size after orientation changes in iOS.
+3. Use a more readable tab size.
+4. Use the user's configured `sans` font-family by default.
+5. Use the user's configured `sans` font-feature-settings by default.
+6. Use the user's configured `sans` font-variation-settings by default.
+*/
+
+html {
+ line-height: 1.5;
+ /* 1 */
+ -webkit-text-size-adjust: 100%;
+ /* 2 */
+ -moz-tab-size: 4;
+ /* 3 */
+ -o-tab-size: 4;
+ tab-size: 4;
+ /* 3 */
+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ /* 4 */
+ font-feature-settings: normal;
+ /* 5 */
+ font-variation-settings: normal;
+ /* 6 */
+}
+
+/*
+1. Remove the margin in all browsers.
+2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
+*/
+
+body {
+ margin: 0;
+ /* 1 */
+ line-height: inherit;
+ /* 2 */
+}
+
+/*
+1. Add the correct height in Firefox.
+2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
+3. Ensure horizontal rules are visible by default.
+*/
+
+hr {
+ height: 0;
+ /* 1 */
+ color: inherit;
+ /* 2 */
+ border-top-width: 1px;
+ /* 3 */
+}
+
+/*
+Add the correct text decoration in Chrome, Edge, and Safari.
+*/
+
+abbr:where([title]) {
+ -webkit-text-decoration: underline dotted;
+ text-decoration: underline dotted;
+}
+
+/*
+Remove the default font size and weight for headings.
+*/
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-size: inherit;
+ font-weight: inherit;
+}
+
+/*
+Reset links to optimize for opt-in styling instead of opt-out.
+*/
+
+a {
+ color: inherit;
+ text-decoration: inherit;
+}
+
+/*
+Add the correct font weight in Edge and Safari.
+*/
+
+b,
+strong {
+ font-weight: bolder;
+}
+
+/*
+1. Use the user's configured `mono` font family by default.
+2. Correct the odd `em` font sizing in all browsers.
+*/
+
+code,
+kbd,
+samp,
+pre {
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+ /* 1 */
+ font-size: 1em;
+ /* 2 */
+}
+
+/*
+Add the correct font size in all browsers.
+*/
+
+small {
+ font-size: 80%;
+}
+
+/*
+Prevent `sub` and `sup` elements from affecting the line height in all browsers.
+*/
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+sup {
+ top: -0.5em;
+}
+
+/*
+1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
+2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
+3. Remove gaps between table borders by default.
+*/
+
+table {
+ text-indent: 0;
+ /* 1 */
+ border-color: inherit;
+ /* 2 */
+ border-collapse: collapse;
+ /* 3 */
+}
+
+/*
+1. Change the font styles in all browsers.
+2. Remove the margin in Firefox and Safari.
+3. Remove default padding in all browsers.
+*/
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: inherit;
+ /* 1 */
+ font-feature-settings: inherit;
+ /* 1 */
+ font-variation-settings: inherit;
+ /* 1 */
+ font-size: 100%;
+ /* 1 */
+ font-weight: inherit;
+ /* 1 */
+ line-height: inherit;
+ /* 1 */
+ color: inherit;
+ /* 1 */
+ margin: 0;
+ /* 2 */
+ padding: 0;
+ /* 3 */
+}
+
+/*
+Remove the inheritance of text transform in Edge and Firefox.
+*/
+
+button,
+select {
+ text-transform: none;
+}
+
+/*
+1. Correct the inability to style clickable types in iOS and Safari.
+2. Remove default button styles.
+*/
+
+button,
+[type='button'],
+[type='reset'],
+[type='submit'] {
+ -webkit-appearance: button;
+ /* 1 */
+ background-color: transparent;
+ /* 2 */
+ background-image: none;
+ /* 2 */
+}
+
+/*
+Use the modern Firefox focus style for all focusable elements.
+*/
+
+:-moz-focusring {
+ outline: auto;
+}
+
+/*
+Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
+*/
+
+:-moz-ui-invalid {
+ box-shadow: none;
+}
+
+/*
+Add the correct vertical alignment in Chrome and Firefox.
+*/
+
+progress {
+ vertical-align: baseline;
+}
+
+/*
+Correct the cursor style of increment and decrement buttons in Safari.
+*/
+
+::-webkit-inner-spin-button,
+::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/*
+1. Correct the odd appearance in Chrome and Safari.
+2. Correct the outline style in Safari.
+*/
+
+[type='search'] {
+ -webkit-appearance: textfield;
+ /* 1 */
+ outline-offset: -2px;
+ /* 2 */
+}
+
+/*
+Remove the inner padding in Chrome and Safari on macOS.
+*/
+
+::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/*
+1. Correct the inability to style clickable types in iOS and Safari.
+2. Change font properties to `inherit` in Safari.
+*/
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button;
+ /* 1 */
+ font: inherit;
+ /* 2 */
+}
+
+/*
+Add the correct display in Chrome and Safari.
+*/
+
+summary {
+ display: list-item;
+}
+
+/*
+Removes the default spacing and border for appropriate elements.
+*/
+
+blockquote,
+dl,
+dd,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+hr,
+figure,
+p,
+pre {
+ margin: 0;
+}
+
+fieldset {
+ margin: 0;
+ padding: 0;
+}
+
+legend {
+ padding: 0;
+}
+
+ol,
+ul,
+menu {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+/*
+Reset default styling for dialogs.
+*/
+
+dialog {
+ padding: 0;
+}
+
+/*
+Prevent resizing textareas horizontally by default.
+*/
+
+textarea {
+ resize: vertical;
+}
+
+/*
+1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
+2. Set the default placeholder color to the user's configured gray 400 color.
+*/
+
+input::-moz-placeholder, textarea::-moz-placeholder {
+ opacity: 1;
+ /* 1 */
+ color: #9ca3af;
+ /* 2 */
+}
+
+input::placeholder,
+textarea::placeholder {
+ opacity: 1;
+ /* 1 */
+ color: #9ca3af;
+ /* 2 */
+}
+
+/*
+Set the default cursor for buttons.
+*/
+
+button,
+[role="button"] {
+ cursor: pointer;
+}
+
+/*
+Make sure disabled buttons don't get the pointer cursor.
+*/
+
+:disabled {
+ cursor: default;
+}
+
+/*
+1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
+2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
+ This can trigger a poorly considered lint error in some tools but is included by design.
+*/
+
+img,
+svg,
+video,
+canvas,
+audio,
+iframe,
+embed,
+object {
+ display: block;
+ /* 1 */
+ vertical-align: middle;
+ /* 2 */
+}
+
+/*
+Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
+*/
+
+img,
+video {
+ max-width: 100%;
+ height: auto;
+}
+
+/* Make elements with the HTML hidden attribute stay hidden by default */
+
+[hidden] {
+ display: none;
+}
+
+*, ::before, ::after {
+ --tw-border-spacing-x: 0;
+ --tw-border-spacing-y: 0;
+ --tw-translate-x: 0;
+ --tw-translate-y: 0;
+ --tw-rotate: 0;
+ --tw-skew-x: 0;
+ --tw-skew-y: 0;
+ --tw-scale-x: 1;
+ --tw-scale-y: 1;
+ --tw-pan-x: ;
+ --tw-pan-y: ;
+ --tw-pinch-zoom: ;
+ --tw-scroll-snap-strictness: proximity;
+ --tw-gradient-from-position: ;
+ --tw-gradient-via-position: ;
+ --tw-gradient-to-position: ;
+ --tw-ordinal: ;
+ --tw-slashed-zero: ;
+ --tw-numeric-figure: ;
+ --tw-numeric-spacing: ;
+ --tw-numeric-fraction: ;
+ --tw-ring-inset: ;
+ --tw-ring-offset-width: 0px;
+ --tw-ring-offset-color: #fff;
+ --tw-ring-color: rgb(59 130 246 / 0.5);
+ --tw-ring-offset-shadow: 0 0 #0000;
+ --tw-ring-shadow: 0 0 #0000;
+ --tw-shadow: 0 0 #0000;
+ --tw-shadow-colored: 0 0 #0000;
+ --tw-blur: ;
+ --tw-brightness: ;
+ --tw-contrast: ;
+ --tw-grayscale: ;
+ --tw-hue-rotate: ;
+ --tw-invert: ;
+ --tw-saturate: ;
+ --tw-sepia: ;
+ --tw-drop-shadow: ;
+ --tw-backdrop-blur: ;
+ --tw-backdrop-brightness: ;
+ --tw-backdrop-contrast: ;
+ --tw-backdrop-grayscale: ;
+ --tw-backdrop-hue-rotate: ;
+ --tw-backdrop-invert: ;
+ --tw-backdrop-opacity: ;
+ --tw-backdrop-saturate: ;
+ --tw-backdrop-sepia: ;
+}
+
+::backdrop {
+ --tw-border-spacing-x: 0;
+ --tw-border-spacing-y: 0;
+ --tw-translate-x: 0;
+ --tw-translate-y: 0;
+ --tw-rotate: 0;
+ --tw-skew-x: 0;
+ --tw-skew-y: 0;
+ --tw-scale-x: 1;
+ --tw-scale-y: 1;
+ --tw-pan-x: ;
+ --tw-pan-y: ;
+ --tw-pinch-zoom: ;
+ --tw-scroll-snap-strictness: proximity;
+ --tw-gradient-from-position: ;
+ --tw-gradient-via-position: ;
+ --tw-gradient-to-position: ;
+ --tw-ordinal: ;
+ --tw-slashed-zero: ;
+ --tw-numeric-figure: ;
+ --tw-numeric-spacing: ;
+ --tw-numeric-fraction: ;
+ --tw-ring-inset: ;
+ --tw-ring-offset-width: 0px;
+ --tw-ring-offset-color: #fff;
+ --tw-ring-color: rgb(59 130 246 / 0.5);
+ --tw-ring-offset-shadow: 0 0 #0000;
+ --tw-ring-shadow: 0 0 #0000;
+ --tw-shadow: 0 0 #0000;
+ --tw-shadow-colored: 0 0 #0000;
+ --tw-blur: ;
+ --tw-brightness: ;
+ --tw-contrast: ;
+ --tw-grayscale: ;
+ --tw-hue-rotate: ;
+ --tw-invert: ;
+ --tw-saturate: ;
+ --tw-sepia: ;
+ --tw-drop-shadow: ;
+ --tw-backdrop-blur: ;
+ --tw-backdrop-brightness: ;
+ --tw-backdrop-contrast: ;
+ --tw-backdrop-grayscale: ;
+ --tw-backdrop-hue-rotate: ;
+ --tw-backdrop-invert: ;
+ --tw-backdrop-opacity: ;
+ --tw-backdrop-saturate: ;
+ --tw-backdrop-sepia: ;
+}
+
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border-width: 0;
+}
+
+.pointer-events-none {
+ pointer-events: none;
+}
+
+.invisible {
+ visibility: hidden;
+}
+
+.fixed {
+ position: fixed;
+}
+
+.absolute {
+ position: absolute;
+}
+
+.relative {
+ position: relative;
+}
+
+.inset-y-0 {
+ top: 0px;
+ bottom: 0px;
+}
+
+.bottom-0 {
+ bottom: 0px;
+}
+
+.bottom-2 {
+ bottom: 0.5rem;
+}
+
+.bottom-2\.5 {
+ bottom: 0.625rem;
+}
+
+.left-0 {
+ left: 0px;
+}
+
+.right-0 {
+ right: 0px;
+}
+
+.right-2 {
+ right: 0.5rem;
+}
+
+.right-2\.5 {
+ right: 0.625rem;
+}
+
+.top-0 {
+ top: 0px;
+}
+
+.z-50 {
+ z-index: 50;
+}
+
+.m-auto {
+ margin: auto;
+}
+
+.mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.mb-0 {
+ margin-bottom: 0px;
+}
+
+.mb-2 {
+ margin-bottom: 0.5rem;
+}
+
+.mb-4 {
+ margin-bottom: 1rem;
+}
+
+.ml-2 {
+ margin-left: 0.5rem;
+}
+
+.ml-4 {
+ margin-left: 1rem;
+}
+
+.mr-5 {
+ margin-right: 1.25rem;
+}
+
+.mt-1 {
+ margin-top: 0.25rem;
+}
+
+.mr-2 {
+ margin-right: 0.5rem;
+}
+
+.mr-8 {
+ margin-right: 2rem;
+}
+
+.mr-20 {
+ margin-right: 5rem;
+}
+
+.mr-6 {
+ margin-right: 1.5rem;
+}
+
+.mr-4 {
+ margin-right: 1rem;
+}
+
+.ml-auto {
+ margin-left: auto;
+}
+
+.block {
+ display: block;
+}
+
+.inline-block {
+ display: inline-block;
+}
+
+.flex {
+ display: flex;
+}
+
+.inline-flex {
+ display: inline-flex;
+}
+
+.hidden {
+ display: none;
+}
+
+.h-10 {
+ height: 2.5rem;
+}
+
+.h-4 {
+ height: 1rem;
+}
+
+.h-6 {
+ height: 1.5rem;
+}
+
+.h-screen {
+ height: 100vh;
+}
+
+.h-3 {
+ height: 0.75rem;
+}
+
+.h-8 {
+ height: 2rem;
+}
+
+.h-\[calc\(100\%-1rem\)\] {
+ height: calc(100% - 1rem);
+}
+
+.max-h-full {
+ max-height: 100%;
+}
+
+.min-h-screen {
+ min-height: 100vh;
+}
+
+.w-10 {
+ width: 2.5rem;
+}
+
+.w-14 {
+ width: 3.5rem;
+}
+
+.w-4 {
+ width: 1rem;
+}
+
+.w-6 {
+ width: 1.5rem;
+}
+
+.w-full {
+ width: 100%;
+}
+
+.w-2 {
+ width: 0.5rem;
+}
+
+.w-3 {
+ width: 0.75rem;
+}
+
+.w-8 {
+ width: 2rem;
+}
+
+.max-w-2xl {
+ max-width: 42rem;
+}
+
+.flex-grow {
+ flex-grow: 1;
+}
+
+.grow {
+ flex-grow: 1;
+}
+
+.cursor-not-allowed {
+ cursor: not-allowed;
+}
+
+.flex-row {
+ flex-direction: row;
+}
+
+.flex-col {
+ flex-direction: column;
+}
+
+.flex-wrap {
+ flex-wrap: wrap;
+}
+
+.items-start {
+ align-items: flex-start;
+}
+
+.items-center {
+ align-items: center;
+}
+
+.justify-center {
+ justify-content: center;
+}
+
+.justify-between {
+ justify-content: space-between;
+}
+
+.space-y-6 > :not([hidden]) ~ :not([hidden]) {
+ --tw-space-y-reverse: 0;
+ margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
+ margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
+}
+
+.space-x-8 > :not([hidden]) ~ :not([hidden]) {
+ --tw-space-x-reverse: 0;
+ margin-right: calc(2rem * var(--tw-space-x-reverse));
+ margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse)));
+}
+
+.space-x-4 > :not([hidden]) ~ :not([hidden]) {
+ --tw-space-x-reverse: 0;
+ margin-right: calc(1rem * var(--tw-space-x-reverse));
+ margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
+}
+
+.space-x-2 > :not([hidden]) ~ :not([hidden]) {
+ --tw-space-x-reverse: 0;
+ margin-right: calc(0.5rem * var(--tw-space-x-reverse));
+ margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
+}
+
+.overflow-hidden {
+ overflow: hidden;
+}
+
+.overflow-y-auto {
+ overflow-y: auto;
+}
+
+.overflow-x-hidden {
+ overflow-x: hidden;
+}
+
+.overflow-y-hidden {
+ overflow-y: hidden;
+}
+
+.rounded {
+ border-radius: 0.25rem;
+}
+
+.rounded-full {
+ border-radius: 9999px;
+}
+
+.rounded-lg {
+ border-radius: 0.5rem;
+}
+
+.rounded-md {
+ border-radius: 0.375rem;
+}
+
+.rounded-b {
+ border-bottom-right-radius: 0.25rem;
+ border-bottom-left-radius: 0.25rem;
+}
+
+.rounded-t {
+ border-top-left-radius: 0.25rem;
+ border-top-right-radius: 0.25rem;
+}
+
+.border {
+ border-width: 1px;
+}
+
+.border-r {
+ border-right-width: 1px;
+}
+
+.border-b {
+ border-bottom-width: 1px;
+}
+
+.border-t {
+ border-top-width: 1px;
+}
+
+.border-gray-300 {
+ --tw-border-opacity: 1;
+ border-color: rgb(209 213 219 / var(--tw-border-opacity));
+}
+
+.border-gray-200 {
+ --tw-border-opacity: 1;
+ border-color: rgb(229 231 235 / var(--tw-border-opacity));
+}
+
+.bg-black {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+}
+
+.bg-blue-700 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(29 78 216 / var(--tw-bg-opacity));
+}
+
+.bg-gray-100 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(243 244 246 / var(--tw-bg-opacity));
+}
+
+.bg-white {
+ --tw-bg-opacity: 1;
+ background-color: rgb(255 255 255 / var(--tw-bg-opacity));
+}
+
+.bg-blue-800 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(30 64 175 / var(--tw-bg-opacity));
+}
+
+.bg-blue-600 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(37 99 235 / var(--tw-bg-opacity));
+}
+
+.bg-gray-800 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(31 41 55 / var(--tw-bg-opacity));
+}
+
+.bg-blue-500 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(59 130 246 / var(--tw-bg-opacity));
+}
+
+.bg-transparent {
+ background-color: transparent;
+}
+
+.bg-orange-300 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(253 186 116 / var(--tw-bg-opacity));
+}
+
+.bg-green-300 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(134 239 172 / var(--tw-bg-opacity));
+}
+
+.bg-red-300 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(252 165 165 / var(--tw-bg-opacity));
+}
+
+.bg-red-500 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(239 68 68 / var(--tw-bg-opacity));
+}
+
+.bg-opacity-50 {
+ --tw-bg-opacity: 0.5;
+}
+
+.fill-orange-300 {
+ fill: #fdba74;
+}
+
+.p-1 {
+ padding: 0.25rem;
+}
+
+.p-1\.5 {
+ padding: 0.375rem;
+}
+
+.p-2 {
+ padding: 0.5rem;
+}
+
+.p-4 {
+ padding: 1rem;
+}
+
+.p-6 {
+ padding: 1.5rem;
+}
+
+.px-16 {
+ padding-left: 4rem;
+ padding-right: 4rem;
+}
+
+.px-2 {
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+}
+
+.px-4 {
+ padding-left: 1rem;
+ padding-right: 1rem;
+}
+
+.px-7 {
+ padding-left: 1.75rem;
+ padding-right: 1.75rem;
+}
+
+.py-0 {
+ padding-top: 0px;
+ padding-bottom: 0px;
+}
+
+.py-1 {
+ padding-top: 0.25rem;
+ padding-bottom: 0.25rem;
+}
+
+.py-14 {
+ padding-top: 3.5rem;
+ padding-bottom: 3.5rem;
+}
+
+.py-2 {
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+}
+
+.py-3 {
+ padding-top: 0.75rem;
+ padding-bottom: 0.75rem;
+}
+
+.py-4 {
+ padding-top: 1rem;
+ padding-bottom: 1rem;
+}
+
+.px-5 {
+ padding-left: 1.25rem;
+ padding-right: 1.25rem;
+}
+
+.py-2\.5 {
+ padding-top: 0.625rem;
+ padding-bottom: 0.625rem;
+}
+
+.pb-4 {
+ padding-bottom: 1rem;
+}
+
+.pl-10 {
+ padding-left: 2.5rem;
+}
+
+.pl-2 {
+ padding-left: 0.5rem;
+}
+
+.pl-2\.5 {
+ padding-left: 0.625rem;
+}
+
+.pl-3 {
+ padding-left: 0.75rem;
+}
+
+.pr-8 {
+ padding-right: 2rem;
+}
+
+.pl-4 {
+ padding-left: 1rem;
+}
+
+.pl-6 {
+ padding-left: 1.5rem;
+}
+
+.pl-5 {
+ padding-left: 1.25rem;
+}
+
+.text-center {
+ text-align: center;
+}
+
+.text-base {
+ font-size: 1rem;
+ line-height: 1.5rem;
+}
+
+.text-sm {
+ font-size: 0.875rem;
+ line-height: 1.25rem;
+}
+
+.text-xl {
+ font-size: 1.25rem;
+ line-height: 1.75rem;
+}
+
+.text-xs {
+ font-size: 0.75rem;
+ line-height: 1rem;
+}
+
+.font-bold {
+ font-weight: 700;
+}
+
+.font-medium {
+ font-weight: 500;
+}
+
+.font-semibold {
+ font-weight: 600;
+}
+
+.italic {
+ font-style: italic;
+}
+
+.leading-relaxed {
+ line-height: 1.625;
+}
+
+.text-black {
+ --tw-text-opacity: 1;
+ color: rgb(0 0 0 / var(--tw-text-opacity));
+}
+
+.text-gray-500 {
+ --tw-text-opacity: 1;
+ color: rgb(107 114 128 / var(--tw-text-opacity));
+}
+
+.text-gray-700 {
+ --tw-text-opacity: 1;
+ color: rgb(55 65 81 / var(--tw-text-opacity));
+}
+
+.text-gray-800 {
+ --tw-text-opacity: 1;
+ color: rgb(31 41 55 / var(--tw-text-opacity));
+}
+
+.text-gray-900 {
+ --tw-text-opacity: 1;
+ color: rgb(17 24 39 / var(--tw-text-opacity));
+}
+
+.text-white {
+ --tw-text-opacity: 1;
+ color: rgb(255 255 255 / var(--tw-text-opacity));
+}
+
+.text-gray-400 {
+ --tw-text-opacity: 1;
+ color: rgb(156 163 175 / var(--tw-text-opacity));
+}
+
+.text-blue-200 {
+ --tw-text-opacity: 1;
+ color: rgb(191 219 254 / var(--tw-text-opacity));
+}
+
+.text-blue-800 {
+ --tw-text-opacity: 1;
+ color: rgb(30 64 175 / var(--tw-text-opacity));
+}
+
+.text-rose-800 {
+ --tw-text-opacity: 1;
+ color: rgb(159 18 57 / var(--tw-text-opacity));
+}
+
+.text-sky-700 {
+ --tw-text-opacity: 1;
+ color: rgb(3 105 161 / var(--tw-text-opacity));
+}
+
+.text-sky-300 {
+ --tw-text-opacity: 1;
+ color: rgb(125 211 252 / var(--tw-text-opacity));
+}
+
+.text-orange-300 {
+ --tw-text-opacity: 1;
+ color: rgb(253 186 116 / var(--tw-text-opacity));
+}
+
+.text-orange-500 {
+ --tw-text-opacity: 1;
+ color: rgb(249 115 22 / var(--tw-text-opacity));
+}
+
+.underline {
+ text-decoration-line: underline;
+}
+
+.line-through {
+ text-decoration-line: line-through;
+}
+
+.shadow {
+ --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
+ --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
+}
+
+.outline {
+ outline-style: solid;
+}
+
+.outline-0 {
+ outline-width: 0px;
+}
+
+.filter {
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
+}
+
+.transition-colors {
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+ transition-duration: 150ms;
+}
+
+.duration-200 {
+ transition-duration: 200ms;
+}
+
+.hover\:bg-blue-800:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(30 64 175 / var(--tw-bg-opacity));
+}
+
+.hover\:bg-gray-100:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(243 244 246 / var(--tw-bg-opacity));
+}
+
+.hover\:bg-white:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(255 255 255 / var(--tw-bg-opacity));
+}
+
+.hover\:bg-gray-900:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(17 24 39 / var(--tw-bg-opacity));
+}
+
+.hover\:bg-gray-500:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(107 114 128 / var(--tw-bg-opacity));
+}
+
+.hover\:bg-gray-800:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(31 41 55 / var(--tw-bg-opacity));
+}
+
+.hover\:bg-gray-200:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(229 231 235 / var(--tw-bg-opacity));
+}
+
+.hover\:text-gray-900:hover {
+ --tw-text-opacity: 1;
+ color: rgb(17 24 39 / var(--tw-text-opacity));
+}
+
+.focus\:z-10:focus {
+ z-index: 10;
+}
+
+.focus\:outline-none:focus {
+ outline: 2px solid transparent;
+ outline-offset: 2px;
+}
+
+.focus\:ring-4:focus {
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
+}
+
+.focus\:ring-blue-300:focus {
+ --tw-ring-opacity: 1;
+ --tw-ring-color: rgb(147 197 253 / var(--tw-ring-opacity));
+}
+
+:is([dir="rtl"] .rtl\:border-l) {
+ border-left-width: 1px;
+}
+
+:is([dir="rtl"] .rtl\:border-r-0) {
+ border-right-width: 0px;
+}
+
+@media (prefers-color-scheme: dark) {
+ .dark\:border-gray-700 {
+ --tw-border-opacity: 1;
+ border-color: rgb(55 65 81 / var(--tw-border-opacity));
+ }
+
+ .dark\:border-gray-500 {
+ --tw-border-opacity: 1;
+ border-color: rgb(107 114 128 / var(--tw-border-opacity));
+ }
+
+ .dark\:border-gray-600 {
+ --tw-border-opacity: 1;
+ border-color: rgb(75 85 99 / var(--tw-border-opacity));
+ }
+
+ .dark\:bg-black {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+
+ .dark\:bg-blue-600 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(37 99 235 / var(--tw-bg-opacity));
+ }
+
+ .dark\:bg-gray-800 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(31 41 55 / var(--tw-bg-opacity));
+ }
+
+ .dark\:bg-gray-700 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(55 65 81 / var(--tw-bg-opacity));
+ }
+
+ .dark\:text-gray-200 {
+ --tw-text-opacity: 1;
+ color: rgb(229 231 235 / var(--tw-text-opacity));
+ }
+
+ .dark\:text-gray-400 {
+ --tw-text-opacity: 1;
+ color: rgb(156 163 175 / var(--tw-text-opacity));
+ }
+
+ .dark\:text-white {
+ --tw-text-opacity: 1;
+ color: rgb(255 255 255 / var(--tw-text-opacity));
+ }
+
+ .dark\:text-gray-500 {
+ --tw-text-opacity: 1;
+ color: rgb(107 114 128 / var(--tw-text-opacity));
+ }
+
+ .dark\:text-gray-300 {
+ --tw-text-opacity: 1;
+ color: rgb(209 213 219 / var(--tw-text-opacity));
+ }
+
+ .dark\:hover\:bg-blue-700:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(29 78 216 / var(--tw-bg-opacity));
+ }
+
+ .dark\:hover\:bg-gray-800:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(31 41 55 / var(--tw-bg-opacity));
+ }
+
+ .dark\:hover\:bg-gray-600:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(75 85 99 / var(--tw-bg-opacity));
+ }
+
+ .dark\:hover\:text-white:hover {
+ --tw-text-opacity: 1;
+ color: rgb(255 255 255 / var(--tw-text-opacity));
+ }
+
+ .dark\:focus\:ring-blue-800:focus {
+ --tw-ring-opacity: 1;
+ --tw-ring-color: rgb(30 64 175 / var(--tw-ring-opacity));
+ }
+
+ .dark\:focus\:ring-gray-600:focus {
+ --tw-ring-opacity: 1;
+ --tw-ring-color: rgb(75 85 99 / var(--tw-ring-opacity));
+ }
+}
+
+@media (min-width: 768px) {
+ .md\:inset-0 {
+ inset: 0px;
+ }
+}
+
+@media (min-width: 1024px) {
+ .lg\:space-x-8 > :not([hidden]) ~ :not([hidden]) {
+ --tw-space-x-reverse: 0;
+ margin-right: calc(2rem * var(--tw-space-x-reverse));
+ margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse)));
+ }
+}
diff --git a/src/style.css b/src/style.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/src/style.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/src/themes/materialDark.ts b/src/themes/materialDark.ts
new file mode 100644
index 0000000..a2bb087
--- /dev/null
+++ b/src/themes/materialDark.ts
@@ -0,0 +1,209 @@
+import { EditorView } from '@codemirror/view'
+import { Extension } from '@codemirror/state'
+import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'
+import { tags as t } from '@lezer/highlight'
+
+const base00 = 'black', base01 = '#505d64',
+ base02 = 'white', base03 = '#707d8b',
+ base04 = '#a0a4ae', base05 = '#bdbdbd',
+ base06 = '#e0e0e0', base07 = '#fdf6e3',
+ base_red = '#ff5f52', base_deeporange = '#ff6e40',
+ base_pink = '#fa5788', base_yellow = '#facf4e',
+ base_orange = '#ffad42', base_cyan = '#1E6AE1',
+ base_indigo = '#7186f0', base_purple = '#D09EBF',
+ base_green = '#82d47c', base_lightgreen = '#82d47c',
+ base_teal = '#4ebaaa'
+
+const invalid = base_red,
+ darkBackground = '#fdf6e3',
+ highlightBackground = '#545b61',
+ background = base00,
+ tooltipBackground = base01,
+ selection = base07,
+ cursor = base04
+
+/// The editor theme styles for Material Dark.
+export const materialDarkTheme = EditorView.theme(
+ {
+ '&': {
+ color: base05,
+ backgroundColor: background
+ },
+
+ '.cm-content': {
+ caretColor: cursor
+ },
+
+ '.cm-cursor, .cm-dropCursor': { borderLeftColor: cursor },
+ '&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection':
+ { backgroundColor: selection, border: `0.5px solid ${base_teal}` },
+
+ '.cm-panels': { backgroundColor: darkBackground, color: base03 },
+ '.cm-panels.cm-panels-top': { borderBottom: '2px solid black' },
+ '.cm-panels.cm-panels-bottom': { borderTop: '2px solid black' },
+
+ '.cm-searchMatch': {
+ outline: `1px solid ${base_yellow}`,
+ backgroundColor: 'transparent'
+ },
+ '.cm-searchMatch.cm-searchMatch-selected': {
+ backgroundColor: highlightBackground
+ },
+
+ '.cm-activeLine': { backgroundColor: highlightBackground },
+ '.cm-selectionMatch': {
+ backgroundColor: darkBackground,
+ outline: `1px solid ${base_teal}`
+ },
+
+ '&.cm-focused .cm-matchingBracket': {
+ color: base06,
+ outline: `1px solid ${base_teal}`
+ },
+
+ '&.cm-focused .cm-nonmatchingBracket': {
+ color: base_red
+ },
+
+ '.cm-gutters': {
+ backgroundColor: base00,
+ borderRight: `1px solid ${base07}`,
+ color: base02
+ },
+
+ '.cm-activeLineGutter': {
+ backgroundColor: highlightBackground,
+ color: base07
+ },
+
+ '.cm-foldPlaceholder': {
+ backgroundColor: 'transparent',
+ border: 'none',
+ color: `${base07}`,
+ },
+
+ '.cm-tooltip': {
+ border: 'none',
+ backgroundColor: tooltipBackground
+ },
+ '.cm-tooltip .cm-tooltip-arrow:before': {
+ borderTopColor: 'transparent',
+ borderBottomColor: 'transparent'
+ },
+ '.cm-tooltip .cm-tooltip-arrow:after': {
+ borderTopColor: tooltipBackground,
+ borderBottomColor: tooltipBackground
+ },
+ '.cm-tooltip-autocomplete': {
+ '& > ul > li[aria-selected]': {
+ backgroundColor: highlightBackground,
+ color: base03
+ }
+ }
+ },
+ { dark: true }
+)
+
+/// The highlighting style for code in the Material Dark theme.
+export const materialDarkHighlightStyle = HighlightStyle.define([
+ { tag: t.keyword, color: base_purple },
+ {
+ tag: [t.name, t.deleted, t.character, t.macroName],
+ color: base_cyan
+ },
+ { tag: [t.propertyName], color: base_yellow },
+ { tag: [t.variableName], color: base05 },
+ { tag: [t.function(t.variableName)], color: base_cyan },
+ { tag: [t.labelName], color: base_purple },
+ {
+ tag: [t.color, t.constant(t.name), t.standard(t.name)],
+ color: base_yellow
+ },
+ { tag: [t.definition(t.name), t.separator], color: base_pink },
+ { tag: [t.brace], color: base_purple },
+ {
+ tag: [t.annotation],
+ color: invalid
+ },
+ {
+ tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace],
+ color: base_orange
+ },
+ {
+ tag: [t.typeName, t.className],
+ color: base_orange
+ },
+ {
+ tag: [t.operator, t.operatorKeyword],
+ color: base_indigo
+ },
+ {
+ tag: [t.tagName],
+ color: base_deeporange
+ },
+ {
+ tag: [t.squareBracket],
+ color: base_red
+ },
+ {
+ tag: [t.angleBracket],
+ color: base02
+ },
+ {
+ tag: [t.attributeName],
+ color: base05
+ },
+ {
+ tag: [t.regexp],
+ color: invalid
+ },
+ {
+ tag: [t.quote],
+ color: base_green
+ },
+ { tag: [t.string], color: base_lightgreen },
+ {
+ tag: t.link,
+ color: base_cyan,
+ textDecoration: 'underline',
+ textUnderlinePosition: 'under'
+ },
+ {
+ tag: [t.url, t.escape, t.special(t.string)],
+ color: base_yellow
+ },
+ { tag: [t.meta], color: base03 },
+ { tag: [t.comment], color: base02, fontStyle: 'italic' },
+ { tag: t.monospace, color: base05 },
+ { tag: t.strong, fontWeight: 'bold', color: base_red },
+ { tag: t.emphasis, fontStyle: 'italic', color: base_lightgreen },
+ { tag: t.strikethrough, textDecoration: 'line-through' },
+ { tag: t.heading, fontWeight: 'bold', color: base_yellow },
+ { tag: t.heading1, fontWeight: 'bold', color: base_yellow },
+ {
+ tag: [t.heading2, t.heading3, t.heading4],
+ fontWeight: 'bold',
+ color: base_yellow
+ },
+ {
+ tag: [t.heading5, t.heading6],
+ color: base_yellow
+ },
+ { tag: [t.atom, t.bool, t.special(t.variableName)], color: base_cyan },
+ {
+ tag: [t.processingInstruction, t.inserted],
+ color: base_red
+ },
+ {
+ tag: [t.contentSeparator],
+ color: base_cyan
+ },
+ { tag: t.invalid, color: base02, borderBottom: `1px dotted ${base_red}` }
+])
+
+/// Extension to enable the Material Dark theme (both the editor theme and
+/// the highlight style).
+export const materialDark: Extension = [
+ materialDarkTheme,
+ syntaxHighlighting(materialDarkHighlightStyle)
+]
\ No newline at end of file
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/tailwind.config.js b/tailwind.config.js
new file mode 100644
index 0000000..d37737f
--- /dev/null
+++ b/tailwind.config.js
@@ -0,0 +1,12 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: [
+ "./index.html",
+ "./src/**/*.{js,ts,jsx,tsx}",
+ ],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+}
+
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..75abdef
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,23 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"]
+}
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 0000000..e4fa2de
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,920 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@alloc/quick-lru@^5.2.0":
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
+ integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
+
+"@codemirror/autocomplete@^6.0.0":
+ version "6.9.0"
+ resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.9.0.tgz#1a1e63122288b8f8e1e9d7aff2eb39a83e04d8a9"
+ integrity sha512-Fbwm0V/Wn3BkEJZRhr0hi5BhCo5a7eBL6LYaliPjOSwCyfOpnjXY59HruSxOUNV+1OYer0Tgx1zRNQttjXyDog==
+ dependencies:
+ "@codemirror/language" "^6.0.0"
+ "@codemirror/state" "^6.0.0"
+ "@codemirror/view" "^6.6.0"
+ "@lezer/common" "^1.0.0"
+
+"@codemirror/commands@^6.0.0":
+ version "6.2.4"
+ resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.2.4.tgz#b8a0e5ce72448c092ba4c4b1d902e6f183948aec"
+ integrity sha512-42lmDqVH0ttfilLShReLXsDfASKLXzfyC36bzwcqzox9PlHulMcsUOfHXNo2X2aFMVNUoQ7j+d4q5bnfseYoOA==
+ dependencies:
+ "@codemirror/language" "^6.0.0"
+ "@codemirror/state" "^6.2.0"
+ "@codemirror/view" "^6.0.0"
+ "@lezer/common" "^1.0.0"
+
+"@codemirror/lang-javascript@^6.1.9":
+ version "6.1.9"
+ resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.1.9.tgz#19065ad32db7b3797829eca01b8d9c69da5fd0d6"
+ integrity sha512-z3jdkcqOEBT2txn2a87A0jSy6Te3679wg/U8QzMeftFt+4KA6QooMwfdFzJiuC3L6fXKfTXZcDocoaxMYfGz0w==
+ dependencies:
+ "@codemirror/autocomplete" "^6.0.0"
+ "@codemirror/language" "^6.6.0"
+ "@codemirror/lint" "^6.0.0"
+ "@codemirror/state" "^6.0.0"
+ "@codemirror/view" "^6.0.0"
+ "@lezer/common" "^1.0.0"
+ "@lezer/javascript" "^1.0.0"
+
+"@codemirror/language@^6.0.0", "@codemirror/language@^6.6.0":
+ version "6.8.0"
+ resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.8.0.tgz#f2d7eea6b338c25593d800f2293b062d9f9856db"
+ integrity sha512-r1paAyWOZkfY0RaYEZj3Kul+MiQTEbDvYqf8gPGaRvNneHXCmfSaAVFjwRUPlgxS8yflMxw2CTu6uCMp8R8A2g==
+ dependencies:
+ "@codemirror/state" "^6.0.0"
+ "@codemirror/view" "^6.0.0"
+ "@lezer/common" "^1.0.0"
+ "@lezer/highlight" "^1.0.0"
+ "@lezer/lr" "^1.0.0"
+ style-mod "^4.0.0"
+
+"@codemirror/lint@^6.0.0":
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.4.0.tgz#3507e937aa9415ef0831ff04734ef0e736e75014"
+ integrity sha512-6VZ44Ysh/Zn07xrGkdtNfmHCbGSHZzFBdzWi0pbd7chAQ/iUcpLGX99NYRZTa7Ugqg4kEHCqiHhcZnH0gLIgSg==
+ dependencies:
+ "@codemirror/state" "^6.0.0"
+ "@codemirror/view" "^6.0.0"
+ crelt "^1.0.5"
+
+"@codemirror/search@^6.0.0":
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.5.0.tgz#308f9968434e0e6ed59c9ec36a0239eb1dfc5d92"
+ integrity sha512-64/M40YeJPToKvGO6p3fijo2vwUEj4nACEAXElCaYQ50HrXSvRaK+NHEhSh73WFBGdvIdhrV+lL9PdJy2RfCYA==
+ dependencies:
+ "@codemirror/state" "^6.0.0"
+ "@codemirror/view" "^6.0.0"
+ crelt "^1.0.5"
+
+"@codemirror/state@^6.0.0", "@codemirror/state@^6.1.4", "@codemirror/state@^6.2.0":
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.1.tgz#6dc8d8e5abb26b875e3164191872d69a5e85bd73"
+ integrity sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==
+
+"@codemirror/view@^6.0.0", "@codemirror/view@^6.6.0":
+ version "6.15.3"
+ resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.15.3.tgz#b26dac3e1812821daa6da25f59ffb26c9b9b75f3"
+ integrity sha512-chNgR8H7Ipx7AZUt0+Kknk7BCow/ron3mHd1VZdM7hQXiI79+UlWqcxpCiexTxZQ+iSkqndk3HHAclJOcjSuog==
+ dependencies:
+ "@codemirror/state" "^6.1.4"
+ style-mod "^4.0.0"
+ w3c-keyname "^2.2.4"
+
+"@esbuild/android-arm64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.16.tgz#34f562abc0015933aabd41b3d50d8d3359e30155"
+ integrity sha512-wsCqSPqLz+6Ov+OM4EthU43DyYVVyfn15S4j1bJzylDpc1r1jZFFfJQNfDuT8SlgwuqpmpJXK4uPlHGw6ve7eA==
+
+"@esbuild/android-arm@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.16.tgz#ef6f9aa59a79a9b9330a2e73f7eb402c6630c267"
+ integrity sha512-gCHjjQmA8L0soklKbLKA6pgsLk1byULuHe94lkZDzcO3/Ta+bbeewJioEn1Fr7kgy9NWNFy/C+MrBwC6I/WCug==
+
+"@esbuild/android-x64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.16.tgz#ed7444cb17542932c67b15e20528686853239cfd"
+ integrity sha512-ldsTXolyA3eTQ1//4DS+E15xl0H/3DTRJaRL0/0PgkqDsI0fV/FlOtD+h0u/AUJr+eOTlZv4aC9gvfppo3C4sw==
+
+"@esbuild/darwin-arm64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.16.tgz#3c5a083e6e08a50f478fa243939989d86be1c6bf"
+ integrity sha512-aBxruWCII+OtluORR/KvisEw0ALuw/qDQWvkoosA+c/ngC/Kwk0lLaZ+B++LLS481/VdydB2u6tYpWxUfnLAIw==
+
+"@esbuild/darwin-x64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.16.tgz#a8f3b61bee2807131cbe28eb164ad2b0333b59f5"
+ integrity sha512-6w4Dbue280+rp3LnkgmriS1icOUZDyPuZo/9VsuMUTns7SYEiOaJ7Ca1cbhu9KVObAWfmdjUl4gwy9TIgiO5eA==
+
+"@esbuild/freebsd-arm64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.16.tgz#9bdbb3f0e5f0842b21c9b8602e70c106174ac24c"
+ integrity sha512-x35fCebhe9s979DGKbVAwXUOcTmCIE32AIqB9CB1GralMIvxdnMLAw5CnID17ipEw9/3MvDsusj/cspYt2ZLNQ==
+
+"@esbuild/freebsd-x64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.16.tgz#24f73956436495cc7a5a4bf06be6b661aea6a2c1"
+ integrity sha512-YM98f+PeNXF3GbxIJlUsj+McUWG1irguBHkszCIwfr3BXtXZsXo0vqybjUDFfu9a8Wr7uUD/YSmHib+EeGAFlg==
+
+"@esbuild/linux-arm64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.16.tgz#244569757f9cbd912f5a595a8ad8144f8c915f13"
+ integrity sha512-XIqhNUxJiuy+zsR77+H5Z2f7s4YRlriSJKtvx99nJuG5ATuJPjmZ9n0ANgnGlPCpXGSReFpgcJ7O3SMtzIFeiQ==
+
+"@esbuild/linux-arm@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.16.tgz#d63923c63af534032cc5ea0b2a0b3de10f8357f5"
+ integrity sha512-b5ABb+5Ha2C9JkeZXV+b+OruR1tJ33ePmv9ZwMeETSEKlmu/WJ45XTTG+l6a2KDsQtJJ66qo/hbSGBtk0XVLHw==
+
+"@esbuild/linux-ia32@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.16.tgz#a8825ccea6309f0bccfc5d87b43163ba804c2f20"
+ integrity sha512-no+pfEpwnRvIyH+txbBAWtjxPU9grslmTBfsmDndj7bnBmr55rOo/PfQmRfz7Qg9isswt1FP5hBbWb23fRWnow==
+
+"@esbuild/linux-loong64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.16.tgz#f530e820fc3c61cf2206155b994aeab53b6d25be"
+ integrity sha512-Zbnczs9ZXjmo0oZSS0zbNlJbcwKXa/fcNhYQjahDs4Xg18UumpXG/lwM2lcSvHS3mTrRyCYZvJbmzYc4laRI1g==
+
+"@esbuild/linux-mips64el@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.16.tgz#2d47ace539257896865d243641bd6716684a1e82"
+ integrity sha512-YMF7hih1HVR/hQVa/ot4UVffc5ZlrzEb3k2ip0nZr1w6fnYypll9td2qcoMLvd3o8j3y6EbJM3MyIcXIVzXvQQ==
+
+"@esbuild/linux-ppc64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.16.tgz#d6913e7e9be9e242a6a20402800141bdbe7009f7"
+ integrity sha512-Wkz++LZ29lDwUyTSEnzDaaP5OveOgTU69q9IyIw9WqLRxM4BjTBjz9un4G6TOvehWpf/J3gYVFN96TjGHrbcNQ==
+
+"@esbuild/linux-riscv64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.16.tgz#8f33b627389c8234fe61f4636c134f17fb1d9b09"
+ integrity sha512-LFMKZ30tk78/mUv1ygvIP+568bwf4oN6reG/uczXnz6SvFn4e2QUFpUpZY9iSJT6Qpgstrhef/nMykIXZtZWGQ==
+
+"@esbuild/linux-s390x@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.16.tgz#4d44c030f78962cf410f604f92fcc1505e4afdde"
+ integrity sha512-3ZC0BgyYHYKfZo3AV2/66TD/I9tlSBaW7eWTEIkrQQKfJIifKMMttXl9FrAg+UT0SGYsCRLI35Gwdmm96vlOjg==
+
+"@esbuild/linux-x64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.16.tgz#8846d00e16b1e93eb488c8b4dd51c946adfc236f"
+ integrity sha512-xu86B3647DihHJHv/wx3NCz2Dg1gjQ8bbf9cVYZzWKY+gsvxYmn/lnVlqDRazObc3UMwoHpUhNYaZset4X8IPA==
+
+"@esbuild/netbsd-x64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.16.tgz#6514a86bd07744f3100d2813ea2fb6520d53e72e"
+ integrity sha512-uVAgpimx9Ffw3xowtg/7qQPwHFx94yCje+DoBx+LNm2ePDpQXHrzE+Sb0Si2VBObYz+LcRps15cq+95YM7gkUw==
+
+"@esbuild/openbsd-x64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.16.tgz#ae67ce766d58aab6c0e6037f1a76f15df4a2a5fe"
+ integrity sha512-6OjCQM9wf7z8/MBi6BOWaTL2AS/SZudsZtBziXMtNI8r/U41AxS9x7jn0ATOwVy08OotwkPqGRMkpPR2wcTJXA==
+
+"@esbuild/sunos-x64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.16.tgz#998efe8a58374b7351ac710455051639a6ce6a05"
+ integrity sha512-ZoNkruFYJp9d1LbUYCh8awgQDvB9uOMZqlQ+gGEZR7v6C+N6u7vPr86c+Chih8niBR81Q/bHOSKGBK3brJyvkQ==
+
+"@esbuild/win32-arm64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.16.tgz#8de33682243508eef8d4de1816df2c05adad2b21"
+ integrity sha512-+j4anzQ9hrs+iqO+/wa8UE6TVkKua1pXUb0XWFOx0FiAj6R9INJ+WE//1/Xo6FG1vB5EpH3ko+XcgwiDXTxcdw==
+
+"@esbuild/win32-ia32@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.16.tgz#95c9f4274fb3ef9e449d464ffe3e3b7fa091503b"
+ integrity sha512-5PFPmq3sSKTp9cT9dzvI67WNfRZGvEVctcZa1KGjDDu4n3H8k59Inbk0du1fz0KrAbKKNpJbdFXQMDUz7BG4rQ==
+
+"@esbuild/win32-x64@0.18.16":
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.16.tgz#5be58d31d0120c68af8e38b702e6937ce764cd68"
+ integrity sha512-sCIVrrtcWN5Ua7jYXNG1xD199IalrbfV2+0k/2Zf2OyV2FtnQnMgdzgpRAbi4AWlKJj1jkX+M+fEGPQj6BQB4w==
+
+"@jridgewell/gen-mapping@^0.3.2":
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
+ integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
+ dependencies:
+ "@jridgewell/set-array" "^1.0.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/resolve-uri@3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
+ integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
+
+"@jridgewell/set-array@^1.0.1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
+ integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
+
+"@jridgewell/sourcemap-codec@1.4.14":
+ version "1.4.14"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
+ integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
+
+"@jridgewell/sourcemap-codec@^1.4.10":
+ version "1.4.15"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+ integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
+"@jridgewell/trace-mapping@^0.3.9":
+ version "0.3.18"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6"
+ integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==
+ dependencies:
+ "@jridgewell/resolve-uri" "3.1.0"
+ "@jridgewell/sourcemap-codec" "1.4.14"
+
+"@lezer/common@^1.0.0":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.0.3.tgz#1808f70e2b0a7b1fdcbaf5c074723d2d4ed1e4c5"
+ integrity sha512-JH4wAXCgUOcCGNekQPLhVeUtIqjH0yPBs7vvUdSjyQama9618IOKFJwkv2kcqdhF0my8hQEgCTEJU0GIgnahvA==
+
+"@lezer/highlight@^1.0.0", "@lezer/highlight@^1.1.3":
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.1.6.tgz#87e56468c0f43c2a8b3dc7f0b7c2804b34901556"
+ integrity sha512-cmSJYa2us+r3SePpRCjN5ymCqCPv+zyXmDl0ciWtVaNiORT/MxM7ZgOMQZADD0o51qOaOg24qc/zBViOIwAjJg==
+ dependencies:
+ "@lezer/common" "^1.0.0"
+
+"@lezer/javascript@^1.0.0":
+ version "1.4.4"
+ resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.4.4.tgz#f876c1ad2ecc2a52d9e33b5f5c0bd9935ea2d8c0"
+ integrity sha512-0BiBjpEcrt2IXrIzEAsdTLylrVhGHRqVQL3baTBx1sf4qewjIvhG1/pTUumu7W/7YR0AASjLQOQxFmo5EvNmzQ==
+ dependencies:
+ "@lezer/highlight" "^1.1.3"
+ "@lezer/lr" "^1.3.0"
+
+"@lezer/lr@^1.0.0", "@lezer/lr@^1.3.0":
+ version "1.3.9"
+ resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.3.9.tgz#cb299816d1c58efcca23ebbeb70bb4204fdd001b"
+ integrity sha512-XPz6dzuTHlnsbA5M2DZgjflNQ+9Hi5Swhic0RULdp3oOs3rh6bqGZolosVqN/fQIT8uNiepzINJDnS39oweTHQ==
+ dependencies:
+ "@lezer/common" "^1.0.0"
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@replit/codemirror-vim@^6.0.14":
+ version "6.0.14"
+ resolved "https://registry.yarnpkg.com/@replit/codemirror-vim/-/codemirror-vim-6.0.14.tgz#8f44740b0497406b551726946c9b30f21c867671"
+ integrity sha512-wwhqhvL76FdRTdwfUWpKCbv0hkp2fvivfMosDVlL/popqOiNLtUhL02ThgHZH8mus/NkVr5Mj582lyFZqQrjOA==
+
+any-promise@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
+ integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
+
+anymatch@~3.1.2:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+arg@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
+ integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
+
+autoprefixer@^10.4.14:
+ version "10.4.14"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d"
+ integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==
+ dependencies:
+ browserslist "^4.21.5"
+ caniuse-lite "^1.0.30001464"
+ fraction.js "^4.2.0"
+ normalize-range "^0.1.2"
+ picocolors "^1.0.0"
+ postcss-value-parser "^4.2.0"
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+binary-extensions@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+ integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+braces@^3.0.2, braces@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+browserslist@^4.21.5:
+ version "4.21.9"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635"
+ integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==
+ dependencies:
+ caniuse-lite "^1.0.30001503"
+ electron-to-chromium "^1.4.431"
+ node-releases "^2.0.12"
+ update-browserslist-db "^1.0.11"
+
+camelcase-css@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
+ integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
+
+caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001503:
+ version "1.0.30001517"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz#90fabae294215c3495807eb24fc809e11dc2f0a8"
+ integrity sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==
+
+chokidar@^3.5.3:
+ version "3.5.3"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
+ integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
+ dependencies:
+ anymatch "~3.1.2"
+ braces "~3.0.2"
+ glob-parent "~5.1.2"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.6.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+codemirror@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.1.tgz#62b91142d45904547ee3e0e0e4c1a79158035a29"
+ integrity sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==
+ dependencies:
+ "@codemirror/autocomplete" "^6.0.0"
+ "@codemirror/commands" "^6.0.0"
+ "@codemirror/language" "^6.0.0"
+ "@codemirror/lint" "^6.0.0"
+ "@codemirror/search" "^6.0.0"
+ "@codemirror/state" "^6.0.0"
+ "@codemirror/view" "^6.0.0"
+
+commander@^4.0.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
+ integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+crelt@^1.0.5:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.6.tgz#7cc898ea74e190fb6ef9dae57f8f81cf7302df72"
+ integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==
+
+cssesc@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
+ integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+
+didyoumean@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
+ integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
+
+dlv@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
+ integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
+
+electron-to-chromium@^1.4.431:
+ version "1.4.468"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.468.tgz#3cbf64ad67d9f12bfe69fefe5eb1935ec4f6ab7a"
+ integrity sha512-6M1qyhaJOt7rQtNti1lBA0GwclPH+oKCmsra/hkcWs5INLxfXXD/dtdnaKUYQu/pjOBP/8Osoe4mAcNvvzoFag==
+
+esbuild@^0.18.10:
+ version "0.18.16"
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.16.tgz#bbeb058c556152bcbff4e8168e7c93020ccf09c3"
+ integrity sha512-1xLsOXrDqwdHxyXb/x/SOyg59jpf/SH7YMvU5RNSU7z3TInaASNJWNFJ6iRvLvLETZMasF3d1DdZLg7sgRimRQ==
+ optionalDependencies:
+ "@esbuild/android-arm" "0.18.16"
+ "@esbuild/android-arm64" "0.18.16"
+ "@esbuild/android-x64" "0.18.16"
+ "@esbuild/darwin-arm64" "0.18.16"
+ "@esbuild/darwin-x64" "0.18.16"
+ "@esbuild/freebsd-arm64" "0.18.16"
+ "@esbuild/freebsd-x64" "0.18.16"
+ "@esbuild/linux-arm" "0.18.16"
+ "@esbuild/linux-arm64" "0.18.16"
+ "@esbuild/linux-ia32" "0.18.16"
+ "@esbuild/linux-loong64" "0.18.16"
+ "@esbuild/linux-mips64el" "0.18.16"
+ "@esbuild/linux-ppc64" "0.18.16"
+ "@esbuild/linux-riscv64" "0.18.16"
+ "@esbuild/linux-s390x" "0.18.16"
+ "@esbuild/linux-x64" "0.18.16"
+ "@esbuild/netbsd-x64" "0.18.16"
+ "@esbuild/openbsd-x64" "0.18.16"
+ "@esbuild/sunos-x64" "0.18.16"
+ "@esbuild/win32-arm64" "0.18.16"
+ "@esbuild/win32-ia32" "0.18.16"
+ "@esbuild/win32-x64" "0.18.16"
+
+escalade@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
+ integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+
+fast-glob@^3.2.12:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4"
+ integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
+fastq@^1.6.0:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
+ integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
+ dependencies:
+ reusify "^1.0.4"
+
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+fraction.js@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
+ integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+fsevents@~2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
+function-bind@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+glob-parent@^5.1.2, glob-parent@~5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob-parent@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+ dependencies:
+ is-glob "^4.0.3"
+
+glob@7.1.6:
+ version "7.1.6"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
+ integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-core-module@^2.11.0:
+ version "2.12.1"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd"
+ integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==
+ dependencies:
+ has "^1.0.3"
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+jiti@^1.18.2:
+ version "1.19.1"
+ resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.1.tgz#fa99e4b76a23053e0e7cde098efe1704a14c16f1"
+ integrity sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==
+
+lilconfig@^2.0.5, lilconfig@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
+ integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
+
+lines-and-columns@^1.1.6:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
+ integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+
+merge2@^1.3.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+micromatch@^4.0.4, micromatch@^4.0.5:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+ integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+ dependencies:
+ braces "^3.0.2"
+ picomatch "^2.3.1"
+
+minimatch@^3.0.4:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+mz@^2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
+ integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
+ dependencies:
+ any-promise "^1.0.0"
+ object-assign "^4.0.1"
+ thenify-all "^1.0.0"
+
+nanoid@^3.3.6:
+ version "3.3.6"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
+ integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
+
+node-releases@^2.0.12:
+ version "2.0.13"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d"
+ integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+normalize-range@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+ integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
+
+object-assign@^4.0.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+ integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
+
+object-hash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
+ integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+picocolors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
+ integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+ integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
+
+pirates@^4.0.1:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
+ integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==
+
+postcss-import@^15.1.0:
+ version "15.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70"
+ integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==
+ dependencies:
+ postcss-value-parser "^4.0.0"
+ read-cache "^1.0.0"
+ resolve "^1.1.7"
+
+postcss-js@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2"
+ integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==
+ dependencies:
+ camelcase-css "^2.0.1"
+
+postcss-load-config@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.1.tgz#152383f481c2758274404e4962743191d73875bd"
+ integrity sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==
+ dependencies:
+ lilconfig "^2.0.5"
+ yaml "^2.1.1"
+
+postcss-nested@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c"
+ integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==
+ dependencies:
+ postcss-selector-parser "^6.0.11"
+
+postcss-selector-parser@^6.0.11:
+ version "6.0.13"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b"
+ integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
+ integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
+
+postcss@^8.4.23, postcss@^8.4.26, postcss@^8.4.27:
+ version "8.4.27"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057"
+ integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==
+ dependencies:
+ nanoid "^3.3.6"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.2"
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+read-cache@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
+ integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
+ dependencies:
+ pify "^2.3.0"
+
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
+resolve@^1.1.7, resolve@^1.22.2:
+ version "1.22.2"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
+ integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
+ dependencies:
+ is-core-module "^2.11.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rollup@^3.25.2:
+ version "3.26.3"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.26.3.tgz#bbc8818cadd0aebca348dbb3d68d296d220967b8"
+ integrity sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ==
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+source-map-js@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
+ integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
+
+style-mod@^4.0.0:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.0.3.tgz#136c4abc905f82a866a18b39df4dc08ec762b1ad"
+ integrity sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw==
+
+sucrase@^3.32.0:
+ version "3.34.0"
+ resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.34.0.tgz#1e0e2d8fcf07f8b9c3569067d92fbd8690fb576f"
+ integrity sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.2"
+ commander "^4.0.0"
+ glob "7.1.6"
+ lines-and-columns "^1.1.6"
+ mz "^2.7.0"
+ pirates "^4.0.1"
+ ts-interface-checker "^0.1.9"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+tailwindcss@^3.3.3:
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.3.tgz#90da807393a2859189e48e9e7000e6880a736daf"
+ integrity sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==
+ dependencies:
+ "@alloc/quick-lru" "^5.2.0"
+ arg "^5.0.2"
+ chokidar "^3.5.3"
+ didyoumean "^1.2.2"
+ dlv "^1.1.3"
+ fast-glob "^3.2.12"
+ glob-parent "^6.0.2"
+ is-glob "^4.0.3"
+ jiti "^1.18.2"
+ lilconfig "^2.1.0"
+ micromatch "^4.0.5"
+ normalize-path "^3.0.0"
+ object-hash "^3.0.0"
+ picocolors "^1.0.0"
+ postcss "^8.4.23"
+ postcss-import "^15.1.0"
+ postcss-js "^4.0.1"
+ postcss-load-config "^4.0.1"
+ postcss-nested "^6.0.1"
+ postcss-selector-parser "^6.0.11"
+ resolve "^1.22.2"
+ sucrase "^3.32.0"
+
+thenify-all@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
+ integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==
+ dependencies:
+ thenify ">= 3.1.0 < 4"
+
+"thenify@>= 3.1.0 < 4":
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f"
+ integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
+ dependencies:
+ any-promise "^1.0.0"
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+ts-interface-checker@^0.1.9:
+ version "0.1.13"
+ resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
+ integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
+
+typescript@^5.0.2:
+ version "5.1.6"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274"
+ integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
+
+update-browserslist-db@^1.0.11:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940"
+ integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==
+ dependencies:
+ escalade "^3.1.1"
+ picocolors "^1.0.0"
+
+util-deprecate@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
+
+vite@^4.4.5:
+ version "4.4.6"
+ resolved "https://registry.yarnpkg.com/vite/-/vite-4.4.6.tgz#97a0a43868ec773fd88980d7c323c80233521cf1"
+ integrity sha512-EY6Mm8vJ++S3D4tNAckaZfw3JwG3wa794Vt70M6cNJ6NxT87yhq7EC8Rcap3ahyHdo8AhCmV9PTk+vG1HiYn1A==
+ dependencies:
+ esbuild "^0.18.10"
+ postcss "^8.4.26"
+ rollup "^3.25.2"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+w3c-keyname@^2.2.4:
+ version "2.2.8"
+ resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5"
+ integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+yaml@^2.1.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b"
+ integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==
+
+zzfx@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/zzfx/-/zzfx-1.2.0.tgz#021e5df8e1605f507e2dde15608eba22798b424b"
+ integrity sha512-RtFz6PTMfCmxTfaCOv6GWAV4YaL/T0hltiMGkd87clybO8WLPlH6kX8sNkZGFKw9YPyu1UNsUYf/5/Vn4dondA==