public commit

This commit is contained in:
dswbx
2024-11-16 12:01:47 +01:00
commit 90f80c4280
582 changed files with 49291 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
import { type ModalProps, Tabs } from "@mantine/core";
import type { ContextModalProps } from "@mantine/modals";
import { transformObject } from "core/utils";
import type { ComponentProps } from "react";
import { JsonViewer } from "../../components/code/JsonViewer";
type JsonViewerProps = Omit<ComponentProps<typeof JsonViewer>, "title" | "json">;
type Primitive = object | string | number | boolean | any[];
type DebugProps = {
data: {
[key: string]: ({ label: string; value: Primitive } & JsonViewerProps) | Primitive;
};
} & JsonViewerProps;
export function DebugModal({ innerProps }: ContextModalProps<DebugProps>) {
const { data, ...jsonViewerProps } = innerProps;
const tabs = transformObject(data, (item, name) => {
if (typeof item === "object" && "label" in item) {
return item;
}
return {
label: <span className="font-mono">{name}</span>,
value: item,
expand: 10,
showCopy: true,
...jsonViewerProps
};
});
const count = Object.keys(tabs).length;
function renderTab({ value, label, ...props }: (typeof tabs)[keyof typeof tabs]) {
return <JsonViewer json={value as any} {...props} />;
}
return (
<div className="bg-background">
{count > 1 ? (
<Tabs defaultValue={Object.keys(tabs)[0]}>
<div className="sticky top-0 bg-background z-10">
<Tabs.List>
{Object.entries(tabs).map(([key, tab]) => (
<Tabs.Tab key={key} value={key}>
{tab.label}
</Tabs.Tab>
))}
</Tabs.List>
</div>
{Object.entries(tabs).map(([key, tab]) => (
<Tabs.Panel key={key} value={key}>
{renderTab(tab)}
</Tabs.Panel>
))}
</Tabs>
) : (
renderTab({
// @ts-expect-error
...tabs[Object.keys(tabs)[0]],
// @ts-expect-error
title: tabs[Object.keys(tabs)[0]].label
})
)}
</div>
);
}
DebugModal.defaultTitle = false;
DebugModal.modalProps = {
withCloseButton: false,
size: "lg",
classNames: {
body: "!p-0"
}
} satisfies Omit<ModalProps, "opened" | "onClose">;

View File

@@ -0,0 +1,69 @@
import { useRef, useState } from "react";
import { Button } from "ui";
import {
JsonSchemaForm,
type JsonSchemaFormProps,
type JsonSchemaFormRef
} from "ui/components/form/json-schema/JsonSchemaForm";
import type { ContextModalProps } from "@mantine/modals";
type Props = JsonSchemaFormProps & {
onSubmit?: (data: any) => void | Promise<void>;
};
export function SchemaFormModal({
context,
id,
innerProps: { schema, uiSchema, onSubmit }
}: ContextModalProps<Props>) {
const [valid, setValid] = useState(false);
const formRef = useRef<JsonSchemaFormRef>(null);
function handleChange(data) {
const valid = formRef.current?.validateForm() ?? false;
console.log("Data changed", data, valid);
setValid(valid);
}
function handleClose() {
context.closeModal(id);
}
async function handleClickAdd() {
await onSubmit?.(formRef.current?.formData());
handleClose();
}
return (
<div className="pt-3 pb-3 px-3 gap-4 flex flex-col">
<JsonSchemaForm
tagName="form"
ref={formRef}
schema={schema}
uiSchema={uiSchema}
className="legacy hide-required-mark fieldset-alternative mute-root"
onChange={handleChange}
onSubmit={handleClickAdd}
/>
<div className="flex flex-row justify-end gap-2">
<Button onClick={handleClose}>Cancel</Button>
<Button variant="primary" onClick={handleClickAdd} disabled={!valid}>
Create
</Button>
</div>
</div>
);
}
SchemaFormModal.defaultTitle = "JSON Schema Form Modal";
SchemaFormModal.modalProps = {
classNames: {
size: "md",
root: "bknd-admin",
header: "!bg-primary/5 border-b border-b-muted !py-3 px-5 !h-auto !min-h-px",
content: "rounded-lg select-none",
title: "font-bold !text-md",
body: "!p-0"
}
};

View File

@@ -0,0 +1,22 @@
import type { ContextModalProps } from "@mantine/modals";
export function TestModal({ context, id, innerProps }: ContextModalProps<{ modalBody: string }>) {
return (
<>
<span>{innerProps.modalBody}</span>
<button onClick={() => context.closeModal(id)}>Close modal</button>
</>
);
}
TestModal.defaultTitle = "Test Modal";
TestModal.modalProps = {
classNames: {
size: "md",
root: "bknd-admin",
header: "!bg-primary/5 border-b border-b-muted !py-3 px-5 !h-auto !min-h-px",
content: "rounded-lg select-none",
title: "font-bold !text-md",
body: "py-3 px-5 gap-4 flex flex-col"
}
};

View File

@@ -0,0 +1,57 @@
import type { ModalProps } from "@mantine/core";
import { ModalsProvider, modals as mantineModals } from "@mantine/modals";
import { transformObject } from "core/utils";
import type { ComponentProps } from "react";
import { DebugModal } from "./debug/DebugModal";
import { SchemaFormModal } from "./debug/SchemaFormModal";
import { TestModal } from "./debug/TestModal";
const modals = {
test: TestModal,
debug: DebugModal,
form: SchemaFormModal
};
declare module "@mantine/modals" {
export interface MantineModalsOverride {
modals: typeof modals;
}
}
export function BkndModalsProvider({ children }) {
return (
<ModalsProvider modals={modals} modalProps={{ className: "bknd-admin" }}>
{children}
</ModalsProvider>
);
}
function open<Modal extends keyof typeof modals>(
modal: Modal,
innerProps: ComponentProps<(typeof modals)[Modal]>["innerProps"],
{ title: _title, ...modalProps }: Partial<ModalProps> = {}
) {
const title = _title ?? modals[modal].defaultTitle ?? undefined;
const cmpModalProps = modals[modal].modalProps ?? {};
return mantineModals.openContextModal({
title,
...modalProps,
...cmpModalProps,
modal,
innerProps
});
}
function close<Modal extends keyof typeof modals>(modal: Modal) {
return mantineModals.close(modal);
}
export const bkndModals = {
ids: transformObject(modals, (key) => key) as unknown as Record<
keyof typeof modals,
keyof typeof modals
>,
open,
close,
closeAll: mantineModals.closeAll
};