@sqrzro/admin 2.1.0-bz.0 → 2.1.0-bz.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +8 -5
- package/dist/components/AppLayout/index.d.ts +4 -1
- package/dist/components/AppLayout/index.js +7 -4
- package/dist/components/AppNavigation/index.js +4 -3
- package/dist/components/Auth/index.d.ts +5 -0
- package/dist/components/Auth/index.js +12 -0
- package/dist/components/Badge/index.d.ts +8 -0
- package/dist/components/Badge/index.js +11 -0
- package/dist/components/Dashboard/index.js +1 -1
- package/dist/components/DateFilter/index.js +0 -1
- package/dist/components/FilterBar/index.d.ts +4 -3
- package/dist/components/FilterBar/index.js +12 -3
- package/dist/components/FilterBarItem/index.d.ts +2 -1
- package/dist/components/FilterBarItem/index.js +2 -2
- package/dist/components/GridList/index.d.ts +2 -2
- package/dist/components/GridList/index.js +1 -1
- package/dist/components/GridListItem/index.d.ts +1 -1
- package/dist/components/GridListItem/index.js +3 -2
- package/dist/components/InfoPanel/index.d.ts +8 -0
- package/dist/components/InfoPanel/index.js +10 -0
- package/dist/components/List/index.d.ts +12 -10
- package/dist/components/List/index.js +7 -5
- package/dist/components/ListActions/index.js +1 -1
- package/dist/components/ListItem/index.d.ts +9 -6
- package/dist/components/ListItem/index.js +8 -4
- package/dist/components/MeActions/index.js +3 -10
- package/dist/components/MePanel/index.d.ts +6 -1
- package/dist/components/MePanel/index.js +2 -5
- package/dist/components/Page/index.d.ts +1 -1
- package/dist/components/Page/index.js +2 -2
- package/dist/components/Panel/index.d.ts +1 -1
- package/dist/components/Panel/index.js +1 -1
- package/dist/components/RootLayout/index.d.ts +2 -1
- package/dist/components/RootLayout/index.js +12 -5
- package/dist/components/SettingsForm/index.d.ts +2 -0
- package/dist/components/SettingsForm/index.js +9 -0
- package/dist/components/SettingsPage/index.d.ts +2 -0
- package/dist/components/SettingsPage/index.js +7 -0
- package/dist/components/Table/index.d.ts +2 -2
- package/dist/components/TableClientComponent/index.d.ts +4 -4
- package/dist/components/TableClientComponent/index.js +17 -4
- package/dist/components/Tabs/index.js +20 -2
- package/dist/components/index.d.ts +12 -4
- package/dist/components/index.js +6 -2
- package/dist/services/ConfigService.d.ts +3 -1
- package/dist/services/ConfigService.js +5 -5
- package/dist/styles/config.js +94 -35
- package/dist/styles/postcss.d.ts +6 -0
- package/dist/styles/postcss.js +4 -0
- package/dist/styles/tailwind.d.ts +10 -0
- package/dist/styles/tailwind.js +72 -0
- package/package.json +66 -76
- package/postcss.js +3 -0
- package/tailwind.d.ts +1 -0
- package/tailwind.js +1 -0
- package/.babelrc.json +0 -16
- package/.eslintignore +0 -6
- package/.eslintrc +0 -5
- package/.sqrzrorc +0 -5
- package/.storybook/main.js +0 -11
- package/.storybook/preview-head.html +0 -3
- package/.storybook/preview.js +0 -1
- package/.turbo/turbo-build.log +0 -20
- package/.turbo/turbo-prettier.log +0 -43
- package/COMPONENTS.md +0 -45
- package/dist/components/LoginForm/index.d.ts +0 -6
- package/dist/components/LoginForm/index.js +0 -7
- package/dist/styles.css +0 -1723
- package/dist/utility/formatters.d.ts +0 -1
- package/dist/utility/formatters.js +0 -8
- package/next-env.d.ts +0 -5
- package/postcss.config.js +0 -3
- package/prettier.config.js +0 -1
- package/src/components/AppLayout/index.tsx +0 -32
- package/src/components/AppNavigation/index.tsx +0 -39
- package/src/components/BooleanFilter/index.tsx +0 -28
- package/src/components/Config/index.tsx +0 -17
- package/src/components/Dashboard/index.tsx +0 -15
- package/src/components/DateFilter/index.tsx +0 -49
- package/src/components/DropdownFilter/index.tsx +0 -19
- package/src/components/FilterBar/index.tsx +0 -35
- package/src/components/FilterBarItem/index.tsx +0 -126
- package/src/components/GridList/index.tsx +0 -11
- package/src/components/GridListItem/index.tsx +0 -31
- package/src/components/Icon/index.tsx +0 -33
- package/src/components/List/index.tsx +0 -70
- package/src/components/ListAction/index.tsx +0 -25
- package/src/components/ListActions/index.tsx +0 -43
- package/src/components/ListItem/index.tsx +0 -56
- package/src/components/LoginForm/index.tsx +0 -34
- package/src/components/MeActions/index.tsx +0 -21
- package/src/components/MePanel/index.tsx +0 -21
- package/src/components/Page/index.tsx +0 -60
- package/src/components/PageActions/index.tsx +0 -22
- package/src/components/Panel/Panel.spec.tsx +0 -10
- package/src/components/Panel/Panel.stories.tsx +0 -9
- package/src/components/Panel/index.tsx +0 -15
- package/src/components/RootLayout/index.tsx +0 -39
- package/src/components/Table/index.tsx +0 -34
- package/src/components/TableClientComponent/index.tsx +0 -112
- package/src/components/Tabs/index.tsx +0 -25
- package/src/components/index.ts +0 -68
- package/src/icons/ErrorIcon/index.tsx +0 -19
- package/src/icons/InfoIcon/index.tsx +0 -19
- package/src/icons/SuccessIcon/index.tsx +0 -19
- package/src/icons/WarningIcon/index.tsx +0 -19
- package/src/index.ts +0 -3
- package/src/interfaces.ts +0 -3
- package/src/react.d.ts +0 -12
- package/src/services/ConfigService.ts +0 -24
- package/src/styles/config.ts +0 -95
- package/src/styles/tailwind.css +0 -47
- package/src/utility/formatters.ts +0 -9
- package/tailwind.config.js +0 -16
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -18
package/LICENSE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright
|
|
1
|
+
Copyright 2024 Richard Carter
|
|
2
2
|
|
|
3
3
|
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
4
4
|
|
package/README.md
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
<h1>
|
|
4
|
+
<img src="assets/logo.svg" alt="" width="64" style="margin-bottom: 5px">
|
|
5
|
+
<br />
|
|
6
|
+
Square Zero Admin
|
|
7
|
+
</h1>
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
<p>An intentionally opionated collection of components, hooks, services and utilities that lets you very quickly build admin systems in Typescript & React.</p>
|
|
10
|
+
<p>[Click here to get started](/story/guides-installation--page)</p>
|
|
8
11
|
|
|
9
12
|
<hr />
|
|
10
13
|
|
|
11
|
-
[](https://github.com/sqrzro/admin/blob/main/LICENSE) [](https://www.npmjs.com/package/@sqrzro/admin) [](https://github.com/sqrzro/admin/actions/workflows/development.yml)
|
|
14
|
+
[](https://github.com/sqrzro/sqrzro/admin/blob/main/LICENSE) [](https://www.npmjs.com/package/@sqrzro/admin) [](https://github.com/sqrzro/sqrzro/admin/actions/workflows/development.yml)
|
|
12
15
|
|
|
13
16
|
</div>
|
|
14
17
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
export interface AppLayoutProps {
|
|
3
3
|
children: React.ReactNode;
|
|
4
|
+
user?: {
|
|
5
|
+
name: string;
|
|
6
|
+
} | null;
|
|
4
7
|
}
|
|
5
|
-
declare function AppLayout({ children }: Readonly<AppLayoutProps>): React.ReactElement;
|
|
8
|
+
declare function AppLayout({ children, user }: Readonly<AppLayoutProps>): React.ReactElement;
|
|
6
9
|
export default AppLayout;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
'use server';
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
3
|
+
import { Container, Link, tw } from '@sqrzro/components';
|
|
4
|
+
import { cookies } from 'next/headers';
|
|
4
5
|
import { getConfig } from '../../services/ConfigService';
|
|
5
6
|
import AppNavigation from '../AppNavigation';
|
|
6
7
|
import MePanel from '../MePanel';
|
|
7
|
-
function AppLayout({ children }) {
|
|
8
|
-
|
|
8
|
+
function AppLayout({ children, user }) {
|
|
9
|
+
const config = getConfig();
|
|
10
|
+
const layout = cookies().get('layout')?.value || 'topbar';
|
|
11
|
+
return (_jsxs("div", { className: tw('', layout === 'sidebar' ? 'grid grid-cols-[12rem_1fr]' : null), children: [_jsx("header", { className: "bg-slate-800", children: _jsx(Container, { isFullWidth: true, children: _jsxs("div", { className: tw('flex h-16 items-center border-b border-slate-700', layout === 'sidebar' ? 'h-screen flex-col' : null), children: [_jsxs(Link, { className: "h-9 w-9", href: "/", children: [config.logo?.(), _jsx("span", { className: "sr-only", children: config.app.name })] }), _jsx(AppNavigation, {}), _jsx(MePanel, { user: user })] }) }) }), _jsx("main", { className: "mb-10 block", children: children })] }));
|
|
9
12
|
}
|
|
10
13
|
export default AppLayout;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import
|
|
4
|
-
import { Link } from '@sqrzro/components';
|
|
3
|
+
import { Link, tw } from '@sqrzro/components';
|
|
5
4
|
import { useNavigation } from '@sqrzro/hooks';
|
|
6
5
|
import { getConfig } from '../../services/ConfigService';
|
|
7
6
|
function getNavigation() {
|
|
@@ -10,6 +9,8 @@ function getNavigation() {
|
|
|
10
9
|
}
|
|
11
10
|
function AppNavigation() {
|
|
12
11
|
const navigation = useNavigation(getNavigation());
|
|
13
|
-
return (_jsx("ul", { className: "flex h-full items-center gap-2
|
|
12
|
+
return (_jsx("nav", { className: "h-full pl-6", children: _jsx("ul", { className: "flex h-full items-center gap-2", children: navigation.map(({ href, isActive, label }) => (_jsx("li", { className: "h-full", children: _jsx(Link, { className: tw('relative flex h-full items-center px-1 font-semibold', isActive
|
|
13
|
+
? 'before:bg-primary text-white before:absolute before:bottom-0 before:left-0 before:right-0 before:h-1'
|
|
14
|
+
: 'text-white/80 hover:text-white'), href: href, children: label }) }, href))) }) }));
|
|
14
15
|
}
|
|
15
16
|
export default AppNavigation;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Auth as AuthComponent } from '@sqrzro/components';
|
|
3
|
+
const classNames = {
|
|
4
|
+
root: 'bg-slate-800 gap-8',
|
|
5
|
+
logo: 'mx-auto flex h-12 w-32 items-end',
|
|
6
|
+
panel: 'rounded bg-white p-8 shadow-lg',
|
|
7
|
+
title: 'text-lg font-semibold mb-4 leading-none',
|
|
8
|
+
};
|
|
9
|
+
function Auth(props) {
|
|
10
|
+
return _jsx(AuthComponent, { ...props, classNames: classNames });
|
|
11
|
+
}
|
|
12
|
+
export default Auth;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { StyleVariant } from '@sqrzro/interfaces';
|
|
3
|
+
export interface BadgeProps {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
variant: StyleVariant;
|
|
6
|
+
}
|
|
7
|
+
declare function Badge({ children, variant }: Readonly<BadgeProps>): React.ReactElement;
|
|
8
|
+
export default Badge;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { tw } from '@sqrzro/components';
|
|
3
|
+
const variantMap = {
|
|
4
|
+
info: 'bg-sky-100 border-sky-300 text-sky-700',
|
|
5
|
+
warning: 'bg-yellow-100 border-yellow-300 text-yellow-700',
|
|
6
|
+
success: 'bg-emerald-100 border-emerald-300 text-emerald-600',
|
|
7
|
+
};
|
|
8
|
+
function Badge({ children, variant }) {
|
|
9
|
+
return (_jsx("strong", { className: tw('block rounded border px-2 py-1 text-xs', variantMap[variant]), children: children }));
|
|
10
|
+
}
|
|
11
|
+
export default Badge;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
function Dashboard({ children, title }) {
|
|
3
|
-
return (_jsxs("div", { children: [_jsx("h1", { className: "mx-auto text-center text-4xl font-semibold", children: title }), children] }));
|
|
3
|
+
return (_jsxs("div", { className: "py-8", children: [_jsx("h1", { className: "mx-auto text-center text-4xl font-semibold", children: title }), children] }));
|
|
4
4
|
}
|
|
5
5
|
export default Dashboard;
|
|
@@ -4,7 +4,6 @@ function DateFilter({ name, onChange, value }) {
|
|
|
4
4
|
return _jsx(CalendarInput, { name: name, onChange: onChange, value: value, isPanelOnly: true, isRange: true });
|
|
5
5
|
}
|
|
6
6
|
export function transformDateValue(value) {
|
|
7
|
-
//return value?.split(',').map((item) => new Date(item)) || [];
|
|
8
7
|
return value || '';
|
|
9
8
|
}
|
|
10
9
|
const LENGTH_OF_YEAR = 4;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import type { FilterObject } from '../FilterBarItem';
|
|
3
|
-
export type
|
|
3
|
+
export type { FilterObject } from '../FilterBarItem';
|
|
4
4
|
export interface FilterBarProps {
|
|
5
|
-
|
|
5
|
+
hasSearch?: boolean;
|
|
6
|
+
map?: FilterObject[];
|
|
6
7
|
}
|
|
7
|
-
declare function FilterBar({ map }: Readonly<FilterBarProps>): React.ReactElement;
|
|
8
|
+
declare function FilterBar({ hasSearch, map }: Readonly<FilterBarProps>): React.ReactElement;
|
|
8
9
|
export default FilterBar;
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
3
4
|
import { useFilters } from '@sqrzro/hooks';
|
|
5
|
+
import { useRouter } from 'next/navigation';
|
|
4
6
|
import FilterBarItem from '../FilterBarItem';
|
|
5
|
-
function FilterBar({ map }) {
|
|
7
|
+
function FilterBar({ hasSearch, map }) {
|
|
8
|
+
const router = useRouter();
|
|
6
9
|
const [filters, setFilter] = useFilters();
|
|
10
|
+
const [search, setSearch] = useState(filters.get('search') || '');
|
|
7
11
|
function handleChange(name, value) {
|
|
8
12
|
setFilter(name, value);
|
|
13
|
+
router.refresh();
|
|
9
14
|
}
|
|
10
|
-
return (
|
|
15
|
+
return (_jsxs("ul", { className: "relative flex gap-2 before:absolute before:left-[calc(50%-50vw)] before:top-full before:h-24 before:w-screen before:bg-slate-800", children: [hasSearch ? (_jsx("li", { children: _jsx("input", { name: "search", onChange: (event) => setSearch(event.currentTarget.value), onKeyDown: (event) => {
|
|
16
|
+
if (event.key === 'Enter') {
|
|
17
|
+
setFilter('search', event.currentTarget.value);
|
|
18
|
+
}
|
|
19
|
+
}, value: search }) })) : null, (map || []).map((filter) => (_jsx(FilterBarItem, { onChange: handleChange, value: filters.get(filter.name) || '', ...filter }, filter.name)))] }));
|
|
11
20
|
}
|
|
12
21
|
export default FilterBar;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import type { SimpleObject } from '@sqrzro/interfaces';
|
|
3
|
+
export type FilterType = 'boolean' | 'date' | 'dropdown';
|
|
3
4
|
export interface FilterObject {
|
|
4
5
|
data?: SimpleObject[];
|
|
5
6
|
label: string;
|
|
6
7
|
name: string;
|
|
7
|
-
type:
|
|
8
|
+
type: FilterType;
|
|
8
9
|
}
|
|
9
10
|
interface FilterBarItemProps extends FilterObject {
|
|
10
11
|
onChange: (name: string, value?: string) => void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useRef } from 'react';
|
|
4
|
-
import
|
|
4
|
+
import { tw } from '@sqrzro/components';
|
|
5
5
|
import BooleanFilter, { renderBooleanValue } from '../BooleanFilter';
|
|
6
6
|
import DateFilter, { renderDateValue, transformDateValue } from '../DateFilter';
|
|
7
7
|
import DropdownFilter, { renderDropdownValue } from '../DropdownFilter';
|
|
@@ -26,6 +26,6 @@ function FilterBarItem({ data, label, name, onChange, type, value, }) {
|
|
|
26
26
|
onChange(name, '');
|
|
27
27
|
}
|
|
28
28
|
const { component: FilterComponent, renderValue, size, transformValue } = map[type];
|
|
29
|
-
return (_jsxs("li", { className:
|
|
29
|
+
return (_jsxs("li", { className: tw('relative inline-flex gap-2 rounded-full border px-5 py-2 text-xs text-white', value ? 'border-solid border-slate-400' : 'border-dashed border-slate-400', value ? 'bg-slate-700 pr-10' : 'text-slate-300'), children: [_jsx("p", { className: "", children: label }), value ? (_jsx("p", { className: "border-l border-l-slate-300 pl-2 font-semibold", children: renderValue(value, data) })) : null, _jsx("button", { className: tw('absolute left-0 top-0 h-full select-none text-transparent', value ? 'right-10' : 'right-0'), id: `${name}-control`, popovertarget: `${name}-target`, type: "button", children: "Edit" }), value ? (_jsxs("button", { className: "absolute right-0 top-0 flex h-full w-10 select-none items-center justify-center", onClick: handleClear, type: "button", children: [_jsx("span", { className: "sr-only", children: "Remove" }), _jsx("span", { className: "flex h-4 w-4 items-center justify-center rounded-full bg-white leading-none text-slate-800", children: "\u00D7" })] })) : null, _jsx("div", { ref: panel, anchor: `${name}-control`, className: tw('show left-[anchor(left)] top-[anchor(bottom)] -ml-px mt-2 origin-top-left origin-top-left rounded bg-white shadow-lg', size || DEFAULT_SIZE), id: `${name}-target`, popover: "auto", children: _jsx("div", { className: "py-1", role: "none", children: _jsx(FilterComponent, { data: data, name: name, onChange: handleChange, value: transformValue ? transformValue(value) : value }) }) })] }));
|
|
30
30
|
}
|
|
31
31
|
export default FilterBarItem;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import type { ListProps } from '../List';
|
|
3
|
-
export type GridListProps<
|
|
4
|
-
declare function GridList<
|
|
3
|
+
export type GridListProps<Item, Params> = Omit<ListProps<Item, Params>, 'renderItem'>;
|
|
4
|
+
declare function GridList<Item extends object, Params = object>(props: GridListProps<Item, Params>): React.ReactElement;
|
|
5
5
|
export default GridList;
|
|
@@ -2,6 +2,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import GridListItem from '../GridListItem';
|
|
3
3
|
import List from '../List';
|
|
4
4
|
function GridList(props) {
|
|
5
|
-
return _jsx(List, { ...props,
|
|
5
|
+
return _jsx(List, { ...props, columns: 3, renderItem: GridListItem });
|
|
6
6
|
}
|
|
7
7
|
export default GridList;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import type { ListObject } from '../ListItem';
|
|
3
|
-
declare function GridListItem({ actions
|
|
3
|
+
declare function GridListItem({ actions, href, id, image, imageHref, meta, subtitle, title, }: Readonly<ListObject>): React.ReactElement;
|
|
4
4
|
export default GridListItem;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment } from 'react';
|
|
2
3
|
import { Link } from '@sqrzro/components';
|
|
3
4
|
import { renderMeta } from '../ListItem';
|
|
4
|
-
function GridListItem({ actions: Actions, href, id, image, meta, title, }) {
|
|
5
|
-
return (_jsx("li", { children: _jsxs("article", { className: "overflow-hidden rounded-
|
|
5
|
+
function GridListItem({ actions: Actions, href, id, image, imageHref, meta, subtitle, title, }) {
|
|
6
|
+
return (_jsx("li", { children: _jsxs("article", { className: "bg-panel overflow-hidden rounded p-4 shadow", children: [_jsx("div", { className: "relative mb-4 h-64 rounded border border border-slate-300 bg-slate-50 p-4", children: image ? (_jsxs(Fragment, { children: [_jsx("img", { alt: "", className: "h-full w-full object-contain", src: image }), imageHref ? (_jsx(Link, { className: "absolute inset-0", href: imageHref, scroll: false, children: _jsx("span", { className: "sr-only", children: "Edit Image" }) })) : null] })) : imageHref ? (_jsxs(Link, { className: "absolute inset-0 flex flex-col items-center justify-center gap-3 font-semibold text-slate-500", href: imageHref, scroll: false, children: [_jsx("i", { className: "block h-12 w-12 rounded-full border-2 border-slate-300" }), "Add Image"] })) : null }), _jsx("h2", { className: "text-base font-semibold", children: href ? _jsx(Link, { href: href, children: title }) : title }), subtitle ? _jsx("p", { className: "text-xs text-slate-500", children: subtitle }) : null, meta ? (_jsxs(Fragment, { children: [_jsx("hr", { className: "my-4" }), _jsx("div", { className: "flex items-center justify-between", children: meta ? renderMeta(meta) : null })] })) : null, href ? (_jsxs(Fragment, { children: [_jsx("hr", { className: "my-4" }), _jsx(Link, { href: href, scroll: false, children: "Edit" })] })) : null] }) }));
|
|
6
7
|
}
|
|
7
8
|
export default GridListItem;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { StyleVariant } from '@sqrzro/interfaces';
|
|
3
|
+
export interface InfoPanelProps {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
variant?: StyleVariant;
|
|
6
|
+
}
|
|
7
|
+
declare function InfoPanel({ children, variant }: Readonly<InfoPanelProps>): React.ReactElement;
|
|
8
|
+
export default InfoPanel;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { tw } from '@sqrzro/components';
|
|
3
|
+
const variantMap = {
|
|
4
|
+
info: 'bg-sky-50 border-sky-200 text-sky-700',
|
|
5
|
+
warning: 'bg-yellow-50 border-yellow-100 text-yellow-700',
|
|
6
|
+
};
|
|
7
|
+
function InfoPanel({ children, variant = 'info' }) {
|
|
8
|
+
return (_jsx("aside", { className: tw('rounded border px-3 py-2', variantMap[variant]), children: children }));
|
|
9
|
+
}
|
|
10
|
+
export default InfoPanel;
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { EmptyMessageProps } from '@sqrzro/components';
|
|
3
|
+
import type { Errorable } from '@sqrzro/interfaces';
|
|
4
|
+
import type { FilterObject } from '../FilterBar';
|
|
4
5
|
import type { ListObject } from '../ListItem';
|
|
5
6
|
export interface ListComponentProps {
|
|
6
7
|
params?: Record<string, string>;
|
|
7
8
|
searchParams?: Record<string, string>;
|
|
8
9
|
}
|
|
9
|
-
export interface ListProps<
|
|
10
|
+
export interface ListProps<Item, Params = object> {
|
|
10
11
|
actions?: ({ id }: {
|
|
11
12
|
readonly id: number;
|
|
12
13
|
}) => React.ReactElement;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
columns?: number;
|
|
15
|
+
emptyMessageProps?: EmptyMessageProps;
|
|
16
|
+
filters?: FilterObject[];
|
|
17
|
+
fn: (params?: Params, searchParams?: URLSearchParams) => Promise<Errorable<Item[]>>;
|
|
18
|
+
hasSearch?: boolean;
|
|
16
19
|
renderItem?: (props: ListObject) => React.ReactElement;
|
|
17
|
-
params?:
|
|
18
|
-
|
|
19
|
-
transformer?: (item: T) => ListObject;
|
|
20
|
+
params?: Params;
|
|
21
|
+
transformer?: (item: Item) => ListObject;
|
|
20
22
|
}
|
|
21
|
-
declare function List<
|
|
23
|
+
declare function List<Item extends object, Params = object>({ actions, columns, emptyMessageProps, filters, fn, hasSearch, params, renderItem, transformer, }: Readonly<ListProps<Item, Params>>): Promise<React.ReactElement>;
|
|
22
24
|
export default List;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
'use server';
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { Fragment } from 'react';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
4
|
+
import { EmptyMessage, tw } from '@sqrzro/components';
|
|
5
|
+
import { headers } from 'next/headers';
|
|
5
6
|
import FilterBar from '../FilterBar';
|
|
6
7
|
import ListItem from '../ListItem';
|
|
7
8
|
function defaultTransformer() {
|
|
@@ -10,13 +11,14 @@ function defaultTransformer() {
|
|
|
10
11
|
title: '',
|
|
11
12
|
};
|
|
12
13
|
}
|
|
13
|
-
async function List({ actions,
|
|
14
|
+
async function List({ actions, columns, emptyMessageProps, filters, fn, hasSearch, params, renderItem = ListItem, transformer, }) {
|
|
15
|
+
const searchParams = new URLSearchParams(headers().get('x-search-params') || '');
|
|
14
16
|
const [response, error] = await fn(params, searchParams);
|
|
15
17
|
if (error) {
|
|
16
|
-
return _jsx("div", { children: "
|
|
18
|
+
return _jsx("div", { children: "Error" });
|
|
17
19
|
}
|
|
18
20
|
const data = response.map(transformer || defaultTransformer);
|
|
19
21
|
const hasFilters = Boolean(Object.keys(searchParams || []).length);
|
|
20
|
-
return (_jsxs(Fragment, { children: [filters && (data.length || hasFilters) ? _jsx(FilterBar, { map: filters }) : null, data.length ? (_jsx("ul", { className:
|
|
22
|
+
return (_jsxs(Fragment, { children: [(filters || hasSearch) && (data.length || hasFilters) ? (_jsx(FilterBar, { hasSearch: hasSearch, map: filters })) : null, data.length ? (_jsx("ul", { className: tw('relative', columns ? 'grid grid-cols-3 gap-6' : 'flex flex-col gap-4'), children: data.map((item) => renderItem({ actions, ...item })) })) : (_jsx(EmptyMessage, { ...emptyMessageProps }))] }));
|
|
21
23
|
}
|
|
22
24
|
export default List;
|
|
@@ -7,6 +7,6 @@ function ListActions({ actions, id }) {
|
|
|
7
7
|
function toggleIsOpen() {
|
|
8
8
|
setIsOpen(!isOpen);
|
|
9
9
|
}
|
|
10
|
-
return (_jsxs("div", { ref: ref, className: "flex flex-row-reverse items-center gap-4", children: [_jsxs("button", { className: "h-4 rotate-90 text-xs leading-[1em] tracking-tighter text-slate-500", onClick: toggleIsOpen, type: "button", children: ["\u2022\u2022\u2022", _jsxs("span", { className: "sr-only", children: [isOpen ? 'Close' : 'Open', " Actions"] })] }), isOpen ? (_jsx("ul", { className: "
|
|
10
|
+
return (_jsxs("div", { ref: ref, className: "flex flex-row-reverse items-center gap-4", children: [_jsxs("button", { className: "h-4 rotate-90 text-xs leading-[1em] tracking-tighter text-slate-500", onClick: toggleIsOpen, type: "button", children: ["\u2022\u2022\u2022", _jsxs("span", { className: "sr-only", children: [isOpen ? 'Close' : 'Open', " Actions"] })] }), isOpen ? (_jsx("ul", { className: "show relative flex origin-right gap-4 bg-white before:absolute before:left-[-999em] before:right-full before:h-full before:bg-white/80", children: actions.map(({ label, onClick, variant }) => (_jsx("li", { children: _jsx(ListAction, { id: id, label: label, onClick: onClick, variant: variant }) }, label))) })) : null] }));
|
|
11
11
|
}
|
|
12
12
|
export default ListActions;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
export interface ListObject {
|
|
3
3
|
actions?: ({ id }: {
|
|
4
|
-
id: number;
|
|
4
|
+
id: number | string;
|
|
5
5
|
}) => React.ReactElement;
|
|
6
6
|
href?: string;
|
|
7
|
-
id: number;
|
|
8
|
-
image?: string;
|
|
9
|
-
|
|
7
|
+
id: number | string;
|
|
8
|
+
image?: string | null;
|
|
9
|
+
imageHref?: string | null;
|
|
10
|
+
meta?: React.ReactNode[] | Record<string, React.ReactNode>;
|
|
11
|
+
subtitle?: React.ReactNode | null;
|
|
10
12
|
title: string;
|
|
11
13
|
}
|
|
12
|
-
export declare function renderMeta(meta:
|
|
13
|
-
declare function ListItem({ actions: Actions,
|
|
14
|
+
export declare function renderMeta(meta: ListObject['meta']): React.ReactElement | null;
|
|
15
|
+
declare function ListItem({ actions: Actions, // eslint-disable-line @typescript-eslint/naming-convention
|
|
16
|
+
href, id, meta, title, }: Readonly<ListObject>): React.ReactElement;
|
|
14
17
|
export default ListItem;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Link } from '@sqrzro/components';
|
|
3
3
|
export function renderMeta(meta) {
|
|
4
|
+
if (!meta) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
4
7
|
if (Array.isArray(meta)) {
|
|
5
|
-
return (_jsx("ul", { className: "flex gap-4 text-xs", children: meta.map((item) => (_jsx("li", { children: item }, item))) }));
|
|
8
|
+
return (_jsx("ul", { className: "flex items-center gap-4 text-xs text-slate-600", children: meta.map((item) => (_jsx("li", { children: item }, item?.toString()))) }));
|
|
6
9
|
}
|
|
7
|
-
return (_jsx("
|
|
10
|
+
return (_jsx("table", { className: "w-full text-xs", children: _jsx("tbody", { children: Object.entries(meta).map(([key, value]) => (_jsxs("tr", { className: "odd:bg-slate-100", children: [_jsx("th", { className: "p-2 font-semibold", children: key }), _jsx("td", { className: "p-2 text-right", children: value || '-' })] }, key))) }) }));
|
|
8
11
|
}
|
|
9
|
-
function ListItem({ actions: Actions,
|
|
10
|
-
|
|
12
|
+
function ListItem({ actions: Actions, // eslint-disable-line @typescript-eslint/naming-convention
|
|
13
|
+
href, id, meta, title, }) {
|
|
14
|
+
return (_jsx("li", { children: _jsxs("article", { className: "bg-panel overflow-hidden rounded p-4 shadow-[0px_0px_0px_1px_rgba(9,9,11,0.07),0px_2px_2px_0px_rgba(9,9,11,0.05)]", children: [_jsx("h2", { className: "border-b border-slate-200 pb-3 text-lg font-semibold", children: href ? _jsx(Link, { href: href, children: title }) : title }), _jsxs("div", { className: "mt-4 flex items-center justify-between", children: [meta ? renderMeta(meta) : null, Actions ? _jsx(Actions, { id: id }) : null] })] }) }));
|
|
11
15
|
}
|
|
12
16
|
export default ListItem;
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { removeSession } from '@sqrzro/server';
|
|
4
|
-
import { useRouter } from 'next/navigation';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Link, LogoutButton } from '@sqrzro/components';
|
|
5
3
|
function MeActions() {
|
|
6
|
-
|
|
7
|
-
async function handleLogout() {
|
|
8
|
-
await removeSession();
|
|
9
|
-
router.refresh();
|
|
10
|
-
}
|
|
11
|
-
return (_jsx("button", { className: "text-xs text-gray-300", onClick: handleLogout, type: "button", children: "Log Out" }));
|
|
4
|
+
return (_jsxs("ul", { className: "flex gap-2 text-xs text-slate-300", children: [_jsx("li", { children: _jsx(Link, { href: "/settings", children: "Settings" }) }), _jsx("li", { children: _jsx(LogoutButton, {}) })] }));
|
|
12
5
|
}
|
|
13
6
|
export default MeActions;
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
|
|
2
|
+
interface MePanelProps {
|
|
3
|
+
user?: {
|
|
4
|
+
name: string;
|
|
5
|
+
} | null;
|
|
6
|
+
}
|
|
7
|
+
declare function MePanel({ user }: Readonly<MePanelProps>): React.ReactElement;
|
|
3
8
|
export default MePanel;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
'use server';
|
|
2
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { getIdFromSession } from '@sqrzro/server';
|
|
4
2
|
import MeActions from '../MeActions';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return (_jsxs("div", { className: "ml-auto flex items-center gap-3", children: [_jsxs("div", { className: "flex flex-col items-end text-white", children: [_jsx("strong", { children: id }), _jsx(MeActions, {})] }), _jsx("div", { className: "h-9 w-9 rounded-full border-4 border-gray-500" })] }));
|
|
3
|
+
function MePanel({ user }) {
|
|
4
|
+
return (_jsxs("div", { className: "ml-auto flex items-center gap-3", children: [_jsxs("div", { className: "flex flex-col gap-0.5 items-end text-white", children: [_jsx("strong", { children: user?.name }), _jsx(MeActions, {})] }), _jsx("div", { className: "h-9 w-9 rounded-full border-4 border-slate-500" })] }));
|
|
8
5
|
}
|
|
9
6
|
export default MePanel;
|
|
@@ -8,5 +8,5 @@ export interface PageProps {
|
|
|
8
8
|
tabs?: LinkableAction[];
|
|
9
9
|
title: string;
|
|
10
10
|
}
|
|
11
|
-
declare function Page({
|
|
11
|
+
declare function Page({ basePath, children, isFullWidth, tabs, title, }: Readonly<PageProps>): React.ReactElement;
|
|
12
12
|
export default Page;
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Fragment } from 'react';
|
|
3
3
|
import { Container } from '@sqrzro/components';
|
|
4
4
|
import Tabs from '../Tabs';
|
|
5
|
-
function Page({
|
|
6
|
-
return (_jsxs(Fragment, { children: [_jsx("header", { className: "bg-
|
|
5
|
+
function Page({ basePath, children, isFullWidth, tabs, title, }) {
|
|
6
|
+
return (_jsxs(Fragment, { children: [_jsx("header", { className: "bg-slate-800 pb-16 text-white", children: _jsxs(Container, { isFullWidth: isFullWidth, children: [_jsxs("div", { className: "flex items-center justify-between py-10", children: [_jsx("h1", { className: "min-h-10 text-3xl font-semibold", children: title }), _jsx("div", { id: "page-actions" })] }), tabs ? (_jsx("div", { className: "-mt-4 mb-8", children: _jsx(Tabs, { basePath: basePath, data: tabs }) })) : null] }) }), _jsx(Container, { isFullWidth: isFullWidth, children: _jsx("div", { className: "-mt-16 flex flex-col gap-8", children: children }) })] }));
|
|
7
7
|
}
|
|
8
8
|
export default Page;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
function Panel({ children, title }) {
|
|
3
|
-
return (_jsxs("article", { children: [title ? _jsx("h3", { children: title }) : null, children] }));
|
|
3
|
+
return (_jsxs("article", { className: "bg-panel relative overflow-hidden rounded p-6 shadow-[0px_0px_0px_1px_rgba(9,9,11,0.07),0px_2px_2px_0px_rgba(9,9,11,0.05)]", children: [title ? (_jsx("h3", { className: "mb-4 border-b border-slate-200 pb-3 text-lg font-semibold leading-none", children: title })) : null, children] }));
|
|
4
4
|
}
|
|
5
5
|
export default Panel;
|
|
@@ -3,6 +3,7 @@ import type { Config as ConfigObject } from '../../services/ConfigService';
|
|
|
3
3
|
export interface RootLayoutProps {
|
|
4
4
|
children: React.ReactNode;
|
|
5
5
|
config?: ConfigObject;
|
|
6
|
+
logo?: () => React.ReactElement;
|
|
6
7
|
}
|
|
7
|
-
declare function RootLayout({ children, config }: Readonly<RootLayoutProps>): React.ReactElement;
|
|
8
|
+
declare function RootLayout({ children, config, logo }: Readonly<RootLayoutProps>): React.ReactElement;
|
|
8
9
|
export default RootLayout;
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/* eslint-disable react/no-danger */
|
|
2
3
|
import { Suspense } from 'react';
|
|
3
|
-
import {
|
|
4
|
+
import { Inter as getInter } from 'next/font/google';
|
|
5
|
+
import { ClassNames, Toaster, tw } from '@sqrzro/components';
|
|
4
6
|
import { setConfig } from '../../services/ConfigService';
|
|
5
7
|
import classNames from '../../styles/config';
|
|
6
8
|
import Config from '../Config';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
const inter = getInter({
|
|
10
|
+
subsets: ['latin'],
|
|
11
|
+
variable: '--font-inter',
|
|
12
|
+
});
|
|
13
|
+
function RootLayout({ children, config, logo }) {
|
|
9
14
|
if (config) {
|
|
10
|
-
setConfig(config);
|
|
15
|
+
setConfig(config, logo);
|
|
11
16
|
}
|
|
12
|
-
return (_jsxs("html", { lang: "en", children: [_jsx("head", {}), _jsxs("body", {
|
|
17
|
+
return (_jsxs("html", { lang: "en", children: [_jsx("head", {}), _jsxs("body", { className: tw(inter.variable, 'overflow-x-hidden overflow-y-scroll bg-slate-50 font-sans text-sm text-slate-800 has-[[data-modal][open]]:overflow-hidden'), children: [_jsx("script", { dangerouslySetInnerHTML: {
|
|
18
|
+
__html: "(function(d){var v=d.createElement('div'),t=d.createElement('style'),s=v.style;s.overflowY='scroll';s.width='50';s.height='50';d.body.append(v);t.innerHTML='body:has([data-modal][open]){padding-right:'+(v.offsetWidth-v.clientWidth)+'px}';d.body.append(t);v.remove()}(document))",
|
|
19
|
+
} }), _jsx(Config, { data: config }), _jsx(ClassNames, { data: classNames }), children, _jsx(Suspense, { fallback: null, children: _jsx(Toaster, {}) })] })] }));
|
|
13
20
|
}
|
|
14
21
|
export default RootLayout;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { EditableForm } from '@sqrzro/components';
|
|
4
|
+
import { useEditableForm } from '@sqrzro/hooks';
|
|
5
|
+
function SettingsForm() {
|
|
6
|
+
const { formProps } = useEditableForm({});
|
|
7
|
+
return (_jsx(EditableForm, { title: "Appearance", ...formProps, children: "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Iure, aperiam modi. Atque, nemo qui! Quae consectetur tempora beatae, ducimus reprehenderit, et aliquam quod est, quidem fugiat impedit sit nihil cum!" }));
|
|
8
|
+
}
|
|
9
|
+
export default SettingsForm;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import type {
|
|
2
|
+
import type { Errorable } from '@sqrzro/interfaces';
|
|
3
3
|
import type { TableClientComponentProps } from '../TableClientComponent';
|
|
4
4
|
export interface TableProps<T> extends Omit<TableClientComponentProps, 'data'> {
|
|
5
|
-
fn: (filters?: Record<string, string>) =>
|
|
5
|
+
fn: (filters?: Record<string, string>) => Promise<Errorable<T[]>>;
|
|
6
6
|
searchParams?: Record<string, string>;
|
|
7
7
|
}
|
|
8
8
|
declare function Table<T>({ columns, fn, searchParams, }: Readonly<TableProps<T>>): Promise<React.ReactElement>;
|
|
@@ -3,13 +3,13 @@ export interface TableItemObject {
|
|
|
3
3
|
[key: string]: string;
|
|
4
4
|
id: string;
|
|
5
5
|
}
|
|
6
|
-
interface TableColumnObject {
|
|
6
|
+
export interface TableColumnObject {
|
|
7
7
|
key: string;
|
|
8
|
-
title
|
|
9
|
-
type?: 'string';
|
|
8
|
+
title?: string;
|
|
9
|
+
type?: 'number' | 'string';
|
|
10
10
|
}
|
|
11
11
|
export interface TableClientComponentProps {
|
|
12
|
-
columns: TableColumnObject[];
|
|
12
|
+
columns: string[] | TableColumnObject[];
|
|
13
13
|
data: TableItemObject[];
|
|
14
14
|
}
|
|
15
15
|
declare function TableClientComponent({ columns, data, }: Readonly<TableClientComponentProps>): React.ReactElement;
|