refactor progress

This commit is contained in:
Hampus Kraft
2026-02-17 12:22:36 +00:00
parent cb31608523
commit d5abd1a7e4
8257 changed files with 1190207 additions and 761040 deletions

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import {cn} from '@fluxer/admin/src/utils/ClassNames';
import type {PropsWithChildren} from 'hono/jsx';
export type BoxSpacing = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
export type BoxBackground = 'white' | 'gray-50' | 'gray-100' | 'transparent';
export type BoxBorder = 'none' | 'gray-200' | 'gray-300';
export type BoxRounded = 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';
export interface BoxProps {
p?: BoxSpacing;
m?: BoxSpacing;
bg?: BoxBackground;
border?: BoxBorder;
rounded?: BoxRounded;
}
const backgroundClasses: Record<BoxBackground, string> = {
white: 'bg-white',
'gray-50': 'bg-gray-50',
'gray-100': 'bg-gray-100',
transparent: 'bg-transparent',
};
const borderClasses: Record<BoxBorder, string> = {
none: '',
'gray-200': 'border border-gray-200',
'gray-300': 'border border-gray-300',
};
const roundedClasses: Record<BoxRounded, string> = {
none: 'rounded-none',
sm: 'rounded-sm',
md: 'rounded-md',
lg: 'rounded-lg',
xl: 'rounded-xl',
'2xl': 'rounded-2xl',
full: 'rounded-full',
};
function getPaddingClass(p: BoxSpacing): string {
return `p-${p}`;
}
function getMarginClass(m: BoxSpacing): string {
return `m-${m}`;
}
export function Box({
p,
m,
bg = 'transparent',
border = 'none',
rounded = 'none',
children,
}: PropsWithChildren<BoxProps>) {
const classes = cn(
p !== undefined && getPaddingClass(p),
m !== undefined && getMarginClass(m),
backgroundClasses[bg],
borderClasses[border],
roundedClasses[rounded],
);
return <div class={classes}>{children}</div>;
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import {PageContainer} from '@fluxer/admin/src/components/ui/Layout/PageContainer';
import type {Child, PropsWithChildren} from 'hono/jsx';
export interface DetailPageLayoutProps {
header: Child;
tabs?: Child;
}
export function DetailPageLayout({header, tabs, children}: PropsWithChildren<DetailPageLayoutProps>) {
return (
<PageContainer>
{header}
{tabs}
{children}
</PageContainer>
);
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import {cn} from '@fluxer/admin/src/utils/ClassNames';
import type {PropsWithChildren} from 'hono/jsx';
export type FlexDirection = 'row' | 'col' | 'row-reverse' | 'col-reverse';
export type FlexAlign = 'start' | 'center' | 'end' | 'baseline' | 'stretch';
export type FlexJustify = 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';
export type FlexWrap = 'wrap' | 'nowrap' | 'wrap-reverse';
export interface FlexProps {
direction?: FlexDirection;
align?: FlexAlign;
justify?: FlexJustify;
gap?: number | string;
wrap?: FlexWrap;
}
const directionClasses: Record<FlexDirection, string> = {
row: 'flex-row',
col: 'flex-col',
'row-reverse': 'flex-row-reverse',
'col-reverse': 'flex-col-reverse',
};
const alignClasses: Record<FlexAlign, string> = {
start: 'items-start',
center: 'items-center',
end: 'items-end',
baseline: 'items-baseline',
stretch: 'items-stretch',
};
const justifyClasses: Record<FlexJustify, string> = {
start: 'justify-start',
center: 'justify-center',
end: 'justify-end',
between: 'justify-between',
around: 'justify-around',
evenly: 'justify-evenly',
};
const wrapClasses: Record<FlexWrap, string> = {
wrap: 'flex-wrap',
nowrap: 'flex-nowrap',
'wrap-reverse': 'flex-wrap-reverse',
};
function getGapClass(gap: number | string): string {
if (typeof gap === 'number') {
return `gap-${gap}`;
}
return gap;
}
export function Flex({
direction = 'row',
align = 'stretch',
justify = 'start',
gap,
wrap = 'nowrap',
children,
}: PropsWithChildren<FlexProps>) {
const classes = cn(
'flex',
directionClasses[direction],
alignClasses[align],
justifyClasses[justify],
gap !== undefined && getGapClass(gap),
wrapClasses[wrap],
);
return <div class={classes}>{children}</div>;
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import type {PropsWithChildren} from 'hono/jsx';
export interface FormGridProps {
cols?: 2 | 3 | 4;
gap?: 'sm' | 'md' | 'lg';
}
const colsClasses = {
2: 'md:grid-cols-2',
3: 'md:grid-cols-3',
4: 'md:grid-cols-4',
};
const gapClasses = {
sm: 'gap-2',
md: 'gap-4',
lg: 'gap-6',
};
export function FormGrid({cols = 2, gap = 'md', children}: PropsWithChildren<FormGridProps>) {
return <div class={`grid grid-cols-1 ${colsClasses[cols]} ${gapClasses[gap]}`}>{children}</div>;
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import {cn} from '@fluxer/admin/src/utils/ClassNames';
import type {PropsWithChildren} from 'hono/jsx';
export type HStackAlign = 'start' | 'center' | 'end' | 'baseline' | 'stretch';
export type HStackJustify = 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';
export interface HStackProps {
gap?: number | string;
align?: HStackAlign;
justify?: HStackJustify;
class?: string;
}
const alignClasses: Record<HStackAlign, string> = {
start: 'items-start',
center: 'items-center',
end: 'items-end',
baseline: 'items-baseline',
stretch: 'items-stretch',
};
const justifyClasses: Record<HStackJustify, string> = {
start: 'justify-start',
center: 'justify-center',
end: 'justify-end',
between: 'justify-between',
around: 'justify-around',
evenly: 'justify-evenly',
};
function getGapClass(gap: number | string): string {
if (typeof gap === 'number') {
return `gap-${gap}`;
}
return gap;
}
export function HStack({
gap = 4,
align = 'center',
justify = 'start',
class: className,
children,
}: PropsWithChildren<HStackProps>) {
const classes = cn('flex flex-row', getGapClass(gap), alignClasses[align], justifyClasses[justify], className);
return <div class={classes}>{children}</div>;
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import type {PropsWithChildren} from 'hono/jsx';
export interface PageContainerProps {
maxWidth?: 'full' | '7xl';
}
export function PageContainer({maxWidth = '7xl', children}: PropsWithChildren<PageContainerProps>) {
const widthClass = maxWidth === 'full' ? 'w-full' : 'max-w-7xl';
return <div class={`mx-auto ${widthClass} space-y-6`}>{children}</div>;
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import {cn} from '@fluxer/admin/src/utils/ClassNames';
import type {Child, PropsWithChildren} from 'hono/jsx';
export interface PageHeaderProps {
title: string;
description?: string;
actions?: Child;
}
export function PageHeader({title, description, actions, children}: PropsWithChildren<PageHeaderProps>) {
return (
<div>
<div class={cn('flex items-start justify-between', description ? 'mb-2' : 'mb-0')}>
<div class="flex min-w-0 flex-1 flex-col gap-2">
<h1 class="font-bold text-3xl text-gray-900">{title}</h1>
{description && <p class="text-base text-gray-600">{description}</p>}
</div>
{actions && <div class="ml-4 flex-shrink-0">{actions}</div>}
</div>
{children}
</div>
);
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import {cn} from '@fluxer/admin/src/utils/ClassNames';
import type {PropsWithChildren} from 'hono/jsx';
export type PageLayoutMaxWidth = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | '7xl';
export interface PageLayoutProps {
maxWidth?: PageLayoutMaxWidth;
padding?: boolean;
}
const maxWidthClasses: Record<PageLayoutMaxWidth, string> = {
sm: 'max-w-sm',
md: 'max-w-md',
lg: 'max-w-lg',
xl: 'max-w-xl',
'2xl': 'max-w-2xl',
'3xl': 'max-w-3xl',
'4xl': 'max-w-4xl',
'5xl': 'max-w-5xl',
'6xl': 'max-w-6xl',
'7xl': 'max-w-7xl',
};
export function PageLayout({maxWidth = '7xl', padding = false, children}: PropsWithChildren<PageLayoutProps>) {
const classes = cn('mx-auto w-full', maxWidthClasses[maxWidth], padding && 'px-4 sm:px-6 lg:px-8');
return <div class={classes}>{children}</div>;
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import {PageContainer} from '@fluxer/admin/src/components/ui/Layout/PageContainer';
import {PageHeader} from '@fluxer/admin/src/components/ui/Layout/PageHeader';
import type {Child, PropsWithChildren} from 'hono/jsx';
export interface SearchListPageLayoutProps {
title: string;
description?: string;
actions?: Child;
searchForm: Child;
}
export function SearchListPageLayout({
title,
description,
actions,
searchForm,
children,
}: PropsWithChildren<SearchListPageLayoutProps>) {
return (
<PageContainer>
<PageHeader title={title} description={description} actions={actions} />
{searchForm}
{children}
</PageContainer>
);
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import type {PropsWithChildren} from 'hono/jsx';
export interface TwoColumnGridProps {
gap?: 'sm' | 'md' | 'lg';
}
const gapClasses = {
sm: 'gap-2',
md: 'gap-4',
lg: 'gap-6',
};
export function TwoColumnGrid({gap = 'md', children}: PropsWithChildren<TwoColumnGridProps>) {
return <div class={`grid grid-cols-1 md:grid-cols-2 ${gapClasses[gap]}`}>{children}</div>;
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import {cn} from '@fluxer/admin/src/utils/ClassNames';
import type {PropsWithChildren} from 'hono/jsx';
export type VStackAlign = 'start' | 'center' | 'end' | 'stretch';
export interface VStackProps {
gap?: number | string;
align?: VStackAlign;
class?: string;
}
const alignClasses: Record<VStackAlign, string> = {
start: 'items-start',
center: 'items-center',
end: 'items-end',
stretch: 'items-stretch',
};
function getGapClass(gap: number | string): string {
if (typeof gap === 'number') {
return `gap-${gap}`;
}
return gap;
}
export function VStack({gap = 4, align = 'stretch', class: className, children}: PropsWithChildren<VStackProps>) {
const classes = cn('flex flex-col', getGapClass(gap), alignClasses[align], className);
return <div class={classes}>{children}</div>;
}