feat(ui): add analytics primitives and layout patterns
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
import {
|
||||
createContext,
|
||||
forwardRef,
|
||||
useContext,
|
||||
type ComponentPropsWithoutRef
|
||||
} from "react";
|
||||
|
||||
import {
|
||||
inputGroupAffixVariants,
|
||||
inputGroupVariants
|
||||
} from "./input-group.variants";
|
||||
import { cn } from "../lib/cn";
|
||||
import type { VariantProps } from "../lib/cva";
|
||||
import type { FieldStateProps } from "../lib/contracts";
|
||||
import { createDataAttributes, createSlot } from "../lib/contracts";
|
||||
import { useFieldContext } from "./field";
|
||||
|
||||
type InputGroupContextValue = {
|
||||
disabled: boolean;
|
||||
invalid: boolean;
|
||||
readOnly: boolean;
|
||||
required: boolean;
|
||||
size: Exclude<VariantProps<typeof inputGroupVariants>["size"], null | undefined>;
|
||||
};
|
||||
|
||||
const InputGroupContext = createContext<InputGroupContextValue | null>(null);
|
||||
|
||||
export function useInputGroupContext() {
|
||||
return useContext(InputGroupContext);
|
||||
}
|
||||
|
||||
export type InputGroupProps = ComponentPropsWithoutRef<"div"> &
|
||||
FieldStateProps &
|
||||
VariantProps<typeof inputGroupVariants>;
|
||||
|
||||
export const InputGroup = forwardRef<HTMLDivElement, InputGroupProps>(function InputGroup(
|
||||
{
|
||||
className,
|
||||
disabled,
|
||||
invalid,
|
||||
readOnly,
|
||||
required,
|
||||
size = "md",
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) {
|
||||
const field = useFieldContext();
|
||||
const resolvedDisabled = disabled ?? field?.disabled ?? false;
|
||||
const resolvedInvalid = invalid ?? field?.invalid ?? false;
|
||||
const resolvedReadOnly = readOnly ?? field?.readOnly ?? false;
|
||||
const resolvedRequired = required ?? field?.required ?? false;
|
||||
const resolvedSize = size ?? "md";
|
||||
|
||||
return (
|
||||
<InputGroupContext.Provider
|
||||
value={{
|
||||
disabled: resolvedDisabled,
|
||||
invalid: resolvedInvalid,
|
||||
readOnly: resolvedReadOnly,
|
||||
required: resolvedRequired,
|
||||
size: resolvedSize
|
||||
}}
|
||||
>
|
||||
<div
|
||||
{...props}
|
||||
{...createSlot("control")}
|
||||
{...createDataAttributes({
|
||||
disabled: resolvedDisabled,
|
||||
invalid: resolvedInvalid,
|
||||
readonly: resolvedReadOnly,
|
||||
required: resolvedRequired,
|
||||
size: resolvedSize
|
||||
})}
|
||||
className={cn(inputGroupVariants({ size: resolvedSize }), className)}
|
||||
ref={ref}
|
||||
/>
|
||||
</InputGroupContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
export type InputGroupPrefixProps = ComponentPropsWithoutRef<"div">;
|
||||
|
||||
export const InputGroupPrefix = forwardRef<HTMLDivElement, InputGroupPrefixProps>(
|
||||
function InputGroupPrefix({ className, ...props }, ref) {
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
{...createSlot("prefix")}
|
||||
className={cn(inputGroupAffixVariants(), className)}
|
||||
ref={ref}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export type InputGroupSuffixProps = ComponentPropsWithoutRef<"div">;
|
||||
|
||||
export const InputGroupSuffix = forwardRef<HTMLDivElement, InputGroupSuffixProps>(
|
||||
function InputGroupSuffix({ className, ...props }, ref) {
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
{...createSlot("suffix")}
|
||||
className={cn(inputGroupAffixVariants(), className)}
|
||||
ref={ref}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user