soluid 0.1.1
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/LICENSE +21 -0
- package/README.md +62 -0
- package/dist/commands/add.js +31 -0
- package/dist/commands/init.js +56 -0
- package/dist/commands/install.js +110 -0
- package/dist/commands/list.js +54 -0
- package/dist/commands/remove.js +25 -0
- package/dist/components/data/Card.d.ts +22 -0
- package/dist/components/data/DescriptionList.d.ts +11 -0
- package/dist/components/data/EmptyState.d.ts +10 -0
- package/dist/components/data/Skeleton.d.ts +8 -0
- package/dist/components/data/Table.d.ts +23 -0
- package/dist/components/data/index.d.ts +10 -0
- package/dist/components/feedback/Alert.d.ts +9 -0
- package/dist/components/feedback/Dialog.d.ts +25 -0
- package/dist/components/feedback/Drawer.d.ts +11 -0
- package/dist/components/feedback/Progress.d.ts +8 -0
- package/dist/components/feedback/Spinner.d.ts +7 -0
- package/dist/components/feedback/Toast.d.ts +10 -0
- package/dist/components/feedback/index.d.ts +12 -0
- package/dist/components/form/Checkbox.d.ts +14 -0
- package/dist/components/form/CheckboxGroup.d.ts +10 -0
- package/dist/components/form/CheckboxGroupContext.d.ts +6 -0
- package/dist/components/form/FormField.d.ts +11 -0
- package/dist/components/form/FormFieldContext.d.ts +8 -0
- package/dist/components/form/NumberInput.d.ts +15 -0
- package/dist/components/form/RadioButton.d.ts +10 -0
- package/dist/components/form/RadioGroup.d.ts +11 -0
- package/dist/components/form/RadioGroupContext.d.ts +7 -0
- package/dist/components/form/Select.d.ts +19 -0
- package/dist/components/form/Switch.d.ts +12 -0
- package/dist/components/form/TextArea.d.ts +15 -0
- package/dist/components/form/TextField.d.ts +14 -0
- package/dist/components/form/index.d.ts +26 -0
- package/dist/components/general/Badge.d.ts +9 -0
- package/dist/components/general/Button.d.ts +10 -0
- package/dist/components/general/IconButton.d.ts +8 -0
- package/dist/components/general/Tag.d.ts +10 -0
- package/dist/components/general/Tooltip.d.ts +6 -0
- package/dist/components/general/index.d.ts +10 -0
- package/dist/components/layout/Divider.d.ts +7 -0
- package/dist/components/layout/HStack.d.ts +10 -0
- package/dist/components/layout/Spacer.d.ts +3 -0
- package/dist/components/layout/Stack.d.ts +9 -0
- package/dist/components/layout/index.d.ts +7 -0
- package/dist/components/navigation/Breadcrumb.d.ts +14 -0
- package/dist/components/navigation/Menu.d.ts +7 -0
- package/dist/components/navigation/Pagination.d.ts +9 -0
- package/dist/components/navigation/Tabs.d.ts +27 -0
- package/dist/components/navigation/index.d.ts +8 -0
- package/dist/components/utility/Popover.d.ts +7 -0
- package/dist/components/utility/VisuallyHidden.d.ts +6 -0
- package/dist/components/utility/index.d.ts +4 -0
- package/dist/config.js +26 -0
- package/dist/core/SouiProvider.d.ts +7 -0
- package/dist/core/context.d.ts +6 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/theme.d.ts +7 -0
- package/dist/core/types.d.ts +35 -0
- package/dist/core/utils.d.ts +2 -0
- package/dist/dev/App.d.ts +3 -0
- package/dist/dev/index.d.ts +1 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +53 -0
- package/dist/primitives/createDisclosure.d.ts +27 -0
- package/dist/primitives/createFocusTrap.d.ts +10 -0
- package/dist/primitives/createPagination.d.ts +23 -0
- package/dist/primitives/createToast.d.ts +23 -0
- package/dist/primitives/createToggle.d.ts +19 -0
- package/dist/primitives/index.d.ts +10 -0
- package/dist/registry.js +410 -0
- package/dist/rewrite-imports.js +42 -0
- package/package.json +36 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { InteractiveProps } from "../../core/types";
|
|
3
|
+
import "./Select.css";
|
|
4
|
+
export interface SelectOption<T extends string = string> {
|
|
5
|
+
value: T;
|
|
6
|
+
label: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface SelectProps<T extends string = string> extends InteractiveProps {
|
|
10
|
+
value?: T;
|
|
11
|
+
onChange?: (value: T) => void;
|
|
12
|
+
options: SelectOption<T>[];
|
|
13
|
+
placeholder?: string;
|
|
14
|
+
label: string;
|
|
15
|
+
error?: string;
|
|
16
|
+
hint?: string;
|
|
17
|
+
required?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function Select<T extends string = string>(props: SelectProps<T>): JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { CommonProps } from "../../core/types";
|
|
3
|
+
import "./Switch.css";
|
|
4
|
+
export interface SwitchProps extends CommonProps {
|
|
5
|
+
checked?: boolean;
|
|
6
|
+
onChange?: (checked: boolean) => void;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
size?: "sm" | "md";
|
|
9
|
+
label?: string;
|
|
10
|
+
children?: JSX.Element;
|
|
11
|
+
}
|
|
12
|
+
export declare function Switch(props: SwitchProps): JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { CommonProps } from "../../core/types";
|
|
3
|
+
import "./TextArea.css";
|
|
4
|
+
export interface TextAreaProps extends CommonProps {
|
|
5
|
+
value?: string;
|
|
6
|
+
onInput?: (value: string) => void;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
rows?: number;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
label: string;
|
|
11
|
+
error?: string;
|
|
12
|
+
hint?: string;
|
|
13
|
+
required?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function TextArea(props: TextAreaProps): JSX.Element;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { InteractiveProps } from "../../core/types";
|
|
3
|
+
import "./TextField.css";
|
|
4
|
+
export interface TextFieldProps extends InteractiveProps {
|
|
5
|
+
value?: string;
|
|
6
|
+
onInput?: (value: string) => void;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
type?: "text" | "email" | "password" | "url" | "tel";
|
|
9
|
+
label: string;
|
|
10
|
+
error?: string;
|
|
11
|
+
hint?: string;
|
|
12
|
+
required?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function TextField(props: TextFieldProps): JSX.Element;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export { FormField } from "./FormField";
|
|
2
|
+
export type { FormFieldProps } from "./FormField";
|
|
3
|
+
export { FormFieldContext, useFormField } from "./FormFieldContext";
|
|
4
|
+
export type { FormFieldContextValue } from "./FormFieldContext";
|
|
5
|
+
export { TextField } from "./TextField";
|
|
6
|
+
export type { TextFieldProps } from "./TextField";
|
|
7
|
+
export { TextArea } from "./TextArea";
|
|
8
|
+
export type { TextAreaProps } from "./TextArea";
|
|
9
|
+
export { NumberInput } from "./NumberInput";
|
|
10
|
+
export type { NumberInputProps } from "./NumberInput";
|
|
11
|
+
export { Select } from "./Select";
|
|
12
|
+
export type { SelectProps, SelectOption } from "./Select";
|
|
13
|
+
export { Checkbox } from "./Checkbox";
|
|
14
|
+
export type { CheckboxProps } from "./Checkbox";
|
|
15
|
+
export { CheckboxGroup } from "./CheckboxGroup";
|
|
16
|
+
export type { CheckboxGroupProps } from "./CheckboxGroup";
|
|
17
|
+
export { CheckboxGroupContext, useCheckboxGroup } from "./CheckboxGroupContext";
|
|
18
|
+
export type { CheckboxGroupContextValue } from "./CheckboxGroupContext";
|
|
19
|
+
export { RadioGroup } from "./RadioGroup";
|
|
20
|
+
export type { RadioGroupProps } from "./RadioGroup";
|
|
21
|
+
export { RadioButton } from "./RadioButton";
|
|
22
|
+
export type { RadioButtonProps } from "./RadioButton";
|
|
23
|
+
export { RadioGroupContext, useRadioGroup } from "./RadioGroupContext";
|
|
24
|
+
export type { RadioGroupContextValue } from "./RadioGroupContext";
|
|
25
|
+
export { Switch } from "./Switch";
|
|
26
|
+
export type { SwitchProps } from "./Switch";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { CommonProps, Variant } from "../../core/types";
|
|
3
|
+
import "./Badge.css";
|
|
4
|
+
export interface BadgeProps extends CommonProps {
|
|
5
|
+
variant?: Variant;
|
|
6
|
+
size?: "sm" | "md";
|
|
7
|
+
children: JSX.Element;
|
|
8
|
+
}
|
|
9
|
+
export declare function Badge(props: BadgeProps & JSX.HTMLAttributes<HTMLSpanElement>): JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { VariantProps, ButtonVariant } from "../../core/types";
|
|
3
|
+
import "./Button.css";
|
|
4
|
+
export interface ButtonProps extends VariantProps<ButtonVariant> {
|
|
5
|
+
iconLeft?: JSX.Element;
|
|
6
|
+
iconRight?: JSX.Element;
|
|
7
|
+
loading?: boolean;
|
|
8
|
+
children: JSX.Element;
|
|
9
|
+
}
|
|
10
|
+
export declare function Button(props: ButtonProps & JSX.ButtonHTMLAttributes<HTMLButtonElement>): JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { VariantProps, ButtonVariant } from "../../core/types";
|
|
3
|
+
import "./IconButton.css";
|
|
4
|
+
export interface IconButtonProps extends VariantProps<ButtonVariant> {
|
|
5
|
+
icon: JSX.Element;
|
|
6
|
+
"aria-label": string;
|
|
7
|
+
}
|
|
8
|
+
export declare function IconButton(props: IconButtonProps & JSX.ButtonHTMLAttributes<HTMLButtonElement>): JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { CommonProps, Variant } from "../../core/types";
|
|
3
|
+
import "./Tag.css";
|
|
4
|
+
export interface TagProps extends CommonProps {
|
|
5
|
+
variant?: Variant;
|
|
6
|
+
size?: "sm" | "md";
|
|
7
|
+
onRemove?: () => void;
|
|
8
|
+
children: JSX.Element;
|
|
9
|
+
}
|
|
10
|
+
export declare function Tag(props: TagProps & JSX.HTMLAttributes<HTMLSpanElement>): JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { Button } from "./Button";
|
|
2
|
+
export type { ButtonProps } from "./Button";
|
|
3
|
+
export { IconButton } from "./IconButton";
|
|
4
|
+
export type { IconButtonProps } from "./IconButton";
|
|
5
|
+
export { Badge } from "./Badge";
|
|
6
|
+
export type { BadgeProps } from "./Badge";
|
|
7
|
+
export { Tag } from "./Tag";
|
|
8
|
+
export type { TagProps } from "./Tag";
|
|
9
|
+
export { Tooltip } from "./Tooltip";
|
|
10
|
+
export type { TooltipProps } from "./Tooltip";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { CommonProps } from "../../core/types";
|
|
3
|
+
import "./Divider.css";
|
|
4
|
+
export interface DividerProps extends CommonProps {
|
|
5
|
+
orientation?: "horizontal" | "vertical";
|
|
6
|
+
}
|
|
7
|
+
export declare function Divider(props: DividerProps & JSX.HTMLAttributes<HTMLHRElement>): JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { CommonProps } from "../../core/types";
|
|
3
|
+
import "./HStack.css";
|
|
4
|
+
export interface HStackProps extends CommonProps {
|
|
5
|
+
gap?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
6
|
+
align?: "start" | "center" | "end" | "stretch";
|
|
7
|
+
wrap?: boolean;
|
|
8
|
+
children: JSX.Element;
|
|
9
|
+
}
|
|
10
|
+
export declare function HStack(props: HStackProps & JSX.HTMLAttributes<HTMLDivElement>): JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { CommonProps } from "../../core/types";
|
|
3
|
+
import "./Stack.css";
|
|
4
|
+
export interface StackProps extends CommonProps {
|
|
5
|
+
gap?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
6
|
+
align?: "start" | "center" | "end" | "stretch";
|
|
7
|
+
children: JSX.Element;
|
|
8
|
+
}
|
|
9
|
+
export declare function Stack(props: StackProps & JSX.HTMLAttributes<HTMLDivElement>): JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { Stack } from "./Stack";
|
|
2
|
+
export type { StackProps } from "./Stack";
|
|
3
|
+
export { HStack } from "./HStack";
|
|
4
|
+
export type { HStackProps } from "./HStack";
|
|
5
|
+
export { Divider } from "./Divider";
|
|
6
|
+
export type { DividerProps } from "./Divider";
|
|
7
|
+
export { Spacer } from "./Spacer";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { CommonProps } from "../../core/types";
|
|
3
|
+
import "./Breadcrumb.css";
|
|
4
|
+
export interface BreadcrumbProps extends CommonProps {
|
|
5
|
+
children: JSX.Element;
|
|
6
|
+
}
|
|
7
|
+
export interface BreadcrumbItemProps {
|
|
8
|
+
href?: string;
|
|
9
|
+
current?: boolean;
|
|
10
|
+
class?: string;
|
|
11
|
+
children: JSX.Element;
|
|
12
|
+
}
|
|
13
|
+
export declare function Breadcrumb(props: BreadcrumbProps): JSX.Element;
|
|
14
|
+
export declare function BreadcrumbItem(props: BreadcrumbItemProps): JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { CommonProps } from "../../core/types";
|
|
3
|
+
export interface MenuProps extends CommonProps {
|
|
4
|
+
children: JSX.Element;
|
|
5
|
+
}
|
|
6
|
+
/** Placeholder: full implementation requires Popover integration */
|
|
7
|
+
export declare function Menu(props: MenuProps): JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CommonProps } from "../../core/types";
|
|
2
|
+
import "./Pagination.css";
|
|
3
|
+
export interface PaginationProps extends CommonProps {
|
|
4
|
+
page: number;
|
|
5
|
+
totalPages: number;
|
|
6
|
+
onChange: (page: number) => void;
|
|
7
|
+
size?: "sm" | "md";
|
|
8
|
+
}
|
|
9
|
+
export declare function Pagination(props: PaginationProps): import("solid-js").JSX.Element;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { CommonProps } from "../../core/types";
|
|
3
|
+
import "./Tabs.css";
|
|
4
|
+
export interface TabsProps extends CommonProps {
|
|
5
|
+
value: string;
|
|
6
|
+
onChange: (value: string) => void;
|
|
7
|
+
children: JSX.Element;
|
|
8
|
+
}
|
|
9
|
+
export interface TabListProps {
|
|
10
|
+
class?: string;
|
|
11
|
+
children: JSX.Element;
|
|
12
|
+
}
|
|
13
|
+
export interface TabProps {
|
|
14
|
+
value: string;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
class?: string;
|
|
17
|
+
children: JSX.Element;
|
|
18
|
+
}
|
|
19
|
+
export interface TabPanelProps {
|
|
20
|
+
value: string;
|
|
21
|
+
class?: string;
|
|
22
|
+
children: JSX.Element;
|
|
23
|
+
}
|
|
24
|
+
export declare function Tabs(props: TabsProps): JSX.Element;
|
|
25
|
+
export declare function TabList(props: TabListProps): JSX.Element;
|
|
26
|
+
export declare function Tab(props: TabProps): JSX.Element;
|
|
27
|
+
export declare function TabPanel(props: TabPanelProps): JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { Tabs, TabList, Tab, TabPanel } from "./Tabs";
|
|
2
|
+
export type { TabsProps, TabListProps, TabProps, TabPanelProps } from "./Tabs";
|
|
3
|
+
export { Breadcrumb, BreadcrumbItem } from "./Breadcrumb";
|
|
4
|
+
export type { BreadcrumbProps, BreadcrumbItemProps } from "./Breadcrumb";
|
|
5
|
+
export { Pagination } from "./Pagination";
|
|
6
|
+
export type { PaginationProps } from "./Pagination";
|
|
7
|
+
export { Menu } from "./Menu";
|
|
8
|
+
export type { MenuProps } from "./Menu";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { CommonProps } from "../../core/types";
|
|
3
|
+
export interface PopoverProps extends CommonProps {
|
|
4
|
+
children: JSX.Element;
|
|
5
|
+
}
|
|
6
|
+
/** Placeholder: full implementation requires floating-ui integration */
|
|
7
|
+
export declare function Popover(props: PopoverProps): JSX.Element;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
export const PROJECT_NAME = "soluid";
|
|
4
|
+
export const CONFIG_FILENAME = `${PROJECT_NAME}.config.json`;
|
|
5
|
+
export const DEFAULT_CSS_FILENAME = `${PROJECT_NAME}.css`;
|
|
6
|
+
export const defaultConfig = {
|
|
7
|
+
componentDir: "src/components/ui",
|
|
8
|
+
alias: "",
|
|
9
|
+
aliasBase: "src",
|
|
10
|
+
cssPath: `src/styles/${DEFAULT_CSS_FILENAME}`,
|
|
11
|
+
components: [],
|
|
12
|
+
};
|
|
13
|
+
export function findConfigPath(cwd) {
|
|
14
|
+
return path.join(cwd, CONFIG_FILENAME);
|
|
15
|
+
}
|
|
16
|
+
export function loadConfig(cwd) {
|
|
17
|
+
const configPath = findConfigPath(cwd);
|
|
18
|
+
if (!fs.existsSync(configPath))
|
|
19
|
+
return null;
|
|
20
|
+
const raw = fs.readFileSync(configPath, "utf-8");
|
|
21
|
+
return JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
export function saveConfig(cwd, config) {
|
|
24
|
+
const configPath = findConfigPath(cwd);
|
|
25
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
26
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { SouiProvider } from "./SouiProvider";
|
|
2
|
+
export type { SouiProviderProps } from "./SouiProvider";
|
|
3
|
+
export { SouiContext, useSoui } from "./context";
|
|
4
|
+
export type { SouiContextValue } from "./context";
|
|
5
|
+
export { createTheme } from "./theme";
|
|
6
|
+
export type { Density, Size, Variant, ButtonVariant, FeedbackVariant, CommonProps, InteractiveProps, VariantProps, ColorDefinition, DateFormatConfig, ThemeConfig, DataAttributes, HTMLProps, } from "./types";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
export type Density = "normal" | "dense";
|
|
3
|
+
export type Size = "sm" | "md" | "lg";
|
|
4
|
+
export type Variant = "primary" | "neutral" | "danger" | "success" | "warning" | "info";
|
|
5
|
+
export type ButtonVariant = Extract<Variant, "primary" | "neutral" | "danger">;
|
|
6
|
+
export type FeedbackVariant = Extract<Variant, "success" | "danger" | "warning" | "info">;
|
|
7
|
+
export interface CommonProps {
|
|
8
|
+
class?: string;
|
|
9
|
+
density?: Density;
|
|
10
|
+
}
|
|
11
|
+
export interface InteractiveProps extends CommonProps {
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
size?: Size;
|
|
14
|
+
}
|
|
15
|
+
export interface VariantProps<V extends string = Variant> extends InteractiveProps {
|
|
16
|
+
variant?: V;
|
|
17
|
+
}
|
|
18
|
+
export interface ColorDefinition {
|
|
19
|
+
name: string;
|
|
20
|
+
base: string;
|
|
21
|
+
}
|
|
22
|
+
export type { Locale } from "date-fns";
|
|
23
|
+
import type { Locale } from "date-fns";
|
|
24
|
+
export interface DateFormatConfig {
|
|
25
|
+
displayFormat: string;
|
|
26
|
+
locale?: Locale;
|
|
27
|
+
}
|
|
28
|
+
export interface ThemeConfig {
|
|
29
|
+
density?: Density;
|
|
30
|
+
theme?: "light" | "dark";
|
|
31
|
+
dateFormat?: DateFormatConfig;
|
|
32
|
+
colors?: ColorDefinition[];
|
|
33
|
+
}
|
|
34
|
+
export type DataAttributes = Record<`data-${string}`, string | undefined>;
|
|
35
|
+
export type HTMLProps<T extends HTMLElement = HTMLElement> = JSX.HTMLAttributes<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.soui-stack{display:flex;flex-direction:column}.soui-stack--gap-1{gap:var(--soui-space-1)}.soui-stack--gap-2{gap:var(--soui-space-2)}.soui-stack--gap-3{gap:var(--soui-space-3)}.soui-stack--gap-4{gap:var(--soui-space-4)}.soui-stack--gap-5{gap:var(--soui-space-5)}.soui-stack--gap-6{gap:var(--soui-space-6)}.soui-stack--align-start{align-items:flex-start}.soui-stack--align-center{align-items:center}.soui-stack--align-end{align-items:flex-end}.soui-stack--align-stretch{align-items:stretch}.soui-hstack{display:flex;flex-direction:row}.soui-hstack--wrap{flex-wrap:wrap}.soui-hstack--gap-1{gap:var(--soui-space-1)}.soui-hstack--gap-2{gap:var(--soui-space-2)}.soui-hstack--gap-3{gap:var(--soui-space-3)}.soui-hstack--gap-4{gap:var(--soui-space-4)}.soui-hstack--gap-5{gap:var(--soui-space-5)}.soui-hstack--gap-6{gap:var(--soui-space-6)}.soui-hstack--align-start{align-items:flex-start}.soui-hstack--align-center{align-items:center}.soui-hstack--align-end{align-items:flex-end}.soui-hstack--align-stretch{align-items:stretch}.soui-divider{border:none;margin:0}.soui-divider--horizontal{width:100%;height:1px;background-color:var(--soui-border)}.soui-divider--vertical{width:1px;align-self:stretch;background-color:var(--soui-border)}.soui-spacer{flex:1}.soui-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--soui-space-2);border:1px solid transparent;border-radius:var(--soui-radius);font-family:inherit;font-weight:500;line-height:var(--soui-line-height);cursor:pointer;transition:background-color .15s,border-color .15s,color .15s;white-space:nowrap;-webkit-user-select:none;user-select:none}.soui-button:disabled{opacity:.5;cursor:not-allowed}.soui-button--sm{height:var(--soui-control-height-sm);padding:0 var(--soui-space-3);font-size:var(--soui-font-size-sm)}.soui-button--md{height:var(--soui-control-height-md);padding:0 var(--soui-space-4);font-size:var(--soui-font-size-md)}.soui-button--lg{height:var(--soui-control-height-lg);padding:0 var(--soui-space-5);font-size:var(--soui-font-size-lg)}.soui-button--primary{background-color:var(--soui-color-primary-base);color:var(--soui-color-primary-fg)}.soui-button--primary:hover:not(:disabled){background-color:var(--soui-color-primary-hover)}.soui-button--primary:active:not(:disabled){background-color:var(--soui-color-primary-active)}.soui-button--neutral{background-color:transparent;color:var(--soui-text);border-color:var(--soui-color-neutral-border)}.soui-button--neutral:hover:not(:disabled){background-color:var(--soui-color-neutral-subtle)}.soui-button--neutral:active:not(:disabled){background-color:var(--soui-color-neutral-border)}.soui-button--danger{background-color:var(--soui-color-danger-base);color:var(--soui-color-danger-fg)}.soui-button--danger:hover:not(:disabled){background-color:var(--soui-color-danger-hover)}.soui-button--danger:active:not(:disabled){background-color:var(--soui-color-danger-active)}.soui-button--loading{position:relative;color:transparent;pointer-events:none}.soui-button__spinner{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center}.soui-button__spinner:after{content:"";width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:soui-button-spin .6s linear infinite}@keyframes soui-button-spin{to{transform:rotate(360deg)}}.soui-button--loading.soui-button--primary .soui-button__spinner,.soui-button--loading.soui-button--danger .soui-button__spinner{color:var(--soui-color-primary-fg)}.soui-button--loading.soui-button--neutral .soui-button__spinner{color:var(--soui-text)}.soui-button__icon{display:inline-flex;align-items:center;flex-shrink:0}.soui-icon-button{display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;border-radius:var(--soui-radius);font-family:inherit;cursor:pointer;transition:background-color .15s,border-color .15s,color .15s;-webkit-user-select:none;user-select:none;padding:0}.soui-icon-button:disabled{opacity:.5;cursor:not-allowed}.soui-icon-button--sm{width:var(--soui-control-height-sm);height:var(--soui-control-height-sm);font-size:var(--soui-font-size-sm)}.soui-icon-button--md{width:var(--soui-control-height-md);height:var(--soui-control-height-md);font-size:var(--soui-font-size-md)}.soui-icon-button--lg{width:var(--soui-control-height-lg);height:var(--soui-control-height-lg);font-size:var(--soui-font-size-lg)}.soui-icon-button--primary{background-color:var(--soui-color-primary-base);color:var(--soui-color-primary-fg)}.soui-icon-button--primary:hover:not(:disabled){background-color:var(--soui-color-primary-hover)}.soui-icon-button--primary:active:not(:disabled){background-color:var(--soui-color-primary-active)}.soui-icon-button--neutral{background-color:transparent;color:var(--soui-text);border-color:var(--soui-color-neutral-border)}.soui-icon-button--neutral:hover:not(:disabled){background-color:var(--soui-color-neutral-subtle)}.soui-icon-button--neutral:active:not(:disabled){background-color:var(--soui-color-neutral-border)}.soui-icon-button--danger{background-color:var(--soui-color-danger-base);color:var(--soui-color-danger-fg)}.soui-icon-button--danger:hover:not(:disabled){background-color:var(--soui-color-danger-hover)}.soui-icon-button--danger:active:not(:disabled){background-color:var(--soui-color-danger-active)}.soui-badge{display:inline-flex;align-items:center;border-radius:var(--soui-radius);font-weight:500;line-height:1;white-space:nowrap}.soui-badge--sm{padding:var(--soui-space-1) var(--soui-space-2);font-size:var(--soui-font-size-sm)}.soui-badge--md{padding:var(--soui-space-1) var(--soui-space-3);font-size:var(--soui-font-size-md)}.soui-badge--primary{background-color:var(--soui-color-primary-subtle);color:var(--soui-color-primary-subtle-fg)}.soui-badge--neutral{background-color:var(--soui-color-neutral-subtle);color:var(--soui-color-neutral-subtle-fg)}.soui-badge--danger{background-color:var(--soui-color-danger-subtle);color:var(--soui-color-danger-subtle-fg)}.soui-badge--success{background-color:var(--soui-color-success-subtle);color:var(--soui-color-success-subtle-fg)}.soui-badge--warning{background-color:var(--soui-color-warning-subtle);color:var(--soui-color-warning-subtle-fg)}.soui-badge--info{background-color:var(--soui-color-info-subtle);color:var(--soui-color-info-subtle-fg)}.soui-tag{display:inline-flex;align-items:center;gap:var(--soui-space-1);border-radius:var(--soui-radius);font-weight:500;line-height:1;white-space:nowrap}.soui-tag--sm{padding:var(--soui-space-1) var(--soui-space-2);font-size:var(--soui-font-size-sm)}.soui-tag--md{padding:var(--soui-space-1) var(--soui-space-3);font-size:var(--soui-font-size-md)}.soui-tag--primary{background-color:var(--soui-color-primary-subtle);color:var(--soui-color-primary-subtle-fg)}.soui-tag--neutral{background-color:var(--soui-color-neutral-subtle);color:var(--soui-color-neutral-subtle-fg)}.soui-tag--danger{background-color:var(--soui-color-danger-subtle);color:var(--soui-color-danger-subtle-fg)}.soui-tag--success{background-color:var(--soui-color-success-subtle);color:var(--soui-color-success-subtle-fg)}.soui-tag--warning{background-color:var(--soui-color-warning-subtle);color:var(--soui-color-warning-subtle-fg)}.soui-tag--info{background-color:var(--soui-color-info-subtle);color:var(--soui-color-info-subtle-fg)}.soui-tag__remove{display:inline-flex;align-items:center;justify-content:center;width:1em;height:1em;padding:0;border:none;background:none;color:inherit;cursor:pointer;border-radius:2px;opacity:.7;transition:opacity .15s;font-size:inherit;line-height:1}.soui-tag__remove:hover{opacity:1}.soui-form-field{display:flex;flex-direction:column;gap:var(--soui-space-1)}.soui-form-field__label{font-size:var(--soui-font-size-sm);font-weight:500;color:var(--soui-text);line-height:var(--soui-line-height)}.soui-form-field__required{color:var(--soui-color-danger-base);margin-left:var(--soui-space-1)}.soui-form-field__hint{font-size:var(--soui-font-size-sm);color:var(--soui-text-muted);margin:0;line-height:var(--soui-line-height)}.soui-form-field__error{font-size:var(--soui-font-size-sm);color:var(--soui-color-danger-base);margin:0;line-height:var(--soui-line-height)}.soui-text-field__input{width:100%;border:1px solid var(--soui-border);border-radius:var(--soui-radius);background-color:var(--soui-bg);color:var(--soui-text);font-family:inherit;line-height:var(--soui-line-height);transition:border-color .15s,box-shadow .15s;box-sizing:border-box}.soui-text-field__input::placeholder{color:var(--soui-text-muted)}.soui-text-field__input:focus{outline:none;border-color:var(--soui-ring);box-shadow:0 0 0 1px var(--soui-ring)}.soui-text-field__input:disabled{opacity:.5;cursor:not-allowed}.soui-text-field__input[aria-invalid=true]{border-color:var(--soui-color-danger-base)}.soui-text-field__input[aria-invalid=true]:focus{border-color:var(--soui-color-danger-base);box-shadow:0 0 0 1px var(--soui-color-danger-base)}.soui-text-field__input--sm{height:var(--soui-control-height-sm);padding:0 var(--soui-space-2);font-size:var(--soui-font-size-sm)}.soui-text-field__input--md{height:var(--soui-control-height-md);padding:0 var(--soui-space-3);font-size:var(--soui-font-size-md)}.soui-text-field__input--lg{height:var(--soui-control-height-lg);padding:0 var(--soui-space-4);font-size:var(--soui-font-size-lg)}.soui-textarea__input{width:100%;border:1px solid var(--soui-border);border-radius:var(--soui-radius);background-color:var(--soui-bg);color:var(--soui-text);font-family:inherit;font-size:var(--soui-font-size-md);line-height:var(--soui-line-height);padding:var(--soui-space-2) var(--soui-space-3);resize:vertical;transition:border-color .15s,box-shadow .15s;box-sizing:border-box}.soui-textarea__input::placeholder{color:var(--soui-text-muted)}.soui-textarea__input:focus{outline:none;border-color:var(--soui-ring);box-shadow:0 0 0 1px var(--soui-ring)}.soui-textarea__input:disabled{opacity:.5;cursor:not-allowed}.soui-textarea__input[aria-invalid=true]{border-color:var(--soui-color-danger-base)}.soui-textarea__input[aria-invalid=true]:focus{border-color:var(--soui-color-danger-base);box-shadow:0 0 0 1px var(--soui-color-danger-base)}.soui-number-input{display:inline-flex;align-items:center;border:1px solid var(--soui-border);border-radius:var(--soui-radius);background-color:var(--soui-bg);overflow:hidden;transition:border-color .15s,box-shadow .15s;width:100%}.soui-number-input:focus-within{border-color:var(--soui-ring);box-shadow:0 0 0 1px var(--soui-ring)}.soui-number-input:has([aria-invalid=true]){border-color:var(--soui-color-danger-base)}.soui-number-input:has([aria-invalid=true]):focus-within{border-color:var(--soui-color-danger-base);box-shadow:0 0 0 1px var(--soui-color-danger-base)}.soui-number-input__input{flex:1;min-width:0;border:none;background:transparent;color:var(--soui-text);font-family:inherit;text-align:center;line-height:var(--soui-line-height);-moz-appearance:textfield;box-sizing:border-box}.soui-number-input__input::-webkit-inner-spin-button,.soui-number-input__input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.soui-number-input__input:focus{outline:none}.soui-number-input__input:disabled{opacity:.5;cursor:not-allowed}.soui-number-input__button{display:inline-flex;align-items:center;justify-content:center;border:none;background-color:var(--soui-color-neutral-subtle);color:var(--soui-text);font-family:inherit;font-weight:600;cursor:pointer;flex-shrink:0;-webkit-user-select:none;user-select:none;transition:background-color .15s}.soui-number-input__button:hover:not(:disabled){background-color:var(--soui-color-neutral-border)}.soui-number-input__button:active:not(:disabled){background-color:var(--soui-color-neutral-active);color:var(--soui-color-neutral-fg)}.soui-number-input__button:disabled{opacity:.5;cursor:not-allowed}.soui-number-input--sm{height:var(--soui-control-height-sm)}.soui-number-input--sm .soui-number-input__input{font-size:var(--soui-font-size-sm)}.soui-number-input--sm .soui-number-input__button{width:var(--soui-control-height-sm);font-size:var(--soui-font-size-sm)}.soui-number-input--md{height:var(--soui-control-height-md)}.soui-number-input--md .soui-number-input__input{font-size:var(--soui-font-size-md)}.soui-number-input--md .soui-number-input__button{width:var(--soui-control-height-md);font-size:var(--soui-font-size-md)}.soui-number-input--lg{height:var(--soui-control-height-lg)}.soui-number-input--lg .soui-number-input__input{font-size:var(--soui-font-size-lg)}.soui-number-input--lg .soui-number-input__button{width:var(--soui-control-height-lg);font-size:var(--soui-font-size-lg)}.soui-select__wrapper{position:relative;width:100%}.soui-select__input{width:100%;border:1px solid var(--soui-border);border-radius:var(--soui-radius);background-color:var(--soui-bg);color:var(--soui-text);font-family:inherit;line-height:var(--soui-line-height);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;transition:border-color .15s,box-shadow .15s;box-sizing:border-box}.soui-select__arrow{position:absolute;right:var(--soui-space-3);top:50%;transform:translateY(-50%);width:12px;height:12px;pointer-events:none;color:var(--soui-text-muted)}.soui-select__input:focus{outline:none;border-color:var(--soui-ring);box-shadow:0 0 0 1px var(--soui-ring)}.soui-select__input:disabled{opacity:.5;cursor:not-allowed}.soui-select__input[aria-invalid=true]{border-color:var(--soui-color-danger-base)}.soui-select__input[aria-invalid=true]:focus{border-color:var(--soui-color-danger-base);box-shadow:0 0 0 1px var(--soui-color-danger-base)}.soui-select__input--sm{height:var(--soui-control-height-sm);padding:0 var(--soui-space-5) 0 var(--soui-space-2);font-size:var(--soui-font-size-sm)}.soui-select__input--md{height:var(--soui-control-height-md);padding:0 var(--soui-space-5) 0 var(--soui-space-3);font-size:var(--soui-font-size-md)}.soui-select__input--lg{height:var(--soui-control-height-lg);padding:0 var(--soui-space-6) 0 var(--soui-space-4);font-size:var(--soui-font-size-lg)}.soui-checkbox{display:inline-flex;align-items:center;gap:var(--soui-space-2);cursor:pointer;-webkit-user-select:none;user-select:none;line-height:var(--soui-line-height)}.soui-checkbox--disabled{opacity:.5;cursor:not-allowed}.soui-checkbox__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.soui-checkbox__indicator{display:inline-flex;align-items:center;justify-content:center;border:2px solid var(--soui-border);border-radius:calc(var(--soui-radius) / 2);background-color:var(--soui-bg);color:var(--soui-color-primary-fg);flex-shrink:0;transition:background-color .15s,border-color .15s}.soui-checkbox__input:checked+.soui-checkbox__indicator,.soui-checkbox__input:indeterminate+.soui-checkbox__indicator{background-color:var(--soui-color-primary-base);border-color:var(--soui-color-primary-base)}.soui-checkbox__input:focus-visible+.soui-checkbox__indicator{outline:2px solid var(--soui-ring);outline-offset:2px}.soui-checkbox__icon{width:100%;height:100%}.soui-checkbox__label{color:var(--soui-text)}.soui-checkbox--sm .soui-checkbox__indicator{width:14px;height:14px}.soui-checkbox--sm .soui-checkbox__label{font-size:var(--soui-font-size-sm)}.soui-checkbox--md .soui-checkbox__indicator{width:18px;height:18px}.soui-checkbox--md .soui-checkbox__label{font-size:var(--soui-font-size-md)}.soui-checkbox-group{border:none;padding:0;margin:0}.soui-checkbox-group__label{font-size:var(--soui-font-size-sm);font-weight:500;color:var(--soui-text);line-height:var(--soui-line-height);margin-bottom:var(--soui-space-2)}.soui-checkbox-group__items{display:flex;flex-direction:column;gap:var(--soui-space-2)}.soui-radio-group{border:none;padding:0;margin:0}.soui-radio-group__label{font-size:var(--soui-font-size-sm);font-weight:500;color:var(--soui-text);line-height:var(--soui-line-height);margin-bottom:var(--soui-space-2)}.soui-radio-group__items{display:flex;flex-direction:column;gap:var(--soui-space-2)}.soui-radio-button{display:inline-flex;align-items:center;gap:var(--soui-space-2);cursor:pointer;-webkit-user-select:none;user-select:none;line-height:var(--soui-line-height)}.soui-radio-button--disabled{opacity:.5;cursor:not-allowed}.soui-radio-button__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.soui-radio-button__indicator{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border:2px solid var(--soui-border);border-radius:50%;background-color:var(--soui-bg);flex-shrink:0;transition:border-color .15s}.soui-radio-button__input:checked+.soui-radio-button__indicator{border-color:var(--soui-color-primary-base)}.soui-radio-button__input:focus-visible+.soui-radio-button__indicator{outline:2px solid var(--soui-ring);outline-offset:2px}.soui-radio-button__dot{width:8px;height:8px;border-radius:50%;background-color:transparent;transition:background-color .15s}.soui-radio-button__input:checked+.soui-radio-button__indicator .soui-radio-button__dot{background-color:var(--soui-color-primary-base)}.soui-radio-button__label{color:var(--soui-text);font-size:var(--soui-font-size-md)}.soui-switch{display:inline-flex;align-items:center;gap:var(--soui-space-2);cursor:pointer;-webkit-user-select:none;user-select:none;line-height:var(--soui-line-height)}.soui-switch--disabled{opacity:.5;cursor:not-allowed}.soui-switch__track{position:relative;display:inline-flex;align-items:center;border:none;border-radius:9999px;background-color:var(--soui-color-neutral-border);cursor:inherit;padding:2px;flex-shrink:0;transition:background-color .2s}.soui-switch__track[aria-checked=true]{background-color:var(--soui-color-primary-base)}.soui-switch__track:focus-visible{outline:2px solid var(--soui-ring);outline-offset:2px}.soui-switch__track:disabled{cursor:not-allowed}.soui-switch__thumb{display:block;border-radius:50%;background-color:#fff;transition:transform .2s;flex-shrink:0}.soui-switch__label{color:var(--soui-text)}.soui-switch--sm .soui-switch__track{width:28px;height:16px}.soui-switch--sm .soui-switch__thumb{width:12px;height:12px}.soui-switch--sm .soui-switch__track[aria-checked=true] .soui-switch__thumb{transform:translate(12px)}.soui-switch--sm .soui-switch__label{font-size:var(--soui-font-size-sm)}.soui-switch--md .soui-switch__track{width:40px;height:22px}.soui-switch--md .soui-switch__thumb{width:18px;height:18px}.soui-switch--md .soui-switch__track[aria-checked=true] .soui-switch__thumb{transform:translate(18px)}.soui-switch--md .soui-switch__label{font-size:var(--soui-font-size-md)}.soui-card{background-color:var(--soui-bg);border:1px solid var(--soui-border);border-radius:var(--soui-radius);overflow:hidden}.soui-card__header{padding:var(--soui-space-4) var(--soui-space-5);border-bottom:1px solid var(--soui-border);font-weight:600;font-size:var(--soui-font-size-lg);color:var(--soui-text)}.soui-card__body{padding:var(--soui-space-4) var(--soui-space-5);color:var(--soui-text)}.soui-card__footer{padding:var(--soui-space-3) var(--soui-space-5);border-top:1px solid var(--soui-border);background-color:var(--soui-bg-subtle)}.soui-description-list{margin:0;padding:0;color:var(--soui-text)}.soui-description-list__term{font-weight:600;font-size:var(--soui-font-size-sm);color:var(--soui-text-muted);margin-bottom:var(--soui-space-1)}.soui-description-list__detail{margin:0 0 var(--soui-space-4) 0;font-size:var(--soui-font-size-md)}.soui-description-list--2col{display:grid;grid-template-columns:1fr 1fr;gap:0 var(--soui-space-6)}.soui-description-list--2col .soui-description-list__detail{margin-bottom:var(--soui-space-4)}.soui-skeleton{background-color:var(--soui-border);border-radius:var(--soui-radius);animation:soui-skeleton-pulse 1.5s ease-in-out infinite}.soui-skeleton--text{width:100%;height:1em;border-radius:var(--soui-radius)}.soui-skeleton--circle{width:40px;height:40px;border-radius:50%}.soui-skeleton--rect{width:100%;height:100px}@keyframes soui-skeleton-pulse{0%,to{opacity:1}50%{opacity:.4}}.soui-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--soui-space-6);text-align:center}.soui-empty-state__icon{margin-bottom:var(--soui-space-4);color:var(--soui-text-muted);font-size:48px;line-height:1}.soui-empty-state__title{margin:0 0 var(--soui-space-2) 0;font-size:var(--soui-font-size-lg);font-weight:600;color:var(--soui-text)}.soui-empty-state__description{margin:0 0 var(--soui-space-4) 0;font-size:var(--soui-font-size-md);color:var(--soui-text-muted);max-width:360px}.soui-empty-state__action{margin-top:var(--soui-space-2)}.soui-table-wrapper{overflow-x:auto;border:1px solid var(--soui-border);border-radius:var(--soui-radius)}.soui-table{width:100%;border-collapse:collapse;font-size:var(--soui-font-size-md);color:var(--soui-text)}.soui-table__row--header{background-color:var(--soui-bg-subtle)}.soui-table__header{font-weight:600;text-align:start;white-space:nowrap}.soui-table__cell{padding:var(--soui-space-3) var(--soui-space-4);border-bottom:1px solid var(--soui-border)}.soui-table__cell--start{text-align:start}.soui-table__cell--center{text-align:center}.soui-table__cell--end{text-align:end}.soui-table__cell--checkbox{width:40px;text-align:center}.soui-table__row:last-child .soui-table__cell{border-bottom:none}.soui-table__row--selected{background-color:var(--soui-color-primary-subtle)}.soui-table__row:hover:not(.soui-table__row--header){background-color:var(--soui-bg-subtle)}.soui-table__row--selected:hover{background-color:var(--soui-color-primary-subtle)}.soui-table__sort-button{display:inline-flex;align-items:center;gap:var(--soui-space-1);padding:0;border:none;background:none;font:inherit;font-weight:600;color:inherit;cursor:pointer}.soui-table__sort-icon{display:inline-flex;align-items:center;margin-left:var(--soui-space-1)}.soui-table__sort-icon:after{content:"↕";font-size:1em;opacity:.35}.soui-table__sort-icon--asc:after{content:"▲";font-size:.7em;opacity:1}.soui-table__sort-icon--desc:after{content:"▼";font-size:.7em;opacity:1}.soui-dialog-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;background-color:#00000080;z-index:1000}.soui-dialog{background-color:var(--soui-bg);border:1px solid var(--soui-border);border-radius:var(--soui-radius);box-shadow:0 8px 32px #0003;max-height:85vh;display:flex;flex-direction:column;overflow:hidden}.soui-dialog--sm{width:400px;max-width:90vw}.soui-dialog--md{width:560px;max-width:90vw}.soui-dialog--lg{width:720px;max-width:90vw}.soui-dialog__header{padding:var(--soui-space-4) var(--soui-space-5);border-bottom:1px solid var(--soui-border);font-weight:600;font-size:var(--soui-font-size-lg);color:var(--soui-text);flex-shrink:0}.soui-dialog__body{padding:var(--soui-space-4) var(--soui-space-5);overflow-y:auto;flex:1;color:var(--soui-text)}.soui-dialog__footer{padding:var(--soui-space-3) var(--soui-space-5);border-top:1px solid var(--soui-border);display:flex;justify-content:flex-end;gap:var(--soui-space-2);flex-shrink:0}.soui-drawer-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background-color:#00000080;z-index:1000}.soui-drawer{position:fixed;top:0;bottom:0;background-color:var(--soui-bg);border:1px solid var(--soui-border);box-shadow:0 8px 32px #0003;display:flex;flex-direction:column;overflow-y:auto}.soui-drawer--left{left:0}.soui-drawer--right{right:0}.soui-drawer--sm{width:280px;max-width:80vw}.soui-drawer--md{width:400px;max-width:80vw}.soui-drawer--lg{width:560px;max-width:80vw}.soui-alert{display:flex;align-items:flex-start;gap:var(--soui-space-3);padding:var(--soui-space-3) var(--soui-space-4);border:1px solid transparent;border-radius:var(--soui-radius);font-size:var(--soui-font-size-md);line-height:var(--soui-line-height)}.soui-alert__content{flex:1}.soui-alert__dismiss{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;background:none;font-size:18px;line-height:1;cursor:pointer;border-radius:var(--soui-radius);opacity:.7;color:inherit}.soui-alert__dismiss:hover{opacity:1}.soui-alert--info{background-color:var(--soui-color-info-subtle);color:var(--soui-color-info-subtle-fg);border-color:var(--soui-color-info-border)}.soui-alert--success{background-color:var(--soui-color-success-subtle);color:var(--soui-color-success-subtle-fg);border-color:var(--soui-color-success-border)}.soui-alert--warning{background-color:var(--soui-color-warning-subtle);color:var(--soui-color-warning-subtle-fg);border-color:var(--soui-color-warning-border)}.soui-alert--danger{background-color:var(--soui-color-danger-subtle);color:var(--soui-color-danger-subtle-fg);border-color:var(--soui-color-danger-border)}.soui-toast-container{position:fixed;z-index:1100;display:flex;flex-direction:column;gap:var(--soui-space-2);padding:var(--soui-space-4);pointer-events:none}.soui-toast-container--top-right{top:0;right:0}.soui-toast-container--top-center{top:0;left:50%;transform:translate(-50%)}.soui-toast-container--bottom-right{bottom:0;right:0}.soui-toast-container--bottom-center{bottom:0;left:50%;transform:translate(-50%)}.soui-toast{display:flex;align-items:center;gap:var(--soui-space-3);padding:var(--soui-space-3) var(--soui-space-4);border-radius:var(--soui-radius);font-size:var(--soui-font-size-md);box-shadow:0 4px 16px #00000026;min-width:280px;max-width:420px;pointer-events:auto;animation:soui-toast-enter .2s ease-out}.soui-toast__message{flex:1}.soui-toast__dismiss{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;background:none;font-size:18px;line-height:1;cursor:pointer;border-radius:var(--soui-radius);opacity:.7;color:inherit}.soui-toast__dismiss:hover{opacity:1}.soui-toast--info{background-color:var(--soui-color-info-subtle);color:var(--soui-color-info-subtle-fg);border-left:4px solid var(--soui-color-info-base)}.soui-toast--success{background-color:var(--soui-color-success-subtle);color:var(--soui-color-success-subtle-fg);border-left:4px solid var(--soui-color-success-base)}.soui-toast--warning{background-color:var(--soui-color-warning-subtle);color:var(--soui-color-warning-subtle-fg);border-left:4px solid var(--soui-color-warning-base)}.soui-toast--danger{background-color:var(--soui-color-danger-subtle);color:var(--soui-color-danger-subtle-fg);border-left:4px solid var(--soui-color-danger-base)}@keyframes soui-toast-enter{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.soui-progress{width:100%;background-color:var(--soui-border);border-radius:var(--soui-radius);overflow:hidden}.soui-progress--sm{height:4px}.soui-progress--md{height:8px}.soui-progress__bar{height:100%;border-radius:var(--soui-radius);transition:width .3s ease}.soui-progress--info .soui-progress__bar{background-color:var(--soui-color-info-base)}.soui-progress--success .soui-progress__bar{background-color:var(--soui-color-success-base)}.soui-progress--warning .soui-progress__bar{background-color:var(--soui-color-warning-base)}.soui-progress--danger .soui-progress__bar{background-color:var(--soui-color-danger-base)}.soui-spinner{display:inline-block;border-style:solid;border-radius:50%;border-right-color:transparent;animation:soui-spinner-spin .6s linear infinite}.soui-spinner--sm{width:16px;height:16px;border-width:2px}.soui-spinner--md{width:24px;height:24px;border-width:2px}.soui-spinner--lg{width:36px;height:36px;border-width:3px}.soui-spinner--primary{border-color:var(--soui-color-primary-base);border-right-color:transparent}.soui-spinner--neutral{border-color:var(--soui-color-neutral-base);border-right-color:transparent}@keyframes soui-spinner-spin{to{transform:rotate(360deg)}}.soui-tabs{display:flex;flex-direction:column}.soui-tab-list{display:flex;border-bottom:1px solid var(--soui-border);gap:0}.soui-tab{display:inline-flex;align-items:center;justify-content:center;padding:var(--soui-space-2) var(--soui-space-4);border:none;border-bottom:2px solid transparent;background:none;font:inherit;font-size:var(--soui-font-size-md);font-weight:500;color:var(--soui-text-muted);cursor:pointer;transition:color .15s,border-color .15s;white-space:nowrap;margin-bottom:-1px}.soui-tab:hover:not(:disabled){color:var(--soui-text)}.soui-tab--active{color:var(--soui-color-primary-base);border-bottom-color:var(--soui-color-primary-base)}.soui-tab:disabled{opacity:.5;cursor:not-allowed}.soui-tab-panel{padding:var(--soui-space-4) 0;color:var(--soui-text)}.soui-breadcrumb__list{display:flex;align-items:center;list-style:none;margin:0;padding:0;gap:0;font-size:var(--soui-font-size-md)}.soui-breadcrumb__item{display:inline-flex;align-items:center;color:var(--soui-text-muted)}.soui-breadcrumb__item+.soui-breadcrumb__item:before{content:"/";margin:0 var(--soui-space-2);color:var(--soui-text-muted);opacity:.5}.soui-breadcrumb__item a{color:var(--soui-color-primary-base);text-decoration:none}.soui-breadcrumb__item a:hover{text-decoration:underline}.soui-breadcrumb__item--current{color:var(--soui-text);font-weight:500}.soui-pagination{display:inline-flex;align-items:center;gap:var(--soui-space-2)}.soui-pagination__button{display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--soui-color-neutral-border);border-radius:var(--soui-radius);background:transparent;color:var(--soui-text);font:inherit;cursor:pointer;transition:background-color .15s;white-space:nowrap}.soui-pagination__button:hover:not(:disabled){background-color:var(--soui-color-neutral-subtle)}.soui-pagination__button:disabled{opacity:.5;cursor:not-allowed}.soui-pagination__info{font-size:var(--soui-font-size-md);color:var(--soui-text);min-width:60px;text-align:center}.soui-pagination--sm .soui-pagination__button{height:var(--soui-control-height-sm);padding:0 var(--soui-space-3);font-size:var(--soui-font-size-sm)}.soui-pagination--sm .soui-pagination__info{font-size:var(--soui-font-size-sm)}.soui-pagination--md .soui-pagination__button{height:var(--soui-control-height-md);padding:0 var(--soui-space-4);font-size:var(--soui-font-size-md)}.soui-visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { SouiProvider, useSoui, createTheme, } from "./core";
|
|
2
|
+
export type { SouiProviderProps, SouiContextValue, Density, Size, Variant, ButtonVariant, FeedbackVariant, CommonProps, InteractiveProps, VariantProps, ColorDefinition, DateFormatConfig, ThemeConfig, } from "./core";
|
|
3
|
+
export { createDisclosure, createFocusTrap, createToggle, createToast, createPagination, } from "./primitives";
|
|
4
|
+
export type { DisclosureOptions, DisclosureReturn, FocusTrapOptions, ToggleOptions, ToggleReturn, Toast, ToastOptions, ToastInput, ToastReturn, PaginationOptions, PaginationReturn, } from "./primitives";
|
|
5
|
+
export { Stack, HStack, Divider, Spacer } from "./components/layout";
|
|
6
|
+
export type { StackProps, HStackProps, DividerProps } from "./components/layout";
|
|
7
|
+
export { Button, IconButton, Badge, Tag, Tooltip } from "./components/general";
|
|
8
|
+
export type { ButtonProps, IconButtonProps, BadgeProps, TagProps, TooltipProps, } from "./components/general";
|
|
9
|
+
export { FormField, TextField, TextArea, NumberInput, Select, Checkbox, CheckboxGroup, RadioGroup, RadioButton, Switch, } from "./components/form";
|
|
10
|
+
export type { FormFieldProps, TextFieldProps, TextAreaProps, NumberInputProps, SelectProps, CheckboxProps, CheckboxGroupProps, RadioGroupProps, RadioButtonProps, SwitchProps, } from "./components/form";
|
|
11
|
+
export { Card, CardHeader, CardBody, CardFooter, DescriptionList, Skeleton, EmptyState, Table, } from "./components/data";
|
|
12
|
+
export type { CardProps, DescriptionListProps, SkeletonProps, EmptyStateProps, TableProps, Column, } from "./components/data";
|
|
13
|
+
export { Dialog, DialogHeader, DialogBody, DialogFooter, Drawer, Alert, ToastContainer, useToast, Progress, Spinner, } from "./components/feedback";
|
|
14
|
+
export type { DialogProps, DrawerProps, AlertProps, ToastContainerProps, ProgressProps, SpinnerProps, } from "./components/feedback";
|
|
15
|
+
export { Tabs, TabList, Tab, TabPanel, Breadcrumb, BreadcrumbItem, Pagination, Menu, } from "./components/navigation";
|
|
16
|
+
export type { TabsProps, BreadcrumbProps, BreadcrumbItemProps, PaginationProps, MenuProps, } from "./components/navigation";
|
|
17
|
+
export { VisuallyHidden, Popover } from "./components/utility";
|
|
18
|
+
export type { VisuallyHiddenProps, PopoverProps, } from "./components/utility";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { add } from "./commands/add.js";
|
|
3
|
+
import { init } from "./commands/init.js";
|
|
4
|
+
import { install } from "./commands/install.js";
|
|
5
|
+
import { list } from "./commands/list.js";
|
|
6
|
+
import { remove } from "./commands/remove.js";
|
|
7
|
+
import { CONFIG_FILENAME, PROJECT_NAME } from "./config.js";
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
const command = args[0];
|
|
10
|
+
const rest = args.slice(1);
|
|
11
|
+
const cwd = process.cwd();
|
|
12
|
+
switch (command) {
|
|
13
|
+
case "init":
|
|
14
|
+
await init(cwd);
|
|
15
|
+
break;
|
|
16
|
+
case "install":
|
|
17
|
+
await install(cwd);
|
|
18
|
+
break;
|
|
19
|
+
case "add":
|
|
20
|
+
if (rest.length === 0) {
|
|
21
|
+
console.error(`Usage: npx ${PROJECT_NAME} add <component...>`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
add(cwd, rest);
|
|
25
|
+
break;
|
|
26
|
+
case "remove":
|
|
27
|
+
if (rest.length === 0) {
|
|
28
|
+
console.error(`Usage: npx ${PROJECT_NAME} remove <component...>`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
remove(cwd, rest);
|
|
32
|
+
break;
|
|
33
|
+
case "list": {
|
|
34
|
+
const filter = args.includes("--installed")
|
|
35
|
+
? "installed"
|
|
36
|
+
: args.includes("--not-installed")
|
|
37
|
+
? "not-installed"
|
|
38
|
+
: "all";
|
|
39
|
+
list(cwd, filter);
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
default:
|
|
43
|
+
console.log(`${PROJECT_NAME} - SolidJS Opinionated UI`);
|
|
44
|
+
console.log("");
|
|
45
|
+
console.log("Commands:");
|
|
46
|
+
console.log(` init Create ${CONFIG_FILENAME}`);
|
|
47
|
+
console.log(" install Install components and CSS");
|
|
48
|
+
console.log(" add <component...> Add components to config");
|
|
49
|
+
console.log(" remove <component...> Remove components from config");
|
|
50
|
+
console.log(" list [--installed] List available components");
|
|
51
|
+
console.log(" [--not-installed]");
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Accessor } from "solid-js";
|
|
2
|
+
export interface DisclosureOptions {
|
|
3
|
+
/** Initial open state (uncontrolled) */
|
|
4
|
+
defaultOpen?: boolean;
|
|
5
|
+
/** Controlled open state */
|
|
6
|
+
isOpen?: Accessor<boolean>;
|
|
7
|
+
/** Called when open state changes */
|
|
8
|
+
onOpenChange?: (open: boolean) => void;
|
|
9
|
+
/** ID prefix for aria linking */
|
|
10
|
+
id?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface DisclosureReturn {
|
|
13
|
+
isOpen: Accessor<boolean>;
|
|
14
|
+
open: () => void;
|
|
15
|
+
close: () => void;
|
|
16
|
+
toggle: () => void;
|
|
17
|
+
triggerProps: {
|
|
18
|
+
"aria-expanded": Accessor<boolean>;
|
|
19
|
+
"aria-controls": string;
|
|
20
|
+
onClick: () => void;
|
|
21
|
+
};
|
|
22
|
+
contentProps: {
|
|
23
|
+
id: string;
|
|
24
|
+
role: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export declare function createDisclosure(options?: DisclosureOptions): DisclosureReturn;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Accessor } from "solid-js";
|
|
2
|
+
export interface FocusTrapOptions {
|
|
3
|
+
/** Reactive accessor for the container element */
|
|
4
|
+
container: Accessor<HTMLElement | undefined>;
|
|
5
|
+
/** Whether the trap is active */
|
|
6
|
+
isActive: Accessor<boolean>;
|
|
7
|
+
/** Called when Escape is pressed */
|
|
8
|
+
onClose?: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function createFocusTrap(options: FocusTrapOptions): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Accessor } from "solid-js";
|
|
2
|
+
export interface PaginationOptions {
|
|
3
|
+
/** Total number of items */
|
|
4
|
+
totalItems: Accessor<number>;
|
|
5
|
+
/** Number of items per page (default: 10) */
|
|
6
|
+
pageSize?: Accessor<number>;
|
|
7
|
+
/** Initial page (1-based, default: 1) */
|
|
8
|
+
initialPage?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface PaginationReturn {
|
|
11
|
+
page: Accessor<number>;
|
|
12
|
+
totalPages: Accessor<number>;
|
|
13
|
+
setPage: (page: number) => void;
|
|
14
|
+
next: () => void;
|
|
15
|
+
prev: () => void;
|
|
16
|
+
canNext: Accessor<boolean>;
|
|
17
|
+
canPrev: Accessor<boolean>;
|
|
18
|
+
/** 0-based start index for current page */
|
|
19
|
+
startIndex: Accessor<number>;
|
|
20
|
+
/** 0-based exclusive end index for current page */
|
|
21
|
+
endIndex: Accessor<number>;
|
|
22
|
+
}
|
|
23
|
+
export declare function createPagination(options: PaginationOptions): PaginationReturn;
|