shadcn-svelte-extras
Installation
Section titled “Installation”npm i @sjsf-lab/shadcn-extras-themepnpm add @sjsf-lab/shadcn-extras-themeyarn add @sjsf-lab/shadcn-extras-themebun add @sjsf-lab/shadcn-extras-themedeno add @sjsf-lab/shadcn-extras-themeRequired peer dependencies: @sjsf/form@3.5.0 @sjsf/shadcn4-theme@3.5.0 bits-ui@2.14.0 clsx@2.1.0 svelte@5.34.8 tailwind-merge@3.3.0
Optional peer dependencies: @lucide/svelte@1.0.0 @zxcvbn-ts/core@3.0.0 @zxcvbn-ts/language-common@3.0.0 @zxcvbn-ts/language-en@3.0.0 country-flag-icons@1.5.0 runed@0.37.0 svelte-tel-input@4.0.0 svelte-toolbelt@0.10.0 tailwind-variants@3.2.0 yeezy-dates@1.0.0
Install shadcn-svelte
Section titled “Install shadcn-svelte”Installation - shadcn-svelte
Configuration
Section titled “Configuration”Register the theme source path by adding the following line to the app.css file:
@source "../node_modules/@sjsf-lab/shadcn-extras-theme/dist";Components
Section titled “Components”Since shadcn-svelte and shadcn-svelte-extras are not component libraries
you should provide your components via setThemeContext.
import { setThemeContext } from "@sjsf/shadcn4-theme";import * as components from "@sjsf/shadcn4-theme/new-york";import * as extraComponents from "@sjsf-lab/shadcn-extras-theme/ui";
setThemeContext({ components: { ...components, ...extraComponents } });Extra widgets
Section titled “Extra widgets”You can connect extra widgets using the following include imports:
import "@sjsf-lab/shadcn-extras-theme/extra-widgets/file-drop-zone-include"import "@sjsf-lab/shadcn-extras-theme/extra-widgets/ip-v4-address-input-include"import "@sjsf-lab/shadcn-extras-theme/extra-widgets/nlp-date-input-include"import "@sjsf-lab/shadcn-extras-theme/extra-widgets/password-include"import "@sjsf-lab/shadcn-extras-theme/extra-widgets/phone-input-include"import "@sjsf-lab/shadcn-extras-theme/extra-widgets/star-rating-include"import "@sjsf-lab/shadcn-extras-theme/extra-widgets/tags-input-include"Widgets demo
Section titled “Widgets demo”{ "type": "object", "properties": { "fileDropZone": { "type": "object", "properties": { "default": { "type": "string", "format": "data-url" }, "error": { "type": "string", "format": "data-url" } }, "required": [ "default" ] }, "fileDropZoneMultiple": { "type": "object", "properties": { "default": { "type": "array", "items": { "type": "string", "format": "data-url" } }, "error": { "type": "array", "items": { "type": "string", "format": "data-url" } } }, "required": [ "default" ] }, "ipV4AddressInput": { "type": "object", "properties": { "default": { "type": "string" }, "error": { "type": "string" } }, "required": [ "default" ] }, "nlpDateInput": { "type": "object", "properties": { "default": { "type": "string" }, "error": { "type": "string" } }, "required": [ "default" ] }, "password": { "type": "object", "properties": { "default": { "type": "string" }, "error": { "type": "string" } }, "required": [ "default" ] }, "phoneInput": { "type": "object", "properties": { "default": { "type": "string" }, "error": { "type": "string" } }, "required": [ "default" ] }, "starRating": { "type": "object", "properties": { "default": { "type": "number" }, "error": { "type": "number" } }, "required": [ "default" ] }, "tagsInput": { "type": "object", "properties": { "default": { "type": "array", "items": { "type": "string", "enum": [ "foo", "bar", "fuzz", "qux" ] }, "uniqueItems": true }, "error": { "type": "array", "items": { "type": "string", "enum": [ "foo", "bar", "fuzz", "qux" ] }, "uniqueItems": true } }, "required": [ "default" ] } }}{ "fileDropZone": { "default": { "ui:components": { "stringField": "fileField", "fileWidget": "shadcnExtrasFileDropZoneWidget" }, "ui:options": { "title": "fileDropZone" } }, "error": { "ui:components": { "stringField": "fileField", "fileWidget": "shadcnExtrasFileDropZoneWidget" }, "ui:options": { "title": "fileDropZone" } }, "ui:options": { "layouts": { "object-properties": { "style": "display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;" } } } }, "fileDropZoneMultiple": { "default": { "ui:components": { "arrayField": "arrayFilesField", "fileWidget": "shadcnExtrasFileDropZoneWidget" }, "ui:options": { "title": "fileDropZoneMultiple" } }, "error": { "ui:components": { "arrayField": "arrayFilesField", "fileWidget": "shadcnExtrasFileDropZoneWidget" }, "ui:options": { "title": "fileDropZoneMultiple" } }, "ui:options": { "layouts": { "object-properties": { "style": "display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;" } } } }, "ipV4AddressInput": { "default": { "ui:components": { "textWidget": "shadcnExtrasIPv4AddressInputWidget" }, "ui:options": { "useLabel": false, "title": "ipV4AddressInput" } }, "error": { "ui:components": { "textWidget": "shadcnExtrasIPv4AddressInputWidget" }, "ui:options": { "useLabel": false, "title": "ipV4AddressInput" } }, "ui:options": { "layouts": { "object-properties": { "style": "display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;" } } } }, "nlpDateInput": { "default": { "ui:components": { "textWidget": "shadcnExtrasNLPDateInputWidget" }, "ui:options": { "useLabel": false, "title": "nlpDateInput" } }, "error": { "ui:components": { "textWidget": "shadcnExtrasNLPDateInputWidget" }, "ui:options": { "useLabel": false, "title": "nlpDateInput" } }, "ui:options": { "layouts": { "object-properties": { "style": "display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;" } } } }, "password": { "default": { "ui:components": { "textWidget": "shadcnExtrasPasswordWidget" }, "ui:options": { "title": "password" } }, "error": { "ui:components": { "textWidget": "shadcnExtrasPasswordWidget" }, "ui:options": { "title": "password" } }, "ui:options": { "layouts": { "object-properties": { "style": "display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;" } } } }, "phoneInput": { "default": { "ui:components": { "textWidget": "shadcnExtrasPhoneInputWidget" }, "ui:options": { "title": "phoneInput" } }, "error": { "ui:components": { "textWidget": "shadcnExtrasPhoneInputWidget" }, "ui:options": { "title": "phoneInput" } }, "ui:options": { "layouts": { "object-properties": { "style": "display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;" } } } }, "starRating": { "default": { "ui:components": { "numberWidget": "shadcnExtrasStarRatingWidget" }, "ui:options": { "useLabel": false, "title": "starRating" } }, "error": { "ui:components": { "numberWidget": "shadcnExtrasStarRatingWidget" }, "ui:options": { "useLabel": false, "title": "starRating" } }, "ui:options": { "layouts": { "object-properties": { "style": "display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;" } } } }, "tagsInput": { "default": { "ui:components": { "arrayField": "arrayTagsField", "tagsWidget": "shadcnExtrasTagsInputWidget" }, "ui:options": { "title": "tagsInput" } }, "error": { "ui:components": { "arrayField": "arrayTagsField", "tagsWidget": "shadcnExtrasTagsInputWidget" }, "ui:options": { "title": "tagsInput" } }, "ui:options": { "layouts": { "object-properties": { "style": "display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;" } } } }}Supported validation events
Section titled “Supported validation events”| fileDropZone | |
| fileDropZoneMultiple | |
| ipV4AddressInput | |
| nlpDateInput | |
| password | |
| phoneInput | |
| starRating | |
| tagsInput |
UI options
Section titled “UI options”import type { DateValue } from "@internationalized/date";import type { ButtonType, LayoutType } from "@sjsf/form/fields/components";import type { Range } from "@sjsf/form/lib/range";import type { ButtonGroupProps, FieldProps,} from "@sjsf/shadcn4-theme/components/layout.svelte";import type { Button } from "@sjsf/shadcn4-theme/new-york";import type { CalendarSingleRootProps, CheckboxRootProps, LabelRootProps, RadioGroupItemProps, RadioGroupRootProps, RatingGroupRootProps, SelectMultipleRootProps, SelectSingleRootProps, SelectTriggerProps, SliderSingleRootProps, SliderMultipleRootProps, SwitchRootProps, WithElementRef, WithoutChildrenOrChild, CommandInputProps, SingleToggleGroupRootPropsWithoutHTML, BitsPrimitiveDivAttributes, Without, ToggleGroupRootPropsWithoutHTML, ToggleGroupItemProps, RangeCalendarRootProps,} from "bits-ui";import type { ComponentProps } from "svelte";import type { HTMLAttributes, HTMLFieldsetAttributes, HTMLFormAttributes, HTMLInputAttributes, HTMLInputTypeAttribute, HTMLTextareaAttributes,} from "svelte/elements";
type InputType = Exclude<HTMLInputTypeAttribute, "file">;
type InputProps = WithElementRef< Omit<HTMLInputAttributes, "type"> & ( | { type: "file"; files?: FileList } | { type?: InputType; files?: undefined } )>;
type ToggleVariants = { variant?: "default" | "outline" | undefined; size?: "default" | "sm" | "lg" | undefined;};
type ToggleGroupProps = SingleToggleGroupRootPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, ToggleGroupRootPropsWithoutHTML> & ToggleVariants;
export interface UiOptions { shadcn4Button?: ComponentProps<typeof Button>; shadcn4Buttons?: { [B in ButtonType]: ComponentProps<typeof Button>; }; /** * Overrides the attributes of the description. */ descriptionAttributes?: HTMLAttributes<HTMLDivElement>; /** * Overrides the attributes of the errors list. */ errorsList?: HTMLAttributes<HTMLUListElement>;
form?: HTMLFormAttributes; /** * Overrides the attributes of the help. */ helpAttributes?: HTMLAttributes<HTMLDivElement>;
shadcn4Label?: LabelRootProps; /** * Overrides the attributes of any layout component. */ layout?: HTMLAttributes<HTMLDivElement>; /** * Overrides the attributes of a layout with a specific type. * This override takes precedence over the `layout` override, but does not replace it. */ layouts?: { [L in LayoutType]?: HTMLAttributes<HTMLDivElement>; }; shadcn4ButtonGroup?: ButtonGroupProps; shadcn4Field?: FieldProps; shadcn4FieldSet?: HTMLFieldsetAttributes; shadcn4SubmitButton?: ComponentProps<typeof Button>; /** * Overrides the attributes of the field title */ titleAttributes?: HTMLAttributes<HTMLDivElement>;
shadcn4Checkbox?: WithoutChildrenOrChild<CheckboxRootProps>;
shadcn4Number?: InputProps;
shadcn4Select?: Omit<SelectSingleRootProps, "type">; shadcn4SelectTrigger?: SelectTriggerProps;
shadcn4Text?: InputProps;
shadcn4Checkboxes?: WithoutChildrenOrChild<CheckboxRootProps>;
shadcn4ComboboxTrigger?: ComponentProps<typeof Button>; shadcn4ComboboxInput?: CommandInputProps; shadcn4ComboboxEmptyText?: string;
shadcn4DatePicker?: Omit< WithoutChildrenOrChild<CalendarSingleRootProps>, "type" >; shadcn4DatePickerTrigger?: ComponentProps<typeof Button>; shadcn4DateFormatter?: (date: Date) => string;
shadcn4DateRangePicker?: RangeCalendarRootProps; shadcn4DateRangePickerPlaceholder?: string; shadcn4DateRangeFormatter?: (range: Range<DateValue | undefined>) => string;
file?: HTMLInputAttributes;
shadcn4MultiSelect?: Omit<SelectMultipleRootProps, "type">; shadcn4MultiSelectTrigger?: SelectTriggerProps;
shadcn4RadioButtons?: ToggleGroupProps; shadcn4RadioButtonsItem?: ToggleGroupItemProps & ToggleVariants;
shadcn4RadioGroup?: WithoutChildrenOrChild<RadioGroupRootProps>; shadcn4RadioItem?: Omit<WithoutChildrenOrChild<RadioGroupItemProps>, "value">;
shadcn4Range?: Omit<WithoutChildrenOrChild<SliderSingleRootProps>, "type">;
shadcn4RangeSlider?: Omit< WithoutChildrenOrChild<SliderMultipleRootProps>, "type" >;
shadcn4Switch?: WithoutChildrenOrChild<SwitchRootProps>;
textarea?: HTMLTextareaAttributes;
/** * Overrides the props of the file drop zone widget. */ shadcnExtrasFileDropZone?: Record<string, unknown>; /** * Overrides the props of the IPv4 address input widget. */ shadcnExtrasIPv4AddressInput?: Record<string, unknown>; /** * Overrides the props of the NLP date input widget. */ shadcnExtrasNLPDateInput?: Record<string, unknown>; /** * Overrides the props of the password input widget. */ shadcnExtrasPassword?: Record<string, unknown>; /** * Overrides the props of the phone input widget. */ shadcnExtrasPhoneInput?: Record<string, unknown>; /** * Overrides the props of the star rating widget. */ shadcnExtrasStarRating?: RatingGroupRootProps; /** * Overrides the props of the tags input widget. */ shadcnExtrasTagsInput?: Record<string, unknown>;}