+12








fcd7c979df
Co-authored-by: Artur <145776561+arturict@users.noreply.github.com> Co-authored-by: arturict <arturict@users.noreply.github.com> Co-authored-by: Thomas <thomas@ajnart.fr> Co-authored-by: Afonso Jorge Ramos <afonsojorgeramos@gmail.com> Co-authored-by: Danura30082 <danura30082+github@gmail.com> Co-authored-by: Kushie <122986913+kushiemoon-dev@users.noreply.github.com> Co-authored-by: ajnart <thomas@ajnart.fr> Co-authored-by: ajnart <thomas@ajnart.dev> Co-authored-by: chenjun <chenjun@foxmail.com> Co-authored-by: Wikibear <wikibear@users.noreply.github.com> Co-authored-by: Bergasha <bergasha@gmail.com> Co-authored-by: leafyelin <43306196+leafyelin@users.noreply.github.com> Co-authored-by: Lucas Araujo <lucas.lra@gmail.com> Co-authored-by: GreenMonito <86085570+GreenMonito@users.noreply.github.com> Co-authored-by: Nerdy-Technician <roffo@nerdy-technician.social> Co-authored-by: Jun <34545896+jcstrong@users.noreply.github.com> Co-authored-by: Edmond Abraham <54119952+gitedmond@users.noreply.github.com> Co-authored-by: thrawnx <tight.bulb9384@fastmail.com> Co-authored-by: Chris <58918656+nordada@users.noreply.github.com> Co-authored-by: yi111 <153097222+Yi-111-a@users.noreply.github.com> Co-authored-by: Yanis <naamaneyanis@gmail.com> Co-authored-by: Wikibear <me@sej.de> Co-authored-by: alessiottavo <93441886+alessiottavo@users.noreply.github.com>
107 lines
3.0 KiB
TypeScript
107 lines
3.0 KiB
TypeScript
"use client";
|
|
|
|
import type { ReactNode } from "react";
|
|
import { useRef, useState } from "react";
|
|
import { FloatingIndicator, Stack, TextInput, UnstyledButton } from "@mantine/core";
|
|
|
|
import type { UrlTemplateMode } from "@homarr/definitions";
|
|
import { useI18n } from "@homarr/translation/client";
|
|
|
|
import { useOnboardingSounds } from "./use-onboarding-sounds";
|
|
import classes from "./onboarding-studio.module.css";
|
|
|
|
interface FloatingControlProps<T extends string> {
|
|
value: T;
|
|
onChange: (value: T) => void;
|
|
options: readonly { value: T; label: ReactNode }[];
|
|
ariaLabel: string;
|
|
}
|
|
|
|
export const OnboardingFloatingControl = <T extends string>({
|
|
value,
|
|
onChange,
|
|
options,
|
|
ariaLabel,
|
|
}: FloatingControlProps<T>) => {
|
|
const [rootRef, setRootRef] = useState<HTMLFieldSetElement | null>(null);
|
|
const controlRefs = useRef<Record<string, HTMLButtonElement | null>>({});
|
|
const sounds = useOnboardingSounds();
|
|
|
|
return (
|
|
<div className={classes.floatingControlScroller}>
|
|
<fieldset ref={setRootRef} className={classes.floatingControlRoot} aria-label={ariaLabel}>
|
|
<FloatingIndicator
|
|
target={controlRefs.current[value] ?? null}
|
|
parent={rootRef}
|
|
className={classes.floatingControlIndicator}
|
|
/>
|
|
{options.map((option) => {
|
|
const selected = value === option.value;
|
|
return (
|
|
<UnstyledButton
|
|
key={option.value}
|
|
ref={(node) => {
|
|
controlRefs.current[option.value] = node;
|
|
}}
|
|
type="button"
|
|
className={classes.floatingControl}
|
|
data-active={selected}
|
|
aria-pressed={selected}
|
|
onClick={() => {
|
|
sounds.click();
|
|
onChange(option.value);
|
|
}}
|
|
>
|
|
{option.label}
|
|
</UnstyledButton>
|
|
);
|
|
})}
|
|
</fieldset>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
interface ServiceUrlTemplateProps {
|
|
serverOrigin: string;
|
|
onServerOriginChange: (value: string) => void;
|
|
mode: UrlTemplateMode;
|
|
onModeChange: (value: UrlTemplateMode) => void;
|
|
readOnly?: boolean;
|
|
required?: boolean;
|
|
}
|
|
|
|
export const ServiceUrlTemplate = ({
|
|
serverOrigin,
|
|
onServerOriginChange,
|
|
mode,
|
|
onModeChange,
|
|
readOnly,
|
|
required,
|
|
}: ServiceUrlTemplateProps) => {
|
|
const t = useI18n("common.serviceUrlTemplate");
|
|
|
|
return (
|
|
<Stack gap="sm">
|
|
<TextInput
|
|
label={t("serverTitle")}
|
|
placeholder="home.lan · 192.168.1.10 · https://homarr.example.com"
|
|
value={serverOrigin}
|
|
onChange={(event) => onServerOriginChange(event.currentTarget.value)}
|
|
readOnly={readOnly}
|
|
required={required}
|
|
withAsterisk={required}
|
|
/>
|
|
<OnboardingFloatingControl
|
|
ariaLabel={t("urlModeLabel")}
|
|
value={mode}
|
|
onChange={onModeChange}
|
|
options={[
|
|
{ value: "hostPort", label: t("hostPort") },
|
|
{ value: "subdomain", label: t("subdomain") },
|
|
{ value: "path", label: t("path") },
|
|
]}
|
|
/>
|
|
</Stack>
|
|
);
|
|
};
|