mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-17 04:46:05 +00:00
admin ui: started color centralization + made sidebar resizable
This commit is contained in:
@@ -3,7 +3,6 @@ import { getBrowser } from "core/utils";
|
||||
import type { Field } from "data";
|
||||
import { Switch as RadixSwitch } from "radix-ui";
|
||||
import {
|
||||
type ChangeEventHandler,
|
||||
type ComponentPropsWithoutRef,
|
||||
type ElementType,
|
||||
forwardRef,
|
||||
@@ -12,7 +11,7 @@ import {
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { TbCalendar, TbChevronDown, TbInfoCircle } from "react-icons/tb";
|
||||
import { TbCalendar, TbChevronDown, TbEye, TbEyeOff, TbInfoCircle } from "react-icons/tb";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { IconButton } from "ui/components/buttons/IconButton";
|
||||
import { useEvent } from "ui/hooks/use-event";
|
||||
@@ -89,7 +88,7 @@ export const Input = forwardRef<HTMLInputElement, React.ComponentProps<"input">>
|
||||
{...props}
|
||||
ref={ref}
|
||||
className={twMerge(
|
||||
"bg-muted/40 h-11 rounded-md py-2.5 px-4 outline-none",
|
||||
"bg-muted/40 h-11 rounded-md py-2.5 px-4 outline-none w-full",
|
||||
disabledOrReadonly && "bg-muted/50 text-primary/50",
|
||||
!disabledOrReadonly &&
|
||||
"focus:bg-muted focus:outline-none focus:ring-2 focus:ring-zinc-500 focus:border-transparent transition-all",
|
||||
@@ -99,6 +98,40 @@ export const Input = forwardRef<HTMLInputElement, React.ComponentProps<"input">>
|
||||
);
|
||||
});
|
||||
|
||||
export const TypeAwareInput = forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
|
||||
(props, ref) => {
|
||||
if (props.type === "password") {
|
||||
return <Password {...props} ref={ref} />;
|
||||
}
|
||||
|
||||
return <Input {...props} ref={ref} />;
|
||||
},
|
||||
);
|
||||
|
||||
export const Password = forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
|
||||
(props, ref) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
function handleToggle() {
|
||||
setVisible((v) => !v);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative w-full">
|
||||
<Input {...props} type={visible ? "text" : "password"} className="w-full" ref={ref} />
|
||||
<div className="absolute right-3 top-0 bottom-0 flex items-center">
|
||||
<IconButton
|
||||
Icon={visible ? TbEyeOff : TbEye}
|
||||
onClick={handleToggle}
|
||||
variant="ghost"
|
||||
className="opacity-70"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export const Textarea = forwardRef<HTMLTextAreaElement, React.ComponentProps<"textarea">>(
|
||||
(props, ref) => {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { JsonSchema } from "json-schema-library";
|
||||
import type { ChangeEvent, ComponentPropsWithoutRef } from "react";
|
||||
import type { ChangeEvent, ComponentPropsWithoutRef, ReactNode } from "react";
|
||||
import ErrorBoundary from "ui/components/display/ErrorBoundary";
|
||||
import * as Formy from "ui/components/form/Formy";
|
||||
import { useEvent } from "ui/hooks/use-event";
|
||||
@@ -13,6 +13,7 @@ export type FieldProps = {
|
||||
onChange?: (e: ChangeEvent<any>) => void;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
inputProps?: Partial<FieldComponentProps>;
|
||||
} & Omit<FieldwrapperProps, "children" | "schema">;
|
||||
|
||||
export const Field = (props: FieldProps) => {
|
||||
@@ -31,7 +32,14 @@ const fieldErrorBoundary =
|
||||
</Pre>
|
||||
);
|
||||
|
||||
const FieldImpl = ({ name, onChange, placeholder, required: _required, ...props }: FieldProps) => {
|
||||
const FieldImpl = ({
|
||||
name,
|
||||
onChange,
|
||||
placeholder,
|
||||
required: _required,
|
||||
inputProps,
|
||||
...props
|
||||
}: FieldProps) => {
|
||||
const { path, setValue, schema, ...ctx } = useDerivedFieldContext(name);
|
||||
const required = typeof _required === "boolean" ? _required : ctx.required;
|
||||
//console.log("Field", { name, path, schema });
|
||||
@@ -64,6 +72,7 @@ const FieldImpl = ({ name, onChange, placeholder, required: _required, ...props
|
||||
return (
|
||||
<FieldWrapper name={name} required={required} schema={schema} {...props}>
|
||||
<FieldComponent
|
||||
{...inputProps}
|
||||
schema={schema}
|
||||
name={name}
|
||||
required={required}
|
||||
@@ -81,10 +90,12 @@ export const Pre = ({ children }) => (
|
||||
</pre>
|
||||
);
|
||||
|
||||
export const FieldComponent = ({
|
||||
schema,
|
||||
..._props
|
||||
}: { schema: JsonSchema } & ComponentPropsWithoutRef<"input">) => {
|
||||
export type FieldComponentProps = {
|
||||
schema: JsonSchema;
|
||||
render?: (props: Omit<FieldComponentProps, "render">) => ReactNode;
|
||||
} & ComponentPropsWithoutRef<"input">;
|
||||
|
||||
export const FieldComponent = ({ schema, render, ..._props }: FieldComponentProps) => {
|
||||
const { value } = useFormValue(_props.name!, { strict: true });
|
||||
if (!isTypeSchema(schema)) return null;
|
||||
const props = {
|
||||
@@ -97,6 +108,8 @@ export const FieldComponent = ({
|
||||
: "",
|
||||
};
|
||||
|
||||
if (render) return render({ schema, ...props });
|
||||
|
||||
if (schema.enum) {
|
||||
return <Formy.Select id={props.name} options={schema.enum} {...(props as any)} />;
|
||||
}
|
||||
@@ -158,5 +171,7 @@ export const FieldComponent = ({
|
||||
}
|
||||
}
|
||||
|
||||
return <Formy.Input id={props.name} {...props} value={props.value ?? ""} {...additional} />;
|
||||
return (
|
||||
<Formy.TypeAwareInput id={props.name} {...props} value={props.value ?? ""} {...additional} />
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user