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.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/dist/commands/add.js +31 -0
  4. package/dist/commands/init.js +56 -0
  5. package/dist/commands/install.js +110 -0
  6. package/dist/commands/list.js +54 -0
  7. package/dist/commands/remove.js +25 -0
  8. package/dist/components/data/Card.d.ts +22 -0
  9. package/dist/components/data/DescriptionList.d.ts +11 -0
  10. package/dist/components/data/EmptyState.d.ts +10 -0
  11. package/dist/components/data/Skeleton.d.ts +8 -0
  12. package/dist/components/data/Table.d.ts +23 -0
  13. package/dist/components/data/index.d.ts +10 -0
  14. package/dist/components/feedback/Alert.d.ts +9 -0
  15. package/dist/components/feedback/Dialog.d.ts +25 -0
  16. package/dist/components/feedback/Drawer.d.ts +11 -0
  17. package/dist/components/feedback/Progress.d.ts +8 -0
  18. package/dist/components/feedback/Spinner.d.ts +7 -0
  19. package/dist/components/feedback/Toast.d.ts +10 -0
  20. package/dist/components/feedback/index.d.ts +12 -0
  21. package/dist/components/form/Checkbox.d.ts +14 -0
  22. package/dist/components/form/CheckboxGroup.d.ts +10 -0
  23. package/dist/components/form/CheckboxGroupContext.d.ts +6 -0
  24. package/dist/components/form/FormField.d.ts +11 -0
  25. package/dist/components/form/FormFieldContext.d.ts +8 -0
  26. package/dist/components/form/NumberInput.d.ts +15 -0
  27. package/dist/components/form/RadioButton.d.ts +10 -0
  28. package/dist/components/form/RadioGroup.d.ts +11 -0
  29. package/dist/components/form/RadioGroupContext.d.ts +7 -0
  30. package/dist/components/form/Select.d.ts +19 -0
  31. package/dist/components/form/Switch.d.ts +12 -0
  32. package/dist/components/form/TextArea.d.ts +15 -0
  33. package/dist/components/form/TextField.d.ts +14 -0
  34. package/dist/components/form/index.d.ts +26 -0
  35. package/dist/components/general/Badge.d.ts +9 -0
  36. package/dist/components/general/Button.d.ts +10 -0
  37. package/dist/components/general/IconButton.d.ts +8 -0
  38. package/dist/components/general/Tag.d.ts +10 -0
  39. package/dist/components/general/Tooltip.d.ts +6 -0
  40. package/dist/components/general/index.d.ts +10 -0
  41. package/dist/components/layout/Divider.d.ts +7 -0
  42. package/dist/components/layout/HStack.d.ts +10 -0
  43. package/dist/components/layout/Spacer.d.ts +3 -0
  44. package/dist/components/layout/Stack.d.ts +9 -0
  45. package/dist/components/layout/index.d.ts +7 -0
  46. package/dist/components/navigation/Breadcrumb.d.ts +14 -0
  47. package/dist/components/navigation/Menu.d.ts +7 -0
  48. package/dist/components/navigation/Pagination.d.ts +9 -0
  49. package/dist/components/navigation/Tabs.d.ts +27 -0
  50. package/dist/components/navigation/index.d.ts +8 -0
  51. package/dist/components/utility/Popover.d.ts +7 -0
  52. package/dist/components/utility/VisuallyHidden.d.ts +6 -0
  53. package/dist/components/utility/index.d.ts +4 -0
  54. package/dist/config.js +26 -0
  55. package/dist/core/SouiProvider.d.ts +7 -0
  56. package/dist/core/context.d.ts +6 -0
  57. package/dist/core/index.d.ts +6 -0
  58. package/dist/core/theme.d.ts +7 -0
  59. package/dist/core/types.d.ts +35 -0
  60. package/dist/core/utils.d.ts +2 -0
  61. package/dist/dev/App.d.ts +3 -0
  62. package/dist/dev/index.d.ts +1 -0
  63. package/dist/index.css +1 -0
  64. package/dist/index.d.ts +18 -0
  65. package/dist/index.js +53 -0
  66. package/dist/primitives/createDisclosure.d.ts +27 -0
  67. package/dist/primitives/createFocusTrap.d.ts +10 -0
  68. package/dist/primitives/createPagination.d.ts +23 -0
  69. package/dist/primitives/createToast.d.ts +23 -0
  70. package/dist/primitives/createToggle.d.ts +19 -0
  71. package/dist/primitives/index.d.ts +10 -0
  72. package/dist/registry.js +410 -0
  73. package/dist/rewrite-imports.js +42 -0
  74. 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,6 @@
1
+ import type { JSX } from "solid-js";
2
+ export interface TooltipProps {
3
+ content?: string;
4
+ children: JSX.Element;
5
+ }
6
+ export declare function Tooltip(props: TooltipProps): 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,3 @@
1
+ import type { JSX } from "solid-js";
2
+ import "./Spacer.css";
3
+ export declare function Spacer(props: 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;
@@ -0,0 +1,6 @@
1
+ import type { JSX } from "solid-js";
2
+ import "./VisuallyHidden.css";
3
+ export interface VisuallyHiddenProps {
4
+ children: JSX.Element;
5
+ }
6
+ export declare function VisuallyHidden(props: VisuallyHiddenProps): JSX.Element;
@@ -0,0 +1,4 @@
1
+ export { VisuallyHidden } from "./VisuallyHidden";
2
+ export type { VisuallyHiddenProps } from "./VisuallyHidden";
3
+ export { Popover } from "./Popover";
4
+ export type { PopoverProps } from "./Popover";
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,7 @@
1
+ import type { JSX } from "solid-js";
2
+ import type { ThemeConfig } from "./types";
3
+ export interface SouiProviderProps {
4
+ config?: ThemeConfig;
5
+ children: JSX.Element;
6
+ }
7
+ export declare function SouiProvider(props: SouiProviderProps): JSX.Element;
@@ -0,0 +1,6 @@
1
+ import type { DateFormatConfig } from "./types";
2
+ export interface SouiContextValue {
3
+ dateFormat: DateFormatConfig;
4
+ }
5
+ export declare const SouiContext: import("solid-js").Context<SouiContextValue>;
6
+ export declare function useSoui(): SouiContextValue;
@@ -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,7 @@
1
+ import type { ColorDefinition } from "./types";
2
+ interface ThemeResult {
3
+ cssText: string;
4
+ warnings: string[];
5
+ }
6
+ export declare function createTheme(colors: ColorDefinition[]): ThemeResult;
7
+ export {};
@@ -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,2 @@
1
+ /** Join class names, filtering out falsy values */
2
+ export declare function cls(...classes: (string | false | null | undefined)[]): string;
@@ -0,0 +1,3 @@
1
+ import "../core/tokens.css";
2
+ import "./catalog.css";
3
+ export declare function App(): import("solid-js").JSX.Element;
@@ -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}
@@ -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;