diff --git a/app/components/note/Avatar.tsx b/app/components/note/Avatar.tsx
new file mode 100644
index 0000000..930d48f
--- /dev/null
+++ b/app/components/note/Avatar.tsx
@@ -0,0 +1,97 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { useOthers, useSelf } from '@liveblocks/react/suspense'
+import cn from 'classnames'
+import { Tooltip } from 'radix-ui'
+
+import { getPresenceColor } from './Presence'
+
+export const Avatars = () => {
+ const users = useOthers()
+ const currentUser = useSelf()
+
+ // Removes duplicate users and other sessions that match the current user
+ const filteredUsers = users.filter(
+ (user, index, self) =>
+ user.id !== currentUser.id &&
+ user.info.name !== 'Service Account' &&
+ index === self.findIndex((u) => u.id === user.id),
+ )
+
+ const hasMoreUsers = filteredUsers.length > 3
+
+ return (
+
+
+ {currentUser &&
}
+
+ {filteredUsers.slice(0, 3).map(({ id, connectionId, info }) => {
+ return (
+
+ )
+ })}
+
+ {hasMoreUsers && (
+
+{filteredUsers.length - 3}
+ )}
+
+
+ )
+}
+
+export const Avatar = ({
+ id,
+ name,
+ className,
+}: {
+ id: string
+ name: string
+ className?: string
+}) => {
+ const { fg, bg } = getPresenceColor(id)
+
+ return (
+
+
+
+ {getInitials(name)}
+
+
+
+ {name}
+
+
+ )
+}
+
+export const getInitials = (text: string) => {
+ const names = text.split(' ')
+ let initials = names[0].substring(0, 1).toUpperCase()
+
+ if (names.length > 1) {
+ initials += names[names.length - 1].substring(0, 1).toUpperCase()
+ }
+ return initials
+}
diff --git a/app/components/note/Editor.tsx b/app/components/note/Editor.tsx
new file mode 100644
index 0000000..6416ef1
--- /dev/null
+++ b/app/components/note/Editor.tsx
@@ -0,0 +1,110 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { EditorState } from '@codemirror/state'
+import { useRoom } from '@liveblocks/react/suspense'
+import { LiveblocksYjsProvider } from '@liveblocks/yjs'
+import { createTheme, type CreateThemeOptions } from '@uiw/codemirror-themes'
+import { basicSetup, EditorView } from 'codemirror'
+import { useCallback, useEffect, useState, type Dispatch, type SetStateAction } from 'react'
+import { yCollab } from 'y-codemirror.next'
+import * as Y from 'yjs'
+
+import { getPresenceColor } from './Presence'
+
+const themeSettings: CreateThemeOptions['settings'] = {
+ background: 'var(--surface-raise)',
+ foreground: 'var(--content-raise)',
+ caret: 'var(--base-neutral-800)',
+ selection: 'rgba(255, 255, 255, 0.1)',
+ selectionMatch: 'rgba(255, 255, 255, 0.2)',
+ gutterBackground: 'var(--base-neutral-200)',
+ gutterForeground: 'var(--base-neutral-600)',
+ gutterBorder: 'transparent',
+ lineHighlight: 'rgba(255, 255, 255, 0.1)',
+}
+
+export const theme = (options?: Partial
) => {
+ const { theme = 'dark' } = options || {}
+ return createTheme({
+ theme: theme,
+ settings: {
+ ...themeSettings,
+ },
+ styles: [],
+ })
+}
+
+const EditorWrapper = ({
+ userId,
+ userName,
+ onUpdate,
+}: {
+ userId: string
+ userName: string
+ onUpdate: Dispatch>
+}) => {
+ const room = useRoom()
+ const [element, setElement] = useState()
+
+ const ref = useCallback((node: HTMLElement | null) => {
+ if (!node) return
+ setElement(node)
+ }, [])
+
+ useEffect(() => {
+ let provider: LiveblocksYjsProvider
+ let ydoc: Y.Doc
+ let view: EditorView
+
+ if (!element || !room) {
+ return
+ }
+
+ ydoc = new Y.Doc()
+ provider = new LiveblocksYjsProvider(room as any, ydoc)
+ const ytext = ydoc.getText('codemirror')
+ const undoManager = new Y.UndoManager(ytext)
+
+ const { fg } = getPresenceColor(userId)
+
+ provider.awareness.setLocalStateField('user', {
+ name: userName,
+ color: fg,
+ })
+
+ const state = EditorState.create({
+ doc: ytext.toString(),
+ extensions: [
+ basicSetup,
+ yCollab(ytext, provider.awareness, { undoManager }),
+ theme(),
+ EditorView.lineWrapping,
+ EditorView.updateListener.of((update) => {
+ if (update.docChanged) {
+ onUpdate(update.state.doc.toString())
+ }
+ }),
+ ],
+ })
+
+ view = new EditorView({
+ state,
+ parent: element,
+ })
+
+ return () => {
+ ydoc?.destroy()
+ provider?.destroy()
+ view?.destroy()
+ }
+ }, [element, room, onUpdate, userName, userId])
+
+ return
+}
+
+export default EditorWrapper
diff --git a/app/components/note/NoteForm.tsx b/app/components/note/NoteForm.tsx
new file mode 100644
index 0000000..9bffcce
--- /dev/null
+++ b/app/components/note/NoteForm.tsx
@@ -0,0 +1,261 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { useMutation, useStorage, useSyncStatus } from '@liveblocks/react/suspense'
+import { Spinner } from '@oxide/design-system'
+import { Asciidoc, prepareDocument, type Options } from '@oxide/react-asciidoc'
+import * as Dropdown from '@radix-ui/react-dropdown-menu'
+import { useFetcher } from '@remix-run/react'
+import { useQueryClient, type QueryClient } from '@tanstack/react-query'
+import dayjs from 'dayjs'
+import { useCallback, useMemo, useState, type ChangeEvent } from 'react'
+
+import { opts } from '~/components/AsciidocBlocks'
+import { DropdownItem, DropdownMenu } from '~/components/Dropdown'
+import Icon from '~/components/Icon'
+import { ad } from '~/utils/asciidoctor'
+
+import { MinimalDocument } from '../AsciidocBlocks/Document'
+import { Avatars } from './Avatar'
+import EditorWrapper from './Editor'
+import RoomErrors from './RoomErrors'
+import { SidebarIcon } from './Sidebar'
+
+const noteOpts: Options = {
+ ...opts,
+ customDocument: MinimalDocument,
+}
+
+function debounce any>(
+ func: T,
+ wait: number,
+): (...args: Parameters) => void {
+ let timeout: NodeJS.Timeout | null = null
+
+ return (...args: Parameters) => {
+ if (timeout) {
+ clearTimeout(timeout)
+ }
+
+ timeout = setTimeout(() => {
+ func(...args)
+ }, wait)
+ }
+}
+
+// debouncing the invalidate when the title changes
+export const invalidateNotes = debounce((queryClient: QueryClient) => {
+ queryClient.invalidateQueries({ queryKey: ['notesList'] })
+}, 500)
+
+export const NoteForm = ({
+ userId,
+ userName,
+ id,
+ isOwner,
+ published,
+ sidebarOpen,
+ setSidebarOpen,
+}: {
+ userId: string
+ userName: string
+ id: string
+ isOwner: boolean
+ published: 'true' | 'false'
+ sidebarOpen: boolean
+ setSidebarOpen: (bool: boolean) => void
+}) => {
+ const title = useStorage((root) => root.meta.title)
+ const lastUpdated = useStorage((root) => root.meta.lastUpdated)
+ const queryClient = useQueryClient()
+
+ const handleChange = useMutation(({ storage }, e: ChangeEvent) => {
+ storage.get('meta').set('title', e.target.value)
+ invalidateNotes(queryClient)
+ }, [])
+
+ const [body, setBody] = useState('')
+
+ // Handle window resizing
+ const [leftPaneWidth, setLeftPaneWidth] = useState(50) // Initial width in percentage
+
+ const handleMouseDown = useCallback(
+ (e: React.MouseEvent) => {
+ e.preventDefault()
+ const startX = e.clientX
+ const startWidth = leftPaneWidth
+
+ const handleMouseMove = (moveEvent: MouseEvent) => {
+ const dx = moveEvent.clientX - startX
+ const newWidth =
+ (((startWidth / 100) * window.innerWidth + dx) * 100) / window.innerWidth
+ setLeftPaneWidth(Math.max(20, Math.min(80, newWidth)))
+ }
+
+ const handleMouseUp = () => {
+ document.removeEventListener('mousemove', handleMouseMove)
+ document.removeEventListener('mouseup', handleMouseUp)
+ }
+
+ document.addEventListener('mousemove', handleMouseMove)
+ document.addEventListener('mouseup', handleMouseUp)
+ },
+ [leftPaneWidth],
+ )
+
+ const doc = useMemo(() => {
+ const adoc = ad.load(body, {
+ standalone: true,
+ attributes: {
+ sectnums: false,
+ },
+ })
+ adoc.setTitle(title) // use note title as document title
+ return prepareDocument(adoc)
+ }, [title, body])
+
+ return (
+
+
+
+
setSidebarOpen(!sidebarOpen)}
+ className="-m-2 -mr-1 rounded p-2 hover:bg-hover"
+ type="button"
+ >
+
+
+
+
+ {title ? title : 'Title...'}
+
+
+
+
+ {isOwner &&
}
+
+ {/* todo: Handle errors visibly not just console */}
+
+
+
+
+ {lastUpdated && (
+
+ {dayjs(lastUpdated).format('MMM D YYYY, h:mm A')}
+
+ )}
+
+
+
+
+
+
+ )
+}
+
+export const TypingIndicator = () => (
+
+
+
+
+
+)
+
+const SavingIndicator = () => {
+ const syncStatus = useSyncStatus({ smooth: true })
+
+ return (
+
+
+ {syncStatus === 'synchronized' ? (
+
+ ) : (
+
+ )}
+
+
+ )
+}
+
+const MoreDropdown = ({ id, published }: { id: string; published: 'true' | 'false' }) => {
+ const fetcher = useFetcher()
+
+ const handleDelete = () => {
+ if (window.confirm('Are you sure you want to delete this note?')) {
+ fetcher.submit(null, {
+ method: 'post',
+ action: `/notes/${id}/delete`,
+ })
+ }
+ }
+
+ const handlePublish = async () => {
+ const isPublished = published === 'true'
+ const confirmationMessage = isPublished
+ ? 'Are you sure you want to unpublish this note?'
+ : 'Are you sure you want to publish this note?'
+
+ if (window.confirm(confirmationMessage)) {
+ fetcher.submit(
+ { publish: isPublished ? 'false' : 'true' },
+ {
+ method: 'post',
+ action: `/notes/${id}/publish`,
+ encType: 'application/json',
+ },
+ )
+ }
+ }
+
+ return (
+
+
+
+
+
+
+
+ {published === 'true' ? 'Unpublish' : 'Publish'}
+
+
+ Delete
+
+
+
+ )
+}
diff --git a/app/components/note/Presence.ts b/app/components/note/Presence.ts
new file mode 100644
index 0000000..add48f5
--- /dev/null
+++ b/app/components/note/Presence.ts
@@ -0,0 +1,24 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+export const PRESENCE_COLORS = [
+ { fg: 'var(--base-green-800)', bg: 'var(--base-green-200)' },
+ { fg: 'var(--base-yellow-800)', bg: 'var(--base-yellow-200)' },
+ { fg: 'var(--base-blue-800)', bg: 'var(--base-blue-200)' },
+ { fg: 'var(--base-purple-800)', bg: 'var(--base-purple-200)' },
+] as const
+
+/*
+ Get a hash from users name and pick a colour from it
+ For easy deterministic user colours
+ */
+export const getPresenceColor = (name: string) => {
+ const hash = name.split('').reduce((acc, char) => {
+ return char.charCodeAt(0) + ((acc << 5) - acc)
+ }, 0)
+ return PRESENCE_COLORS[Math.abs(hash) % PRESENCE_COLORS.length]
+}
diff --git a/app/components/note/RoomErrors.tsx b/app/components/note/RoomErrors.tsx
new file mode 100644
index 0000000..b7bbe84
--- /dev/null
+++ b/app/components/note/RoomErrors.tsx
@@ -0,0 +1,53 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { useErrorListener, useLostConnectionListener } from '@liveblocks/react/suspense'
+
+export default function RoomErrors() {
+ useErrorListener((error) => {
+ console.log(error)
+ switch (error.code) {
+ case -1:
+ // Authentication error
+ console.error("You don't have access to this room")
+ break
+
+ case 4001:
+ // Could not connect because you don't have access to this room
+ console.error("You don't have access to this room")
+ break
+
+ case 4005:
+ // Could not connect because room was full
+ console.error('Could not connect because the room is full')
+ break
+
+ default:
+ // Unexpected error
+ console.error('An unexpected error happenned')
+ break
+ }
+ })
+
+ useLostConnectionListener((event) => {
+ switch (event) {
+ case 'lost':
+ console.info('Still trying to reconnect…')
+ break
+
+ case 'restored':
+ console.log('Successfully reconnected again!')
+ break
+
+ case 'failed':
+ console.error('Could not restore the connection')
+ break
+ }
+ })
+
+ return null
+}
diff --git a/app/components/note/Sidebar.tsx b/app/components/note/Sidebar.tsx
new file mode 100644
index 0000000..01bd889
--- /dev/null
+++ b/app/components/note/Sidebar.tsx
@@ -0,0 +1,155 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { buttonStyle } from '@oxide/design-system'
+import { Link, NavLink } from '@remix-run/react'
+import { useQuery } from '@tanstack/react-query'
+import cn from 'classnames'
+import { type ReactNode } from 'react'
+
+import Icon from '~/components/Icon'
+
+interface Note {
+ id: string
+ metadata: {
+ title: string
+ published: string
+ }
+ user: string
+}
+
+export function useNotes() {
+ return useQuery({
+ queryKey: ['notesList'],
+ queryFn: async () => {
+ const response = await fetch('/notes/list')
+ return response.json()
+ },
+ refetchInterval: 30000, // refetch every 30 seconds
+ })
+}
+
+const navLinkStyles = ({ isActive }: { isActive: boolean }) => {
+ const activeStyle = isActive
+ ? 'bg-accent-secondary hover:!bg-accent-secondary-hover text-accent'
+ : null
+ return `block text-sans-md text-secondary hover:bg-hover px-2 py-1 rounded flex items-center group justify-between ${activeStyle}`
+}
+
+const Divider = ({ className }: { className?: string }) => (
+
+)
+
+export const SidebarIcon = () => (
+
+
+
+)
+
+const BackToRfds = () => (
+
+
+ Back to RFDs
+
+
+)
+
+export const Sidebar = () => {
+ const { data: notes, isLoading } = useNotes()
+
+ const isEmpty = isLoading || !notes || notes.length === 0
+
+ const publishedNotes = notes
+ ? notes.filter((note) => note.metadata.published === 'true')
+ : []
+ const draftNotes = notes
+ ? notes.filter((note) => note.metadata.published === 'false')
+ : []
+
+ return (
+
+ {isEmpty ? (
+ <>
+
+
+ >
+ ) : (
+ <>
+
+
+
+
+ {publishedNotes.length > 0 && (
+ <>
+
+ {publishedNotes.map((note) => (
+
+
+ {note.metadata.title}
+
+
+ ))}
+
+
+ >
+ )}
+
+
+ {draftNotes.map((note) => (
+
+ {note.metadata.title}
{' '}
+
+ ))}
+
+
+
+
+
+ >
+ )}
+
+ )
+}
+
+const LinkSection = ({ label, children }: { label: string; children: ReactNode }) => (
+
+)
diff --git a/app/components/note/oxide-dark.json b/app/components/note/oxide-dark.json
new file mode 100644
index 0000000..2254877
--- /dev/null
+++ b/app/components/note/oxide-dark.json
@@ -0,0 +1,1386 @@
+{
+ "name": "oxide-dark",
+ "colors": {
+ "editor.background": "#080F11",
+ "editor.foreground": "#E7E7E8"
+ },
+ "tokenColors": [
+ {
+ "scope": [
+ "text",
+ "source",
+ "variable.other.readwrite",
+ "punctuation.definition.variable"
+ ],
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": "punctuation",
+ "settings": {
+ "foreground": "#A1A4A5",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": ["comment", "punctuation.definition.comment"],
+ "settings": {
+ "foreground": "#A1A4A5",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": ["string", "punctuation.definition.string"],
+ "settings": {
+ "foreground": "#68D9A7"
+ }
+ },
+ {
+ "scope": "constant.character.escape",
+ "settings": {
+ "foreground": "#EFB7C2"
+ }
+ },
+ {
+ "scope": [
+ "constant.numeric",
+ "variable.other.constant",
+ "entity.name.constant",
+ "constant.language.boolean",
+ "constant.language.false",
+ "constant.language.true",
+ "keyword.other.unit.user-defined",
+ "keyword.other.unit.suffix.floating-point"
+ ],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": [
+ "keyword",
+ "keyword.operator.word",
+ "keyword.operator.new",
+ "variable.language.super",
+ "support.type.primitive",
+ "storage.type",
+ "storage.modifier",
+ "punctuation.definition.keyword"
+ ],
+ "settings": {
+ "foreground": "#C6A5EA",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": "entity.name.tag.documentation",
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": [
+ "keyword.operator",
+ "punctuation.accessor",
+ "punctuation.definition.generic",
+ "meta.function.closure punctuation.section.parameters",
+ "punctuation.definition.tag",
+ "punctuation.separator.key-value"
+ ],
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": [
+ "entity.name.function",
+ "meta.function-call.method",
+ "support.function",
+ "support.function.misc",
+ "variable.function"
+ ],
+ "settings": {
+ "foreground": "#9DAFFA",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": [
+ "entity.name.class",
+ "entity.other.inherited-class",
+ "support.class",
+ "meta.function-call.constructor",
+ "entity.name.struct"
+ ],
+ "settings": {
+ "foreground": "#EDD5A6",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": "entity.name.enum",
+ "settings": {
+ "foreground": "#EDD5A6",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": ["meta.enum variable.other.readwrite", "variable.other.enummember"],
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": "meta.property.object",
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": ["meta.type", "meta.type-alias", "support.type", "entity.name.type"],
+ "settings": {
+ "foreground": "#EDD5A6",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": [
+ "meta.annotation variable.function",
+ "meta.annotation variable.annotation.function",
+ "meta.annotation punctuation.definition.annotation",
+ "meta.decorator",
+ "punctuation.decorator"
+ ],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": ["variable.parameter", "meta.function.parameters"],
+ "settings": {
+ "foreground": "#F39EAE",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": ["constant.language", "support.function.builtin"],
+ "settings": {
+ "foreground": "#F7869B"
+ }
+ },
+ {
+ "scope": "entity.other.attribute-name.documentation",
+ "settings": {
+ "foreground": "#F7869B"
+ }
+ },
+ {
+ "scope": ["keyword.control.directive", "punctuation.definition.directive"],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "punctuation.definition.typeparameters",
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": "entity.name.namespace",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "support.type.property-name.css",
+ "settings": {
+ "foreground": "#9DAFFA",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": [
+ "variable.language.this",
+ "variable.language.this punctuation.definition.variable"
+ ],
+ "settings": {
+ "foreground": "#F7869B"
+ }
+ },
+ {
+ "scope": "variable.object.property",
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": ["string.template variable", "string variable"],
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": "keyword.operator.new",
+ "settings": {
+ "fontStyle": "bold"
+ }
+ },
+ {
+ "scope": "storage.modifier.specifier.extern.cpp",
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": [
+ "entity.name.scope-resolution.template.call.cpp",
+ "entity.name.scope-resolution.parameter.cpp",
+ "entity.name.scope-resolution.cpp",
+ "entity.name.scope-resolution.function.definition.cpp"
+ ],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "storage.type.class.doxygen",
+ "settings": {
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": ["storage.modifier.reference.cpp"],
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": "meta.interpolation.cs",
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": "comment.block.documentation.cs",
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": [
+ "source.css entity.other.attribute-name.class.css",
+ "entity.other.attribute-name.parent-selector.css punctuation.definition.entity.css"
+ ],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "punctuation.separator.operator.css",
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": "source.css entity.other.attribute-name.pseudo-class",
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": "source.css constant.other.unicode-range",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "source.css variable.parameter.url",
+ "settings": {
+ "foreground": "#88DCB7",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": ["support.type.vendored.property-name"],
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": [
+ "source.css meta.property-value variable",
+ "source.css meta.property-value variable.other.less",
+ "source.css meta.property-value variable.other.less punctuation.definition.variable.less",
+ "meta.definition.variable.scss"
+ ],
+ "settings": {
+ "foreground": "#F39EAE"
+ }
+ },
+ {
+ "scope": [
+ "source.css meta.property-list variable",
+ "meta.property-list variable.other.less",
+ "meta.property-list variable.other.less punctuation.definition.variable.less"
+ ],
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": "keyword.other.unit.percentage.css",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "source.css meta.attribute-selector",
+ "settings": {
+ "foreground": "#88DCB7"
+ }
+ },
+ {
+ "scope": [
+ "keyword.other.definition.ini",
+ "punctuation.support.type.property-name.json",
+ "support.type.property-name.json",
+ "punctuation.support.type.property-name.toml",
+ "support.type.property-name.toml",
+ "entity.name.tag.yaml",
+ "punctuation.support.type.property-name.yaml",
+ "support.type.property-name.yaml"
+ ],
+ "settings": {
+ "foreground": "#9DAFFA",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": ["constant.language.json", "constant.language.yaml"],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": ["entity.name.type.anchor.yaml", "variable.other.alias.yaml"],
+ "settings": {
+ "foreground": "#EDD5A6",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": ["support.type.property-name.table", "entity.name.section.group-title.ini"],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "constant.other.time.datetime.offset.toml",
+ "settings": {
+ "foreground": "#EFB7C2"
+ }
+ },
+ {
+ "scope": ["punctuation.definition.anchor.yaml", "punctuation.definition.alias.yaml"],
+ "settings": {
+ "foreground": "#EFB7C2"
+ }
+ },
+ {
+ "scope": "entity.other.document.begin.yaml",
+ "settings": {
+ "foreground": "#EFB7C2"
+ }
+ },
+ {
+ "scope": "markup.changed.diff",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": [
+ "meta.diff.header.from-file",
+ "meta.diff.header.to-file",
+ "punctuation.definition.from-file.diff",
+ "punctuation.definition.to-file.diff"
+ ],
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": "markup.inserted.diff",
+ "settings": {
+ "foreground": "#88DCB7"
+ }
+ },
+ {
+ "scope": "markup.deleted.diff",
+ "settings": {
+ "foreground": "#F7869B"
+ }
+ },
+ {
+ "scope": ["variable.other.env"],
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": ["string.quoted variable.other.env"],
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": "support.function.builtin.gdscript",
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": "constant.language.gdscript",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "comment meta.annotation.go",
+ "settings": {
+ "foreground": "#F39EAE"
+ }
+ },
+ {
+ "scope": "comment meta.annotation.parameters.go",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "constant.language.go",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "variable.graphql",
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": "string.unquoted.alias.graphql",
+ "settings": {
+ "foreground": "#F2CDCD"
+ }
+ },
+ {
+ "scope": "constant.character.enum.graphql",
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": "meta.objectvalues.graphql constant.object.key.graphql string.unquoted.graphql",
+ "settings": {
+ "foreground": "#F2CDCD"
+ }
+ },
+ {
+ "scope": [
+ "keyword.other.doctype",
+ "meta.tag.sgml.doctype punctuation.definition.tag",
+ "meta.tag.metadata.doctype entity.name.tag",
+ "meta.tag.metadata.doctype punctuation.definition.tag"
+ ],
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": ["entity.name.tag"],
+ "settings": {
+ "foreground": "#9DAFFA",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": [
+ "text.html constant.character.entity",
+ "text.html constant.character.entity punctuation",
+ "constant.character.entity.xml",
+ "constant.character.entity.xml punctuation",
+ "constant.character.entity.js.jsx",
+ "constant.charactger.entity.js.jsx punctuation",
+ "constant.character.entity.tsx",
+ "constant.character.entity.tsx punctuation"
+ ],
+ "settings": {
+ "foreground": "#F7869B"
+ }
+ },
+ {
+ "scope": ["entity.other.attribute-name"],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": [
+ "support.class.component",
+ "support.class.component.jsx",
+ "support.class.component.tsx",
+ "support.class.component.vue"
+ ],
+ "settings": {
+ "foreground": "#EFB7C2",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": ["punctuation.definition.annotation", "storage.type.annotation"],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "constant.other.enum.java",
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": "storage.modifier.import.java",
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": "comment.block.javadoc.java keyword.other.documentation.javadoc.java",
+ "settings": {
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": "meta.export variable.other.readwrite.js",
+ "settings": {
+ "foreground": "#F39EAE"
+ }
+ },
+ {
+ "scope": [
+ "variable.other.constant.js",
+ "variable.other.constant.ts",
+ "variable.other.property.js",
+ "variable.other.property.ts"
+ ],
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": ["variable.other.jsdoc", "comment.block.documentation variable.other"],
+ "settings": {
+ "foreground": "#F39EAE",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": "storage.type.class.jsdoc",
+ "settings": {
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": "support.type.object.console.js",
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": ["support.constant.node", "support.type.object.module.js"],
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": "storage.modifier.implements",
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": [
+ "constant.language.null.js",
+ "constant.language.null.ts",
+ "constant.language.undefined.js",
+ "constant.language.undefined.ts",
+ "support.type.builtin.ts"
+ ],
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": "variable.parameter.generic",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": ["keyword.declaration.function.arrow.js", "storage.type.function.arrow.ts"],
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": "punctuation.decorator.ts",
+ "settings": {
+ "foreground": "#9DAFFA",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": [
+ "keyword.operator.expression.in.js",
+ "keyword.operator.expression.in.ts",
+ "keyword.operator.expression.infer.ts",
+ "keyword.operator.expression.instanceof.js",
+ "keyword.operator.expression.instanceof.ts",
+ "keyword.operator.expression.is",
+ "keyword.operator.expression.keyof.ts",
+ "keyword.operator.expression.of.js",
+ "keyword.operator.expression.of.ts",
+ "keyword.operator.expression.typeof.ts"
+ ],
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": "support.function.macro.julia",
+ "settings": {
+ "foreground": "#A7E0C8",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": "constant.language.julia",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "constant.other.symbol.julia",
+ "settings": {
+ "foreground": "#F39EAE"
+ }
+ },
+ {
+ "scope": "text.tex keyword.control.preamble",
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": "text.tex support.function.be",
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": "constant.other.general.math.tex",
+ "settings": {
+ "foreground": "#F2CDCD"
+ }
+ },
+ {
+ "scope": "comment.line.double-dash.documentation.lua storage.type.annotation.lua",
+ "settings": {
+ "foreground": "#C6A5EA",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": [
+ "comment.line.double-dash.documentation.lua entity.name.variable.lua",
+ "comment.line.double-dash.documentation.lua variable.lua"
+ ],
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": [
+ "heading.1.markdown punctuation.definition.heading.markdown",
+ "heading.1.markdown",
+ "heading.1.quarto punctuation.definition.heading.quarto",
+ "heading.1.quarto",
+ "markup.heading.atx.1.mdx",
+ "markup.heading.atx.1.mdx punctuation.definition.heading.mdx",
+ "markup.heading.setext.1.markdown",
+ "markup.heading.heading-0.asciidoc"
+ ],
+ "settings": {
+ "foreground": "#F7869B"
+ }
+ },
+ {
+ "scope": [
+ "heading.2.markdown punctuation.definition.heading.markdown",
+ "heading.2.markdown",
+ "heading.2.quarto punctuation.definition.heading.quarto",
+ "heading.2.quarto",
+ "markup.heading.atx.2.mdx",
+ "markup.heading.atx.2.mdx punctuation.definition.heading.mdx",
+ "markup.heading.setext.2.markdown",
+ "markup.heading.heading-1.asciidoc"
+ ],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": [
+ "heading.3.markdown punctuation.definition.heading.markdown",
+ "heading.3.markdown",
+ "heading.3.quarto punctuation.definition.heading.quarto",
+ "heading.3.quarto",
+ "markup.heading.atx.3.mdx",
+ "markup.heading.atx.3.mdx punctuation.definition.heading.mdx",
+ "markup.heading.heading-2.asciidoc"
+ ],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": [
+ "heading.4.markdown punctuation.definition.heading.markdown",
+ "heading.4.markdown",
+ "heading.4.quarto punctuation.definition.heading.quarto",
+ "heading.4.quarto",
+ "markup.heading.atx.4.mdx",
+ "markup.heading.atx.4.mdx punctuation.definition.heading.mdx",
+ "markup.heading.heading-3.asciidoc"
+ ],
+ "settings": {
+ "foreground": "#88DCB7"
+ }
+ },
+ {
+ "scope": [
+ "heading.5.markdown punctuation.definition.heading.markdown",
+ "heading.5.markdown",
+ "heading.5.quarto punctuation.definition.heading.quarto",
+ "heading.5.quarto",
+ "markup.heading.atx.5.mdx",
+ "markup.heading.atx.5.mdx punctuation.definition.heading.mdx",
+ "markup.heading.heading-4.asciidoc"
+ ],
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": [
+ "heading.6.markdown punctuation.definition.heading.markdown",
+ "heading.6.markdown",
+ "heading.6.quarto punctuation.definition.heading.quarto",
+ "heading.6.quarto",
+ "markup.heading.atx.6.mdx",
+ "markup.heading.atx.6.mdx punctuation.definition.heading.mdx",
+ "markup.heading.heading-5.asciidoc"
+ ],
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": "markup.bold",
+ "settings": {
+ "foreground": "#F7869B",
+ "fontStyle": "bold"
+ }
+ },
+ {
+ "scope": "markup.italic",
+ "settings": {
+ "foreground": "#F7869B",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": "markup.strikethrough",
+ "settings": {
+ "foreground": "#A6ADC8",
+ "fontStyle": "strikethrough"
+ }
+ },
+ {
+ "scope": ["punctuation.definition.link", "markup.underline.link"],
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": [
+ "text.html.markdown punctuation.definition.link.title",
+ "text.html.quarto punctuation.definition.link.title",
+ "string.other.link.title.markdown",
+ "string.other.link.title.quarto",
+ "markup.link",
+ "punctuation.definition.constant.markdown",
+ "punctuation.definition.constant.quarto",
+ "constant.other.reference.link.markdown",
+ "constant.other.reference.link.quarto",
+ "markup.substitution.attribute-reference"
+ ],
+ "settings": {
+ "foreground": "#B4BEFE"
+ }
+ },
+ {
+ "scope": [
+ "punctuation.definition.raw.markdown",
+ "punctuation.definition.raw.quarto",
+ "markup.inline.raw.string.markdown",
+ "markup.inline.raw.string.quarto",
+ "markup.raw.block.markdown",
+ "markup.raw.block.quarto"
+ ],
+ "settings": {
+ "foreground": "#88DCB7"
+ }
+ },
+ {
+ "scope": "fenced_code.block.language",
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": [
+ "markup.fenced_code.block punctuation.definition",
+ "markup.raw support.asciidoc"
+ ],
+ "settings": {
+ "foreground": "#A1A4A5"
+ }
+ },
+ {
+ "scope": ["markup.quote", "punctuation.definition.quote.begin"],
+ "settings": {
+ "foreground": "#EFB7C2"
+ }
+ },
+ {
+ "scope": "meta.separator.markdown",
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": [
+ "punctuation.definition.list.begin.markdown",
+ "punctuation.definition.list.begin.quarto",
+ "markup.list.bullet"
+ ],
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": "markup.heading.quarto",
+ "settings": {
+ "fontStyle": "bold"
+ }
+ },
+ {
+ "scope": [
+ "entity.other.attribute-name.multipart.nix",
+ "entity.other.attribute-name.single.nix"
+ ],
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": "variable.parameter.name.nix",
+ "settings": {
+ "foreground": "#E7E7E8",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": "meta.embedded variable.parameter.name.nix",
+ "settings": {
+ "foreground": "#B4BEFE",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": "string.unquoted.path.nix",
+ "settings": {
+ "foreground": "#EFB7C2",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": ["support.attribute.builtin", "meta.attribute.php"],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "meta.function.parameters.php punctuation.definition.variable.php",
+ "settings": {
+ "foreground": "#F39EAE"
+ }
+ },
+ {
+ "scope": "constant.language.php",
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": "text.html.php support.function",
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": "keyword.other.phpdoc.php",
+ "settings": {
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": ["support.variable.magic.python", "meta.function-call.arguments.python"],
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": ["support.function.magic.python"],
+ "settings": {
+ "foreground": "#9DAFFA",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": [
+ "variable.parameter.function.language.special.self.python",
+ "variable.language.special.self.python"
+ ],
+ "settings": {
+ "foreground": "#F7869B",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": ["keyword.control.flow.python", "keyword.operator.logical.python"],
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": "storage.type.function.python",
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": [
+ "support.token.decorator.python",
+ "meta.function.decorator.identifier.python"
+ ],
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": ["meta.function-call.python"],
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": [
+ "entity.name.function.decorator.python",
+ "punctuation.definition.decorator.python"
+ ],
+ "settings": {
+ "foreground": "#EDD5A6",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": "constant.character.format.placeholder.other.python",
+ "settings": {
+ "foreground": "#EFB7C2"
+ }
+ },
+ {
+ "scope": ["support.type.exception.python", "support.function.builtin.python"],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": ["support.type.python"],
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "constant.language.python",
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": ["meta.indexed-name.python", "meta.item-access.python"],
+ "settings": {
+ "foreground": "#F39EAE",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": "storage.type.string.python",
+ "settings": {
+ "foreground": "#88DCB7",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": "meta.function.parameters.python",
+ "settings": {
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": [
+ "string.regexp punctuation.definition.string.begin",
+ "string.regexp punctuation.definition.string.end"
+ ],
+ "settings": {
+ "foreground": "#EFB7C2"
+ }
+ },
+ {
+ "scope": "keyword.control.anchor.regexp",
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": "string.regexp.ts",
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": [
+ "punctuation.definition.group.regexp",
+ "keyword.other.back-reference.regexp"
+ ],
+ "settings": {
+ "foreground": "#88DCB7"
+ }
+ },
+ {
+ "scope": "punctuation.definition.character-class.regexp",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "constant.other.character-class.regexp",
+ "settings": {
+ "foreground": "#EFB7C2"
+ }
+ },
+ {
+ "scope": "constant.other.character-class.range.regexp",
+ "settings": {
+ "foreground": "#F5E0DC"
+ }
+ },
+ {
+ "scope": "keyword.operator.quantifier.regexp",
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": "constant.character.numeric.regexp",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": [
+ "punctuation.definition.group.no-capture.regexp",
+ "meta.assertion.look-ahead.regexp",
+ "meta.assertion.negative-look-ahead.regexp"
+ ],
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": [
+ "meta.annotation.rust",
+ "meta.annotation.rust punctuation",
+ "meta.attribute.rust",
+ "punctuation.definition.attribute.rust"
+ ],
+ "settings": {
+ "foreground": "#EDD5A6",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": [
+ "meta.attribute.rust string.quoted.double.rust",
+ "meta.attribute.rust string.quoted.single.char.rust"
+ ],
+ "settings": {
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": [
+ "entity.name.function.macro.rules.rust",
+ "storage.type.module.rust",
+ "storage.modifier.rust",
+ "storage.type.struct.rust",
+ "storage.type.enum.rust",
+ "storage.type.trait.rust",
+ "storage.type.union.rust",
+ "storage.type.impl.rust",
+ "storage.type.rust",
+ "storage.type.function.rust",
+ "storage.type.type.rust"
+ ],
+ "settings": {
+ "foreground": "#C6A5EA",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": "entity.name.type.numeric.rust",
+ "settings": {
+ "foreground": "#C6A5EA",
+ "fontStyle": ""
+ }
+ },
+ {
+ "scope": "meta.generic.rust",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "entity.name.impl.rust",
+ "settings": {
+ "foreground": "#EDD5A6",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": "entity.name.module.rust",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "entity.name.trait.rust",
+ "settings": {
+ "foreground": "#EDD5A6",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": "storage.type.source.rust",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "entity.name.union.rust",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": "meta.enum.rust storage.type.source.rust",
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": [
+ "support.macro.rust",
+ "meta.macro.rust support.function.rust",
+ "entity.name.function.macro.rust"
+ ],
+ "settings": {
+ "foreground": "#9DAFFA",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": ["storage.modifier.lifetime.rust", "entity.name.type.lifetime"],
+ "settings": {
+ "foreground": "#9DAFFA",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": "string.quoted.double.rust constant.other.placeholder.rust",
+ "settings": {
+ "foreground": "#EFB7C2"
+ }
+ },
+ {
+ "scope": "meta.function.return-type.rust meta.generic.rust storage.type.rust",
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": "meta.function.call.rust",
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": "punctuation.brackets.angle.rust",
+ "settings": {
+ "foreground": "#9DAFFA"
+ }
+ },
+ {
+ "scope": "constant.other.caps.rust",
+ "settings": {
+ "foreground": "#EDD5A6"
+ }
+ },
+ {
+ "scope": ["meta.function.definition.rust variable.other.rust"],
+ "settings": {
+ "foreground": "#F39EAE"
+ }
+ },
+ {
+ "scope": "meta.function.call.rust variable.other.rust",
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": "variable.language.self.rust",
+ "settings": {
+ "foreground": "#F7869B"
+ }
+ },
+ {
+ "scope": [
+ "variable.other.metavariable.name.rust",
+ "meta.macro.metavariable.rust keyword.operator.macro.dollar.rust"
+ ],
+ "settings": {
+ "foreground": "#EFB7C2"
+ }
+ },
+ {
+ "scope": [
+ "comment.line.shebang",
+ "comment.line.shebang punctuation.definition.comment",
+ "comment.line.shebang",
+ "punctuation.definition.comment.shebang.shell",
+ "meta.shebang.shell"
+ ],
+ "settings": {
+ "foreground": "#EFB7C2",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": "comment.line.shebang constant.language",
+ "settings": {
+ "foreground": "#A7E0C8",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": [
+ "meta.function-call.arguments.shell punctuation.definition.variable.shell",
+ "meta.function-call.arguments.shell punctuation.section.interpolation",
+ "meta.function-call.arguments.shell punctuation.definition.variable.shell",
+ "meta.function-call.arguments.shell punctuation.section.interpolation"
+ ],
+ "settings": {
+ "foreground": "#F7869B"
+ }
+ },
+ {
+ "scope": "meta.string meta.interpolation.parameter.shell variable.other.readwrite",
+ "settings": {
+ "foreground": "#EDD5A6",
+ "fontStyle": "italic"
+ }
+ },
+ {
+ "scope": [
+ "source.shell punctuation.section.interpolation",
+ "punctuation.definition.evaluation.backticks.shell"
+ ],
+ "settings": {
+ "foreground": "#A7E0C8"
+ }
+ },
+ {
+ "scope": "entity.name.tag.heredoc.shell",
+ "settings": {
+ "foreground": "#C6A5EA"
+ }
+ },
+ {
+ "scope": "string.quoted.double.shell variable.other.normal.shell",
+ "settings": {
+ "foreground": "#E7E7E8"
+ }
+ },
+ {
+ "scope": "token.info-token",
+ "settings": {
+ "foreground": "#8BA1FF"
+ }
+ },
+ {
+ "scope": "token.warn-token",
+ "settings": {
+ "foreground": "#F5B944"
+ }
+ },
+ {
+ "scope": "token.error-token",
+ "settings": {
+ "foreground": "#FB6E88"
+ }
+ },
+ {
+ "scope": "token.debug-token",
+ "settings": {
+ "foreground": "#BE95EB"
+ }
+ }
+ ]
+}
diff --git a/app/components/rfd/index.css b/app/components/rfd/index.css
index 907797b..8e2eece 100644
--- a/app/components/rfd/index.css
+++ b/app/components/rfd/index.css
@@ -23,52 +23,3 @@
.dialog[data-leave] {
transition-duration: 50ms;
}
-
-.spinner {
- --radius: 4;
- --PI: 3.14159265358979;
- --circumference: calc(var(--PI) * var(--radius) * 2px);
- animation: rotate 5s linear infinite;
-}
-
-.spinner .path {
- stroke-dasharray: var(--circumference);
- transform-origin: center;
- animation: dash 4s ease-in-out infinite;
- stroke: var(--content-accent);
-}
-
-@media (prefers-reduced-motion) {
- .spinner {
- animation: rotate 6s linear infinite;
- }
-
- .spinner .path {
- animation: none;
- stroke-dasharray: 20;
- stroke-dashoffset: 100;
- }
-
- .spinner-lg .path {
- stroke-dasharray: 50;
- }
-}
-
-.spinner .bg {
- stroke: var(--content-default);
-}
-
-@keyframes rotate {
- 100% {
- transform: rotate(360deg);
- }
-}
-
-@keyframes dash {
- from {
- stroke-dashoffset: var(--circumference);
- }
- to {
- stroke-dashoffset: calc(var(--circumference) * -1);
- }
-}
diff --git a/app/hooks/use-debounce.ts b/app/hooks/use-debounce.ts
new file mode 100644
index 0000000..446299c
--- /dev/null
+++ b/app/hooks/use-debounce.ts
@@ -0,0 +1,34 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { useEffect, useState } from 'react'
+
+/**
+ * Custom hook for debouncing a value.
+ * @template T - The type of the value to be debounced.
+ * @param {T} value - The value to be debounced.
+ * @param {number} [delay] - The delay in milliseconds for debouncing. Defaults to 500 milliseconds.
+ * @returns {T} The debounced value.
+ * @see [Documentation](https://usehooks-ts.com/react-hook/use-debounce)
+ * @example
+ * const debouncedSearchTerm = useDebounce(searchTerm, 300);
+ */
+export function useDebounce(value: T, delay?: number): T {
+ const [debouncedValue, setDebouncedValue] = useState(value)
+
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ setDebouncedValue(value)
+ }, delay ?? 500)
+
+ return () => {
+ clearTimeout(timer)
+ }
+ }, [value, delay])
+
+ return debouncedValue
+}
diff --git a/app/hooks/use-key.ts b/app/hooks/use-key.ts
deleted file mode 100644
index 58bef5d..0000000
--- a/app/hooks/use-key.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, you can obtain one at https://mozilla.org/MPL/2.0/.
- *
- * Copyright Oxide Computer Company
- */
-
-import Mousetrap from 'mousetrap'
-import { useEffect } from 'react'
-
-type Key = Parameters[0]
-type Callback = Parameters[1]
-
-/**
- * Bind a keyboard shortcut with [Mousetrap](https://craig.is/killing/mice).
- * Callback `fn` should be memoized. `key` does not need to be memoized.
- */
-export const useKey = (key: Key, fn: Callback) => {
- useEffect(() => {
- Mousetrap.bind(key, fn)
- return () => {
- Mousetrap.unbind(key)
- }
- // JSON.stringify lets us avoid having to memoize the keys at the call site.
- // Doing something similar with the callback makes less sense.
- /* eslint-disable-next-line react-hooks/exhaustive-deps */
- }, [JSON.stringify(key), fn])
-}
diff --git a/app/root.tsx b/app/root.tsx
index c206421..57cd360 100644
--- a/app/root.tsx
+++ b/app/root.tsx
@@ -14,14 +14,11 @@ import {
} from '@remix-run/node'
import {
isRouteErrorResponse,
- Links,
- Meta,
Outlet,
- Scripts,
- ScrollRestoration,
useLoaderData,
useRouteError,
useRouteLoaderData,
+ type ShouldRevalidateFunction,
} from '@remix-run/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
@@ -29,6 +26,7 @@ import type { Author } from '~/components/rfd/RfdPreview'
import { auth, isAuthenticated } from '~/services/authn.server'
import styles from '~/styles/index.css?url'
+import { Layout } from './components/Layout'
import LoadingBar from './components/LoadingBar'
import { inlineCommentsCookie, themeCookie } from './services/cookies.server'
import { isLocalMode } from './services/rfd.local.server'
@@ -40,6 +38,13 @@ import {
type RfdListItem,
} from './services/rfd.server'
+export const shouldRevalidate: ShouldRevalidateFunction = ({ currentUrl, nextUrl }) => {
+ if (currentUrl.pathname.startsWith('/notes/') && nextUrl.pathname.startsWith('/notes/')) {
+ return false
+ }
+ return true
+}
+
export const meta: MetaFunction = () => {
return [{ title: 'RFD / Oxide' }]
}
@@ -114,29 +119,6 @@ export function ErrorBoundary() {
}
const queryClient = new QueryClient()
-const Layout = ({ children, theme }: { children: React.ReactNode; theme?: string }) => (
-
-
-
-
-
-
-
-
-
- {/* Use plausible analytics only on Vercel */}
- {process.env.NODE_ENV === 'production' && (
-
- )}
-
-
- {children}
-
-
-
-
-)
-
export default function App() {
const { theme, localMode } = useLoaderData()
diff --git a/app/routes/_index.tsx b/app/routes/_index.tsx
index 9e2c0df..a0e3117 100644
--- a/app/routes/_index.tsx
+++ b/app/routes/_index.tsx
@@ -20,6 +20,7 @@ import cn from 'classnames'
import dayjs from 'dayjs'
import fuzzysort from 'fuzzysort'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import { useHotkeys } from 'react-hotkeys-hook'
import { ClientOnly } from '~/components/ClientOnly'
import Container from '~/components/Container'
@@ -29,7 +30,6 @@ import FilterDropdown from '~/components/home/FilterDropdown'
import StatusBadge from '~/components/StatusBadge'
import { ExactMatch, SuggestedAuthors, SuggestedLabels } from '~/components/Suggested'
import { useIsOverflow } from '~/hooks/use-is-overflow'
-import { useKey } from '~/hooks/use-key'
import { useRootLoaderData } from '~/root'
import { rfdSortCookie } from '~/services/cookies.server'
import type { RfdListItem } from '~/services/rfd.server'
@@ -192,7 +192,7 @@ export default function Index() {
return false
}, [inputEl])
- useKey('/', focusInput)
+ useHotkeys('/', focusInput)
const fetcher = useFetcher()
const submitSortOrder = (newSortAttr: SortAttr) => {
diff --git a/app/routes/notes.$id.delete.tsx b/app/routes/notes.$id.delete.tsx
new file mode 100644
index 0000000..ad48231
--- /dev/null
+++ b/app/routes/notes.$id.delete.tsx
@@ -0,0 +1,19 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { redirect, type ActionFunction } from '@remix-run/node'
+
+import { handleNotesAccess, isAuthenticated } from '~/services/authn.server'
+import { client } from '~/services/notes.server'
+
+export const action: ActionFunction = async ({ params, request }) => {
+ const user = await isAuthenticated(request)
+ handleNotesAccess(user)
+
+ await client.deleteRoom(params.id!)
+ return redirect('/notes')
+}
diff --git a/app/routes/notes.$id.publish.tsx b/app/routes/notes.$id.publish.tsx
new file mode 100644
index 0000000..4f14d58
--- /dev/null
+++ b/app/routes/notes.$id.publish.tsx
@@ -0,0 +1,27 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { json, type ActionFunction } from '@remix-run/node'
+
+import { handleNotesAccess, isAuthenticated } from '~/services/authn.server'
+import { client } from '~/services/notes.server'
+
+export const action: ActionFunction = async ({ request, params }) => {
+ const user = await isAuthenticated(request)
+ handleNotesAccess(user)
+
+ const { publish } = await request.json()
+
+ await client.updateRoom(params.id!, {
+ metadata: {
+ published: publish,
+ updated: new Date().toISOString(),
+ },
+ })
+
+ return json({ status: 200 })
+}
diff --git a/app/routes/notes.$id_.tsx b/app/routes/notes.$id_.tsx
new file mode 100644
index 0000000..4298135
--- /dev/null
+++ b/app/routes/notes.$id_.tsx
@@ -0,0 +1,95 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { LiveObject } from '@liveblocks/client'
+import {
+ ClientSideSuspense,
+ LiveblocksProvider,
+ RoomProvider,
+} from '@liveblocks/react/suspense'
+import { type LoaderFunctionArgs } from '@remix-run/node'
+import { useLoaderData, useOutletContext } from '@remix-run/react'
+
+import { NoteForm, TypingIndicator } from '~/components/note/NoteForm'
+import { isAuthenticated } from '~/services/authn.server'
+import { getNote } from '~/services/notes.server'
+import { userIsInternal } from '~/utils/rfdApi'
+
+import { PlaceholderWrapper } from './notes'
+
+export const loader = async ({ params: { id }, request }: LoaderFunctionArgs) => {
+ const user = await isAuthenticated(request)
+
+ if (!id) {
+ throw new Response('Not Found', { status: 404 })
+ }
+
+ const note = await getNote(id)
+
+ if (!note) {
+ throw new Response('Not Found', { status: 404 })
+ }
+
+ if (note.user === user?.id || (note.published && userIsInternal(user))) {
+ return { user, note }
+ } else if (userIsInternal(user) && !note.published) {
+ throw new Response('Note not published', {
+ status: 401,
+ statusText: 'Unauthorized Access: Note Unpublished',
+ })
+ } else {
+ throw new Response('Not Found', { status: 404 })
+ }
+}
+
+export type Presence = {
+ cursor: { x: number; y: number } | null
+ name: string
+ userId: string
+}
+
+export const initialStorage = {
+ meta: new LiveObject({ title: 'Untitled', lastUpdated: new Date().toISOString() }),
+}
+
+export default function NoteEdit() {
+ const { user, note } = useLoaderData()
+
+ const { sidebarOpen, setSidebarOpen } = useOutletContext<{
+ sidebarOpen: boolean
+ setSidebarOpen: (isOpen: boolean) => void
+ }>()
+
+ if (!user) {
+ return null
+ }
+
+ return (
+
+
+
+
+
+ }
+ >
+ setSidebarOpen(bool)}
+ />
+
+
+
+ )
+}
diff --git a/app/routes/notes._index.tsx b/app/routes/notes._index.tsx
new file mode 100644
index 0000000..59ec7e9
--- /dev/null
+++ b/app/routes/notes._index.tsx
@@ -0,0 +1,36 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+
+import { buttonStyle } from '@oxide/design-system/components/dist'
+import { Link } from '@remix-run/react'
+import cn from 'classnames'
+
+import Icon from '~/components/Icon'
+
+import { EMBody, PlaceholderWrapper } from './notes'
+
+export default function Notes() {
+ return (
+
+
+
+
+
+
+
Live AsciiDoc Editor
+
Create, edit, and share notes
+
+ New Note
+
+
+
+ )
+}
diff --git a/app/routes/notes.auth.tsx b/app/routes/notes.auth.tsx
new file mode 100644
index 0000000..38c22ba
--- /dev/null
+++ b/app/routes/notes.auth.tsx
@@ -0,0 +1,38 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { redirect, type LoaderFunction } from '@remix-run/node'
+
+import Icon from '~/components/Icon'
+import { handleNotesAccess, isAuthenticated } from '~/services/authn.server'
+
+import { EMBody, PlaceholderWrapper } from './notes'
+
+export const loader: LoaderFunction = async ({ request }) => {
+ const user = await isAuthenticated(request)
+ const redirectResponse = handleNotesAccess(user)
+ if (!redirectResponse) {
+ return redirect('/notes')
+ } else {
+ return null
+ }
+}
+
+export default function NotesIndex() {
+ return (
+
+
+
+
+
+
+
Cannot be authorized
+
Must be logged in through Google
+
+
+ )
+}
diff --git a/app/routes/notes.list.ts b/app/routes/notes.list.ts
new file mode 100644
index 0000000..fa7f93c
--- /dev/null
+++ b/app/routes/notes.list.ts
@@ -0,0 +1,23 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { type LoaderFunctionArgs } from '@remix-run/server-runtime'
+
+import { handleNotesAccess, isAuthenticated } from '~/services/authn.server'
+import { listNotes } from '~/services/notes.server'
+
+export const loader = async ({ request }: LoaderFunctionArgs) => {
+ const user = await isAuthenticated(request)
+ const redirectResponse = handleNotesAccess(user)
+ if (redirectResponse) return redirectResponse
+
+ if (!user || !user.id) {
+ throw new Response('User not Found', { status: 401 })
+ }
+
+ return await listNotes(user.id)
+}
diff --git a/app/routes/notes.liveblocks-auth.tsx b/app/routes/notes.liveblocks-auth.tsx
new file mode 100644
index 0000000..e823c14
--- /dev/null
+++ b/app/routes/notes.liveblocks-auth.tsx
@@ -0,0 +1,34 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { type ActionFunction } from '@remix-run/node'
+
+import { isAuthenticated } from '~/services/authn.server'
+import { client } from '~/services/notes.server'
+import { userIsInternal } from '~/utils/rfdApi'
+
+export const action: ActionFunction = async ({ request }) => {
+ const user = await isAuthenticated(request)
+
+ if (!user) {
+ throw new Response('Not Found', { status: 404 })
+ }
+
+ const isInternal = userIsInternal(user)
+
+ // probably shouldn't check the perms in both places
+ // todo: clean up auth
+ const { status, body } = await client.identifyUser(
+ {
+ userId: user.id,
+ groupIds: isInternal ? ['employee'] : [],
+ },
+ { userInfo: { name: user.displayName || user.email || '' } },
+ )
+
+ return new Response(body, { status })
+}
diff --git a/app/routes/notes.new.tsx b/app/routes/notes.new.tsx
new file mode 100644
index 0000000..de888e9
--- /dev/null
+++ b/app/routes/notes.new.tsx
@@ -0,0 +1,28 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { redirect, type ActionFunction, type LoaderFunction } from '@remix-run/node'
+
+import { handleNotesAccess, isAuthenticated } from '~/services/authn.server'
+import { addNote } from '~/services/notes.server'
+
+export const action: ActionFunction = async ({ request }) => {
+ const user = await isAuthenticated(request)
+ const redirectResponse = handleNotesAccess(user)
+ if (redirectResponse) return redirectResponse
+
+ if (!user || !user.id) {
+ throw new Response('User not Found', { status: 401 })
+ }
+
+ const id = await addNote('Untitled', user.id)
+ return redirect(`/notes/${id}`)
+}
+
+export const loader: LoaderFunction = async (args) => {
+ return action(args)
+}
diff --git a/app/routes/notes.tsx b/app/routes/notes.tsx
new file mode 100644
index 0000000..5e21e89
--- /dev/null
+++ b/app/routes/notes.tsx
@@ -0,0 +1,102 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+
+import { type LoaderFunctionArgs } from '@remix-run/node'
+import { isRouteErrorResponse, Outlet, useRouteError } from '@remix-run/react'
+import cn from 'classnames'
+import { useState, type ReactNode } from 'react'
+
+import { ErrorPage } from '~/components/ErrorPage'
+import { Sidebar } from '~/components/note/Sidebar'
+import { handleNotesAccess, isAuthenticated } from '~/services/authn.server'
+import { classed } from '~/utils/classed'
+
+export type NoteItem = {
+ id: string
+ title: string
+ user: string
+ body: string
+ created: string
+ updated: string
+ published: boolean
+}
+
+export type NotesOutletContext = {
+ sidebarOpen: boolean
+ setSidebarOpen: (isOpen: boolean) => void
+}
+
+export function ErrorBoundary() {
+ const error = useRouteError()
+
+ if (isRouteErrorResponse(error)) {
+ return (
+
+
+ {error.status === 404 ? 'Page not found' : error.statusText}
+
+ {error.data}
+
+ )
+ }
+
+ return (
+
+ Something went wrong
+ An unexpected error occurred
+
+ )
+}
+
+export const loader = async ({ request }: LoaderFunctionArgs) => {
+ const user = await isAuthenticated(request)
+ const redirectResponse = handleNotesAccess(user)
+ if (redirectResponse) return redirectResponse
+
+ if (!user || !user.id) {
+ throw new Response('User not Found', { status: 401 })
+ }
+
+ return { user }
+}
+
+export default function Notes() {
+ const [sidebarOpen, setSidebarOpen] = useState(true)
+
+ const context: NotesOutletContext = {
+ sidebarOpen,
+ setSidebarOpen,
+ }
+
+ return (
+
+ {sidebarOpen && }
+
+
+ )
+}
+
+export const PlaceholderWrapper = ({ children }: { children: ReactNode }) => (
+
+)
+
+export const EMBody = classed.p`mt-1 text-balance text-sans-md text-default`
diff --git a/app/routes/notes.updated-webhook.ts b/app/routes/notes.updated-webhook.ts
new file mode 100644
index 0000000..4f24ecf
--- /dev/null
+++ b/app/routes/notes.updated-webhook.ts
@@ -0,0 +1,35 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { WebhookHandler } from '@liveblocks/node'
+import { type ActionFunctionArgs } from '@remix-run/node'
+
+import { modifyStorage } from '~/services/notes.server'
+
+export async function action({ request }: ActionFunctionArgs) {
+ try {
+ const webhook = new WebhookHandler(process.env.LIVEBLOCKS_WEBHOOK_KEY!)
+
+ const event = webhook.verifyRequest({
+ headers: request.headers,
+ rawBody: await request.text(),
+ })
+
+ if (event.type === 'ydocUpdated') {
+ await modifyStorage(event.data.roomId, (root) => {
+ root.get('meta').update({
+ lastUpdated: event.data.updatedAt,
+ })
+ })
+ }
+
+ return new Response(null, { status: 200 })
+ } catch (error) {
+ console.error(error)
+ return new Response('Something went wrong', { status: 500 })
+ }
+}
diff --git a/app/routes/rfd.$slug.tsx b/app/routes/rfd.$slug.tsx
index a40664f..8d6f7ff 100644
--- a/app/routes/rfd.$slug.tsx
+++ b/app/routes/rfd.$slug.tsx
@@ -46,6 +46,7 @@ import { fetchGroups } from '~/services/rfd.remote.server'
import { fetchRfd } from '~/services/rfd.server'
import { parseRfdNum } from '~/utils/parseRfdNum'
import { can } from '~/utils/permission'
+import { userIsInternal } from '~/utils/rfdApi'
function isValue(item: T | null | undefined): item is T {
return !!item
@@ -128,7 +129,7 @@ export default function Rfd() {
// This check is merely cosmetic. It hides UI elements that the user does not have access to and
// which will fail if they try to use
- const userIsInternal = user?.groups.some((group) => group === 'oxide-employee')
+ const isInternal = userIsInternal(user)
const bodyRef = useRef(null)
const [activeItem, setActiveItem] = useState('')
@@ -204,7 +205,7 @@ export default function Rfd() {
RFD {number} {title}
- {userIsInternal && (
+ {isInternal && (
@@ -344,7 +345,7 @@ export default function Rfd() {
)
}
-const PropertyRow = ({
+export const PropertyRow = ({
label,
children,
className,
diff --git a/app/services/authn.server.ts b/app/services/authn.server.ts
index fdbd469..78021d0 100644
--- a/app/services/authn.server.ts
+++ b/app/services/authn.server.ts
@@ -7,11 +7,12 @@
*/
import type { RfdPermission } from '@oxide/rfd.ts/client'
+import { redirect } from '@remix-run/server-runtime'
import { Authenticator } from 'remix-auth'
import { sessionStorage } from '~/services/session.server'
import { isTruthy } from '~/utils/isTruthy'
-import type { RfdScope } from '~/utils/rfdApi'
+import { userIsInternal, type RfdScope } from '~/utils/rfdApi'
import {
RfdApiStrategy,
type RfdApiAccessToken,
@@ -161,6 +162,22 @@ async function isAuthenticated(request: Request, options: any): Promise => {
+ try {
+ const room = await client.getRoom(id)
+ return {
+ id,
+ ...(room.metadata as RoomMetadata),
+ }
+ } catch (error) {
+ console.error(error)
+ return null
+ }
+}
+
+export const addNote = async (title: string, user: string) => {
+ const id = nanoid(6)
+ const created = new Date().toISOString()
+
+ await client.createRoom(id, {
+ defaultAccesses: [],
+ usersAccesses: {
+ [`${user}`]: ['room:write'],
+ },
+ groupsAccesses: {
+ employee: ['room:write'],
+ },
+ metadata: {
+ user,
+ created,
+ published: 'false',
+ },
+ })
+
+ return id
+}
+
+export const updateNote = async (id: string, published: string) => {
+ await client.updateRoom(id, {
+ metadata: {
+ published,
+ },
+ })
+}
+
+export const listNotes = async (userId: string) => {
+ const { data } = await client.getRooms({
+ query: {
+ metadata: {
+ user: userId,
+ },
+ },
+ })
+
+ const rooms = await Promise.all(
+ data.map(async (room) => {
+ const storage = await client.getStorageDocument(room.id, 'json')
+
+ return {
+ ...room,
+ metadata: {
+ ...room.metadata,
+ title: storage.meta.title,
+ },
+ }
+ }),
+ )
+
+ return rooms
+}
+
+export const serviceClient = createClient({
+ authEndpoint: async (room) => {
+ if (!room) {
+ return null
+ }
+ const session = client.prepareSession('_SERVICE_ACCOUNT', {
+ userInfo: { name: 'Service Account' },
+ })
+ session.allow(room, session.FULL_ACCESS)
+ const { body } = await session.authorize()
+ return JSON.parse(body)
+ },
+})
+
+export const enterRoom = (roomId: string) => {
+ return serviceClient.enterRoom(roomId, { initialStorage: initialStorage })
+}
+
+export async function modifyStorage(
+ roomId: string,
+ storageChanges: (root: LiveObject) => void,
+) {
+ const roomContext = enterRoom(roomId)
+ const { room } = roomContext
+ const { root } = await room.getStorage()
+
+ // Make storage adjustments in a batch, so they all happen at once
+ room.batch(() => {
+ storageChanges(root)
+ })
+
+ // If storage changes are not synchronized, wait for them to finish
+ if (room.getStorageStatus() !== 'synchronized') {
+ await room.events.storageStatus.waitUntil((status) => status === 'synchronized')
+ }
+
+ roomContext.leave()
+}
diff --git a/app/styles/index.css b/app/styles/index.css
index 0397859..199cff3 100644
--- a/app/styles/index.css
+++ b/app/styles/index.css
@@ -63,6 +63,18 @@ body {
@apply bg-default;
}
+html {
+ @apply h-full;
+}
+
+body.note {
+ @apply mb-0 h-full;
+}
+
+.cm-editor {
+ @apply h-full;
+}
+
@layer base {
body {
@apply text-sans-sm text-raise;
@@ -79,7 +91,7 @@ body {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 50ms;
opacity: 1;
- backdrop-filter: blur(4px);
+ backdrop-filter: blur(24px);
}
/**
@@ -118,12 +130,62 @@ input[type='checkbox']:focus:not(:focus-visible) {
@apply outline-0 ring-0;
}
-.link-with-underline {
- @apply text-default hover:text-raise;
- text-decoration: underline;
- text-decoration-color: var(--content-quinary);
+.typing-indicator {
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+ width: 12px;
+ height: 12px;
+}
+
+.typing-indicator span {
+ display: block;
+ width: 3px;
+ height: 3px;
+ background-color: var(--content-accent);
+ border-radius: 50%;
+ animation: bounce 1.4s infinite both;
+}
+
+.typing-indicator span:nth-child(1) {
+ animation-delay: -0.32s;
+}
+
+.typing-indicator span:nth-child(2) {
+ animation-delay: -0.16s;
+}
- &:hover {
- text-decoration-color: var(--content-tertiary);
+@keyframes bounce {
+ 0%,
+ 80%,
+ 100% {
+ transform: translateY(0);
+ }
+ 40% {
+ transform: translateY(-4px);
}
}
+
+.cm-editor {
+ font-size: 13px;
+ font-family: 'GT America Mono';
+}
+
+.cm-line {
+ padding-left: 12px;
+}
+
+.cm-content {
+ padding-top: 8px;
+ padding-bottom: 8px;
+}
+
+.cm-editor .cm-ySelectionInfo {
+ @apply pointer-events-none absolute -left-px -top-[1.4em] z-[1000] select-none whitespace-nowrap rounded px-0.5 py-px opacity-100 text-sans-md;
+ color: var(--base-purple-200);
+ border-bottom-left-radius: 0;
+}
+
+.cm-editor .cm-ySelectionCaretDot {
+ @apply hidden;
+}
diff --git a/app/utils/rfdApi.ts b/app/utils/rfdApi.ts
index 30a8cda..ff20e6b 100644
--- a/app/utils/rfdApi.ts
+++ b/app/utils/rfdApi.ts
@@ -6,6 +6,8 @@
* Copyright Oxide Computer Company
*/
+import { type User } from '~/services/authn.server'
+
export type RfdScope =
| 'user:info:r'
| 'user:info:w'
@@ -79,3 +81,6 @@ export type GroupResponse = {
updated_at: string
deleted_at: string
}
+
+export const userIsInternal = (user: User | null) =>
+ user ? user.groups.some((group) => group === 'oxide-employee') : false
diff --git a/liveblocks.config.ts b/liveblocks.config.ts
new file mode 100644
index 0000000..4bb6124
--- /dev/null
+++ b/liveblocks.config.ts
@@ -0,0 +1,36 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import { type LiveObject } from '@liveblocks/client'
+
+declare global {
+ interface Liveblocks {
+ Storage: {
+ meta: LiveObject<{
+ title: string
+ lastUpdated: string
+ }>
+ }
+
+ UserMeta: {
+ id: string
+ info: {
+ name: string
+ }
+ }
+
+ RoomData: {
+ RoomMetaData: {
+ user: string
+ created: string
+ published: string
+ }
+ }
+ }
+}
+
+export type LiveblocksStorage = Liveblocks['Storage']
diff --git a/package-lock.json b/package-lock.json
index 3de67fe..028f7d2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,38 +8,47 @@
"@ariakit/react": "^0.3.5",
"@asciidoctor/core": "^3.0.4",
"@floating-ui/react": "^0.17.0",
+ "@liveblocks/client": "^2.16.1",
+ "@liveblocks/node": "^2.16.1",
+ "@liveblocks/react": "^2.16.1",
+ "@liveblocks/yjs": "^2.16.1",
"@meilisearch/instant-meilisearch": "^0.8.2",
"@oxide/design-system": "^2.2.0",
"@oxide/react-asciidoc": "^1.0.3",
"@oxide/rfd.ts": "^0.1.1",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.0.4",
+ "@radix-ui/react-tooltip": "^1.1.7",
"@remix-run/node": "2.15.2",
"@remix-run/react": "^2.15.2",
"@remix-run/serve": "2.15.2",
+ "@sanity/diff-match-patch": "^3.1.1",
"@tanstack/react-query": "^4.3.9",
+ "@uiw/codemirror-themes": "^4.23.7",
"@vercel/remix": "^2.15.2",
"classnames": "^2.3.1",
+ "codemirror": "^6.0.1",
"dayjs": "^1.11.7",
"fuzzysort": "^2.0.1",
"highlight.js": "^11.6.0",
"html-entities": "^2.4.0",
"isbot": "^4",
- "lodash": "^4.17.21",
"marked": "^4.2.5",
"mermaid": "^11.4.1",
"mime-types": "^2.1.35",
- "mousetrap": "^1.6.5",
"octokit": "^3.1.2",
+ "radix-ui": "^1.1.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-hotkeys-hook": "^4.6.1",
"react-instantsearch": "^7.13.4",
- "remeda": "^2.17.4",
+ "remeda": "^2.20.1",
"remix-auth": "^3.6.0",
"remix-auth-oauth2": "^1.11.1",
- "shiki": "^1.23.1",
+ "shiki": "^1.5.1",
"simple-text-diff": "^1.7.0",
"tunnel-rat": "^0.1.2",
+ "y-codemirror.next": "^0.3.5",
"zod": "^3.22.3"
},
"devDependencies": {
@@ -53,7 +62,7 @@
"@types/express": "^4.17.14",
"@types/js-cookie": "^3.0.2",
"@types/jsdom": "^21.1.1",
- "@types/lodash": "^4.14.191",
+ "@types/lodash": "^4.17.15",
"@types/marked": "^4.0.8",
"@types/mime-types": "^2.1.1",
"@types/mousetrap": "^1.6.9",
@@ -925,6 +934,86 @@
"integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==",
"license": "Apache-2.0"
},
+ "node_modules/@codemirror/autocomplete": {
+ "version": "6.18.4",
+ "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.4.tgz",
+ "integrity": "sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA==",
+ "license": "MIT",
+ "dependencies": {
+ "@codemirror/language": "^6.0.0",
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.17.0",
+ "@lezer/common": "^1.0.0"
+ }
+ },
+ "node_modules/@codemirror/commands": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.0.tgz",
+ "integrity": "sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@codemirror/language": "^6.0.0",
+ "@codemirror/state": "^6.4.0",
+ "@codemirror/view": "^6.27.0",
+ "@lezer/common": "^1.1.0"
+ }
+ },
+ "node_modules/@codemirror/language": {
+ "version": "6.10.8",
+ "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.8.tgz",
+ "integrity": "sha512-wcP8XPPhDH2vTqf181U8MbZnW+tDyPYy0UzVOa+oHORjyT+mhhom9vBd7dApJwoDz9Nb/a8kHjJIsuA/t8vNFw==",
+ "license": "MIT",
+ "dependencies": {
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.23.0",
+ "@lezer/common": "^1.1.0",
+ "@lezer/highlight": "^1.0.0",
+ "@lezer/lr": "^1.0.0",
+ "style-mod": "^4.0.0"
+ }
+ },
+ "node_modules/@codemirror/lint": {
+ "version": "6.8.4",
+ "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.4.tgz",
+ "integrity": "sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==",
+ "license": "MIT",
+ "dependencies": {
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.35.0",
+ "crelt": "^1.0.5"
+ }
+ },
+ "node_modules/@codemirror/search": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.8.tgz",
+ "integrity": "sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==",
+ "license": "MIT",
+ "dependencies": {
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.0.0",
+ "crelt": "^1.0.5"
+ }
+ },
+ "node_modules/@codemirror/state": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.1.tgz",
+ "integrity": "sha512-3rA9lcwciEB47ZevqvD8qgbzhM9qMb8vCcQCNmDfVRPQG4JT9mSb0Jg8H7YjKGGQcFnLN323fj9jdnG59Kx6bg==",
+ "license": "MIT",
+ "dependencies": {
+ "@marijn/find-cluster-break": "^1.0.0"
+ }
+ },
+ "node_modules/@codemirror/view": {
+ "version": "6.36.2",
+ "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.2.tgz",
+ "integrity": "sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA==",
+ "license": "MIT",
+ "dependencies": {
+ "@codemirror/state": "^6.5.0",
+ "style-mod": "^4.1.0",
+ "w3c-keyname": "^2.2.4"
+ }
+ },
"node_modules/@csstools/postcss-global-data": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@csstools/postcss-global-data/-/postcss-global-data-1.0.3.tgz",
@@ -1734,6 +1823,91 @@
"resolved": "https://registry.npmjs.org/@jspm/core/-/core-2.1.0.tgz",
"integrity": "sha512-3sRl+pkyFY/kLmHl0cgHiFp2xEqErA8N3ECjMs7serSUBmoJ70lBa0PG5t0IM6WJgdZNyyI0R8YFfi5wM8+mzg=="
},
+ "node_modules/@lezer/common": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
+ "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==",
+ "license": "MIT"
+ },
+ "node_modules/@lezer/highlight": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz",
+ "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
+ "license": "MIT",
+ "dependencies": {
+ "@lezer/common": "^1.0.0"
+ }
+ },
+ "node_modules/@lezer/lr": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz",
+ "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
+ "license": "MIT",
+ "dependencies": {
+ "@lezer/common": "^1.0.0"
+ }
+ },
+ "node_modules/@liveblocks/client": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/@liveblocks/client/-/client-2.16.1.tgz",
+ "integrity": "sha512-+F+nPmrLKSkM62ARlohOlDlcG6zpQE5yESvcfoc99nNyw4/IotAD6/TAICVW3gQG28wjg8SDOKOixtpJmoPo1A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@liveblocks/core": "2.16.1"
+ }
+ },
+ "node_modules/@liveblocks/core": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/@liveblocks/core/-/core-2.16.1.tgz",
+ "integrity": "sha512-hpZQpEq5g139dNu0izIYVKGUSE+wGHl3pokznacegBB58TNanMcrQOv8qWMDbASPJhkPV/Z04OXC0z/YaZT6aw==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@liveblocks/node": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/@liveblocks/node/-/node-2.16.1.tgz",
+ "integrity": "sha512-LMi4iR36dAz3uZ2OWCM06+Q359z0ubRCRf+OObBUTzrcJNwhA7+bZDpcXrVNWlXq2kvoiBmos0/O4ReCu5Wwdg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@liveblocks/core": "2.16.1",
+ "@stablelib/base64": "^1.0.1",
+ "fast-sha256": "^1.3.0",
+ "node-fetch": "^2.6.1"
+ }
+ },
+ "node_modules/@liveblocks/react": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/@liveblocks/react/-/react-2.16.1.tgz",
+ "integrity": "sha512-mZGTGBsKSgAdZgOmKuyKuTgdNzEH1hwPbdJwRUlip7FjJkHsLmz58MuKP0GOjQRVM3iZqbSymaQH20zU4+3NWQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@liveblocks/client": "2.16.1",
+ "@liveblocks/core": "2.16.1"
+ },
+ "peerDependencies": {
+ "react": "^18 || ^19 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/@liveblocks/yjs": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/@liveblocks/yjs/-/yjs-2.16.1.tgz",
+ "integrity": "sha512-KlGw425iHk6tUU2TRo4mxPhKk/OZ07pFz3DM4Zom0fzpZczv5c5OyBH3wmJfKVkAxWDDRN+H0P3JVFbpJ0OWtA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@liveblocks/client": "2.16.1",
+ "@liveblocks/core": "2.16.1",
+ "js-base64": "^3.7.7",
+ "y-indexeddb": "^9.0.12"
+ },
+ "peerDependencies": {
+ "yjs": "^13.6.1"
+ }
+ },
+ "node_modules/@marijn/find-cluster-break": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
+ "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
+ "license": "MIT"
+ },
"node_modules/@mdx-js/mdx": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.3.0.tgz",
@@ -2408,10 +2582,40 @@
"node": ">=18"
}
},
- "node_modules/@radix-ui/primitive": {
+ "node_modules/@radix-ui/number": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz",
- "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA=="
+ "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz",
+ "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
+ "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-accessible-icon": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-accessible-icon/-/react-accessible-icon-1.1.1.tgz",
+ "integrity": "sha512-DH8vuU7oqHt9RhO3V9Z1b8ek+bOl4+9VLsh0cgL6t7f2WhbuOChm3ft0EmCCsfd4ORi7Cs3II4aNcTXi+bh+wg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-visually-hidden": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
},
"node_modules/@radix-ui/react-accordion": {
"version": "1.2.2",
@@ -2444,20 +2648,16 @@
}
}
},
- "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/primitive": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
- "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==",
- "license": "MIT"
- },
- "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-collection": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz",
- "integrity": "sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==",
+ "node_modules/@radix-ui/react-alert-dialog": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.5.tgz",
+ "integrity": "sha512-1Y2sI17QzSZP58RjGtrklfSGIf3AF7U/HkD3aAcAnhOUJrm7+7GG1wRDFaUlSe0nW5B/t4mYd/+7RNbP2Wexug==",
"license": "MIT",
"dependencies": {
+ "@radix-ui/primitive": "1.1.1",
"@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-dialog": "1.1.5",
"@radix-ui/react-primitive": "2.0.1",
"@radix-ui/react-slot": "1.1.1"
},
@@ -2476,28 +2676,36 @@
}
}
},
- "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-compose-refs": {
+ "node_modules/@radix-ui/react-arrow": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
- "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz",
+ "integrity": "sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==",
"license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.0.1"
+ },
"peerDependencies": {
"@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
}
}
},
- "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-primitive": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
- "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
+ "node_modules/@radix-ui/react-aspect-ratio": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.1.tgz",
+ "integrity": "sha512-kNU4FIpcFMBLkOUcgeIteH06/8JLBcYY6Le1iKenDGCYNYFX3TQqCZjzkOsz37h7r94/99GTb7YhEr98ZBJibw==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-slot": "1.1.1"
+ "@radix-ui/react-primitive": "2.0.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -2514,30 +2722,46 @@
}
}
},
- "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-slot": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
- "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
+ "node_modules/@radix-ui/react-avatar": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.2.tgz",
+ "integrity": "sha512-GaC7bXQZ5VgZvVvsJ5mu/AEbjYLnhhkoidOboC50Z6FFlLA03wG2ianUoH+zgDQ31/9gCF59bE4+2bBgTyMiig==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.1"
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
}
}
},
- "node_modules/@radix-ui/react-arrow": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz",
- "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==",
+ "node_modules/@radix-ui/react-checkbox": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.3.tgz",
+ "integrity": "sha512-HD7/ocp8f1B3e6OHygH0n7ZKjONkhciy1Nh0yuBgObqThc3oyx+vuMfFHKAknXRHHWVE9XvXStxJFyjUmB8PIw==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.0.0"
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-previous": "1.1.0",
+ "@radix-ui/react-use-size": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
@@ -2584,13 +2808,33 @@
}
}
},
- "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/primitive": {
+ "node_modules/@radix-ui/react-collection": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
- "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==",
- "license": "MIT"
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz",
+ "integrity": "sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-slot": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
},
- "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-compose-refs": {
+ "node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
"integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
@@ -2605,14 +2849,32 @@
}
}
},
- "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-presence": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz",
- "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==",
+ "node_modules/@radix-ui/react-context": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz",
+ "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context-menu": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.5.tgz",
+ "integrity": "sha512-MY5PFCwo/ICaaQtpQBQ0g19AyjzI0mhz+a2GUWA2pJf4XFkvglAdcgDV2Iqm+lLbXn8hb+6rbLgcmRtc6ImPvg==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.1",
- "@radix-ui/react-use-layout-effect": "1.1.0"
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-menu": "2.1.5",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
@@ -2629,13 +2891,26 @@
}
}
},
- "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-primitive": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
- "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
+ "node_modules/@radix-ui/react-dialog": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.5.tgz",
+ "integrity": "sha512-LaO3e5h/NOEL4OfXjxD43k9Dx+vn+8n+PCFt6uhX/BADFflllyv3WJG6rgvvSVBxpTch938Qq/LGc2MMxipXPw==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-slot": "1.1.1"
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.4",
+ "@radix-ui/react-focus-guards": "1.1.1",
+ "@radix-ui/react-focus-scope": "1.1.1",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-portal": "1.1.3",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-slot": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.2"
},
"peerDependencies": {
"@types/react": "*",
@@ -2652,14 +2927,10 @@
}
}
},
- "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-slot": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
- "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.1"
- },
+ "node_modules/@radix-ui/react-direction": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
+ "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -2670,15 +2941,17 @@
}
}
},
- "node_modules/@radix-ui/react-collection": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz",
- "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==",
+ "node_modules/@radix-ui/react-dismissable-layer": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.4.tgz",
+ "integrity": "sha512-XDUI0IVYVSwjMXxM6P4Dfti7AH+Y4oS/TB+sglZ/EXc7cqLwGAmp1NlMrcUjj7ks6R5WTZuWKv44FBbLpwU3sA==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.0",
- "@radix-ui/react-context": "1.1.0",
- "@radix-ui/react-primitive": "2.0.0",
- "@radix-ui/react-slot": "1.1.0"
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-escape-keydown": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
@@ -2695,26 +2968,41 @@
}
}
},
- "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-context": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
- "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
+ "node_modules/@radix-ui/react-dropdown-menu": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.5.tgz",
+ "integrity": "sha512-50ZmEFL1kOuLalPKHrLWvPFMons2fGx9TqQCWlPwDVpbAnaUJ1g4XNcKqFNMQymYU0kKWR4MDDi+9vUQBGFgcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-menu": "2.1.5",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
+ },
"peerDependencies": {
"@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
}
}
},
- "node_modules/@radix-ui/react-compose-refs": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz",
- "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==",
- "peerDependencies": {
- "@types/react": "*",
+ "node_modules/@radix-ui/react-focus-guards": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz",
+ "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==",
+ "peerDependencies": {
+ "@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
@@ -2723,44 +3011,74 @@
}
}
},
- "node_modules/@radix-ui/react-context": {
+ "node_modules/@radix-ui/react-focus-scope": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz",
- "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz",
+ "integrity": "sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-callback-ref": "1.1.0"
+ },
"peerDependencies": {
"@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
}
}
},
- "node_modules/@radix-ui/react-direction": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
- "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==",
+ "node_modules/@radix-ui/react-form": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-form/-/react-form-0.1.1.tgz",
+ "integrity": "sha512-Ah2TBvzl2trb4DL9DQtyUJgAUfq/djMN7j5CHzdpbdR3W7OL8N4JcJgE80cXMf3ssCE+8yg0zFQoJ0srxqfsFA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-label": "2.1.1",
+ "@radix-ui/react-primitive": "2.0.1"
+ },
"peerDependencies": {
"@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
}
}
},
- "node_modules/@radix-ui/react-dismissable-layer": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz",
- "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==",
+ "node_modules/@radix-ui/react-hover-card": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.5.tgz",
+ "integrity": "sha512-0jPlX3ZrUIhtMAY0m1SBn1koI4Yqsizq2UwdUiQF1GseSZLZBPa6b8tNS+m32K94Yb4wxtWFSQs85wujQvwahg==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.0",
- "@radix-ui/react-compose-refs": "1.1.0",
- "@radix-ui/react-primitive": "2.0.0",
- "@radix-ui/react-use-callback-ref": "1.1.0",
- "@radix-ui/react-use-escape-keydown": "1.1.0"
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.4",
+ "@radix-ui/react-popper": "1.2.1",
+ "@radix-ui/react-portal": "1.1.3",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
@@ -2777,18 +3095,30 @@
}
}
},
- "node_modules/@radix-ui/react-dropdown-menu": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.2.tgz",
- "integrity": "sha512-GVZMR+eqK8/Kes0a36Qrv+i20bAPXSn8rCBTHx30w+3ECnR5o3xixAlqcVaYvLeyKUsm0aqyhWfmUcqufM8nYA==",
+ "node_modules/@radix-ui/react-id": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz",
+ "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==",
"dependencies": {
- "@radix-ui/primitive": "1.1.0",
- "@radix-ui/react-compose-refs": "1.1.0",
- "@radix-ui/react-context": "1.1.1",
- "@radix-ui/react-id": "1.1.0",
- "@radix-ui/react-menu": "2.1.2",
- "@radix-ui/react-primitive": "2.0.0",
- "@radix-ui/react-use-controllable-state": "1.1.0"
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-label": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.1.tgz",
+ "integrity": "sha512-UUw5E4e/2+4kFMH7+YxORXGWggtY6sM8WIwh5RZchhLuUg2H1hc98Py+pr8HMz6rdaYrK2t296ZEjYLOCO5uUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.0.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -2805,28 +3135,62 @@
}
}
},
- "node_modules/@radix-ui/react-focus-guards": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz",
- "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==",
+ "node_modules/@radix-ui/react-menu": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.5.tgz",
+ "integrity": "sha512-uH+3w5heoMJtqVCgYOtYVMECk1TOrkUn0OG0p5MqXC0W2ppcuVeESbou8PTHoqAjbdTEK19AGXBWcEtR5WpEQg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-collection": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-dismissable-layer": "1.1.4",
+ "@radix-ui/react-focus-guards": "1.1.1",
+ "@radix-ui/react-focus-scope": "1.1.1",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-popper": "1.2.1",
+ "@radix-ui/react-portal": "1.1.3",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-roving-focus": "1.1.1",
+ "@radix-ui/react-slot": "1.1.1",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.2"
+ },
"peerDependencies": {
"@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
}
}
},
- "node_modules/@radix-ui/react-focus-scope": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz",
- "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==",
+ "node_modules/@radix-ui/react-menubar": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.5.tgz",
+ "integrity": "sha512-Kzbpcf2bxUmI/G+949+LvSvGkyzIaY7ctb8loydt6YpJR8pQF+j4QbVhYvjs7qxaWK0DEJL3XbP2p46YPRkS3A==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.0",
- "@radix-ui/react-primitive": "2.0.0",
- "@radix-ui/react-use-callback-ref": "1.1.0"
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-collection": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-menu": "2.1.5",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-roving-focus": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
@@ -2843,46 +3207,63 @@
}
}
},
- "node_modules/@radix-ui/react-id": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz",
- "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==",
+ "node_modules/@radix-ui/react-navigation-menu": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.4.tgz",
+ "integrity": "sha512-wUi01RrTDTOoGtjEPHsxlzPtVzVc3R/AZ5wfh0dyqMAqolhHAHvG5iQjBCTi2AjQqa77FWWbA3kE3RkD+bDMgQ==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.0"
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-collection": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-dismissable-layer": "1.1.4",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0",
+ "@radix-ui/react-use-previous": "1.1.0",
+ "@radix-ui/react-visually-hidden": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
}
}
},
- "node_modules/@radix-ui/react-menu": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.2.tgz",
- "integrity": "sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==",
+ "node_modules/@radix-ui/react-popover": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.5.tgz",
+ "integrity": "sha512-YXkTAftOIW2Bt3qKH8vYr6n9gCkVrvyvfiTObVjoHVTHnNj26rmvO87IKa3VgtgCjb8FAQ6qOjNViwl+9iIzlg==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.0",
- "@radix-ui/react-collection": "1.1.0",
- "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-context": "1.1.1",
- "@radix-ui/react-direction": "1.1.0",
- "@radix-ui/react-dismissable-layer": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.4",
"@radix-ui/react-focus-guards": "1.1.1",
- "@radix-ui/react-focus-scope": "1.1.0",
+ "@radix-ui/react-focus-scope": "1.1.1",
"@radix-ui/react-id": "1.1.0",
- "@radix-ui/react-popper": "1.2.0",
- "@radix-ui/react-portal": "1.1.2",
- "@radix-ui/react-presence": "1.1.1",
- "@radix-ui/react-primitive": "2.0.0",
- "@radix-ui/react-roving-focus": "1.1.0",
- "@radix-ui/react-slot": "1.1.0",
- "@radix-ui/react-use-callback-ref": "1.1.0",
- "aria-hidden": "^1.1.1",
- "react-remove-scroll": "2.6.0"
+ "@radix-ui/react-popper": "1.2.1",
+ "@radix-ui/react-portal": "1.1.3",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-slot": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.2"
},
"peerDependencies": {
"@types/react": "*",
@@ -2900,15 +3281,16 @@
}
},
"node_modules/@radix-ui/react-popper": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
- "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz",
+ "integrity": "sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw==",
+ "license": "MIT",
"dependencies": {
"@floating-ui/react-dom": "^2.0.0",
- "@radix-ui/react-arrow": "1.1.0",
- "@radix-ui/react-compose-refs": "1.1.0",
- "@radix-ui/react-context": "1.1.0",
- "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-arrow": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.1",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-layout-effect": "1.1.0",
"@radix-ui/react-use-rect": "1.1.0",
@@ -2934,6 +3316,7 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz",
"integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==",
+ "license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.0.0"
},
@@ -2942,10 +3325,302 @@
"react-dom": ">=16.8.0"
}
},
- "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
- "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
+ "node_modules/@radix-ui/react-portal": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.3.tgz",
+ "integrity": "sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-presence": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz",
+ "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
+ "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-progress": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.1.tgz",
+ "integrity": "sha512-6diOawA84f/eMxFHcWut0aE1C2kyE9dOyCTQOMRR2C/qPiXz/X0SaiA/RLbapQaXUCmy0/hLMf9meSccD1N0pA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-radio-group": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.2.2.tgz",
+ "integrity": "sha512-E0MLLGfOP0l8P/NxgVzfXJ8w3Ch8cdO6UDzJfDChu4EJDy+/WdO5LqpdY8PYnCErkmZH3gZhDL1K7kQ41fAHuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-roving-focus": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-previous": "1.1.0",
+ "@radix-ui/react-use-size": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.1.tgz",
+ "integrity": "sha512-QE1RoxPGJ/Nm8Qmk0PxP8ojmoaS67i0s7hVssS7KuI2FQoc/uzVlZsqKfQvxPE6D8hICCPHJ4D88zNhT3OOmkw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-collection": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-scroll-area": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.2.tgz",
+ "integrity": "sha512-EFI1N/S3YxZEW/lJ/H1jY3njlvTd8tBmgKEn4GHi51+aMm94i6NmAJstsm5cu3yJwYqYc93gpCPm21FeAbFk6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.0",
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-select": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.5.tgz",
+ "integrity": "sha512-eVV7N8jBXAXnyrc+PsOF89O9AfVgGnbLxUtBb0clJ8y8ENMWLARGMI/1/SBRLz7u4HqxLgN71BJ17eono3wcjA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.0",
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-collection": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-dismissable-layer": "1.1.4",
+ "@radix-ui/react-focus-guards": "1.1.1",
+ "@radix-ui/react-focus-scope": "1.1.1",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-popper": "1.2.1",
+ "@radix-ui/react-portal": "1.1.3",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-slot": "1.1.1",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0",
+ "@radix-ui/react-use-previous": "1.1.0",
+ "@radix-ui/react-visually-hidden": "1.1.1",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-separator": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.1.tgz",
+ "integrity": "sha512-RRiNRSrD8iUiXriq/Y5n4/3iE8HzqgLHsusUSg5jVpU2+3tqcUFPJXHDymwEypunc2sWxDUS3UC+rkZRlHedsw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slider": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.2.2.tgz",
+ "integrity": "sha512-sNlU06ii1/ZcbHf8I9En54ZPW0Vil/yPVg4vQMcFNjrIx51jsHbFl1HYHQvCIWJSr1q0ZmA+iIs/ZTv8h7HHSA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.0",
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-collection": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0",
+ "@radix-ui/react-use-previous": "1.1.0",
+ "@radix-ui/react-use-size": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slot": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
+ "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.1"
+ },
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -2956,13 +3631,49 @@
}
}
},
- "node_modules/@radix-ui/react-portal": {
+ "node_modules/@radix-ui/react-switch": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.1.2.tgz",
+ "integrity": "sha512-zGukiWHjEdBCRyXvKR6iXAQG6qXm2esuAD6kDOi9Cn+1X6ev3ASo4+CsYaD6Fov9r/AQFekqnD/7+V0Cs6/98g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-previous": "1.1.0",
+ "@radix-ui/react-use-size": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tabs": {
"version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz",
- "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.2.tgz",
+ "integrity": "sha512-9u/tQJMcC2aGq7KXpGivMm1mgq7oRJKXphDwdypPd/j21j/2znamPU8WkXgnhUaTrSFNIt8XhOyCAupg8/GbwQ==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.0.0",
- "@radix-ui/react-use-layout-effect": "1.1.0"
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-roving-focus": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
@@ -2979,13 +3690,24 @@
}
}
},
- "node_modules/@radix-ui/react-presence": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz",
- "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==",
+ "node_modules/@radix-ui/react-toast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.5.tgz",
+ "integrity": "sha512-ZzUsAaOx8NdXZZKcFNDhbSlbsCUy8qQWmzTdgrlrhhZAOx2ofLtKrBDW9fkqhFvXgmtv560Uj16pkLkqML7SHA==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.0",
- "@radix-ui/react-use-layout-effect": "1.1.0"
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-collection": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.4",
+ "@radix-ui/react-portal": "1.1.3",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0",
+ "@radix-ui/react-visually-hidden": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -3002,12 +3724,15 @@
}
}
},
- "node_modules/@radix-ui/react-primitive": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz",
- "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==",
+ "node_modules/@radix-ui/react-toggle": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.1.tgz",
+ "integrity": "sha512-i77tcgObYr743IonC1hrsnnPmszDRn8p+EGUsUt+5a/JFn28fxaM88Py6V2mc8J5kELMWishI0rLnuGLFD/nnQ==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/react-slot": "1.1.0"
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
@@ -3024,19 +3749,18 @@
}
}
},
- "node_modules/@radix-ui/react-roving-focus": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz",
- "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==",
+ "node_modules/@radix-ui/react-toggle-group": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.1.tgz",
+ "integrity": "sha512-OgDLZEA30Ylyz8YSXvnGqIHtERqnUt1KUYTKdw/y8u7Ci6zGiJfXc02jahmcSNK3YcErqioj/9flWC9S1ihfwg==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.0",
- "@radix-ui/react-collection": "1.1.0",
- "@radix-ui/react-compose-refs": "1.1.0",
- "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
"@radix-ui/react-direction": "1.1.0",
- "@radix-ui/react-id": "1.1.0",
- "@radix-ui/react-primitive": "2.0.0",
- "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-roving-focus": "1.1.1",
+ "@radix-ui/react-toggle": "1.1.1",
"@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
@@ -3054,50 +3778,53 @@
}
}
},
- "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-context": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
- "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-slot": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
- "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
+ "node_modules/@radix-ui/react-toolbar": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-toolbar/-/react-toolbar-1.1.1.tgz",
+ "integrity": "sha512-r7T80WOCHc2n3KRzFCbHWGVzkfVTCzDofGU4gqa5ZuIzgnVaLogGsdyifFJXWQDp0lAr5hrf+X9uqQdE0pa6Ww==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.0"
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-roving-focus": "1.1.1",
+ "@radix-ui/react-separator": "1.1.1",
+ "@radix-ui/react-toggle-group": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
}
}
},
- "node_modules/@radix-ui/react-tabs": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.1.tgz",
- "integrity": "sha512-3GBUDmP2DvzmtYLMsHmpA1GtR46ZDZ+OreXM/N+kkQJOPIgytFWWTfDQmBQKBvaFS0Vno0FktdbVzN28KGrMdw==",
+ "node_modules/@radix-ui/react-tooltip": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.7.tgz",
+ "integrity": "sha512-ss0s80BC0+g0+Zc53MvilcnTYSOi4mSuFWBPYPuTOFGjx+pUU+ZrmamMNwS56t8MTFlniA5ocjd4jYm/CdhbOg==",
+ "license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.0",
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-context": "1.1.1",
- "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-dismissable-layer": "1.1.4",
"@radix-ui/react-id": "1.1.0",
- "@radix-ui/react-presence": "1.1.1",
- "@radix-ui/react-primitive": "2.0.0",
- "@radix-ui/react-roving-focus": "1.1.0",
- "@radix-ui/react-use-controllable-state": "1.1.0"
+ "@radix-ui/react-popper": "1.2.1",
+ "@radix-ui/react-portal": "1.1.3",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-slot": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-visually-hidden": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -3176,6 +3903,21 @@
}
}
},
+ "node_modules/@radix-ui/react-use-previous": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz",
+ "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-use-rect": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz",
@@ -3210,6 +3952,29 @@
}
}
},
+ "node_modules/@radix-ui/react-visually-hidden": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz",
+ "integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/rect": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz",
@@ -3811,6 +4576,15 @@
"integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==",
"dev": true
},
+ "node_modules/@sanity/diff-match-patch": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@sanity/diff-match-patch/-/diff-match-patch-3.1.1.tgz",
+ "integrity": "sha512-dSZqGeYjHKGIkqAzGqLcG92LZyJGX+nYbs/FWawhBbTBDWi21kvQ0hsL3DJThuFVWtZMWTQijN3z6Cnd44Pf2g==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14.18"
+ }
+ },
"node_modules/@shikijs/core": {
"version": "1.24.2",
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.24.2.tgz",
@@ -3880,6 +4654,12 @@
"integrity": "sha512-79QfK1393x9Ho60QFyLti+QfdJzRQCVLFb97kOIV7Eo9vQU/roINgk7m24uv0a7AUvN//RDH36FLjjK48v0s9g==",
"license": "MIT"
},
+ "node_modules/@stablelib/base64": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz",
+ "integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==",
+ "license": "MIT"
+ },
"node_modules/@tailwindcss/line-clamp": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.4.tgz",
@@ -4486,10 +5266,11 @@
}
},
"node_modules/@types/lodash": {
- "version": "4.17.10",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.10.tgz",
- "integrity": "sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==",
- "dev": true
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@types/marked": {
"version": "4.3.2",
@@ -4843,6 +5624,25 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/@uiw/codemirror-themes": {
+ "version": "4.23.7",
+ "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.23.7.tgz",
+ "integrity": "sha512-UNf1XOx1hG9OmJnrtT86PxKcdcwhaNhbrcD+nsk8WxRJ3n5c8nH6euDvgVPdVLPwbizsaQcZTILACgA/FjRpVg==",
+ "license": "MIT",
+ "dependencies": {
+ "@codemirror/language": "^6.0.0",
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://jaywcjlove.github.io/#/sponsor"
+ },
+ "peerDependencies": {
+ "@codemirror/language": ">=6.0.0",
+ "@codemirror/state": ">=6.0.0",
+ "@codemirror/view": ">=6.0.0"
+ }
+ },
"node_modules/@ungap/structured-clone": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
@@ -6110,6 +6910,21 @@
"resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-10.1.1.tgz",
"integrity": "sha512-67ueh2IRGst/51p0n6FvPrnRjAGHY5F8xdjkgrYE7DDzpJe6qA07RYQ9VcoUeo5ATOjSOiWpSL3SWBRRbempMw=="
},
+ "node_modules/codemirror": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
+ "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
+ "license": "MIT",
+ "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"
+ }
+ },
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -6312,6 +7127,12 @@
"layout-base": "^1.0.0"
}
},
+ "node_modules/crelt": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
+ "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
+ "license": "MIT"
+ },
"node_modules/cross-fetch": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz",
@@ -7386,7 +8207,8 @@
"node_modules/detect-node-es": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
- "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+ "license": "MIT"
},
"node_modules/devlop": {
"version": "1.1.0",
@@ -9045,6 +9867,12 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
+ "node_modules/fast-sha256": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz",
+ "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==",
+ "license": "Unlicense"
+ },
"node_modules/fastq": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
@@ -9370,6 +10198,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
"integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -10304,14 +11133,6 @@
"node": ">=12"
}
},
- "node_modules/invariant": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
- "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
- "dependencies": {
- "loose-envify": "^1.0.0"
- }
- },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -10857,6 +11678,16 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
+ "node_modules/isomorphic.js": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz",
+ "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==",
+ "license": "MIT",
+ "funding": {
+ "type": "GitHub Sponsors ❤",
+ "url": "https://github.com/sponsors/dmonad"
+ }
+ },
"node_modules/iterator.prototype": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz",
@@ -10901,6 +11732,12 @@
"jiti": "bin/jiti.js"
}
},
+ "node_modules/js-base64": {
+ "version": "3.7.7",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz",
+ "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -11213,6 +12050,27 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/lib0": {
+ "version": "0.2.99",
+ "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.99.tgz",
+ "integrity": "sha512-vwztYuUf1uf/1zQxfzRfO5yzfNKhTtgOByCruuiQQxWQXnPb8Itaube5ylofcV0oM0aKal9Mv+S1s1Ky0UYP1w==",
+ "license": "MIT",
+ "dependencies": {
+ "isomorphic.js": "^0.2.4"
+ },
+ "bin": {
+ "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js",
+ "0gentesthtml": "bin/gentesthtml.js",
+ "0serve": "bin/0serve.js"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "type": "GitHub Sponsors ❤",
+ "url": "https://github.com/sponsors/dmonad"
+ }
+ },
"node_modules/lilconfig": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
@@ -11269,7 +12127,8 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "license": "MIT"
},
"node_modules/lodash-es": {
"version": "4.17.21",
@@ -12635,11 +13494,6 @@
"node": ">= 0.8"
}
},
- "node_modules/mousetrap": {
- "version": "1.6.5",
- "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz",
- "integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA=="
- },
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
@@ -14511,6 +15365,78 @@
}
]
},
+ "node_modules/radix-ui": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.1.2.tgz",
+ "integrity": "sha512-P2F30iTIG/eheoZbF3QXo7kDoFgnj/zxX1NwPq02G00ggq7OSXFsMuyn98WHtQCql2DsO8ZCbBk+VbbgVrlwOg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-accessible-icon": "1.1.1",
+ "@radix-ui/react-accordion": "1.2.2",
+ "@radix-ui/react-alert-dialog": "1.1.5",
+ "@radix-ui/react-aspect-ratio": "1.1.1",
+ "@radix-ui/react-avatar": "1.1.2",
+ "@radix-ui/react-checkbox": "1.1.3",
+ "@radix-ui/react-collapsible": "1.1.2",
+ "@radix-ui/react-collection": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-context-menu": "2.2.5",
+ "@radix-ui/react-dialog": "1.1.5",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-dismissable-layer": "1.1.4",
+ "@radix-ui/react-dropdown-menu": "2.1.5",
+ "@radix-ui/react-focus-guards": "1.1.1",
+ "@radix-ui/react-focus-scope": "1.1.1",
+ "@radix-ui/react-form": "0.1.1",
+ "@radix-ui/react-hover-card": "1.1.5",
+ "@radix-ui/react-label": "2.1.1",
+ "@radix-ui/react-menu": "2.1.5",
+ "@radix-ui/react-menubar": "1.1.5",
+ "@radix-ui/react-navigation-menu": "1.2.4",
+ "@radix-ui/react-popover": "1.1.5",
+ "@radix-ui/react-popper": "1.2.1",
+ "@radix-ui/react-portal": "1.1.3",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-progress": "1.1.1",
+ "@radix-ui/react-radio-group": "1.2.2",
+ "@radix-ui/react-roving-focus": "1.1.1",
+ "@radix-ui/react-scroll-area": "1.2.2",
+ "@radix-ui/react-select": "2.1.5",
+ "@radix-ui/react-separator": "1.1.1",
+ "@radix-ui/react-slider": "1.2.2",
+ "@radix-ui/react-slot": "1.1.1",
+ "@radix-ui/react-switch": "1.1.2",
+ "@radix-ui/react-tabs": "1.1.2",
+ "@radix-ui/react-toast": "1.2.5",
+ "@radix-ui/react-toggle": "1.1.1",
+ "@radix-ui/react-toggle-group": "1.1.1",
+ "@radix-ui/react-toolbar": "1.1.1",
+ "@radix-ui/react-tooltip": "1.1.7",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-escape-keydown": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0",
+ "@radix-ui/react-use-size": "1.1.0",
+ "@radix-ui/react-visually-hidden": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -14558,6 +15484,16 @@
"react": "^18.3.1"
}
},
+ "node_modules/react-hotkeys-hook": {
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.6.1.tgz",
+ "integrity": "sha512-XlZpbKUj9tkfgPgT9gA+1p7Ey6vFIZHttUjPqpTdyT5nqQ8mHL7elxvSbaC+dpSiHUSmr21Ya1mDxBZG3aje4Q==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=16.8.1",
+ "react-dom": ">=16.8.1"
+ }
+ },
"node_modules/react-instantsearch": {
"version": "7.13.4",
"resolved": "https://registry.npmjs.org/react-instantsearch/-/react-instantsearch-7.13.4.tgz",
@@ -14610,22 +15546,23 @@
}
},
"node_modules/react-remove-scroll": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz",
- "integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==",
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz",
+ "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==",
+ "license": "MIT",
"dependencies": {
- "react-remove-scroll-bar": "^2.3.6",
- "react-style-singleton": "^2.2.1",
+ "react-remove-scroll-bar": "^2.3.7",
+ "react-style-singleton": "^2.2.3",
"tslib": "^2.1.0",
- "use-callback-ref": "^1.3.0",
- "use-sidecar": "^1.1.2"
+ "use-callback-ref": "^1.3.3",
+ "use-sidecar": "^1.1.3"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
- "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -14634,19 +15571,20 @@
}
},
"node_modules/react-remove-scroll-bar": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz",
- "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==",
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
+ "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
+ "license": "MIT",
"dependencies": {
- "react-style-singleton": "^2.2.1",
+ "react-style-singleton": "^2.2.2",
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
- "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -14687,20 +15625,20 @@
}
},
"node_modules/react-style-singleton": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz",
- "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==",
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
+ "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
+ "license": "MIT",
"dependencies": {
"get-nonce": "^1.0.0",
- "invariant": "^2.2.4",
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
- "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -14902,11 +15840,12 @@
}
},
"node_modules/remeda": {
- "version": "2.17.4",
- "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.17.4.tgz",
- "integrity": "sha512-pviU2Ag7Qx9mOCAKO4voxDx/scfLzdhp3v85qDO4xxntQsU76uE9sgrAAdK1ATn4zzaOJqCXYMMNRP+O9F4Wiw==",
+ "version": "2.20.1",
+ "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.20.1.tgz",
+ "integrity": "sha512-gsEsSmjE0CHkNp6xEsWsU/6JVNWq7rqw+ZfzNMbVV4YFIPtTj/i0FfxurTRI6Z9sAnQufU9de2Cb3xHsUTFTMA==",
+ "license": "MIT",
"dependencies": {
- "type-fest": "^4.27.0"
+ "type-fest": "^4.33.0"
}
},
"node_modules/remix-auth": {
@@ -15846,6 +16785,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/style-mod": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
+ "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
+ "license": "MIT"
+ },
"node_modules/style-to-js": {
"version": "1.1.16",
"resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.16.tgz",
@@ -16495,9 +17440,10 @@
}
},
"node_modules/type-fest": {
- "version": "4.29.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.29.0.tgz",
- "integrity": "sha512-RPYt6dKyemXJe7I6oNstcH24myUGSReicxcHTvCLgzm4e0n8y05dGvcGB15/SoPRBmhlMthWQ9pvKyL81ko8nQ==",
+ "version": "4.33.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.33.0.tgz",
+ "integrity": "sha512-s6zVrxuyKbbAsSAD5ZPTB77q4YIdRctkTbJ2/Dqlinwz+8ooH2gd+YA7VA6Pa93KML9GockVvoxjZ2vHP+mu8g==",
+ "license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=16"
},
@@ -16875,9 +17821,10 @@
}
},
"node_modules/use-callback-ref": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz",
- "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==",
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
+ "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
+ "license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
@@ -16885,8 +17832,8 @@
"node": ">=10"
},
"peerDependencies": {
- "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -16895,9 +17842,10 @@
}
},
"node_modules/use-sidecar": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz",
- "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==",
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
+ "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
+ "license": "MIT",
"dependencies": {
"detect-node-es": "^1.1.0",
"tslib": "^2.0.0"
@@ -16906,8 +17854,8 @@
"node": ">=10"
},
"peerDependencies": {
- "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -17651,6 +18599,12 @@
"integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==",
"license": "MIT"
},
+ "node_modules/w3c-keyname": {
+ "version": "2.2.8",
+ "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
+ "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
+ "license": "MIT"
+ },
"node_modules/w3c-xmlserializer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
@@ -17975,6 +18929,44 @@
"node": ">=0.4"
}
},
+ "node_modules/y-codemirror.next": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/y-codemirror.next/-/y-codemirror.next-0.3.5.tgz",
+ "integrity": "sha512-VluNu3e5HfEXybnypnsGwKAj+fKLd4iAnR7JuX1Sfyydmn1jCBS5wwEL/uS04Ch2ib0DnMAOF6ZRR/8kK3wyGw==",
+ "license": "MIT",
+ "dependencies": {
+ "lib0": "^0.2.42"
+ },
+ "funding": {
+ "type": "GitHub Sponsors ❤",
+ "url": "https://github.com/sponsors/dmonad"
+ },
+ "peerDependencies": {
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.0.0",
+ "yjs": "^13.5.6"
+ }
+ },
+ "node_modules/y-indexeddb": {
+ "version": "9.0.12",
+ "resolved": "https://registry.npmjs.org/y-indexeddb/-/y-indexeddb-9.0.12.tgz",
+ "integrity": "sha512-9oCFRSPPzBK7/w5vOkJBaVCQZKHXB/v6SIT+WYhnJxlEC61juqG0hBrAf+y3gmSMLFLwICNH9nQ53uscuse6Hg==",
+ "license": "MIT",
+ "dependencies": {
+ "lib0": "^0.2.74"
+ },
+ "engines": {
+ "node": ">=16.0.0",
+ "npm": ">=8.0.0"
+ },
+ "funding": {
+ "type": "GitHub Sponsors ❤",
+ "url": "https://github.com/sponsors/dmonad"
+ },
+ "peerDependencies": {
+ "yjs": "^13.0.0"
+ }
+ },
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
@@ -17989,6 +18981,24 @@
"node": ">= 6"
}
},
+ "node_modules/yjs": {
+ "version": "13.6.23",
+ "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.23.tgz",
+ "integrity": "sha512-ExtnT5WIOVpkL56bhLeisG/N5c4fmzKn4k0ROVfJa5TY2QHbH7F0Wu2T5ZhR7ErsFWQEFafyrnSI8TPKVF9Few==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lib0": "^0.2.99"
+ },
+ "engines": {
+ "node": ">=16.0.0",
+ "npm": ">=8.0.0"
+ },
+ "funding": {
+ "type": "GitHub Sponsors ❤",
+ "url": "https://github.com/sponsors/dmonad"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/package.json b/package.json
index a3025b8..3086b2e 100644
--- a/package.json
+++ b/package.json
@@ -16,38 +16,47 @@
"@ariakit/react": "^0.3.5",
"@asciidoctor/core": "^3.0.4",
"@floating-ui/react": "^0.17.0",
+ "@liveblocks/client": "^2.16.1",
+ "@liveblocks/node": "^2.16.1",
+ "@liveblocks/react": "^2.16.1",
+ "@liveblocks/yjs": "^2.16.1",
"@meilisearch/instant-meilisearch": "^0.8.2",
"@oxide/design-system": "^2.2.0",
"@oxide/react-asciidoc": "^1.0.3",
"@oxide/rfd.ts": "^0.1.1",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.0.4",
+ "@radix-ui/react-tooltip": "^1.1.7",
"@remix-run/node": "2.15.2",
"@remix-run/react": "^2.15.2",
"@remix-run/serve": "2.15.2",
+ "@sanity/diff-match-patch": "^3.1.1",
"@tanstack/react-query": "^4.3.9",
+ "@uiw/codemirror-themes": "^4.23.7",
"@vercel/remix": "^2.15.2",
"classnames": "^2.3.1",
+ "codemirror": "^6.0.1",
"dayjs": "^1.11.7",
"fuzzysort": "^2.0.1",
"highlight.js": "^11.6.0",
"html-entities": "^2.4.0",
"isbot": "^4",
- "lodash": "^4.17.21",
"marked": "^4.2.5",
"mermaid": "^11.4.1",
"mime-types": "^2.1.35",
- "mousetrap": "^1.6.5",
"octokit": "^3.1.2",
+ "radix-ui": "^1.1.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-hotkeys-hook": "^4.6.1",
"react-instantsearch": "^7.13.4",
- "remeda": "^2.17.4",
+ "remeda": "^2.20.1",
"remix-auth": "^3.6.0",
"remix-auth-oauth2": "^1.11.1",
- "shiki": "^1.23.1",
+ "shiki": "^1.5.1",
"simple-text-diff": "^1.7.0",
"tunnel-rat": "^0.1.2",
+ "y-codemirror.next": "^0.3.5",
"zod": "^3.22.3"
},
"devDependencies": {
@@ -61,7 +70,7 @@
"@types/express": "^4.17.14",
"@types/js-cookie": "^3.0.2",
"@types/jsdom": "^21.1.1",
- "@types/lodash": "^4.14.191",
+ "@types/lodash": "^4.17.15",
"@types/marked": "^4.0.8",
"@types/mime-types": "^2.1.1",
"@types/mousetrap": "^1.6.9",
diff --git a/tsconfig.json b/tsconfig.json
index 5109579..30dc188 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,8 @@
{
"include": ["vite.d.ts", "**/*.ts", "**/*.tsx"],
+ "exclude": ["notes/**"],
"compilerOptions": {
+ "allowImportingTsExtensions": true,
"incremental": true,
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"isolatedModules": true,
diff --git a/vite.config.ts b/vite.config.ts
index 213de3a..f42d157 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -32,4 +32,7 @@ export default defineConfig({
server: {
port: 3000,
},
+ ssr: {
+ noExternal: ['@uiw/codemirror-themes'],
+ },
})