@rlx-ui/mcp 0.0.17 → 0.0.18
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/dist/data/registry.json +39 -17
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/data/registry.json
CHANGED
|
@@ -326,7 +326,7 @@
|
|
|
326
326
|
},
|
|
327
327
|
{
|
|
328
328
|
"name": "form",
|
|
329
|
-
"code": "\"use client\"
|
|
329
|
+
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { Calendar } from \"@rlx-widgets/calendar\";\nimport { CalendarIcon } from \"lucide-react\";\nimport { cn } from \"@rlx-widgets/base\";\nimport { format } from \"date-fns\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@rlx-widgets/popover\";\nimport { toast } from \"sonner\";\nimport { Controller, useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldLabel,\n} from \"@rlx-widgets/field\";\n\nconst FormSchema = z.object({\n dob: z.date().refine((val) => val instanceof Date && !isNaN(val.getTime()), {\n message: \"A date of birth is required.\",\n }),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-8\">\n <Controller\n control={form.control}\n name=\"dob\"\n render={({ field, fieldState }) => (\n <Field\n data-invalid={fieldState.invalid}\n orientation=\"vertical\"\n className=\"flex flex-col\"\n >\n <FieldContent>\n <FieldLabel>Date of birth</FieldLabel>\n <FieldDescription>\n Your date of birth is used to calculate your age.\n </FieldDescription>\n </FieldContent>\n <Popover>\n <PopoverTrigger asChild>\n <Button\n variant={\"outline\"}\n className={cn(\n \"w-[240px] pl-3 text-left font-normal\",\n !field.value && \"text-muted-foreground\"\n )}\n aria-invalid={fieldState.invalid}\n >\n {field.value ? (\n format(field.value, \"PPP\")\n ) : (\n <span>Pick a date</span>\n )}\n <CalendarIcon className=\"ml-auto h-4 w-4 opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\n <Calendar\n mode=\"single\"\n selected={field.value}\n onSelect={field.onChange}\n disabled={(date) =>\n date > new Date() || date < new Date(\"1900-01-01\")\n }\n captionLayout=\"dropdown\"\n />\n </PopoverContent>\n </Popover>\n {fieldState.invalid && (\n <FieldError errors={[fieldState.error]} />\n )}\n </Field>\n )}\n />\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n"
|
|
330
330
|
},
|
|
331
331
|
{
|
|
332
332
|
"name": "month-year-selector",
|
|
@@ -403,7 +403,7 @@
|
|
|
403
403
|
},
|
|
404
404
|
{
|
|
405
405
|
"name": "form",
|
|
406
|
-
"code": "\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\n\nimport { Button } from \"rlx-widgets\";\nimport { Checkbox } from \"rlx-widgets\";\nimport {\n
|
|
406
|
+
"code": "\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Controller, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { Checkbox } from \"@rlx-widgets/checkbox\";\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldLabel,\n} from \"@rlx-widgets/field\";\n\nconst items = [\n {\n id: \"recents\",\n label: \"Recents\",\n },\n {\n id: \"home\",\n label: \"Home\",\n },\n {\n id: \"applications\",\n label: \"Applications\",\n },\n {\n id: \"desktop\",\n label: \"Desktop\",\n },\n {\n id: \"downloads\",\n label: \"Downloads\",\n },\n {\n id: \"documents\",\n label: \"Documents\",\n },\n] as const;\n\nconst FormSchema = z.object({\n items: z.array(z.string()).refine((value) => value.some((item) => item), {\n message: \"You have to select at least one item.\",\n }),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n defaultValues: {\n items: [\"recents\", \"home\"],\n },\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-8\">\n <Controller\n control={form.control}\n name=\"items\"\n render={({ field, fieldState }) => (\n <Field data-invalid={fieldState.invalid} orientation=\"vertical\">\n <FieldContent className=\"mb-4\">\n <FieldLabel className=\"text-base\">Sidebar</FieldLabel>\n <FieldDescription>\n Select the items you want to display in the sidebar.\n </FieldDescription>\n </FieldContent>\n {items.map((item) => (\n <Field\n key={item.id}\n data-invalid={fieldState.invalid}\n orientation=\"horizontal\"\n className=\"flex flex-row items-center gap-2\"\n >\n <Checkbox\n checked={field.value?.includes(item.id)}\n onCheckedChange={(checked) => {\n return checked\n ? field.onChange([...field.value, item.id])\n : field.onChange(\n field.value?.filter((value) => value !== item.id)\n );\n }}\n aria-invalid={fieldState.invalid}\n />\n <FieldLabel className=\"text-sm font-normal\">\n {item.label}\n </FieldLabel>\n </Field>\n ))}\n {fieldState.invalid && (\n <FieldError errors={[fieldState.error]} />\n )}\n </Field>\n )}\n />\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n"
|
|
407
407
|
}
|
|
408
408
|
]
|
|
409
409
|
},
|
|
@@ -615,10 +615,32 @@
|
|
|
615
615
|
"name": "Form",
|
|
616
616
|
"exportName": "Form",
|
|
617
617
|
"packageName": "@rlx-widgets/form",
|
|
618
|
-
"version": "0.0
|
|
618
|
+
"version": "0.1.0",
|
|
619
619
|
"slug": "form",
|
|
620
620
|
"category": "widget",
|
|
621
|
-
"sourceCode": "
|
|
621
|
+
"sourceCode": "// https://github.com/WebDevSimplified/shadcn-field-component/tree/main/src/components\n\nimport { Checkbox } from \"@rlx-widgets/checkbox\";\nimport { Input } from \"@rlx-widgets/input\";\nimport { ReactNode } from \"react\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@rlx-widgets/select\";\nimport { Textarea } from \"@rlx-widgets/textarea\";\nimport {\n Controller,\n ControllerProps,\n FieldPath,\n FieldValues,\n} from \"react-hook-form\";\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldLabel,\n} from \"@rlx-widgets/field\";\n\ntype FormControlProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformedValues = TFieldValues\n> = {\n name: TName;\n label: ReactNode;\n description?: ReactNode;\n placeholder?: string;\n control: ControllerProps<TFieldValues, TName, TTransformedValues>[\"control\"];\n};\n\ntype FormBaseProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformedValues = TFieldValues\n> = FormControlProps<TFieldValues, TName, TTransformedValues> & {\n horizontal?: boolean;\n controlFirst?: boolean;\n children: (\n field: Parameters<\n ControllerProps<TFieldValues, TName, TTransformedValues>[\"render\"]\n >[number][\"field\"] & {\n \"aria-invalid\": boolean;\n id: string;\n }\n ) => ReactNode;\n};\n\ntype FormControlComponent<\n ExtraProps extends Record<string, unknown> = Record<never, never>\n> = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformedValues = TFieldValues\n>(\n props: FormControlProps<TFieldValues, TName, TTransformedValues> & ExtraProps\n) => ReactNode;\n\nfunction FormBase<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformedValues = TFieldValues\n>({\n children,\n control,\n label,\n name,\n description,\n controlFirst,\n horizontal,\n}: FormBaseProps<TFieldValues, TName, TTransformedValues>) {\n return (\n <Controller\n control={control}\n name={name}\n render={({ field, fieldState }) => {\n const labelElement = (\n <>\n <FieldLabel htmlFor={field.name}>{label}</FieldLabel>\n {description && <FieldDescription>{description}</FieldDescription>}\n </>\n );\n const control = children({\n ...field,\n id: field.name,\n \"aria-invalid\": fieldState.invalid,\n });\n const errorElem = fieldState.invalid && (\n <FieldError errors={[fieldState.error]} />\n );\n\n return (\n <Field\n data-invalid={fieldState.invalid}\n orientation={horizontal ? \"horizontal\" : undefined}\n >\n {controlFirst ? (\n <>\n {control}\n <FieldContent>\n {labelElement}\n {errorElem}\n </FieldContent>\n </>\n ) : (\n <>\n <FieldContent>{labelElement}</FieldContent>\n {control}\n {errorElem}\n </>\n )}\n </Field>\n );\n }}\n />\n );\n}\n\nexport const FormInput: FormControlComponent<{\n controlFirst?: boolean;\n horizontal?: boolean;\n}> = ({ placeholder, ...props }) => {\n return (\n <FormBase {...props}>\n {(field) => <Input {...field} placeholder={placeholder} />}\n </FormBase>\n );\n};\n\nexport const FormTextarea: FormControlComponent<{\n controlFirst?: boolean;\n horizontal?: boolean;\n}> = ({ placeholder, ...props }) => {\n return (\n <FormBase {...props}>\n {(field) => <Textarea {...field} placeholder={placeholder} />}\n </FormBase>\n );\n};\n\nexport const FormSelect: FormControlComponent<{\n items: Array<{\n value: string;\n label: string;\n }>;\n controlFirst?: boolean;\n horizontal?: boolean;\n}> = ({ items, placeholder, ...props }) => {\n return (\n <FormBase {...props}>\n {({ onChange, onBlur, ...field }) => (\n <Select {...field} onValueChange={onChange}>\n <SelectTrigger\n aria-invalid={field[\"aria-invalid\"]}\n id={field.id}\n onBlur={onBlur}\n >\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent>\n {items.map((item) => (\n <SelectItem key={item.value} value={item.value}>\n {item.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n </FormBase>\n );\n};\n\nexport const FormCheckbox: FormControlComponent = (props) => {\n return (\n <FormBase {...props} horizontal controlFirst>\n {({ onChange, value, ...field }) => (\n <Checkbox {...field} checked={value} onCheckedChange={onChange} />\n )}\n </FormBase>\n );\n};\n",
|
|
622
|
+
"demos": [
|
|
623
|
+
{
|
|
624
|
+
"name": "complete-form",
|
|
625
|
+
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport {\n FormInput,\n FormTextarea,\n FormSelect,\n FormCheckbox,\n} from \"@rlx-widgets/form\";\nimport { toast } from \"sonner\";\nimport { useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\n\nconst FormSchema = z.object({\n username: z.string().min(2, {\n message: \"Username must be at least 2 characters.\",\n }),\n email: z.string().email({\n message: \"Please select a valid email.\",\n }),\n bio: z.string().min(10, {\n message: \"Bio must be at least 10 characters.\",\n }),\n terms: z.boolean().refine((value) => value === true, {\n message: \"You must accept the terms and conditions.\",\n }),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n defaultValues: {\n username: \"\",\n email: \"\",\n bio: \"\",\n terms: false,\n },\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"w-full max-w-md space-y-6\"\n >\n <FormInput\n control={form.control}\n name=\"username\"\n label=\"Username\"\n description=\"This is your public display name.\"\n />\n <FormSelect\n control={form.control}\n name=\"email\"\n label=\"Email\"\n description=\"Select a verified email to display.\"\n items={[\n { value: \"m@example.com\", label: \"m@example.com\" },\n { value: \"m@google.com\", label: \"m@google.com\" },\n { value: \"m@support.com\", label: \"m@support.com\" },\n ]}\n />\n <FormTextarea\n control={form.control}\n name=\"bio\"\n label=\"Bio\"\n description=\"Tell us a little bit about yourself.\"\n />\n <FormCheckbox\n control={form.control}\n name=\"terms\"\n label=\"Accept terms and conditions\"\n description=\"You agree to our Terms of Service and Privacy Policy.\"\n />\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n"
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
"name": "form-checkbox",
|
|
629
|
+
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { FormCheckbox } from \"@rlx-widgets/form\";\nimport { toast } from \"sonner\";\nimport { useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\n\nconst FormSchema = z.object({\n terms: z.boolean().refine((value) => value === true, {\n message: \"You must accept the terms and conditions.\",\n }),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n defaultValues: {\n terms: false,\n },\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"w-full max-w-md space-y-6\"\n >\n <FormCheckbox\n control={form.control}\n name=\"terms\"\n label=\"Accept terms and conditions\"\n description=\"You agree to our Terms of Service and Privacy Policy.\"\n />\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n\n"
|
|
630
|
+
},
|
|
631
|
+
{
|
|
632
|
+
"name": "form-input",
|
|
633
|
+
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { FormInput } from \"@rlx-widgets/form\";\nimport { toast } from \"sonner\";\nimport { useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\n\nconst FormSchema = z.object({\n username: z.string().min(2, {\n message: \"Username must be at least 2 characters.\",\n }),\n displayName: z.string().min(2, {\n message: \"Display name must be at least 2 characters.\",\n }),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n defaultValues: {\n username: \"\",\n displayName: \"\",\n },\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"w-full max-w-md space-y-6\"\n >\n <FormInput\n control={form.control}\n name=\"username\"\n label=\"Username\"\n description=\"This is your public display name.\"\n />\n <FormInput\n control={form.control}\n name=\"displayName\"\n label=\"Display Name (Control First)\"\n description=\"Control appears before the label.\"\n controlFirst\n />\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n\n"
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
"name": "form-select",
|
|
637
|
+
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { FormSelect } from \"@rlx-widgets/form\";\nimport { toast } from \"sonner\";\nimport { useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\n\nconst FormSchema = z.object({\n email: z.string().email({\n message: \"Please select a valid email.\",\n }),\n backupEmail: z.string().email({\n message: \"Please select a valid backup email.\",\n }),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n defaultValues: {\n email: \"\",\n backupEmail: \"\",\n },\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"w-full max-w-md space-y-6\"\n >\n <FormSelect\n control={form.control}\n name=\"email\"\n label=\"Email\"\n description=\"Select a verified email to display.\"\n items={[\n { value: \"m@example.com\", label: \"m@example.com\" },\n { value: \"m@google.com\", label: \"m@google.com\" },\n { value: \"m@support.com\", label: \"m@support.com\" },\n ]}\n />\n <FormSelect\n control={form.control}\n name=\"backupEmail\"\n label=\"Backup Email (Control First)\"\n description=\"Control appears before the label.\"\n controlFirst\n items={[\n { value: \"m@example.com\", label: \"m@example.com\" },\n { value: \"m@google.com\", label: \"m@google.com\" },\n { value: \"m@support.com\", label: \"m@support.com\" },\n ]}\n />\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n\n"
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
"name": "form-textarea",
|
|
641
|
+
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { FormTextarea } from \"@rlx-widgets/form\";\nimport { toast } from \"sonner\";\nimport { useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\n\nconst FormSchema = z.object({\n bio: z.string().min(10, {\n message: \"Bio must be at least 10 characters.\",\n }),\n notes: z.string().min(10, {\n message: \"Notes must be at least 10 characters.\",\n }),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n defaultValues: {\n bio: \"\",\n notes: \"\",\n },\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"w-full max-w-md space-y-6\"\n >\n <FormTextarea\n control={form.control}\n name=\"bio\"\n label=\"Bio\"\n description=\"Tell us a little bit about yourself.\"\n />\n <FormTextarea\n control={form.control}\n name=\"notes\"\n label=\"Notes (Control First)\"\n description=\"Control appears before the label.\"\n controlFirst\n />\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n\n"
|
|
642
|
+
}
|
|
643
|
+
]
|
|
622
644
|
},
|
|
623
645
|
{
|
|
624
646
|
"name": "Hover Card",
|
|
@@ -658,7 +680,7 @@
|
|
|
658
680
|
},
|
|
659
681
|
{
|
|
660
682
|
"name": "form",
|
|
661
|
-
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { Input } from \"@rlx-widgets/input\";\nimport { toast } from \"sonner\";\nimport { useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport {\n
|
|
683
|
+
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { Input } from \"@rlx-widgets/input\";\nimport { toast } from \"sonner\";\nimport { Controller, useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldLabel,\n} from \"@rlx-widgets/field\";\n\nconst FormSchema = z.object({\n username: z.string().min(2, {\n message: \"Username must be at least 2 characters.\",\n }),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n defaultValues: {\n username: \"\",\n },\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"w-2/3 space-y-6\">\n <Controller\n control={form.control}\n name=\"username\"\n render={({ field, fieldState }) => (\n <Field data-invalid={fieldState.invalid} orientation=\"vertical\">\n <FieldContent>\n <FieldLabel>Username</FieldLabel>\n <FieldDescription>\n This is your public display name.\n </FieldDescription>\n </FieldContent>\n <Input\n placeholder=\"shadcn\"\n {...field}\n aria-invalid={fieldState.invalid}\n />\n {fieldState.invalid && (\n <FieldError errors={[fieldState.error]} />\n )}\n </Field>\n )}\n />\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n"
|
|
662
684
|
},
|
|
663
685
|
{
|
|
664
686
|
"name": "with-button",
|
|
@@ -742,7 +764,7 @@
|
|
|
742
764
|
},
|
|
743
765
|
{
|
|
744
766
|
"name": "form",
|
|
745
|
-
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from \"@rlx-widgets/input-otp\";\nimport { toast } from \"sonner\";\nimport { useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport {\n
|
|
767
|
+
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from \"@rlx-widgets/input-otp\";\nimport { toast } from \"sonner\";\nimport { Controller, useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldLabel,\n} from \"@rlx-widgets/field\";\n\nconst FormSchema = z.object({\n pin: z.string().min(6, {\n message: \"Your one-time password must be 6 characters.\",\n }),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n defaultValues: {\n pin: \"\",\n },\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"w-2/3 space-y-6\">\n <Controller\n control={form.control}\n name=\"pin\"\n render={({ field, fieldState }) => (\n <Field data-invalid={fieldState.invalid} orientation=\"vertical\">\n <FieldContent>\n <FieldLabel>One-Time Password</FieldLabel>\n <FieldDescription>\n Please enter the one-time password sent to your phone.\n </FieldDescription>\n </FieldContent>\n <InputOTP\n maxLength={6}\n {...field}\n aria-invalid={fieldState.invalid}\n >\n <InputOTPGroup>\n <InputOTPSlot index={0} />\n <InputOTPSlot index={1} />\n <InputOTPSlot index={2} />\n <InputOTPSlot index={3} />\n <InputOTPSlot index={4} />\n <InputOTPSlot index={5} />\n </InputOTPGroup>\n </InputOTP>\n {fieldState.invalid && (\n <FieldError errors={[fieldState.error]} />\n )}\n </Field>\n )}\n />\n\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n"
|
|
746
768
|
},
|
|
747
769
|
{
|
|
748
770
|
"name": "pattern",
|
|
@@ -944,7 +966,7 @@
|
|
|
944
966
|
},
|
|
945
967
|
{
|
|
946
968
|
"name": "form",
|
|
947
|
-
"code": "\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\nimport { Button } from \"@rlx-widgets/button\";\nimport {\n
|
|
969
|
+
"code": "\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Controller, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\nimport { Button } from \"@rlx-widgets/button\";\nimport {\n Field,\n FieldContent,\n FieldError,\n FieldLabel,\n} from \"@rlx-widgets/field\";\nimport { RadioGroup, RadioGroupItem } from \"@rlx-widgets/radio-group\";\n\nconst FormSchema = z.object({\n type: z.enum([\"all\", \"mentions\", \"none\"]).refine((val) => !!val, {\n message: \"You need to select a notification type.\",\n }),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"w-2/3 space-y-6\">\n <Controller\n control={form.control}\n name=\"type\"\n render={({ field, fieldState }) => (\n <Field data-invalid={fieldState.invalid} orientation=\"vertical\" className=\"space-y-3\">\n <FieldContent>\n <FieldLabel>Notify me about...</FieldLabel>\n </FieldContent>\n <RadioGroup\n onValueChange={field.onChange}\n value={field.value}\n className=\"flex flex-col\"\n >\n <Field\n data-invalid={fieldState.invalid}\n orientation=\"horizontal\"\n className=\"flex items-center gap-3\"\n >\n <RadioGroupItem value=\"all\" aria-invalid={fieldState.invalid} />\n <FieldLabel className=\"font-normal\">\n All new messages\n </FieldLabel>\n </Field>\n <Field\n data-invalid={fieldState.invalid}\n orientation=\"horizontal\"\n className=\"flex items-center gap-3\"\n >\n <RadioGroupItem value=\"mentions\" aria-invalid={fieldState.invalid} />\n <FieldLabel className=\"font-normal\">\n Direct messages and mentions\n </FieldLabel>\n </Field>\n <Field\n data-invalid={fieldState.invalid}\n orientation=\"horizontal\"\n className=\"flex items-center gap-3\"\n >\n <RadioGroupItem value=\"none\" aria-invalid={fieldState.invalid} />\n <FieldLabel className=\"font-normal\">Nothing</FieldLabel>\n </Field>\n </RadioGroup>\n {fieldState.invalid && (\n <FieldError errors={[fieldState.error]} />\n )}\n </Field>\n )}\n />\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n"
|
|
948
970
|
}
|
|
949
971
|
]
|
|
950
972
|
},
|
|
@@ -1005,7 +1027,7 @@
|
|
|
1005
1027
|
},
|
|
1006
1028
|
{
|
|
1007
1029
|
"name": "form",
|
|
1008
|
-
"code": "\"use client\";\n\nimport Link from \"next/link\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport {\n
|
|
1030
|
+
"code": "\"use client\";\n\nimport Link from \"next/link\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Controller, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldLabel,\n} from \"@rlx-widgets/field\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@rlx-widgets/select\";\n\nconst FormSchema = z.object({\n email: z.email({\n error: \"Please select an email to display.\",\n }),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"w-2/3 space-y-6\">\n <Controller\n control={form.control}\n name=\"email\"\n render={({ field, fieldState }) => (\n <Field data-invalid={fieldState.invalid} orientation=\"vertical\">\n <FieldContent>\n <FieldLabel>Email</FieldLabel>\n <FieldDescription>\n You can manage email addresses in your{\" \"}\n <Link href=\"/examples/forms\">email settings</Link>.\n </FieldDescription>\n </FieldContent>\n <Select onValueChange={field.onChange} value={field.value}>\n <SelectTrigger\n aria-invalid={fieldState.invalid}\n onBlur={field.onBlur}\n >\n <SelectValue placeholder=\"Select a verified email to display\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"m@example.com\">m@example.com</SelectItem>\n <SelectItem value=\"m@google.com\">m@google.com</SelectItem>\n <SelectItem value=\"m@support.com\">m@support.com</SelectItem>\n </SelectContent>\n </Select>\n {fieldState.invalid && (\n <FieldError errors={[fieldState.error]} />\n )}\n </Field>\n )}\n />\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n"
|
|
1009
1031
|
},
|
|
1010
1032
|
{
|
|
1011
1033
|
"name": "scrollable",
|
|
@@ -1144,7 +1166,7 @@
|
|
|
1144
1166
|
},
|
|
1145
1167
|
{
|
|
1146
1168
|
"name": "form",
|
|
1147
|
-
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { Switch } from \"@rlx-widgets/switch\";\nimport { toast } from \"sonner\";\nimport { useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport {\n
|
|
1169
|
+
"code": "\"use client\";\n\nimport { Button } from \"@rlx-widgets/button\";\nimport { Switch } from \"@rlx-widgets/switch\";\nimport { toast } from \"sonner\";\nimport { Controller, useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldLabel,\n} from \"@rlx-widgets/field\";\n\nconst FormSchema = z.object({\n marketing_emails: z.boolean().default(false).optional(),\n security_emails: z.boolean(),\n});\n\nexport const Preview = () => {\n const form = useForm<z.infer<typeof FormSchema>>({\n resolver: zodResolver(FormSchema),\n defaultValues: {\n security_emails: true,\n },\n });\n\n function onSubmit(data: z.infer<typeof FormSchema>) {\n toast(\"You submitted the following values\", {\n description: (\n <pre className=\"mt-2 w-[320px] rounded-md bg-neutral-950 p-4\">\n <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>\n </pre>\n ),\n });\n }\n\n return (\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"w-full space-y-6\">\n <div>\n <h3 className=\"mb-4 text-lg font-medium\">Email Notifications</h3>\n <div className=\"space-y-4\">\n <Controller\n control={form.control}\n name=\"marketing_emails\"\n render={({ field, fieldState }) => (\n <Field\n data-invalid={fieldState.invalid}\n orientation=\"horizontal\"\n className=\"flex flex-row items-center justify-between rounded-lg border p-3 shadow-sm\"\n >\n <FieldContent className=\"space-y-0.5\">\n <FieldLabel>Marketing emails</FieldLabel>\n <FieldDescription>\n Receive emails about new products, features, and more.\n </FieldDescription>\n </FieldContent>\n <Switch\n checked={field.value}\n onCheckedChange={field.onChange}\n aria-invalid={fieldState.invalid}\n />\n {fieldState.invalid && (\n <FieldError errors={[fieldState.error]} />\n )}\n </Field>\n )}\n />\n <Controller\n control={form.control}\n name=\"security_emails\"\n render={({ field, fieldState }) => (\n <Field\n data-invalid={fieldState.invalid}\n orientation=\"horizontal\"\n className=\"flex flex-row items-center justify-between rounded-lg border p-3 shadow-sm\"\n >\n <FieldContent className=\"space-y-0.5\">\n <FieldLabel>Security emails</FieldLabel>\n <FieldDescription>\n Receive emails about your account security.\n </FieldDescription>\n </FieldContent>\n <Switch\n checked={field.value}\n onCheckedChange={field.onChange}\n disabled\n aria-readonly\n aria-invalid={fieldState.invalid}\n />\n {fieldState.invalid && (\n <FieldError errors={[fieldState.error]} />\n )}\n </Field>\n )}\n />\n </div>\n </div>\n <Button type=\"submit\">Submit</Button>\n </form>\n );\n};\n"
|
|
1148
1170
|
}
|
|
1149
1171
|
]
|
|
1150
1172
|
},
|
|
@@ -1355,7 +1377,7 @@
|
|
|
1355
1377
|
"name": "Code Preview Tabs",
|
|
1356
1378
|
"exportName": "CodePreviewTabs",
|
|
1357
1379
|
"packageName": "@rlx-components/code-preview-tabs",
|
|
1358
|
-
"version": "0.0
|
|
1380
|
+
"version": "1.0.0",
|
|
1359
1381
|
"slug": "code-preview-tabs",
|
|
1360
1382
|
"category": "component",
|
|
1361
1383
|
"sourceCode": "\"use client\";\n\nimport { cn } from \"@rlx-widgets/base\";\nimport { CodePreviewTabsProps, PreviewVariants, TabType } from \"./types\";\nimport { ShikiCodeBlock } from \"@rlx-components/shiki-code-block\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@rlx-widgets/tabs\";\nimport { TabTypeEnum } from \"./enums\";\nimport { useMemo, useState } from \"react\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@rlx-widgets/select\";\n\nconst defaultClassNames = {};\n\nexport const CodePreviewTabs = ({\n variants: variantsProp,\n preview,\n code,\n classNames = defaultClassNames,\n lang = \"tsx\",\n}: CodePreviewTabsProps) => {\n const variants = useMemo(() => {\n return variantsProp || { Default: { preview, code } };\n }, [variantsProp, preview, code]);\n\n const [value, setValue] = useState<TabType>(\"preview\");\n const [variant, setVariant] = useState<string>(Object.keys(variants)[0]);\n\n const handleValueChange = (newValue: string) => {\n setValue(newValue as TabType);\n };\n\n return (\n <Tabs\n value={value}\n onValueChange={handleValueChange}\n className=\"relative mt-6 w-full\"\n >\n <div className=\"flex items-center justify-between\">\n <TabsList>\n <TabsTrigger value={TabTypeEnum.PREVIEW}>Preview</TabsTrigger>\n <TabsTrigger value={TabTypeEnum.CODE}>Code</TabsTrigger>\n </TabsList>\n {Object.keys(variants).length > 1 && (\n <Select\n onValueChange={setVariant}\n defaultValue={Object.keys(variants)[0]}\n value={variant}\n >\n <SelectTrigger>\n <SelectValue placeholder=\"Default\" />\n </SelectTrigger>\n <SelectContent>\n {Object.keys(variants).map((variant) => (\n <SelectItem key={variant} value={variant}>\n {variant}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n </div>\n\n <TabsContent value={TabTypeEnum.PREVIEW}>\n <div\n className={cn(\"rounded-md border p-14 h-[400px]\", classNames.preview)}\n >\n <Preview variant={variant} variants={variants} />\n </div>\n </TabsContent>\n\n <TabsContent value={TabTypeEnum.CODE}>\n <ShikiCodeBlock\n code={variants[variant].code}\n lang={lang}\n className={classNames.code}\n />\n </TabsContent>\n </Tabs>\n );\n};\n\nconst Preview = ({\n variant,\n variants,\n}: {\n variant: string;\n variants: PreviewVariants;\n}) => {\n if (typeof variants[variant].preview !== \"function\") {\n return <>{variants[variant].preview}</>;\n }\n\n const Component = variants[variant].preview;\n\n return <Component />;\n};\n",
|
|
@@ -1381,7 +1403,7 @@
|
|
|
1381
1403
|
"name": "Code Tabs",
|
|
1382
1404
|
"exportName": "CodeTabs",
|
|
1383
1405
|
"packageName": "@rlx-components/code-tabs",
|
|
1384
|
-
"version": "0.0
|
|
1406
|
+
"version": "1.0.0",
|
|
1385
1407
|
"slug": "code-tabs",
|
|
1386
1408
|
"category": "component",
|
|
1387
1409
|
"sourceCode": "\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { ShikiCodeBlock } from \"@rlx-components/shiki-code-block\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@rlx-widgets/tabs\";\nimport { cn } from \"@rlx-widgets/base\";\nimport { getThemeBackgroundHex } from \"./utils\";\nimport { CodeTabsProps } from \"./types\";\n\nexport const CodeTabs = ({\n tabs,\n theme = \"ayu-dark\",\n startAdornment,\n}: CodeTabsProps) => {\n const [backgroundColor, setBackgroundColor] = useState<string | undefined>(\n undefined\n );\n const [value, setValue] = useState<string>(tabs[0]?.id ?? \"\");\n\n const handleValueChange = useCallback((newValue: string) => {\n setValue(newValue);\n }, []);\n\n useEffect(() => {\n void getThemeBackgroundHex(theme)\n .then((bgHex) => {\n if (bgHex) {\n setBackgroundColor(bgHex);\n }\n })\n .catch(() => {\n // Silently handle errors - fallback to default bg-muted/30\n });\n }, [theme]);\n\n if (!tabs.length || !value) {\n return null;\n }\n\n return (\n <div className=\"relative w-full\">\n <Tabs\n value={value}\n onValueChange={handleValueChange}\n className=\"w-full gap-0\"\n >\n <div\n className={cn(\n \"border-b pb-0 rounded-lg rounded-b-none\",\n backgroundColor ? \"\" : \"bg-muted/30\"\n )}\n style={backgroundColor ? { backgroundColor } : undefined}\n >\n <TabsList className=\"bg-transparent h-auto p-0\">\n {startAdornment}\n {tabs.map((tab) => (\n <TabsTrigger\n key={tab.id}\n value={tab.id}\n className=\"px-4 py-2.5 border-b-0\"\n >\n {tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </div>\n\n <div className=\"p-0\">\n {tabs.map((tab) => (\n <TabsContent key={tab.id} value={tab.id}>\n <ShikiCodeBlock\n code={tab.code}\n lang={tab.lang}\n className={cn(\n \"h-fit rounded-lg rounded-t-none border-0\",\n tab.codeBlockClassName\n )}\n />\n </TabsContent>\n ))}\n </div>\n </Tabs>\n </div>\n );\n};\n",
|
|
@@ -1421,10 +1443,10 @@
|
|
|
1421
1443
|
"name": "Inline Code",
|
|
1422
1444
|
"exportName": "InlineCode",
|
|
1423
1445
|
"packageName": "@rlx-components/inline-code",
|
|
1424
|
-
"version": "0.0
|
|
1446
|
+
"version": "1.0.0",
|
|
1425
1447
|
"slug": "inline-code",
|
|
1426
1448
|
"category": "component",
|
|
1427
|
-
"sourceCode": "import { cn } from \"@rlx-widgets/base\";\nimport { ReactNode } from \"react\";\n\nexport const InlineCode = ({ className, code, children }: InlineCodeProps) => {\n return (\n <span\n className={cn(\n \"bg-muted rounded px-1 py-0.5 overflow-x-auto text-sm\",\n className\n )}\n >\n <code>{code ?? children}</code>\n </span>\n );\n};\ntype InlineCodeProps =\n | { code: string; children?: never; className?: string }\n | { children: ReactNode; code?: never; className?: string };\n\nexport default InlineCode;\n",
|
|
1449
|
+
"sourceCode": "import { cn } from \"@rlx-widgets/base\";\nimport { ReactNode } from \"react\";\n\nexport const InlineCode = ({ className, code, children }: InlineCodeProps) => {\n return (\n <span\n className={cn(\n \"bg-muted rounded px-1 py-0.5 overflow-x-auto text-sm\",\n className\n )}\n data-slot=\"inline-code-root\"\n >\n <code data-slot=\"inline-code-content\">{code ?? children}</code>\n </span>\n );\n};\ntype InlineCodeProps =\n | { code: string; children?: never; className?: string }\n | { children: ReactNode; code?: never; className?: string };\n\nexport default InlineCode;\n",
|
|
1428
1450
|
"demos": [
|
|
1429
1451
|
{
|
|
1430
1452
|
"name": "default",
|
|
@@ -1498,10 +1520,10 @@
|
|
|
1498
1520
|
"name": "Shiki Code Block",
|
|
1499
1521
|
"exportName": "ShikiCodeBlock",
|
|
1500
1522
|
"packageName": "@rlx-components/shiki-code-block",
|
|
1501
|
-
"version": "0.0
|
|
1523
|
+
"version": "1.0.0",
|
|
1502
1524
|
"slug": "shiki-code-block",
|
|
1503
1525
|
"category": "component",
|
|
1504
|
-
"sourceCode": "\"use client\";\n\nimport { JSX, useLayoutEffect, useState } from \"react\";\nimport { highlight } from \"./utils\";\nimport { Button } from \"@rlx-widgets/button\";\nimport { cn } from \"@rlx-widgets/base\";\nimport { BundledLanguage } from \"shiki/bundle/web\";\nimport { Copy } from \"lucide-react\";\n\nexport const ShikiCodeBlock = ({\n code,\n lang,\n className,\n}: {\n code: string;\n lang: BundledLanguage;\n className?: string;\n}) => {\n const [onHover, setOnHover] = useState(false);\n const [highlightedCode, setHighlightedCode] = useState<JSX.Element>();\n const [copied, setCopied] = useState(false);\n\n const handleCopy = async () => {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n };\n\n useLayoutEffect(() => {\n void highlight({\n code,\n lang,\n className: cn(\"h-[400px]\", className),\n }).then(setHighlightedCode);\n }, [className, code, lang]);\n\n return (\n <div\n onMouseEnter={() => setOnHover(true)}\n onMouseLeave={() => setOnHover(false)}\n className={className}\n data-slot=\"shiki-code-block-root\"\n >\n <div className=\"relative\" data-slot=\"shiki-code-block-container\">\n <div data-slot=\"shiki-code-block-content\">\n {highlightedCode ?? <p>Loading...</p>}\n </div>\n <span\n className={cn(\n \"absolute top-[8px] right-[16px]\",\n \"text-xs\",\n onHover && \"hidden\"\n )}\n data-slot=\"shiki-code-block-lang\"\n >\n {lang}\n </span>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleCopy}\n className={cn(\n \"absolute top-[8px] right-[16px]\",\n \"cursor-pointer\",\n !onHover && \"hidden\"\n )}\n data-slot=\"shiki-code-block-copy-button\"\n >\n <Copy /> {copied ? \"Copied!\" : \"Copy\"}\n </Button>\n </div>\n </div>\n );\n};\n",
|
|
1526
|
+
"sourceCode": "\"use client\";\n\nimport { JSX, useLayoutEffect, useState } from \"react\";\nimport { highlight } from \"./utils\";\nimport { Button } from \"@rlx-widgets/button\";\nimport { cn } from \"@rlx-widgets/base\";\nimport { BundledLanguage, BundledTheme } from \"shiki/bundle/web\";\nimport { Copy } from \"lucide-react\";\n\nexport const ShikiCodeBlock = ({\n code,\n lang,\n className,\n theme = \"ayu-dark\",\n showLineNumbers = false,\n}: {\n code: string;\n lang: BundledLanguage;\n className?: string;\n theme?: BundledTheme;\n showLineNumbers?: boolean;\n}) => {\n const [onHover, setOnHover] = useState(false);\n const [highlightedCode, setHighlightedCode] = useState<JSX.Element>();\n const [copied, setCopied] = useState(false);\n\n const handleCopy = async () => {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n };\n\n useLayoutEffect(() => {\n void highlight({\n code,\n lang,\n theme,\n showLineNumbers,\n className: cn(\"h-[400px]\", className),\n }).then(setHighlightedCode);\n }, [className, code, lang, theme, showLineNumbers]);\n\n return (\n <div\n onMouseEnter={() => setOnHover(true)}\n onMouseLeave={() => setOnHover(false)}\n className={className}\n data-slot=\"shiki-code-block-root\"\n >\n <div className=\"relative\" data-slot=\"shiki-code-block-container\">\n <div data-slot=\"shiki-code-block-content\">\n {highlightedCode ?? <p>Loading...</p>}\n </div>\n <span\n className={cn(\n \"absolute top-[8px] right-[16px]\",\n \"text-xs\",\n onHover && \"hidden\"\n )}\n data-slot=\"shiki-code-block-lang\"\n >\n {lang}\n </span>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleCopy}\n className={cn(\n \"absolute top-[8px] right-[16px]\",\n \"cursor-pointer\",\n !onHover && \"hidden\"\n )}\n data-slot=\"shiki-code-block-copy-button\"\n >\n <Copy /> {copied ? \"Copied!\" : \"Copy\"}\n </Button>\n </div>\n </div>\n );\n};\n",
|
|
1505
1527
|
"demos": [
|
|
1506
1528
|
{
|
|
1507
1529
|
"name": "default",
|
|
@@ -1509,7 +1531,7 @@
|
|
|
1509
1531
|
}
|
|
1510
1532
|
],
|
|
1511
1533
|
"sourceFiles": {
|
|
1512
|
-
"utils/highlight.tsx": "import { codeToHast } from \"shiki/bundle/web\";\nimport { Fragment } from \"react\";\nimport { jsx, jsxs } from \"react/jsx-runtime\";\nimport { toJsxRuntime } from \"hast-util-to-jsx-runtime\";\nimport type { JSX } from \"react\";\nimport type { BundledLanguage } from \"shiki/bundle/web\";\nimport { cn } from \"@rlx-widgets/base\";\n\nexport async function highlight({\n code,\n lang,\n className,\n}: {\n code: string;\n lang: BundledLanguage;\n className?: string;\n}) {\n const out = await codeToHast(code, {\n lang,\n theme
|
|
1534
|
+
"utils/highlight.tsx": "import { codeToHast } from \"shiki/bundle/web\";\nimport { Fragment } from \"react\";\nimport { jsx, jsxs } from \"react/jsx-runtime\";\nimport { toJsxRuntime } from \"hast-util-to-jsx-runtime\";\nimport type { JSX } from \"react\";\nimport type { BundledLanguage, BundledTheme } from \"shiki/bundle/web\";\nimport { cn } from \"@rlx-widgets/base\";\n\nexport async function highlight({\n code,\n lang,\n className,\n theme = \"ayu-dark\",\n showLineNumbers = false,\n}: {\n code: string;\n lang: BundledLanguage;\n className?: string;\n theme?: BundledTheme;\n showLineNumbers?: boolean;\n}) {\n const out = await codeToHast(code, {\n lang,\n theme,\n });\n\n return toJsxRuntime(out, {\n Fragment,\n jsx,\n jsxs,\n components: {\n pre: (props) => (\n <pre\n {...props}\n className={cn(\"rounded p-4 overflow-x-auto\", className)}\n data-slot=\"shiki-code-block-code\"\n />\n ),\n code: (props) => (\n <code\n {...props}\n className={cn(\n showLineNumbers &&\n \"[counter-reset:step] [counter-increment:step_0] [&_.line::before]:[content:counter(step)] [&_.line]:before:[counter-increment:step] [&_.line]:before:w-4 [&_.line]:before:mr-6 [&_.line]:before:inline-block [&_.line]:before:text-right [&_.line]:before:[color:rgba(115,138,148,.4)]\"\n )}\n />\n ),\n },\n }) as JSX.Element;\n}\n"
|
|
1513
1535
|
}
|
|
1514
1536
|
},
|
|
1515
1537
|
{
|
|
@@ -1674,5 +1696,5 @@
|
|
|
1674
1696
|
"sourceCode": "export const isValidDate = (date: Date) => {\n return !Number.isNaN(date.getTime());\n};\n\nexport default isValidDate;\n"
|
|
1675
1697
|
}
|
|
1676
1698
|
],
|
|
1677
|
-
"extractedAt": "
|
|
1699
|
+
"extractedAt": "2026-05-10T06:04:14.124Z"
|
|
1678
1700
|
}
|
package/dist/package.json
CHANGED