import { useState, useSyncExternalStore } from "react"
import { createRoot } from "react-dom/client"
import { flushSync } from "react-dom"
import {
browserSettings,
type SettingDefinition,
} from "@pathmx/core/settings/browser"
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogClose,
} from "../dialog.tsx"
import "../styles.css"
import "./styles.css"
const label = (name: string) =>
name.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (c) => c.toUpperCase())
function Section({ definition }: { definition: SettingDefinition }) {
const settings = browserSettings()!
const [message, setMessage] = useState("")
const [failed, setFailed] = useState(false)
const revision = useSyncExternalStore(
(refresh) => settings.subscribe(definition, refresh),
() => {
try {
return settings.read(definition).revision
} catch (error) {
return String(error)
}
},
)
let snapshot
try {
snapshot = settings.read(definition)
} catch (error) {
return (
Settings could not be loaded: {String(error)}. Your saved data has been
retained.
)
}
const { value, overrides } = snapshot
const fields = definition.jsonSchema.properties as Record<
string,
{
type: string
enum?: string[]
description?: string
minimum?: number
maximum?: number
}
>
function save(next: Record) {
try {
settings.set(definition, next, { revision })
setMessage("Saved on this browser.")
setFailed(false)
} catch (error) {
setMessage(error instanceof Error ? error.message : String(error))
setFailed(true)
}
}
return (
)
}
let returnFocus: HTMLElement | null = null
let show: (section: string, trigger: HTMLElement) => void = () => {}
function SettingsDialog() {
const [open, setOpen] = useState(false)
const [section, setSection] = useState("theme")
show = (section, trigger) => {
returnFocus = trigger
setSection(section)
setOpen(true)
}
const settings = browserSettings()
if (!settings) return null
const selected = settings.definition(section) ?? settings.definitions[0]
return (
)
}
let root: ReturnType | undefined
export function openSettings({
section,
returnFocus,
}: {
section: string
returnFocus: HTMLElement
}) {
if (!root) {
const host = document.createElement("div")
host.dataset.pmxSettingsHost = ""
document.body.append(host)
root = createRoot(host, { identifierPrefix: "pmx-settings-" })
flushSync(() => root!.render())
}
flushSync(() => show(section, returnFocus))
}