@sqrzro/admin 2.1.0-bz.14 → 2.1.0-bz.16

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.
@@ -5,5 +5,5 @@ export interface AppLayoutProps {
5
5
  name: string;
6
6
  } | null;
7
7
  }
8
- declare function AppLayout({ children, user }: Readonly<AppLayoutProps>): React.ReactElement;
8
+ declare function AppLayout({ children, user }: Readonly<AppLayoutProps>): Promise<JSX.Element>;
9
9
  export default AppLayout;
@@ -1,12 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Container, Link, tw } from '@sqrzro/components';
3
- import { cookies } from 'next/headers';
4
3
  import { getConfig } from '../../services/ConfigService';
4
+ import { getLayout } from '../../services/LayoutService';
5
5
  import AppNavigation from '../AppNavigation';
6
6
  import MePanel from '../MePanel';
7
- function AppLayout({ children, user }) {
7
+ async function AppLayout({ children, user }) {
8
8
  const config = getConfig();
9
- const layout = cookies().get('layout')?.value || 'topbar';
10
- 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
+ const layout = await getLayout();
10
+ 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 items-center', layout === 'sidebar'
11
+ ? 'h-screen flex-col py-4'
12
+ : 'h-16 border-b border-slate-700'), children: [_jsxs(Link, { className: tw(layout === 'sidebar' ? 'h-12 w-12' : 'h-9 w-9'), href: "/", children: [config.logo?.(), _jsx("span", { className: "sr-only", children: config.app.name })] }), _jsx(AppNavigation, { layout: layout }), _jsx(MePanel, { user: user })] }) }) }), _jsx("main", { className: "mb-10 block", children: children })] }));
11
13
  }
12
14
  export default AppLayout;
@@ -1,3 +1,6 @@
1
1
  /// <reference types="react" />
2
- declare function AppNavigation(): React.ReactElement;
2
+ interface AppNavigationProps {
3
+ layout: string;
4
+ }
5
+ declare function AppNavigation({ layout }: Readonly<AppNavigationProps>): React.ReactElement;
3
6
  export default AppNavigation;
@@ -7,9 +7,9 @@ function getNavigation() {
7
7
  const { navigation } = getConfig();
8
8
  return Object.entries(navigation).map(([href, label]) => ({ href, label }));
9
9
  }
10
- function AppNavigation() {
10
+ function AppNavigation({ layout }) {
11
11
  const navigation = useNavigation(getNavigation());
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
12
+ return (_jsx("nav", { className: "h-full pl-6", children: _jsx("ul", { className: tw('flex h-full gap-2', layout === 'sidebar' ? 'flex-col items-start' : 'items-center'), children: navigation.map(({ href, isActive, label }) => (_jsx("li", { className: tw(layout === 'sidebar' ? null : 'h-full'), children: _jsx(Link, { className: tw('relative flex h-full items-center px-1 font-semibold', isActive
13
13
  ? 'before:bg-primary text-white before:absolute before:bottom-0 before:left-0 before:right-0 before:h-1'
14
14
  : 'text-white/80 hover:text-white'), href: href, children: label }) }, href))) }) }));
15
15
  }
@@ -3,8 +3,11 @@ import { Auth as AuthComponent } from '@sqrzro/components';
3
3
  const classNames = {
4
4
  root: 'bg-slate-800 gap-8',
5
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',
6
+ panel: 'rounded bg-white p-8 shadow-lg pb-10',
7
+ title: 'text-lg font-semibold mb-6 leading-none',
8
+ link: 'font-semibold text-link',
9
+ actions: 'pt-2 w-full',
10
+ footer: '-mb-2',
8
11
  };
9
12
  function Auth(props) {
10
13
  return _jsx(AuthComponent, { ...props, classNames: classNames });
@@ -1,11 +1,11 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { tw } from '@sqrzro/components';
3
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',
4
+ info: 'bg-sky-100 text-sky-700',
5
+ warning: 'bg-yellow-100 text-yellow-700',
6
+ success: 'bg-emerald-100 text-emerald-600',
7
7
  };
8
8
  function Badge({ children, variant }) {
9
- return (_jsx("strong", { className: tw('block rounded border px-2 py-1 text-xs', variantMap[variant]), children: children }));
9
+ return (_jsxs("strong", { className: tw('inline-flex items-center gap-1.5 rounded-full bg-red-100 px-2 py-1 text-xs font-medium text-red-700'), children: [_jsx("svg", { "aria-hidden": "true", className: "h-1.5 w-1.5 fill-red-500", viewBox: "0 0 6 6", children: _jsx("circle", { cx: "3", cy: "3", r: "3" }) }), children] }));
10
10
  }
11
11
  export default Badge;
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- export type IconType = 'error' | 'info' | 'success' | 'warning';
2
+ export type IconType = 'danger' | 'error' | 'info' | 'success' | 'warning';
3
3
  declare const icons: Record<IconType, () => React.ReactElement>;
4
4
  export interface IconProps {
5
5
  type?: keyof typeof icons;
@@ -4,6 +4,7 @@ import InfoIcon from '../../icons/InfoIcon';
4
4
  import SuccessIcon from '../../icons/SuccessIcon';
5
5
  import WarningIcon from '../../icons/WarningIcon';
6
6
  const icons = {
7
+ danger: ErrorIcon,
7
8
  error: ErrorIcon,
8
9
  info: InfoIcon,
9
10
  success: SuccessIcon,
@@ -1,10 +1,22 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
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',
3
+ import Icon from '../Icon';
4
+ const iconTypeMap = {
5
+ danger: 'danger',
6
+ info: 'info',
7
+ success: 'success',
8
+ warning: 'warning',
6
9
  };
10
+ const classMap = {
11
+ danger: 'bg-red-50 text-red-700',
12
+ info: 'bg-sky-50 text-sky-700',
13
+ success: 'bg-green-50 text-green-700',
14
+ warning: 'bg-yellow-50 text-yellow-700',
15
+ };
16
+ function mapVariantToIconType(variant) {
17
+ return iconTypeMap[variant] || 'info';
18
+ }
7
19
  function InfoPanel({ children, variant = 'info' }) {
8
- return (_jsx("aside", { className: tw('rounded border px-3 py-2', variantMap[variant]), children: children }));
20
+ return (_jsxs("aside", { className: tw('grid grid-cols-[1rem_auto] gap-4 rounded p-4', classMap[variant]), children: [_jsx(Icon, { type: mapVariantToIconType(variant) }), _jsx("div", { children: children })] }));
9
21
  }
10
22
  export default InfoPanel;
@@ -16,9 +16,10 @@ export interface ListProps<Item> {
16
16
  filters?: FilterObject[];
17
17
  fn: (params: Record<string, string>, searchParams: URLSearchParams) => Promise<Errorable<Item[]>>;
18
18
  hasSearch?: boolean;
19
+ isMinimal?: boolean;
19
20
  renderItem?: (props: ListObject) => React.ReactElement;
20
21
  params?: Record<string, string>;
21
22
  transformer?: (item: Item) => ListObject;
22
23
  }
23
- declare function List<Item extends object>({ actions, columns, emptyMessageProps, filters, fn, hasSearch, params, renderItem, transformer, }: Readonly<ListProps<Item>>): Promise<React.ReactElement>;
24
+ declare function List<Item extends object>({ actions, columns, emptyMessageProps, filters, fn, hasSearch, isMinimal, params, renderItem, transformer, }: Readonly<ListProps<Item>>): Promise<React.ReactElement>;
24
25
  export default List;
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Fragment } from 'react';
3
3
  import { EmptyMessage, tw } from '@sqrzro/components';
4
- import { headers } from 'next/headers';
5
4
  import FilterBar from '../FilterBar';
6
5
  import ListItem from '../ListItem';
7
6
  function defaultTransformer() {
@@ -10,14 +9,31 @@ function defaultTransformer() {
10
9
  title: '',
11
10
  };
12
11
  }
13
- async function List({ actions, columns, emptyMessageProps, filters, fn, hasSearch, params, renderItem = ListItem, transformer, }) {
14
- const searchParams = new URLSearchParams(headers().get('x-search-params') || '');
12
+ const reservedSearchParams = ['action'];
13
+ function checkHasFilters(searchParams) {
14
+ return Array.from(searchParams.entries()).some(([key, value]) => !reservedSearchParams.includes(key) && Boolean(value));
15
+ }
16
+ async function List({ actions, columns, emptyMessageProps, filters, fn, hasSearch, isMinimal, params, renderItem = ListItem, transformer, }) {
17
+ let searchParams;
18
+ try {
19
+ const { headers } = await import('next/headers');
20
+ searchParams = new URLSearchParams(headers().get('x-search-params') || '');
21
+ }
22
+ catch (err) {
23
+ searchParams = new URLSearchParams();
24
+ }
15
25
  const [response, error] = await fn(params || {}, searchParams);
16
26
  if (error) {
17
27
  return _jsx("div", { children: "Error" });
18
28
  }
19
29
  const data = response.map(transformer || defaultTransformer);
20
- const hasFilters = Boolean(Object.keys(searchParams || []).length);
21
- 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 }))] }));
30
+ const hasFilters = checkHasFilters(searchParams);
31
+ const componentEmptyMessageProps = hasFilters
32
+ ? {
33
+ children: 'Try adjusting the filters above. If you think this is a mistake, please contact your site administrator.',
34
+ title: 'No results match the current filters',
35
+ }
36
+ : emptyMessageProps;
37
+ 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, { ...componentEmptyMessageProps, classNameProps: { isMinimal } }))] }));
22
38
  }
23
39
  export default List;
@@ -3,15 +3,16 @@ export interface ListObject {
3
3
  actions?: ({ id }: {
4
4
  id: number | string;
5
5
  }) => React.ReactElement;
6
+ description?: React.ReactNode | null;
6
7
  href?: string;
7
8
  id: number | string;
8
9
  image?: string | null;
9
10
  imageHref?: string | null;
10
11
  meta?: React.ReactNode[] | Record<string, React.ReactNode>;
11
12
  subtitle?: React.ReactNode | null;
12
- title: string;
13
+ title?: string;
13
14
  }
14
15
  export declare function renderMeta(meta: ListObject['meta']): React.ReactElement | null;
15
16
  declare function ListItem({ actions: Actions, // eslint-disable-line @typescript-eslint/naming-convention
16
- href, id, meta, title, }: Readonly<ListObject>): React.ReactElement;
17
+ description, href, id, meta, title, }: Readonly<ListObject>): React.ReactElement;
17
18
  export default ListItem;
@@ -10,7 +10,7 @@ export function renderMeta(meta) {
10
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))) }) }));
11
11
  }
12
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] })] }) }));
13
+ description, 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: [title ? (_jsx("h2", { className: "border-b border-slate-200 pb-3 text-lg font-semibold", children: href ? _jsx(Link, { href: href, children: title }) : title })) : null, description ? (_jsx("div", { className: "border-b border-slate-200 pb-3 ", children: description })) : null, _jsxs("div", { className: "mt-4 flex items-center justify-between", children: [meta ? renderMeta(meta) : null, Actions ? _jsx(Actions, { id: id }) : null] })] }) }));
15
15
  }
16
16
  export default ListItem;
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import MeActions from '../MeActions';
3
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" })] }));
4
+ return (_jsxs("div", { className: "ml-auto flex items-center gap-3", children: [_jsxs("div", { className: "flex flex-col items-end gap-0.5 text-white", children: [_jsx("strong", { children: user?.name }), _jsx(MeActions, {})] }), _jsx("div", { className: "h-9 w-9 flex-none rounded-full border-4 border-slate-500" })] }));
5
5
  }
6
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({ basePath, children, isFullWidth, tabs, title, }: Readonly<PageProps>): React.ReactElement;
11
+ declare function Page({ basePath, children, isFullWidth, tabs, title, }: Readonly<PageProps>): Promise<React.ReactElement>;
12
12
  export default Page;
@@ -1,8 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Fragment } from 'react';
3
- import { Container } from '@sqrzro/components';
3
+ import { Container, tw } from '@sqrzro/components';
4
+ import { getLayout } from '../../services/LayoutService';
4
5
  import Tabs from '../Tabs';
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 }) })] }));
6
+ async function Page({ basePath, children, isFullWidth, tabs, title, }) {
7
+ const layout = await getLayout();
8
+ return (_jsxs(Fragment, { children: [_jsx("header", { className: tw('', layout === 'sidebar'
9
+ ? 'border-b border-slate-200 bg-white'
10
+ : 'bg-slate-800 pb-16 text-white'), children: _jsxs(Container, { isFullWidth: layout === 'sidebar' || 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", { className: "flex gap-2", id: "page-actions" })] }), tabs ? (_jsx("div", { className: "-mt-4 mb-8", children: _jsx(Tabs, { basePath: basePath, data: tabs }) })) : null] }) }), _jsx(Container, { isFullWidth: layout === 'sidebar' || isFullWidth, children: _jsx("div", { className: tw('flex flex-col gap-8', layout === 'sidebar' ? 'mt-8' : '-mt-16'), children: children }) })] }));
7
11
  }
8
12
  export default Page;
@@ -1,2 +1,9 @@
1
- declare function SettingsForm(): import("react/jsx-runtime").JSX.Element;
1
+ /// <reference types="react" />
2
+ interface SettingsFormFields {
3
+ layout: string;
4
+ }
5
+ interface SettingsFormProps {
6
+ defaults: Partial<SettingsFormFields>;
7
+ }
8
+ declare function SettingsForm({ defaults }: Readonly<SettingsFormProps>): JSX.Element;
2
9
  export default SettingsForm;
@@ -1,9 +1,14 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { EditableForm } from '@sqrzro/components';
3
+ import { EditableForm, EditableRadioFormField } from '@sqrzro/components';
4
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!" }));
5
+ import { submitLayoutForm } from '../../services/LayoutService';
6
+ const options = { sidebar: 'Side bar', topbar: 'Top bar' };
7
+ function SettingsForm({ defaults }) {
8
+ const { fieldProps, formProps } = useEditableForm({
9
+ defaults,
10
+ onSubmit: submitLayoutForm,
11
+ });
12
+ return (_jsx(EditableForm, { title: "Appearance", ...formProps, children: _jsx(EditableRadioFormField, { ...fieldProps('layout'), options: options, renderValue: (value) => (value ? options[value] || '-' : '-') }) }));
8
13
  }
9
14
  export default SettingsForm;
@@ -1,2 +1,3 @@
1
- declare function SettingsPage(): import("react/jsx-runtime").JSX.Element;
1
+ /// <reference types="react" />
2
+ declare function SettingsPage(): Promise<JSX.Element>;
2
3
  export default SettingsPage;
@@ -1,7 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { getLayout } from '../../services/LayoutService';
2
3
  import Page from '../Page';
3
4
  import SettingsForm from '../SettingsForm';
4
- function SettingsPage() {
5
- return (_jsx(Page, { title: "Settings", children: _jsx(SettingsForm, {}) }));
5
+ async function SettingsPage() {
6
+ const layout = await getLayout();
7
+ return (_jsx(Page, { title: "Settings", children: _jsx(SettingsForm, { defaults: { layout } }) }));
6
8
  }
7
9
  export default SettingsPage;
@@ -7,18 +7,5 @@ function Tabs({ basePath = '', data }) {
7
7
  return (_jsx("nav", { className: "border-b border-slate-700", children: _jsx("ul", { className: "flex gap-4", children: navigation.map(({ href, isActive, label }) => (_jsx("li", { children: _jsx(Link, { className: tw('block px-1 pb-2 font-semibold', isActive
8
8
  ? 'border-primary border-b-4 text-white'
9
9
  : 'text-white/80 hover:text-white'), href: href, children: label }) }, href))) }) }));
10
- // return (
11
- // <nav className="border-y border-slate-700">
12
- // <ul className="flex gap-4 font-semibold">
13
- // {data.map(({ href, label }) => (
14
- // <li key={href}>
15
- // <Link className="block py-2 text-white" href={`${basePath}${href || ''}`}>
16
- // {label}
17
- // </Link>
18
- // </li>
19
- // ))}
20
- // </ul>
21
- // </nav>
22
- // );
23
10
  }
24
11
  export default Tabs;
@@ -1,4 +1,5 @@
1
- export { Button, CalendarInput, ConnectedDropdown, DateFormField, DateInput, Dropdown, DropdownFormField, EditableDateFormField, EditableDropdownFormField, EditableForm, EditableFormField, EditableMultiFormField, EditableNumberFormField, EditableSwitchFormField, EditableTextFormField, Fieldset, Form, FormField, FormSubmit, ImageInput, ImageFormField, Link, ModalForm, MultiFormField, NumberFormField, NumberInput, Switch, SwitchFormField, TextFormField, TextInput, Toaster, } from '@sqrzro/components';
1
+ export { Autocomplete, Button, CalendarInput, ConnectedDropdown, ConfirmableButton, DateFormField, DateInput, Dropdown, DropdownFormField, EditableDateFormField, EditableDropdownFormField, EditableForm, EditableFormField, EditableMultiFormField, EditableNumberFormField, EditableSwitchFormField, EditableTextAreaFormField, EditableTextFormField, EmptyMessage, Fieldset, Form, FormField, FormSubmit, ImageInput, ImageFormField, Link, ModalForm, MultiFormField, NumberFormField, NumberInput, RadioInput, Switch, SwitchFormField, TextArea, TextAreaFormField, TextFormField, TextInput, Toaster, } from '@sqrzro/components';
2
+ export type { DropdownItem } from '@sqrzro/components';
2
3
  export type { AppLayoutProps } from './AppLayout';
3
4
  export { default as AppLayout } from './AppLayout';
4
5
  export type { AuthProps } from './Auth';
@@ -1,5 +1,5 @@
1
1
  // Exported from @sqrzro/components
2
- export { Button, CalendarInput, ConnectedDropdown, DateFormField, DateInput, Dropdown, DropdownFormField, EditableDateFormField, EditableDropdownFormField, EditableForm, EditableFormField, EditableMultiFormField, EditableNumberFormField, EditableSwitchFormField, EditableTextFormField, Fieldset, Form, FormField, FormSubmit, ImageInput, ImageFormField, Link, ModalForm, MultiFormField, NumberFormField, NumberInput, Switch, SwitchFormField, TextFormField, TextInput, Toaster, } from '@sqrzro/components';
2
+ export { Autocomplete, Button, CalendarInput, ConnectedDropdown, ConfirmableButton, DateFormField, DateInput, Dropdown, DropdownFormField, EditableDateFormField, EditableDropdownFormField, EditableForm, EditableFormField, EditableMultiFormField, EditableNumberFormField, EditableSwitchFormField, EditableTextAreaFormField, EditableTextFormField, EmptyMessage, Fieldset, Form, FormField, FormSubmit, ImageInput, ImageFormField, Link, ModalForm, MultiFormField, NumberFormField, NumberInput, RadioInput, Switch, SwitchFormField, TextArea, TextAreaFormField, TextFormField, TextInput, Toaster, } from '@sqrzro/components';
3
3
  export { default as AppLayout } from './AppLayout';
4
4
  export { default as Auth } from './Auth';
5
5
  export { default as Badge } from './Badge';
@@ -0,0 +1,7 @@
1
+ import type { SerializedErrorable } from '@sqrzro/interfaces';
2
+ type Layout = 'sidebar' | 'topbar';
3
+ export declare function getLayout(): Promise<string>;
4
+ export declare function submitLayoutForm(formData: {
5
+ layout: Layout;
6
+ }): Promise<SerializedErrorable<boolean>>;
7
+ export {};
@@ -0,0 +1,9 @@
1
+ 'use server';
2
+ import { cookies } from 'next/headers';
3
+ export async function getLayout() {
4
+ return Promise.resolve(cookies().get('layout')?.value || 'topbar');
5
+ }
6
+ export async function submitLayoutForm(formData) {
7
+ cookies().set('layout', formData.layout);
8
+ return Promise.resolve([true, null]);
9
+ }
@@ -8,7 +8,7 @@ const classNames = twx({
8
8
  root: {
9
9
  danger: 'border-red-500 bg-red-500 text-white',
10
10
  default: tw('text-md h-10 rounded border border-slate-300 bg-white px-5 text-slate-600', props?.isFullWidth ? 'w-full' : null),
11
- primary: 'bg-button-bg text-button-text border-none font-semibold', // shadow-[inset_rgba(255,255,255,0.2)_0_20px]
11
+ primary: 'bg-button-bg text-button-text border-none font-semibold',
12
12
  },
13
13
  }),
14
14
  calendar: () => ({
@@ -30,12 +30,13 @@ const classNames = twx({
30
30
  codeInput: () => ({
31
31
  input: {
32
32
  default: 'focus:border-primary h-10 rounded border border-slate-300 text-center',
33
- error: 'border-red-700',
33
+ error: 'border-red-500',
34
34
  },
35
35
  }),
36
36
  editableFieldset: () => ({
37
- root: 'bg-panel grid grid-cols-[30%_1fr] rounded p-8 shadow',
37
+ root: 'bg-panel grid grid-cols-[30%_1fr] gap-8 rounded p-8 shadow',
38
38
  title: 'mb-8 text-lg font-semibold leading-none text-slate-700',
39
+ description: 'text-slate-600',
39
40
  actions: 'flex justify-end gap-2 border-t border-slate-200 pt-4',
40
41
  }),
41
42
  editableFormField: () => ({
@@ -43,9 +44,12 @@ const classNames = twx({
43
44
  label: 'flex items-center font-semibold leading-none',
44
45
  field: 'flex min-h-10 items-center',
45
46
  }),
46
- emptyMessage: () => ({
47
- root: 'relative mx-auto mt-4 w-full max-w-xl rounded bg-white py-16 text-center text-slate-500 shadow before:pointer-events-none before:absolute before:inset-2 before:border-2 before:border-dashed',
48
- title: 'mb-2 text-xl font-semibold leading-none',
47
+ emptyMessage: (props) => ({
48
+ root: tw('relative mx-auto mt-4 w-full max-w-2xl p-16 text-center text-slate-500', props?.isMinimal
49
+ ? null
50
+ : 'rounded bg-white shadow before:pointer-events-none before:absolute before:inset-2 before:border-2 before:border-dashed'),
51
+ title: 'mb-2 text-pretty text-xl font-semibold leading-tight',
52
+ description: 'text-pretty',
49
53
  action: 'mt-6 flex justify-center',
50
54
  }),
51
55
  dropdown: () => ({
@@ -69,7 +73,7 @@ const classNames = twx({
69
73
  label: tw('flex font-semibold leading-none', props?.isEditable ? 'items-center' : 'mb-2 justify-between'),
70
74
  details: 'mb-2 text-xs font-normal leading-none text-slate-500',
71
75
  optional: 'pl-2 text-xs font-normal leading-none text-slate-500',
72
- error: 'mt-2 flex items-center gap-2 text-red-700 before:h-4 before:w-4 before:rounded-full before:bg-[url(/images/icons/error.svg)]',
76
+ error: 'mt-2 flex items-center gap-2 text-red-700 before:h-4 before:w-4 before:rounded-full before:bg-[url(/admin/images/error.svg)]',
73
77
  }),
74
78
  imageInput: () => ({
75
79
  root: 'h-64 rounded border border-slate-300 bg-slate-50 p-8',
@@ -99,7 +103,7 @@ const classNames = twx({
99
103
  staticTextInput: () => ({
100
104
  root: {
101
105
  default: 'text-md h-10 rounded border border-slate-300 bg-white px-3',
102
- error: 'border-red-700',
106
+ error: 'border-red-500',
103
107
  },
104
108
  }),
105
109
  switch: () => ({
@@ -118,7 +122,7 @@ const classNames = twx({
118
122
  textArea: () => ({
119
123
  root: {
120
124
  default: 'text-md focus:border-primary rounded border border-slate-300 px-3 py-2',
121
- error: 'border-red-700',
125
+ error: 'border-red-500',
122
126
  },
123
127
  }),
124
128
  textButton: () => ({
@@ -127,7 +131,7 @@ const classNames = twx({
127
131
  textInput: () => ({
128
132
  root: {
129
133
  default: 'text-md focus:border-primary h-10 rounded border border-slate-300 px-3',
130
- error: 'border-red-700',
134
+ error: 'border-red-500',
131
135
  },
132
136
  }),
133
137
  toast: () => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqrzro/admin",
3
- "version": "2.1.0-bz.14",
3
+ "version": "2.1.0-bz.16",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "ISC",