mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-22 03:07:04 +02:00
feat: better layout
This commit is contained in:
1 parent
ca39b8e215
commit
4b2367699a
3 files changed
+464
-475
No files matched your search
+4
-3
@@ -28,9 +28,10 @@ const robotoFlex = Roboto_Flex({
|
||||
|
||||
export default function RootLayout({ children }: RootLayoutProps) {
|
||||
const pathname = usePathname();
|
||||
const hideNav =
|
||||
pathname.startsWith('/tools/embed/host') ||
|
||||
pathname.startsWith('/tools/embed/customize');
|
||||
// const hideNav =
|
||||
// pathname.startsWith('/tools/embed/host') ||
|
||||
// pathname.startsWith('/tools/embed/customize');
|
||||
const hideNav = false;
|
||||
const isRoot = pathname === '/';
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as radixColors from '@radix-ui/colors';
|
||||
import {
|
||||
DragHandleDots2Icon,
|
||||
EnterFullScreenIcon,
|
||||
ExitFullScreenIcon,
|
||||
BorderSolidIcon,
|
||||
Cross1Icon,
|
||||
ImageIcon,
|
||||
SquareIcon,
|
||||
} from '@radix-ui/react-icons';
|
||||
import {
|
||||
Box,
|
||||
@@ -47,6 +47,9 @@ import {
|
||||
radixTextWeights,
|
||||
} from '../app/tools/embed/types';
|
||||
import { toColorVar, toRadiusVar } from '../app/tools/embed/utilities';
|
||||
import { imgur } from '../core/blitzkit/imgur';
|
||||
import { NAVBAR_HEIGHT } from './Navbar';
|
||||
import PageWrapper from './PageWrapper';
|
||||
|
||||
interface EmbedConfigInputsProps {
|
||||
config: EmbedConfig;
|
||||
@@ -61,10 +64,7 @@ export function EmbedConfigInputs({
|
||||
setState,
|
||||
children,
|
||||
}: EmbedConfigInputsProps) {
|
||||
const [expanded, setExpanded] = useState(true);
|
||||
const [backgroundImage, setBackgroundImage] = useState(
|
||||
'https://upload.wikimedia.org/wikipedia/commons/f/f6/Swiss_National_Park_131.JPG',
|
||||
);
|
||||
const [backgroundImage, setBackgroundImage] = useState(imgur('SO13zur'));
|
||||
const mutateState = useCallback(
|
||||
(recipe: (draft: ExtractEmbedConfigType<EmbedConfig>) => void) => {
|
||||
setState(produce(recipe));
|
||||
@@ -99,444 +99,53 @@ export function EmbedConfigInputs({
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Flex
|
||||
width="100vw"
|
||||
height="100vh"
|
||||
align="center"
|
||||
justify="center"
|
||||
overflow="hidden"
|
||||
style={{
|
||||
background: `url(${backgroundImage}) center / cover no-repeat`,
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
style={{ position: 'fixed', top: 32, right: 32, minWidth: 320 }}
|
||||
ref={wrapper}
|
||||
>
|
||||
<Inset mb="4">
|
||||
<Flex
|
||||
align="center"
|
||||
justify="center"
|
||||
p="2"
|
||||
mb={expanded ? '2' : '0'}
|
||||
position="relative"
|
||||
style={{
|
||||
backgroundColor: 'var(--color-panel-translucent)',
|
||||
cursor: 'grab',
|
||||
}}
|
||||
onPointerDown={(event) => {
|
||||
event.preventDefault();
|
||||
window.addEventListener('pointermove', handlePointerMove);
|
||||
window.addEventListener('pointerup', handlePointerUp);
|
||||
}}
|
||||
>
|
||||
<Text color="gray" trim="end">
|
||||
<DragHandleDots2Icon style={{ transform: 'rotate(90deg)' }} />
|
||||
</Text>
|
||||
|
||||
<Box
|
||||
position="absolute"
|
||||
right="0"
|
||||
top="50%"
|
||||
pr="2"
|
||||
style={{ transform: 'translateY(-25%)' }}
|
||||
<PageWrapper padding="0" size={1028 + 640}>
|
||||
<Flex>
|
||||
<ScrollArea
|
||||
scrollbars="vertical"
|
||||
style={{ height: '100%', maxWidth: 320 }}
|
||||
>
|
||||
<Flex direction="column" gap="2" p="4">
|
||||
<Button
|
||||
variant="outline"
|
||||
color="gray"
|
||||
mb="6"
|
||||
onClick={() => fileInput.current?.click()}
|
||||
>
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
color="gray"
|
||||
onClick={() => setExpanded((expanded) => !expanded)}
|
||||
>
|
||||
{expanded ? <ExitFullScreenIcon /> : <EnterFullScreenIcon />}
|
||||
</IconButton>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Inset>
|
||||
<ImageIcon /> Upload test background
|
||||
</Button>
|
||||
|
||||
{expanded && (
|
||||
<ScrollArea
|
||||
scrollbars="vertical"
|
||||
style={{ height: '100%', maxHeight: 640 }}
|
||||
>
|
||||
<Flex direction="column" gap="2">
|
||||
<Button
|
||||
variant="outline"
|
||||
color="gray"
|
||||
mb="6"
|
||||
onClick={() => fileInput.current?.click()}
|
||||
>
|
||||
<ImageIcon /> Upload test background
|
||||
</Button>
|
||||
{Object.entries(config).map(([key, setting]) => {
|
||||
let control: ReactNode;
|
||||
|
||||
{Object.entries(config).map(([key, setting]) => {
|
||||
let control: ReactNode;
|
||||
switch (setting.type) {
|
||||
case EmbedConfigType.Boolean: {
|
||||
control = (
|
||||
<Switch
|
||||
checked={state[key] as boolean}
|
||||
onCheckedChange={(checked) =>
|
||||
mutateState((draft) => {
|
||||
draft[key] = checked;
|
||||
})
|
||||
}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (setting.type) {
|
||||
case EmbedConfigType.Boolean: {
|
||||
control = (
|
||||
<Switch
|
||||
checked={state[key] as boolean}
|
||||
onCheckedChange={(checked) =>
|
||||
case EmbedConfigType.FullTextControl: {
|
||||
control = (
|
||||
<>
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={`${(state[key] as EmbedConfigItemType<EmbedConfigType.FullTextControl>).color}`}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = checked;
|
||||
})
|
||||
}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.FullTextControl: {
|
||||
control = (
|
||||
<>
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={`${(state[key] as EmbedConfigItemType<EmbedConfigType.FullTextControl>).color}`}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
(
|
||||
draft[
|
||||
key
|
||||
] as EmbedConfigItemType<EmbedConfigType.FullTextControl>
|
||||
).color = value as RadixTextColor;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
<Select.Item value="undefined">
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: 'white',
|
||||
}}
|
||||
/>{' '}
|
||||
White
|
||||
</Select.Item>
|
||||
<Select.Item value="gray">
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: 'gray',
|
||||
}}
|
||||
/>{' '}
|
||||
Gray
|
||||
</Select.Item>
|
||||
{Object.entries(radixColors)
|
||||
.filter(
|
||||
([key]) =>
|
||||
!key.endsWith('A') &&
|
||||
!key.endsWith('P3') &&
|
||||
!key.endsWith('Dark') &&
|
||||
!radixGrays.includes(key),
|
||||
)
|
||||
.map(([key]) => (
|
||||
<Select.Item key={key} value={key}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: key as RadixColorBase,
|
||||
variant: '9',
|
||||
}),
|
||||
}}
|
||||
/>{' '}
|
||||
{capitalize(key)}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={
|
||||
(
|
||||
state[
|
||||
draft[
|
||||
key
|
||||
] as EmbedConfigItemType<EmbedConfigType.FullTextControl>
|
||||
).size
|
||||
}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
(
|
||||
draft[
|
||||
key
|
||||
] as EmbedConfigItemType<EmbedConfigType.FullTextControl>
|
||||
).size = value as RadixSizeNo0;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(9, (index) => (
|
||||
<Select.Item key={index} value={`${index + 1}`}>
|
||||
Size {index + 1}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={
|
||||
(
|
||||
state[
|
||||
key
|
||||
] as EmbedConfigItemType<EmbedConfigType.FullTextControl>
|
||||
).weight
|
||||
}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
(
|
||||
draft[
|
||||
key
|
||||
] as EmbedConfigItemType<EmbedConfigType.FullTextControl>
|
||||
).weight = value as RadixTextWeight;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{radixTextWeights.map((weight) => (
|
||||
<Select.Item key={weight} value={weight}>
|
||||
{startCase(weight)}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.Number: {
|
||||
control = (
|
||||
<TextField.Root
|
||||
size="1"
|
||||
style={{ width: 64 }}
|
||||
type="number"
|
||||
value={state[key] as number}
|
||||
onChange={(event) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = (
|
||||
event.target as HTMLInputElement
|
||||
).valueAsNumber;
|
||||
});
|
||||
}}
|
||||
>
|
||||
{setting.unit && (
|
||||
<TextField.Slot side="right">px</TextField.Slot>
|
||||
)}
|
||||
</TextField.Root>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.String: {
|
||||
control = (
|
||||
<TextField.Root
|
||||
placeholder="Empty"
|
||||
size="1"
|
||||
style={{ width: 64 }}
|
||||
value={state[key] as string}
|
||||
onChange={(event) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = (
|
||||
event.target as HTMLInputElement
|
||||
).value;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.SizeNo0:
|
||||
case EmbedConfigType.Size: {
|
||||
control = (
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={state[key] as RadixSize}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = value as RadixSize;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(10, (index) =>
|
||||
setting.type === EmbedConfigType.SizeNo0 &&
|
||||
index === 0 ? null : (
|
||||
<Select.Item key={index} value={`${index}`}>
|
||||
{index}
|
||||
</Select.Item>
|
||||
),
|
||||
)}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.Radius: {
|
||||
control = (
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={state[key] as RadixRadius}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = value as RadixRadius;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(5, (index) => (
|
||||
<Select.Item key={index} value={`${index}`}>
|
||||
{index}
|
||||
</Select.Item>
|
||||
))}
|
||||
<Select.Item value="full">Full</Select.Item>
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.Color: {
|
||||
control = (
|
||||
<>
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={(state[key] as RadixColor).base}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
(draft[key] as RadixColor).base =
|
||||
value as RadixColorBase;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{Object.entries(radixColors)
|
||||
.filter(
|
||||
([key]) =>
|
||||
!key.endsWith('A') &&
|
||||
!key.endsWith('P3') &&
|
||||
!key.endsWith('Dark'),
|
||||
)
|
||||
.map(([key]) => (
|
||||
<Select.Item key={key} value={key}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: key as RadixColorBase,
|
||||
variant: '9',
|
||||
}),
|
||||
}}
|
||||
/>{' '}
|
||||
{capitalize(key)}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={(state[key] as RadixColor).variant}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
(draft[key] as RadixColor).variant =
|
||||
value as RadixColorVariant;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(12, (index) => {
|
||||
const variant =
|
||||
`${index + 1}` as RadixColorVariantRaw;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Select.Item key={key} value={variant}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: (state[key] as RadixColor).base,
|
||||
variant,
|
||||
}),
|
||||
}}
|
||||
/>{' '}
|
||||
{variant}
|
||||
</Select.Item>
|
||||
<Select.Item key={key} value={`a${variant}`}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
overflow: 'hidden',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: (state[key] as RadixColor).base,
|
||||
variant: `a${variant}`,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
width: '50%',
|
||||
height: '100%',
|
||||
backgroundColor: toColorVar({
|
||||
base: (state[key] as RadixColor)
|
||||
.base,
|
||||
variant,
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
</Box>{' '}
|
||||
{variant} translucent
|
||||
</Select.Item>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.TextColor: {
|
||||
control = (
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={`${state[key]}`}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = value as RadixTextColor;
|
||||
).color = value as RadixTextColor;
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -596,44 +205,420 @@ export function EmbedConfigInputs({
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
);
|
||||
break;
|
||||
}
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={
|
||||
(
|
||||
state[
|
||||
key
|
||||
] as EmbedConfigItemType<EmbedConfigType.FullTextControl>
|
||||
).size
|
||||
}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
(
|
||||
draft[
|
||||
key
|
||||
] as EmbedConfigItemType<EmbedConfigType.FullTextControl>
|
||||
).size = value as RadixSizeNo0;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(9, (index) => (
|
||||
<Select.Item key={index} value={`${index + 1}`}>
|
||||
Size {index + 1}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={
|
||||
(
|
||||
state[
|
||||
key
|
||||
] as EmbedConfigItemType<EmbedConfigType.FullTextControl>
|
||||
).weight
|
||||
}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
(
|
||||
draft[
|
||||
key
|
||||
] as EmbedConfigItemType<EmbedConfigType.FullTextControl>
|
||||
).weight = value as RadixTextWeight;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{radixTextWeights.map((weight) => (
|
||||
<Select.Item key={weight} value={weight}>
|
||||
{startCase(weight)}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex
|
||||
direction="column"
|
||||
gap="1"
|
||||
mb="1"
|
||||
pb={setting.pad ? '6' : undefined}
|
||||
>
|
||||
<Text color="gray" size="2">
|
||||
{capitalize(startCase(key))}
|
||||
case EmbedConfigType.Number: {
|
||||
control = (
|
||||
<TextField.Root
|
||||
size="1"
|
||||
style={{ width: 64 }}
|
||||
type="number"
|
||||
value={state[key] as number}
|
||||
onChange={(event) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = (
|
||||
event.target as HTMLInputElement
|
||||
).valueAsNumber;
|
||||
});
|
||||
}}
|
||||
>
|
||||
{setting.unit && (
|
||||
<TextField.Slot side="right">px</TextField.Slot>
|
||||
)}
|
||||
</TextField.Root>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.String: {
|
||||
control = (
|
||||
<TextField.Root
|
||||
placeholder="Empty"
|
||||
size="1"
|
||||
style={{ width: 64 }}
|
||||
value={state[key] as string}
|
||||
onChange={(event) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = (event.target as HTMLInputElement).value;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.SizeNo0:
|
||||
case EmbedConfigType.Size: {
|
||||
control = (
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={state[key] as RadixSize}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = value as RadixSize;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(10, (index) =>
|
||||
setting.type === EmbedConfigType.SizeNo0 &&
|
||||
index === 0 ? null : (
|
||||
<Select.Item key={index} value={`${index}`}>
|
||||
{index}
|
||||
</Select.Item>
|
||||
),
|
||||
)}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.Radius: {
|
||||
control = (
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={state[key] as RadixRadius}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = value as RadixRadius;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(5, (index) => (
|
||||
<Select.Item key={index} value={`${index}`}>
|
||||
{index}
|
||||
</Select.Item>
|
||||
))}
|
||||
<Select.Item value="full">Full</Select.Item>
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.Color: {
|
||||
control = (
|
||||
<>
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={(state[key] as RadixColor).base}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
(draft[key] as RadixColor).base =
|
||||
value as RadixColorBase;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{Object.entries(radixColors)
|
||||
.filter(
|
||||
([key]) =>
|
||||
!key.endsWith('A') &&
|
||||
!key.endsWith('P3') &&
|
||||
!key.endsWith('Dark'),
|
||||
)
|
||||
.map(([key]) => (
|
||||
<Select.Item key={key} value={key}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: key as RadixColorBase,
|
||||
variant: '9',
|
||||
}),
|
||||
}}
|
||||
/>{' '}
|
||||
{capitalize(key)}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={(state[key] as RadixColor).variant}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
(draft[key] as RadixColor).variant =
|
||||
value as RadixColorVariant;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
{times(12, (index) => {
|
||||
const variant =
|
||||
`${index + 1}` as RadixColorVariantRaw;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Select.Item key={key} value={variant}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: (state[key] as RadixColor).base,
|
||||
variant,
|
||||
}),
|
||||
}}
|
||||
/>{' '}
|
||||
{variant}
|
||||
</Select.Item>
|
||||
<Select.Item key={key} value={`a${variant}`}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
overflow: 'hidden',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: (state[key] as RadixColor).base,
|
||||
variant: `a${variant}`,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
width: '50%',
|
||||
height: '100%',
|
||||
backgroundColor: toColorVar({
|
||||
base: (state[key] as RadixColor).base,
|
||||
variant,
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
</Box>{' '}
|
||||
{variant} translucent
|
||||
</Select.Item>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case EmbedConfigType.TextColor: {
|
||||
control = (
|
||||
<Select.Root
|
||||
size="1"
|
||||
value={`${state[key]}`}
|
||||
onValueChange={(value) => {
|
||||
mutateState((draft) => {
|
||||
draft[key] = value as RadixTextColor;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
<Select.Item value="undefined">
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: 'white',
|
||||
}}
|
||||
/>{' '}
|
||||
White
|
||||
</Select.Item>
|
||||
<Select.Item value="gray">
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: 'gray',
|
||||
}}
|
||||
/>{' '}
|
||||
Gray
|
||||
</Select.Item>
|
||||
{Object.entries(radixColors)
|
||||
.filter(
|
||||
([key]) =>
|
||||
!key.endsWith('A') &&
|
||||
!key.endsWith('P3') &&
|
||||
!key.endsWith('Dark') &&
|
||||
!radixGrays.includes(key),
|
||||
)
|
||||
.map(([key]) => (
|
||||
<Select.Item key={key} value={key}>
|
||||
<Box
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
verticalAlign: 'text-top',
|
||||
borderRadius: toRadiusVar('full'),
|
||||
backgroundColor: toColorVar({
|
||||
base: key as RadixColorBase,
|
||||
variant: '9',
|
||||
}),
|
||||
}}
|
||||
/>{' '}
|
||||
{capitalize(key)}
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex
|
||||
direction="column"
|
||||
gap="1"
|
||||
mb="1"
|
||||
pb={setting.pad ? '6' : undefined}
|
||||
>
|
||||
<Text color="gray" size="2">
|
||||
{capitalize(startCase(key))}
|
||||
</Text>
|
||||
{control && <Flex gap="1">{control}</Flex>}
|
||||
{!control && (
|
||||
<Text color="red" size="1">
|
||||
Immutable
|
||||
</Text>
|
||||
{control && <Flex gap="1">{control}</Flex>}
|
||||
{!control && (
|
||||
<Text color="red" size="1">
|
||||
Immutable
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
</ScrollArea>
|
||||
)}
|
||||
|
||||
{!expanded && (
|
||||
<Flex justify="center">
|
||||
<Text size="2" color="gray">
|
||||
Expand to configure
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
)}
|
||||
</Card>
|
||||
</ScrollArea>
|
||||
|
||||
{children}
|
||||
</Flex>
|
||||
<Box
|
||||
p="4"
|
||||
flexGrow="1"
|
||||
position="sticky"
|
||||
top={`${NAVBAR_HEIGHT}px`}
|
||||
height={`calc(100vh - ${NAVBAR_HEIGHT}px)`}
|
||||
>
|
||||
<Card style={{ height: '100%' }}>
|
||||
<Flex direction="column" gap="2" height="100%">
|
||||
<Inset style={{ borderRadius: 0 }}>
|
||||
<Flex
|
||||
justify="between"
|
||||
p="2"
|
||||
px="3"
|
||||
style={{
|
||||
backgroundColor: 'var(--color-panel-translucent)',
|
||||
}}
|
||||
>
|
||||
<Text color="gray">Streaming software</Text>
|
||||
|
||||
<Flex align="center" gap="3">
|
||||
<IconButton color="gray" disabled size="1" variant="ghost">
|
||||
<BorderSolidIcon />
|
||||
</IconButton>
|
||||
<IconButton color="gray" disabled size="1" variant="ghost">
|
||||
<SquareIcon />
|
||||
</IconButton>
|
||||
<IconButton color="gray" disabled size="1" variant="ghost">
|
||||
<Cross1Icon />
|
||||
</IconButton>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Inset>
|
||||
|
||||
<Flex
|
||||
mt="4"
|
||||
flexGrow="1"
|
||||
style={{
|
||||
borderRadius: toRadiusVar('3'),
|
||||
overflow: 'hidden',
|
||||
background: `url(${backgroundImage}) center / cover no-repeat`,
|
||||
}}
|
||||
align="center"
|
||||
justify="center"
|
||||
>
|
||||
{children}
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
</Box>
|
||||
</Flex>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Flex, FlexProps, Theme } from '@radix-ui/themes';
|
||||
import { ComponentProps } from 'react';
|
||||
import { RadixSize } from '../app/tools/embed/types';
|
||||
|
||||
type PageWrapperProps = FlexProps & {
|
||||
color?: ComponentProps<typeof Theme>['accentColor'];
|
||||
@@ -7,6 +8,7 @@ type PageWrapperProps = FlexProps & {
|
||||
noMaxWidth?: boolean;
|
||||
containerProps?: ComponentProps<typeof Theme>;
|
||||
noFlex1?: boolean;
|
||||
padding?: RadixSize;
|
||||
};
|
||||
|
||||
export default function PageWrapper({
|
||||
@@ -17,6 +19,7 @@ export default function PageWrapper({
|
||||
noMaxWidth = false,
|
||||
noFlex1 = false,
|
||||
containerProps,
|
||||
padding = '4',
|
||||
...props
|
||||
}: PageWrapperProps) {
|
||||
return (
|
||||
@@ -33,7 +36,7 @@ export default function PageWrapper({
|
||||
<Flex
|
||||
direction="column"
|
||||
gap="4"
|
||||
p="4"
|
||||
p={padding}
|
||||
style={{
|
||||
width: '100%',
|
||||
maxWidth: noMaxWidth ? undefined : size,
|
||||
|
||||
Reference in new issue
Block a user