syntra-ui 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/avatar/Avatar.d.ts +22 -0
- package/dist/components/avatar/avatar.styles.d.ts +6 -0
- package/dist/components/avatar/index.d.ts +3 -0
- package/dist/components/badge/Badge.d.ts +14 -0
- package/dist/components/badge/badge.styles.d.ts +9 -0
- package/dist/components/badge/index.d.ts +3 -0
- package/dist/components/button/button.styles.d.ts +1 -1
- package/dist/components/checkbox/Checkbox.d.ts +18 -0
- package/dist/components/checkbox/checkbox.styles.d.ts +7 -0
- package/dist/components/checkbox/index.d.ts +3 -0
- package/dist/components/index.d.ts +21 -0
- package/dist/components/input/input.styles.d.ts +1 -1
- package/dist/components/modal/Modal.d.ts +44 -0
- package/dist/components/modal/index.d.ts +3 -0
- package/dist/components/modal/modal.styles.d.ts +6 -0
- package/dist/components/select/Select.d.ts +28 -0
- package/dist/components/select/index.d.ts +3 -0
- package/dist/components/select/select.styles.d.ts +8 -0
- package/dist/components/switch/Switch.d.ts +16 -0
- package/dist/components/switch/index.d.ts +3 -0
- package/dist/components/switch/switch.styles.d.ts +6 -0
- package/dist/components/tabs/Tabs.d.ts +38 -0
- package/dist/components/tabs/index.d.ts +3 -0
- package/dist/components/tabs/tabs.styles.d.ts +8 -0
- package/dist/components/textarea/Textarea.d.ts +15 -0
- package/dist/components/textarea/index.d.ts +3 -0
- package/dist/components/textarea/textarea.styles.d.ts +8 -0
- package/dist/components/toast/Toast.d.ts +11 -0
- package/dist/components/toast/Toaster.d.ts +10 -0
- package/dist/components/toast/index.d.ts +5 -0
- package/dist/components/toast/toast-manager.d.ts +35 -0
- package/dist/components/toast/toast.styles.d.ts +5 -0
- package/dist/components/tooltip/Tooltip.d.ts +15 -0
- package/dist/components/tooltip/index.d.ts +3 -0
- package/dist/components/tooltip/tooltip.styles.d.ts +4 -0
- package/dist/hooks/useClickOutside.d.ts +2 -0
- package/dist/hooks/useControllableState.d.ts +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/syntra-ui.cjs +959 -11
- package/dist/syntra-ui.mjs +2758 -520
- package/dist/utils/generate-id.d.ts +1 -0
- package/package.json +9 -2
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode, HTMLAttributes } from 'react';
|
|
2
|
+
import { AvatarSize } from './avatar.styles';
|
|
3
|
+
interface AvatarOwnProps {
|
|
4
|
+
src?: string | null;
|
|
5
|
+
alt?: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
size?: AvatarSize;
|
|
8
|
+
radius?: 'full' | 'md' | 'lg' | 'xl';
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
className?: string;
|
|
11
|
+
style?: CSSProperties;
|
|
12
|
+
}
|
|
13
|
+
type AvatarProps = AvatarOwnProps & Omit<HTMLAttributes<HTMLSpanElement>, keyof AvatarOwnProps>;
|
|
14
|
+
interface AvatarGroupProps {
|
|
15
|
+
children?: ReactNode;
|
|
16
|
+
className?: string;
|
|
17
|
+
style?: CSSProperties;
|
|
18
|
+
}
|
|
19
|
+
declare const Avatar: import('react').ForwardRefExoticComponent<AvatarOwnProps & Omit<HTMLAttributes<HTMLSpanElement>, keyof AvatarOwnProps> & import('react').RefAttributes<HTMLSpanElement>>;
|
|
20
|
+
declare const AvatarGroup: import('react').ForwardRefExoticComponent<AvatarGroupProps & HTMLAttributes<HTMLDivElement> & import('react').RefAttributes<HTMLDivElement>>;
|
|
21
|
+
export { Avatar, AvatarGroup };
|
|
22
|
+
export type { AvatarOwnProps, AvatarProps, AvatarGroupProps };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
3
|
+
declare const AVATAR_CSS = "\n.syntra-avatar {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--_av-size);\n height: var(--_av-size);\n border-radius: var(--_av-radius);\n background: var(--syntra-color-primary-100);\n color: var(--syntra-color-primary-600);\n font-family: inherit;\n font-weight: 600;\n font-size: var(--_av-fz);\n letter-spacing: -0.02em;\n overflow: hidden;\n user-select: none;\n}\n.syntra-avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.syntra-avatar-group {\n display: inline-flex;\n align-items: center;\n}\n.syntra-avatar-group .syntra-avatar {\n border: 2px solid var(--syntra-color-background-default);\n}\n.syntra-avatar-group .syntra-avatar + .syntra-avatar {\n margin-left: calc(var(--_av-size) * -0.3);\n}\n";
|
|
4
|
+
declare function getAvatarSizeStyles(size: AvatarSize): CSSProperties;
|
|
5
|
+
export { AVATAR_CSS, getAvatarSizeStyles };
|
|
6
|
+
export type { AvatarSize };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode, HTMLAttributes } from 'react';
|
|
2
|
+
import { BadgeVariant, BadgeSize, BadgeColorScheme } from './badge.styles';
|
|
3
|
+
interface BadgeOwnProps {
|
|
4
|
+
variant?: BadgeVariant;
|
|
5
|
+
colorScheme?: BadgeColorScheme;
|
|
6
|
+
size?: BadgeSize;
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: CSSProperties;
|
|
10
|
+
}
|
|
11
|
+
type BadgeProps = BadgeOwnProps & Omit<HTMLAttributes<HTMLSpanElement>, keyof BadgeOwnProps>;
|
|
12
|
+
declare const Badge: import('react').ForwardRefExoticComponent<BadgeOwnProps & Omit<HTMLAttributes<HTMLSpanElement>, keyof BadgeOwnProps> & import('react').RefAttributes<HTMLSpanElement>>;
|
|
13
|
+
export { Badge };
|
|
14
|
+
export type { BadgeOwnProps, BadgeProps };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
type BadgeVariant = 'solid' | 'soft' | 'outline' | 'dot';
|
|
3
|
+
type BadgeSize = 'sm' | 'md' | 'lg';
|
|
4
|
+
type BadgeColorScheme = 'primary' | 'neutral' | 'success' | 'warning' | 'danger' | (string & {});
|
|
5
|
+
declare const BADGE_CSS = "\n.syntra-badge {\n display: inline-flex;\n align-items: center;\n gap: var(--_badge-gap);\n font-family: inherit;\n font-weight: 500;\n font-size: var(--_badge-fz);\n letter-spacing: -0.01em;\n line-height: 1;\n padding: var(--_badge-py) var(--_badge-px);\n border-radius: var(--_badge-radius);\n background: var(--_badge-bg);\n color: var(--_badge-color);\n border: 1px solid var(--_badge-border, transparent);\n white-space: nowrap;\n vertical-align: middle;\n}\n.syntra-badge-dot {\n width: var(--_badge-dot-size);\n height: var(--_badge-dot-size);\n border-radius: 50%;\n background: var(--_badge-dot-color);\n flex-shrink: 0;\n}\n";
|
|
6
|
+
declare function getBadgeSizeStyles(size: BadgeSize): CSSProperties;
|
|
7
|
+
declare function getBadgeVariantStyles(variant: BadgeVariant, colorScheme: BadgeColorScheme): CSSProperties;
|
|
8
|
+
export { BADGE_CSS, getBadgeSizeStyles, getBadgeVariantStyles };
|
|
9
|
+
export type { BadgeVariant, BadgeSize, BadgeColorScheme };
|
|
@@ -2,7 +2,7 @@ import { CSSProperties } from 'react';
|
|
|
2
2
|
type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'soft' | 'link';
|
|
3
3
|
type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';
|
|
4
4
|
type ButtonColorScheme = 'primary' | 'neutral' | 'danger' | (string & {});
|
|
5
|
-
declare const BUTTON_CSS = "\n.syntra-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: relative;\n white-space: nowrap;\n user-select: none;\n vertical-align: middle;\n cursor: pointer;\n font-family: inherit;\n font-weight: var(--_btn-fw);\n font-size: var(--_btn-fz);\n height: var(--_btn-h);\n padding-left: var(--_btn-px);\n padding-right: var(--_btn-px);\n gap: var(--_btn-gap);\n border-radius: var(--_btn-radius);\n background: var(--_btn-bg);\n color: var(--_btn-color);\n border: 1px solid var(--_btn-border, transparent);\n transition:
|
|
5
|
+
declare const BUTTON_CSS = "\n.syntra-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: relative;\n white-space: nowrap;\n user-select: none;\n vertical-align: middle;\n cursor: pointer;\n font-family: inherit;\n font-weight: var(--_btn-fw);\n font-size: var(--_btn-fz);\n letter-spacing: -0.01em;\n height: var(--_btn-h);\n padding-left: var(--_btn-px);\n padding-right: var(--_btn-px);\n gap: var(--_btn-gap);\n border-radius: var(--_btn-radius);\n background: var(--_btn-bg);\n color: var(--_btn-color);\n border: 1px solid var(--_btn-border, transparent);\n transition: all 200ms cubic-bezier(0.25, 0.1, 0.25, 1);\n text-decoration: none;\n outline: none;\n -webkit-tap-highlight-color: transparent;\n}\n.syntra-button:hover:not(:disabled):not([data-loading]) {\n background: var(--_btn-bg-hover);\n border-color: var(--_btn-border-hover, transparent);\n color: var(--_btn-color-hover, var(--_btn-color));\n}\n.syntra-button:active:not(:disabled):not([data-loading]) {\n background: var(--_btn-bg-active);\n transform: scale(0.97);\n transition-duration: 80ms;\n}\n.syntra-button:focus-visible {\n outline: 2px solid var(--_btn-ring);\n outline-offset: 2px;\n}\n.syntra-button:disabled,\n.syntra-button[data-loading] {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.syntra-button[data-loading] {\n cursor: wait;\n pointer-events: none;\n}\n.syntra-button[data-full-width] {\n width: 100%;\n}\n.syntra-button[data-variant=\"link\"] {\n height: auto;\n padding-left: 0;\n padding-right: 0;\n background: transparent;\n border-color: transparent;\n}\n.syntra-button[data-variant=\"link\"]:hover:not(:disabled) {\n text-decoration: underline;\n background: transparent;\n}\n.syntra-button[data-variant=\"link\"]:active:not(:disabled) {\n transform: none;\n}\n.syntra-button-label[data-loading] {\n opacity: 0;\n}\n.syntra-button-spinner {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n";
|
|
6
6
|
declare function getButtonSizeStyles(size: ButtonSize): CSSProperties;
|
|
7
7
|
declare function getButtonVariantStyles(variant: ButtonVariant, colorScheme: ButtonColorScheme): CSSProperties;
|
|
8
8
|
export { BUTTON_CSS, getButtonSizeStyles, getButtonVariantStyles };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode, InputHTMLAttributes } from 'react';
|
|
2
|
+
import { CheckboxSize } from './checkbox.styles';
|
|
3
|
+
interface CheckboxOwnProps {
|
|
4
|
+
checked?: boolean;
|
|
5
|
+
defaultChecked?: boolean;
|
|
6
|
+
indeterminate?: boolean;
|
|
7
|
+
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
8
|
+
size?: CheckboxSize;
|
|
9
|
+
label?: ReactNode;
|
|
10
|
+
description?: ReactNode;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
className?: string;
|
|
13
|
+
style?: CSSProperties;
|
|
14
|
+
}
|
|
15
|
+
type CheckboxProps = CheckboxOwnProps & Omit<InputHTMLAttributes<HTMLInputElement>, keyof CheckboxOwnProps>;
|
|
16
|
+
declare const Checkbox: import('react').ForwardRefExoticComponent<CheckboxOwnProps & Omit<InputHTMLAttributes<HTMLInputElement>, keyof CheckboxOwnProps> & import('react').RefAttributes<HTMLInputElement>>;
|
|
17
|
+
export { Checkbox };
|
|
18
|
+
export type { CheckboxOwnProps, CheckboxProps };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
type CheckboxSize = 'sm' | 'md' | 'lg';
|
|
3
|
+
declare const CHECKBOX_CSS = "\n.syntra-checkbox {\n display: inline-flex;\n align-items: center;\n gap: var(--_cb-gap);\n cursor: pointer;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n}\n.syntra-checkbox[data-disabled] {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.syntra-checkbox-input {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n.syntra-checkbox-control {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--_cb-size);\n height: var(--_cb-size);\n border-radius: var(--_cb-radius);\n border: 2px solid var(--syntra-color-border-emphasis);\n background: var(--syntra-color-background-default);\n transition: all 150ms cubic-bezier(0.25, 0.1, 0.25, 1);\n color: #fff;\n}\n.syntra-checkbox-control svg {\n opacity: 0;\n transform: scale(0.5);\n transition: all 150ms cubic-bezier(0.175, 0.885, 0.32, 1.275);\n}\n.syntra-checkbox-input:checked + .syntra-checkbox-control {\n background: var(--syntra-color-primary-500);\n border-color: var(--syntra-color-primary-500);\n}\n.syntra-checkbox-input:checked + .syntra-checkbox-control svg {\n opacity: 1;\n transform: scale(1);\n}\n.syntra-checkbox-input:indeterminate + .syntra-checkbox-control {\n background: var(--syntra-color-primary-500);\n border-color: var(--syntra-color-primary-500);\n}\n.syntra-checkbox-input:indeterminate + .syntra-checkbox-control svg {\n opacity: 1;\n transform: scale(1);\n}\n.syntra-checkbox-input:focus-visible + .syntra-checkbox-control {\n outline: 2px solid var(--syntra-color-primary-500);\n outline-offset: 2px;\n}\n.syntra-checkbox:not([data-disabled]):hover .syntra-checkbox-control {\n border-color: var(--syntra-color-primary-500);\n}\n.syntra-checkbox:not([data-disabled]):active .syntra-checkbox-control {\n transform: scale(0.9);\n transition-duration: 80ms;\n}\n.syntra-checkbox-label {\n font-family: inherit;\n font-size: var(--_cb-fz);\n letter-spacing: -0.01em;\n color: var(--syntra-color-foreground-default);\n line-height: 1.4;\n}\n.syntra-checkbox-description {\n font-size: calc(var(--_cb-fz) * 0.9);\n color: var(--syntra-color-foreground-muted);\n line-height: 1.4;\n margin-top: 1px;\n}\n";
|
|
4
|
+
declare function getCheckboxSizeStyles(size: CheckboxSize): CSSProperties;
|
|
5
|
+
declare function getCheckboxIconSize(size: CheckboxSize): number;
|
|
6
|
+
export { CHECKBOX_CSS, getCheckboxSizeStyles, getCheckboxIconSize };
|
|
7
|
+
export type { CheckboxSize };
|
|
@@ -4,3 +4,24 @@ export { Input } from './input';
|
|
|
4
4
|
export type { InputOwnProps, InputProps, InputVariant, InputSize } from './input';
|
|
5
5
|
export { Spinner } from './spinner';
|
|
6
6
|
export type { SpinnerProps } from './spinner';
|
|
7
|
+
export { Select } from './select';
|
|
8
|
+
export type { SelectOwnProps, SelectOption, SelectVariant, SelectSize } from './select';
|
|
9
|
+
export { Tabs, TabList, Tab, TabPanel } from './tabs';
|
|
10
|
+
export type { TabsOwnProps, TabListOwnProps, TabOwnProps, TabPanelOwnProps, TabsVariant, TabsSize, TabsOrientation } from './tabs';
|
|
11
|
+
export { Toaster } from './toast';
|
|
12
|
+
export { toast } from './toast';
|
|
13
|
+
export type { ToasterProps, ToastType, ToastPosition, ToastOptions } from './toast';
|
|
14
|
+
export { Modal, ModalHeader, ModalBody, ModalFooter } from './modal';
|
|
15
|
+
export type { ModalOwnProps, ModalSize } from './modal';
|
|
16
|
+
export { Checkbox } from './checkbox';
|
|
17
|
+
export type { CheckboxOwnProps, CheckboxProps, CheckboxSize } from './checkbox';
|
|
18
|
+
export { Switch } from './switch';
|
|
19
|
+
export type { SwitchOwnProps, SwitchProps, SwitchSize } from './switch';
|
|
20
|
+
export { Badge } from './badge';
|
|
21
|
+
export type { BadgeOwnProps, BadgeProps, BadgeVariant, BadgeSize, BadgeColorScheme } from './badge';
|
|
22
|
+
export { Avatar, AvatarGroup } from './avatar';
|
|
23
|
+
export type { AvatarOwnProps, AvatarProps, AvatarGroupProps, AvatarSize } from './avatar';
|
|
24
|
+
export { Textarea } from './textarea';
|
|
25
|
+
export type { TextareaOwnProps, TextareaProps, TextareaVariant, TextareaSize } from './textarea';
|
|
26
|
+
export { Tooltip } from './tooltip';
|
|
27
|
+
export type { TooltipProps, TooltipPosition } from './tooltip';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CSSProperties } from 'react';
|
|
2
2
|
type InputVariant = 'outline' | 'filled' | 'unstyled';
|
|
3
3
|
type InputSize = 'xs' | 'sm' | 'md' | 'lg';
|
|
4
|
-
declare const INPUT_CSS = "\n.syntra-input-wrapper {\n display: inline-flex;\n align-items: center;\n position: relative;\n width: var(--_input-w, auto);\n height: var(--_input-h);\n padding-left: var(--_input-px);\n padding-right: var(--_input-px);\n gap: var(--_input-gap);\n border-radius: var(--_input-radius);\n background: var(--_input-bg);\n border: 1px solid var(--_input-border, transparent);\n font-family: inherit;\n font-size: var(--_input-fz);\n transition: border-color
|
|
4
|
+
declare const INPUT_CSS = "\n.syntra-input-wrapper {\n display: inline-flex;\n align-items: center;\n position: relative;\n width: var(--_input-w, auto);\n height: var(--_input-h);\n padding-left: var(--_input-px);\n padding-right: var(--_input-px);\n gap: var(--_input-gap);\n border-radius: var(--_input-radius);\n background: var(--_input-bg);\n border: 1px solid var(--_input-border, transparent);\n font-family: inherit;\n font-size: var(--_input-fz);\n transition: border-color 200ms cubic-bezier(0.25, 0.1, 0.25, 1),\n box-shadow 200ms cubic-bezier(0.25, 0.1, 0.25, 1),\n background 200ms cubic-bezier(0.25, 0.1, 0.25, 1);\n}\n.syntra-input-wrapper:focus-within:not([data-disabled]):not([data-variant=\"unstyled\"]) {\n border-color: var(--_input-focus-border);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_input-focus-border) 16%, transparent);\n}\n.syntra-input-wrapper[data-invalid]:not([data-disabled]) {\n border-color: var(--_input-invalid-border);\n}\n.syntra-input-wrapper[data-invalid]:focus-within:not([data-disabled]) {\n border-color: var(--_input-invalid-border);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_input-invalid-border) 16%, transparent);\n}\n.syntra-input-wrapper[data-disabled] {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.syntra-input {\n flex: 1;\n min-width: 0;\n height: 100%;\n border: none;\n outline: none;\n background: transparent;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n letter-spacing: -0.01em;\n padding: 0;\n}\n.syntra-input::placeholder {\n color: var(--syntra-color-foreground-subtle);\n}\n.syntra-input:disabled {\n cursor: not-allowed;\n}\n.syntra-input-section {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n color: var(--syntra-color-foreground-muted);\n}\n";
|
|
5
5
|
declare function getInputSizeStyles(size: InputSize): CSSProperties;
|
|
6
6
|
declare function getInputVariantStyles(variant: InputVariant): CSSProperties;
|
|
7
7
|
export { INPUT_CSS, getInputSizeStyles, getInputVariantStyles };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
import { ModalSize } from './modal.styles';
|
|
3
|
+
interface ModalOwnProps {
|
|
4
|
+
opened: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
title?: ReactNode;
|
|
7
|
+
size?: ModalSize;
|
|
8
|
+
closeOnOverlayClick?: boolean;
|
|
9
|
+
closeOnEscape?: boolean;
|
|
10
|
+
showCloseButton?: boolean;
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
footer?: ReactNode;
|
|
13
|
+
className?: string;
|
|
14
|
+
style?: CSSProperties;
|
|
15
|
+
overlayClassName?: string;
|
|
16
|
+
overlayStyle?: CSSProperties;
|
|
17
|
+
}
|
|
18
|
+
declare function ModalHeader({ children, className, style }: {
|
|
19
|
+
children?: ReactNode;
|
|
20
|
+
className?: string;
|
|
21
|
+
style?: CSSProperties;
|
|
22
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
declare namespace ModalHeader {
|
|
24
|
+
var displayName: string;
|
|
25
|
+
}
|
|
26
|
+
declare function ModalBody({ children, className, style }: {
|
|
27
|
+
children?: ReactNode;
|
|
28
|
+
className?: string;
|
|
29
|
+
style?: CSSProperties;
|
|
30
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
declare namespace ModalBody {
|
|
32
|
+
var displayName: string;
|
|
33
|
+
}
|
|
34
|
+
declare function ModalFooter({ children, className, style }: {
|
|
35
|
+
children?: ReactNode;
|
|
36
|
+
className?: string;
|
|
37
|
+
style?: CSSProperties;
|
|
38
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
declare namespace ModalFooter {
|
|
40
|
+
var displayName: string;
|
|
41
|
+
}
|
|
42
|
+
declare const Modal: import('react').ForwardRefExoticComponent<ModalOwnProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
43
|
+
export { Modal, ModalHeader, ModalBody, ModalFooter };
|
|
44
|
+
export type { ModalOwnProps };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
type ModalSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
3
|
+
declare const MODAL_CSS = "\n.syntra-modal-overlay {\n position: fixed;\n inset: 0;\n z-index: 9998;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n animation: syntra-overlay-in 200ms cubic-bezier(0.25, 0.1, 0.25, 1);\n}\n.syntra-modal-overlay[data-exiting] {\n animation: syntra-overlay-out 150ms cubic-bezier(0.25, 0.1, 0.25, 1) forwards;\n}\n@keyframes syntra-overlay-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n@keyframes syntra-overlay-out {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n\n.syntra-modal {\n position: relative;\n display: flex;\n flex-direction: column;\n width: var(--_modal-w);\n max-width: var(--_modal-max-w);\n max-height: calc(100vh - 32px);\n background: var(--syntra-color-background-default);\n border: 1px solid var(--syntra-color-border-muted);\n border-radius: 16px;\n box-shadow: 0 24px 48px rgba(0, 0, 0, 0.16), 0 8px 16px rgba(0, 0, 0, 0.08);\n outline: none;\n animation: syntra-modal-in 250ms cubic-bezier(0.2, 0, 0, 1);\n overflow: hidden;\n}\n.syntra-modal-overlay[data-exiting] .syntra-modal {\n animation: syntra-modal-out 150ms cubic-bezier(0.25, 0.1, 0.25, 1) forwards;\n}\n@keyframes syntra-modal-in {\n from { opacity: 0; transform: scale(0.95) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n@keyframes syntra-modal-out {\n from { opacity: 1; transform: scale(1) translateY(0); }\n to { opacity: 0; transform: scale(0.95) translateY(8px); }\n}\n\n.syntra-modal-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px 0;\n gap: 12px;\n}\n.syntra-modal-title {\n font-size: var(--syntra-font-fontSize-lg);\n font-weight: 600;\n letter-spacing: -0.02em;\n color: var(--syntra-color-foreground-default);\n line-height: 1.3;\n margin: 0;\n}\n.syntra-modal-close {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n background: var(--syntra-color-background-emphasis);\n padding: 0;\n cursor: pointer;\n color: var(--syntra-color-foreground-muted);\n border-radius: 50%;\n flex-shrink: 0;\n transition: background 100ms ease, color 100ms ease;\n}\n.syntra-modal-close:hover {\n background: var(--syntra-color-background-subtle);\n color: var(--syntra-color-foreground-default);\n}\n.syntra-modal-close:active {\n transform: scale(0.9);\n}\n\n.syntra-modal-body {\n padding: 16px 24px;\n overflow-y: auto;\n flex: 1;\n font-size: var(--syntra-font-fontSize-sm);\n line-height: 1.55;\n color: var(--syntra-color-foreground-default);\n}\n\n.syntra-modal-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n padding: 0 24px 20px;\n}\n";
|
|
4
|
+
declare function getModalSizeStyles(size: ModalSize): CSSProperties;
|
|
5
|
+
export { MODAL_CSS, getModalSizeStyles };
|
|
6
|
+
export type { ModalSize };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { SyntraStyleProps } from '../../primitives/style-props';
|
|
3
|
+
import { SelectVariant, SelectSize } from './select.styles';
|
|
4
|
+
interface SelectOption {
|
|
5
|
+
value: string;
|
|
6
|
+
label: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface SelectOwnProps extends SyntraStyleProps {
|
|
10
|
+
options: SelectOption[];
|
|
11
|
+
value?: string | string[];
|
|
12
|
+
defaultValue?: string | string[];
|
|
13
|
+
onChange?: (value: string | string[]) => void;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
searchable?: boolean;
|
|
16
|
+
multiple?: boolean;
|
|
17
|
+
clearable?: boolean;
|
|
18
|
+
variant?: SelectVariant;
|
|
19
|
+
size?: SelectSize;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
invalid?: boolean;
|
|
22
|
+
maxDropdownHeight?: number;
|
|
23
|
+
className?: string;
|
|
24
|
+
style?: CSSProperties;
|
|
25
|
+
}
|
|
26
|
+
declare const Select: import('react').ForwardRefExoticComponent<SelectOwnProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
27
|
+
export { Select };
|
|
28
|
+
export type { SelectOwnProps, SelectOption };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
type SelectVariant = 'outline' | 'filled' | 'unstyled';
|
|
3
|
+
type SelectSize = 'xs' | 'sm' | 'md' | 'lg';
|
|
4
|
+
declare const SELECT_CSS = "\n.syntra-select-wrapper {\n display: inline-flex;\n position: relative;\n width: var(--_select-w, auto);\n}\n.syntra-select-trigger {\n display: inline-flex;\n align-items: center;\n width: 100%;\n min-height: var(--_select-h);\n padding-left: var(--_select-px);\n padding-right: var(--_select-px);\n gap: var(--_select-gap);\n border-radius: var(--_select-radius);\n background: var(--_select-bg);\n border: 1px solid var(--_select-border, transparent);\n font-family: inherit;\n font-size: var(--_select-fz);\n letter-spacing: -0.01em;\n color: inherit;\n cursor: pointer;\n outline: none;\n transition: border-color 200ms cubic-bezier(0.25, 0.1, 0.25, 1),\n box-shadow 200ms cubic-bezier(0.25, 0.1, 0.25, 1),\n background 200ms cubic-bezier(0.25, 0.1, 0.25, 1);\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n}\n.syntra-select-trigger:focus:not([data-disabled]):not([data-variant=\"unstyled\"]) {\n border-color: var(--_select-focus-border);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_select-focus-border) 16%, transparent);\n}\n.syntra-select-trigger[data-invalid]:not([data-disabled]) {\n border-color: var(--_select-invalid-border);\n}\n.syntra-select-trigger[data-invalid]:focus:not([data-disabled]) {\n border-color: var(--_select-invalid-border);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_select-invalid-border) 16%, transparent);\n}\n.syntra-select-trigger[data-disabled] {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.syntra-select-trigger[data-open] {\n border-color: var(--_select-focus-border);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_select-focus-border) 16%, transparent);\n}\n.syntra-select-value {\n flex: 1;\n min-width: 0;\n text-align: left;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.syntra-select-placeholder {\n color: var(--syntra-color-foreground-subtle);\n}\n.syntra-select-tags {\n flex: 1;\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n padding: 4px 0;\n min-width: 0;\n}\n.syntra-select-tag {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 2px 8px;\n border-radius: 6px;\n background: var(--syntra-color-primary-50);\n color: var(--syntra-color-primary-600);\n font-size: 0.85em;\n font-weight: 500;\n line-height: 1.4;\n max-width: 160px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.syntra-select-tag-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n border: none;\n background: none;\n padding: 0;\n cursor: pointer;\n border-radius: 4px;\n color: var(--syntra-color-primary-400);\n flex-shrink: 0;\n transition: color 100ms ease, background 100ms ease;\n}\n.syntra-select-tag-remove:hover {\n background: var(--syntra-color-primary-100);\n color: var(--syntra-color-primary-600);\n}\n.syntra-select-chevron {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n color: var(--syntra-color-foreground-subtle);\n transition: transform 250ms cubic-bezier(0.25, 0.1, 0.25, 1);\n}\n.syntra-select-chevron[data-open] {\n transform: rotate(180deg);\n}\n.syntra-select-clear {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 18px;\n height: 18px;\n border: none;\n background: none;\n padding: 0;\n cursor: pointer;\n color: var(--syntra-color-foreground-subtle);\n border-radius: 50%;\n transition: color 100ms ease, background 100ms ease;\n}\n.syntra-select-clear:hover {\n color: var(--syntra-color-foreground-default);\n background: var(--syntra-color-background-emphasis);\n}\n.syntra-select-dropdown {\n position: fixed;\n z-index: 9999;\n min-width: var(--_dropdown-min-w, 200px);\n max-height: var(--_dropdown-max-h, 250px);\n overflow-y: auto;\n overflow-x: hidden;\n background: color-mix(in srgb, var(--syntra-color-background-default) 85%, transparent);\n border: 1px solid var(--syntra-color-border-muted);\n border-radius: 12px;\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.06);\n padding: 4px;\n backdrop-filter: blur(24px) saturate(180%);\n -webkit-backdrop-filter: blur(24px) saturate(180%);\n animation: syntra-select-in 180ms cubic-bezier(0.2, 0, 0, 1);\n}\n@keyframes syntra-select-in {\n from { opacity: 0; transform: scale(0.96) translateY(-4px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n.syntra-select-search {\n display: block;\n width: calc(100% - 8px);\n margin: 4px auto 4px;\n padding: 7px 10px;\n border: 1px solid var(--syntra-color-border-muted);\n border-radius: 8px;\n background: var(--syntra-color-background-default);\n font-family: inherit;\n font-size: inherit;\n color: inherit;\n outline: none;\n transition: border-color 150ms ease, box-shadow 150ms ease;\n}\n.syntra-select-search:focus {\n border-color: var(--syntra-color-primary-500);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--syntra-color-primary-500) 12%, transparent);\n}\n.syntra-select-search::placeholder {\n color: var(--syntra-color-foreground-subtle);\n}\n.syntra-select-option {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 7px 10px;\n border: none;\n background: none;\n font-family: inherit;\n font-size: inherit;\n color: inherit;\n cursor: pointer;\n border-radius: 8px;\n text-align: left;\n outline: none;\n transition: background 80ms ease;\n}\n.syntra-select-option:hover,\n.syntra-select-option[data-focused] {\n background: var(--syntra-color-primary-500);\n color: #fff;\n}\n.syntra-select-option[data-focused] .syntra-select-check {\n color: #fff;\n}\n.syntra-select-option[data-selected] {\n font-weight: 500;\n}\n.syntra-select-option[data-selected]:not(:hover):not([data-focused]) {\n color: var(--syntra-color-primary-500);\n}\n.syntra-select-option[data-disabled] {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.syntra-select-option[data-disabled]:hover {\n background: none;\n color: inherit;\n}\n.syntra-select-check {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n color: var(--syntra-color-primary-500);\n}\n.syntra-select-empty {\n padding: 16px 8px;\n text-align: center;\n color: var(--syntra-color-foreground-subtle);\n font-size: 0.9em;\n}\n";
|
|
5
|
+
declare function getSelectSizeStyles(size: SelectSize): CSSProperties;
|
|
6
|
+
declare function getSelectVariantStyles(variant: SelectVariant): CSSProperties;
|
|
7
|
+
export { SELECT_CSS, getSelectSizeStyles, getSelectVariantStyles };
|
|
8
|
+
export type { SelectVariant, SelectSize };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode, InputHTMLAttributes } from 'react';
|
|
2
|
+
import { SwitchSize } from './switch.styles';
|
|
3
|
+
interface SwitchOwnProps {
|
|
4
|
+
checked?: boolean;
|
|
5
|
+
defaultChecked?: boolean;
|
|
6
|
+
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
7
|
+
size?: SwitchSize;
|
|
8
|
+
label?: ReactNode;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
className?: string;
|
|
11
|
+
style?: CSSProperties;
|
|
12
|
+
}
|
|
13
|
+
type SwitchProps = SwitchOwnProps & Omit<InputHTMLAttributes<HTMLInputElement>, keyof SwitchOwnProps>;
|
|
14
|
+
declare const Switch: import('react').ForwardRefExoticComponent<SwitchOwnProps & Omit<InputHTMLAttributes<HTMLInputElement>, keyof SwitchOwnProps> & import('react').RefAttributes<HTMLInputElement>>;
|
|
15
|
+
export { Switch };
|
|
16
|
+
export type { SwitchOwnProps, SwitchProps };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
type SwitchSize = 'sm' | 'md' | 'lg';
|
|
3
|
+
declare const SWITCH_CSS = "\n.syntra-switch {\n display: inline-flex;\n align-items: center;\n gap: var(--_sw-gap);\n cursor: pointer;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n}\n.syntra-switch[data-disabled] {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.syntra-switch-input {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n.syntra-switch-track {\n position: relative;\n display: flex;\n align-items: center;\n width: var(--_sw-w);\n height: var(--_sw-h);\n border-radius: var(--_sw-h);\n background: var(--syntra-color-gray-300);\n transition: background 200ms cubic-bezier(0.25, 0.1, 0.25, 1);\n flex-shrink: 0;\n}\n.syntra-switch-input:checked + .syntra-switch-track {\n background: var(--syntra-color-primary-500);\n}\n.syntra-switch-input:focus-visible + .syntra-switch-track {\n outline: 2px solid var(--syntra-color-primary-500);\n outline-offset: 2px;\n}\n.syntra-switch:not([data-disabled]):active .syntra-switch-thumb {\n width: calc(var(--_sw-thumb) + 3px);\n}\n.syntra-switch-thumb {\n position: absolute;\n left: 2px;\n width: var(--_sw-thumb);\n height: var(--_sw-thumb);\n border-radius: 50%;\n background: #fff;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15), 0 1px 1px rgba(0, 0, 0, 0.06);\n transition: left 200ms cubic-bezier(0.25, 0.1, 0.25, 1),\n width 150ms cubic-bezier(0.25, 0.1, 0.25, 1);\n}\n.syntra-switch-input:checked + .syntra-switch-track .syntra-switch-thumb {\n left: calc(var(--_sw-w) - var(--_sw-thumb) - 2px);\n}\n.syntra-switch:not([data-disabled]):active .syntra-switch-input:checked + .syntra-switch-track .syntra-switch-thumb {\n left: calc(var(--_sw-w) - var(--_sw-thumb) - 5px);\n}\n.syntra-switch-label {\n font-family: inherit;\n font-size: var(--_sw-fz);\n letter-spacing: -0.01em;\n color: var(--syntra-color-foreground-default);\n line-height: 1.4;\n}\n";
|
|
4
|
+
declare function getSwitchSizeStyles(size: SwitchSize): CSSProperties;
|
|
5
|
+
export { SWITCH_CSS, getSwitchSizeStyles };
|
|
6
|
+
export type { SwitchSize };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode, HTMLAttributes } from 'react';
|
|
2
|
+
import { SyntraStyleProps } from '../../primitives/style-props';
|
|
3
|
+
import { TabsVariant, TabsSize, TabsOrientation } from './tabs.styles';
|
|
4
|
+
interface TabsOwnProps extends SyntraStyleProps {
|
|
5
|
+
value?: string;
|
|
6
|
+
defaultValue?: string;
|
|
7
|
+
onChange?: (value: string) => void;
|
|
8
|
+
variant?: TabsVariant;
|
|
9
|
+
size?: TabsSize;
|
|
10
|
+
orientation?: TabsOrientation;
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
className?: string;
|
|
13
|
+
style?: CSSProperties;
|
|
14
|
+
}
|
|
15
|
+
declare const Tabs: import('react').ForwardRefExoticComponent<TabsOwnProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
16
|
+
interface TabListOwnProps {
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
className?: string;
|
|
19
|
+
style?: CSSProperties;
|
|
20
|
+
}
|
|
21
|
+
declare const TabList: import('react').ForwardRefExoticComponent<TabListOwnProps & Omit<HTMLAttributes<HTMLDivElement>, keyof TabListOwnProps> & import('react').RefAttributes<HTMLDivElement>>;
|
|
22
|
+
interface TabOwnProps {
|
|
23
|
+
value: string;
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
children?: ReactNode;
|
|
26
|
+
className?: string;
|
|
27
|
+
style?: CSSProperties;
|
|
28
|
+
}
|
|
29
|
+
declare const Tab: import('react').ForwardRefExoticComponent<TabOwnProps & Omit<HTMLAttributes<HTMLButtonElement>, keyof TabOwnProps> & import('react').RefAttributes<HTMLButtonElement>>;
|
|
30
|
+
interface TabPanelOwnProps {
|
|
31
|
+
value: string;
|
|
32
|
+
children?: ReactNode;
|
|
33
|
+
className?: string;
|
|
34
|
+
style?: CSSProperties;
|
|
35
|
+
}
|
|
36
|
+
declare const TabPanel: import('react').ForwardRefExoticComponent<TabPanelOwnProps & Omit<HTMLAttributes<HTMLDivElement>, keyof TabPanelOwnProps> & import('react').RefAttributes<HTMLDivElement>>;
|
|
37
|
+
export { Tabs, TabList, Tab, TabPanel };
|
|
38
|
+
export type { TabsOwnProps, TabListOwnProps, TabOwnProps, TabPanelOwnProps };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
type TabsVariant = 'line' | 'pills' | 'enclosed';
|
|
3
|
+
type TabsSize = 'sm' | 'md' | 'lg';
|
|
4
|
+
type TabsOrientation = 'horizontal' | 'vertical';
|
|
5
|
+
declare const TABS_CSS = "\n.syntra-tabs {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n.syntra-tabs[data-orientation=\"vertical\"] {\n flex-direction: row;\n}\n\n/* \u2500\u2500 TabList \u2500\u2500 */\n.syntra-tab-list {\n display: flex;\n align-items: center;\n position: relative;\n gap: var(--_tabs-gap);\n}\n.syntra-tab-list[data-orientation=\"vertical\"] {\n flex-direction: column;\n align-items: stretch;\n}\n\n/* line variant */\n.syntra-tab-list[data-variant=\"line\"] {\n border-bottom: 1px solid var(--syntra-color-border-muted);\n}\n.syntra-tab-list[data-variant=\"line\"][data-orientation=\"vertical\"] {\n border-bottom: none;\n border-right: 1px solid var(--syntra-color-border-muted);\n}\n\n/* pills variant \u2014 Apple segmented control style */\n.syntra-tab-list[data-variant=\"pills\"] {\n background: var(--syntra-color-background-emphasis);\n border-radius: 10px;\n padding: 3px;\n gap: 2px;\n}\n\n/* enclosed variant */\n.syntra-tab-list[data-variant=\"enclosed\"] {\n border-bottom: 1px solid var(--syntra-color-border-muted);\n}\n.syntra-tab-list[data-variant=\"enclosed\"][data-orientation=\"vertical\"] {\n border-bottom: none;\n border-right: 1px solid var(--syntra-color-border-muted);\n}\n\n/* \u2500\u2500 Indicator (line variant) \u2500\u2500 */\n.syntra-tab-indicator {\n position: absolute;\n bottom: -1px;\n left: var(--_indicator-left, 0);\n width: var(--_indicator-width, 0);\n height: 2px;\n background: var(--syntra-color-primary-500);\n border-radius: 1px;\n transition: left 280ms cubic-bezier(0.4, 0, 0.2, 1),\n width 280ms cubic-bezier(0.4, 0, 0.2, 1),\n top 280ms cubic-bezier(0.4, 0, 0.2, 1),\n height 280ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n.syntra-tab-list[data-orientation=\"vertical\"] .syntra-tab-indicator {\n bottom: auto;\n right: -1px;\n left: auto;\n top: var(--_indicator-top, 0);\n width: 2px;\n height: var(--_indicator-height, 0);\n}\n\n/* \u2500\u2500 Tab \u2500\u2500 */\n.syntra-tab {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n position: relative;\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n border: none;\n outline: none;\n font-family: inherit;\n font-weight: 500;\n font-size: var(--_tab-fz);\n letter-spacing: -0.01em;\n padding: var(--_tab-py) var(--_tab-px);\n color: var(--syntra-color-foreground-muted);\n background: transparent;\n transition: all 200ms cubic-bezier(0.25, 0.1, 0.25, 1);\n -webkit-tap-highlight-color: transparent;\n}\n.syntra-tab:hover:not(:disabled) {\n color: var(--syntra-color-foreground-default);\n}\n.syntra-tab:active:not(:disabled) {\n transform: scale(0.97);\n transition-duration: 80ms;\n}\n.syntra-tab:focus-visible {\n outline: 2px solid var(--syntra-color-primary-500);\n outline-offset: -2px;\n border-radius: 8px;\n}\n.syntra-tab:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n/* line variant tab */\n.syntra-tab[data-variant=\"line\"][data-selected] {\n color: var(--syntra-color-primary-500);\n}\n\n/* pills variant tab \u2014 Apple segmented control */\n.syntra-tab[data-variant=\"pills\"] {\n border-radius: 7px;\n padding: var(--_tab-py) var(--_tab-px);\n}\n.syntra-tab[data-variant=\"pills\"][data-selected] {\n background: var(--syntra-color-background-default);\n color: var(--syntra-color-foreground-default);\n font-weight: 600;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04);\n}\n.syntra-tab[data-variant=\"pills\"]:active:not(:disabled) {\n transform: scale(0.96);\n}\n\n/* enclosed variant tab */\n.syntra-tab[data-variant=\"enclosed\"] {\n border: 1px solid transparent;\n border-bottom: none;\n border-radius: 8px 8px 0 0;\n margin-bottom: -1px;\n}\n.syntra-tab[data-variant=\"enclosed\"][data-selected] {\n background: var(--syntra-color-background-default);\n border-color: var(--syntra-color-border-muted);\n color: var(--syntra-color-foreground-default);\n font-weight: 600;\n}\n.syntra-tab[data-variant=\"enclosed\"][data-orientation=\"vertical\"] {\n border-bottom: 1px solid transparent;\n border-right: none;\n border-radius: 8px 0 0 8px;\n margin-bottom: 0;\n margin-right: -1px;\n}\n.syntra-tab[data-variant=\"enclosed\"][data-orientation=\"vertical\"][data-selected] {\n border-color: var(--syntra-color-border-muted);\n border-right-color: var(--syntra-color-background-default);\n}\n\n/* \u2500\u2500 TabPanel \u2500\u2500 */\n.syntra-tab-panel {\n padding: var(--_tabs-panel-py) 0;\n outline: none;\n}\n.syntra-tab-panel:focus-visible {\n outline: 2px solid var(--syntra-color-primary-500);\n outline-offset: 2px;\n border-radius: 8px;\n}\n";
|
|
6
|
+
declare function getTabsSizeStyles(size: TabsSize): CSSProperties;
|
|
7
|
+
export { TABS_CSS, getTabsSizeStyles };
|
|
8
|
+
export type { TabsVariant, TabsSize, TabsOrientation };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CSSProperties, TextareaHTMLAttributes } from 'react';
|
|
2
|
+
import { SyntraStyleProps } from '../../primitives/style-props';
|
|
3
|
+
import { TextareaVariant, TextareaSize } from './textarea.styles';
|
|
4
|
+
interface TextareaOwnProps extends SyntraStyleProps {
|
|
5
|
+
variant?: TextareaVariant;
|
|
6
|
+
size?: TextareaSize;
|
|
7
|
+
invalid?: boolean;
|
|
8
|
+
autosize?: boolean;
|
|
9
|
+
className?: string;
|
|
10
|
+
style?: CSSProperties;
|
|
11
|
+
}
|
|
12
|
+
type TextareaProps = TextareaOwnProps & Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, keyof TextareaOwnProps>;
|
|
13
|
+
declare const Textarea: import('react').ForwardRefExoticComponent<TextareaOwnProps & Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, keyof TextareaOwnProps> & import('react').RefAttributes<HTMLTextAreaElement>>;
|
|
14
|
+
export { Textarea };
|
|
15
|
+
export type { TextareaOwnProps, TextareaProps };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
type TextareaVariant = 'outline' | 'filled' | 'unstyled';
|
|
3
|
+
type TextareaSize = 'sm' | 'md' | 'lg';
|
|
4
|
+
declare const TEXTAREA_CSS = "\n.syntra-textarea {\n display: block;\n width: 100%;\n min-height: var(--_ta-min-h);\n padding: var(--_ta-py) var(--_ta-px);\n border-radius: var(--_ta-radius);\n background: var(--_ta-bg);\n border: 1px solid var(--_ta-border, transparent);\n font-family: inherit;\n font-size: var(--_ta-fz);\n letter-spacing: -0.01em;\n line-height: 1.55;\n color: inherit;\n resize: vertical;\n outline: none;\n transition: border-color 200ms cubic-bezier(0.25, 0.1, 0.25, 1),\n box-shadow 200ms cubic-bezier(0.25, 0.1, 0.25, 1);\n}\n.syntra-textarea:focus:not([data-variant=\"unstyled\"]) {\n border-color: var(--_ta-focus-border);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_ta-focus-border) 16%, transparent);\n}\n.syntra-textarea[data-invalid] {\n border-color: var(--_ta-invalid-border);\n}\n.syntra-textarea[data-invalid]:focus {\n border-color: var(--_ta-invalid-border);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_ta-invalid-border) 16%, transparent);\n}\n.syntra-textarea:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n resize: none;\n}\n.syntra-textarea::placeholder {\n color: var(--syntra-color-foreground-subtle);\n}\n";
|
|
5
|
+
declare function getTextareaSizeStyles(size: TextareaSize): CSSProperties;
|
|
6
|
+
declare function getTextareaVariantStyles(variant: TextareaVariant): CSSProperties;
|
|
7
|
+
export { TEXTAREA_CSS, getTextareaSizeStyles, getTextareaVariantStyles };
|
|
8
|
+
export type { TextareaVariant, TextareaSize };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ToastType } from './toast.styles';
|
|
2
|
+
interface ToastProps {
|
|
3
|
+
id: string;
|
|
4
|
+
message: string;
|
|
5
|
+
type: ToastType;
|
|
6
|
+
exiting: boolean;
|
|
7
|
+
onDismiss: (id: string) => void;
|
|
8
|
+
}
|
|
9
|
+
declare function ToastItem({ id, message, type, exiting, onDismiss }: ToastProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export { ToastItem };
|
|
11
|
+
export type { ToastProps };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ToastPosition } from './toast.styles';
|
|
2
|
+
interface ToasterProps {
|
|
3
|
+
position?: ToastPosition;
|
|
4
|
+
}
|
|
5
|
+
declare function Toaster({ position }: ToasterProps): import('react').ReactPortal | null;
|
|
6
|
+
declare namespace Toaster {
|
|
7
|
+
var displayName: string;
|
|
8
|
+
}
|
|
9
|
+
export { Toaster };
|
|
10
|
+
export type { ToasterProps };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ToastType } from './toast.styles';
|
|
2
|
+
interface ToastOptions {
|
|
3
|
+
duration?: number;
|
|
4
|
+
type?: ToastType;
|
|
5
|
+
}
|
|
6
|
+
interface ToastItem {
|
|
7
|
+
id: string;
|
|
8
|
+
message: string;
|
|
9
|
+
type: ToastType;
|
|
10
|
+
duration: number;
|
|
11
|
+
exiting: boolean;
|
|
12
|
+
}
|
|
13
|
+
type ToastListener = (toasts: ToastItem[]) => void;
|
|
14
|
+
declare class ToastManager {
|
|
15
|
+
private toasts;
|
|
16
|
+
private listeners;
|
|
17
|
+
subscribe(listener: ToastListener): () => void;
|
|
18
|
+
private notify;
|
|
19
|
+
add(message: string, options?: ToastOptions): string;
|
|
20
|
+
dismiss(id: string): void;
|
|
21
|
+
clear(): void;
|
|
22
|
+
getToasts(): ToastItem[];
|
|
23
|
+
}
|
|
24
|
+
declare const manager: ToastManager;
|
|
25
|
+
declare function toast(message: string, options?: ToastOptions): string;
|
|
26
|
+
declare namespace toast {
|
|
27
|
+
var success: (message: string, options?: Omit<ToastOptions, "type">) => string;
|
|
28
|
+
var error: (message: string, options?: Omit<ToastOptions, "type">) => string;
|
|
29
|
+
var warning: (message: string, options?: Omit<ToastOptions, "type">) => string;
|
|
30
|
+
var info: (message: string, options?: Omit<ToastOptions, "type">) => string;
|
|
31
|
+
var dismiss: (id: string) => void;
|
|
32
|
+
var clear: () => void;
|
|
33
|
+
}
|
|
34
|
+
export { manager, toast };
|
|
35
|
+
export type { ToastItem, ToastOptions, ToastListener };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info';
|
|
2
|
+
type ToastPosition = 'top-right' | 'top-left' | 'top-center' | 'bottom-right' | 'bottom-left' | 'bottom-center';
|
|
3
|
+
declare const TOAST_CSS = "\n.syntra-toaster {\n position: fixed;\n z-index: 99999;\n display: flex;\n flex-direction: column;\n gap: 10px;\n pointer-events: none;\n padding: 20px;\n max-height: 100vh;\n overflow: hidden;\n}\n.syntra-toaster[data-position=\"top-right\"] {\n top: 0; right: 0;\n align-items: flex-end;\n}\n.syntra-toaster[data-position=\"top-left\"] {\n top: 0; left: 0;\n align-items: flex-start;\n}\n.syntra-toaster[data-position=\"top-center\"] {\n top: 0; left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n.syntra-toaster[data-position=\"bottom-right\"] {\n bottom: 0; right: 0;\n align-items: flex-end;\n flex-direction: column-reverse;\n}\n.syntra-toaster[data-position=\"bottom-left\"] {\n bottom: 0; left: 0;\n align-items: flex-start;\n flex-direction: column-reverse;\n}\n.syntra-toaster[data-position=\"bottom-center\"] {\n bottom: 0; left: 50%;\n transform: translateX(-50%);\n align-items: center;\n flex-direction: column-reverse;\n}\n\n/* \u2500\u2500 Toast \u2500\u2500 */\n.syntra-toast {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n min-width: 320px;\n max-width: 480px;\n padding: 14px 16px;\n border-radius: 14px;\n background: color-mix(in srgb, var(--syntra-color-background-default) 80%, transparent);\n border: 1px solid var(--syntra-color-border-muted);\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.06);\n backdrop-filter: blur(24px) saturate(180%);\n -webkit-backdrop-filter: blur(24px) saturate(180%);\n pointer-events: auto;\n font-family: inherit;\n font-size: var(--syntra-font-fontSize-sm);\n letter-spacing: -0.01em;\n color: var(--syntra-color-foreground-default);\n animation: syntra-toast-in 300ms cubic-bezier(0.2, 0, 0, 1) forwards;\n}\n.syntra-toast[data-exiting] {\n animation: syntra-toast-out 200ms cubic-bezier(0.4, 0, 1, 1) forwards;\n}\n\n/* Slide directions */\n@keyframes syntra-toast-in {\n from { opacity: 0; transform: translateX(calc(100% + 20px)); }\n to { opacity: 1; transform: translateX(0); }\n}\n@keyframes syntra-toast-out {\n from { opacity: 1; transform: translateX(0); }\n to { opacity: 0; transform: translateX(calc(100% + 20px)); }\n}\n.syntra-toaster[data-position=\"top-left\"] .syntra-toast,\n.syntra-toaster[data-position=\"bottom-left\"] .syntra-toast {\n animation-name: syntra-toast-in-left;\n}\n.syntra-toaster[data-position=\"top-left\"] .syntra-toast[data-exiting],\n.syntra-toaster[data-position=\"bottom-left\"] .syntra-toast[data-exiting] {\n animation-name: syntra-toast-out-left;\n}\n.syntra-toaster[data-position=\"top-center\"] .syntra-toast {\n animation-name: syntra-toast-in-top;\n}\n.syntra-toaster[data-position=\"top-center\"] .syntra-toast[data-exiting] {\n animation-name: syntra-toast-out-top;\n}\n.syntra-toaster[data-position=\"bottom-center\"] .syntra-toast {\n animation-name: syntra-toast-in-bottom;\n}\n.syntra-toaster[data-position=\"bottom-center\"] .syntra-toast[data-exiting] {\n animation-name: syntra-toast-out-bottom;\n}\n\n@keyframes syntra-toast-in-left {\n from { opacity: 0; transform: translateX(calc(-100% - 20px)); }\n to { opacity: 1; transform: translateX(0); }\n}\n@keyframes syntra-toast-out-left {\n from { opacity: 1; transform: translateX(0); }\n to { opacity: 0; transform: translateX(calc(-100% - 20px)); }\n}\n@keyframes syntra-toast-in-top {\n from { opacity: 0; transform: translateY(-100%); }\n to { opacity: 1; transform: translateY(0); }\n}\n@keyframes syntra-toast-out-top {\n from { opacity: 1; transform: translateY(0); }\n to { opacity: 0; transform: translateY(-100%); }\n}\n@keyframes syntra-toast-in-bottom {\n from { opacity: 0; transform: translateY(100%); }\n to { opacity: 1; transform: translateY(0); }\n}\n@keyframes syntra-toast-out-bottom {\n from { opacity: 1; transform: translateY(0); }\n to { opacity: 0; transform: translateY(100%); }\n}\n\n/* \u2500\u2500 Icon \u2500\u2500 */\n.syntra-toast-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 20px;\n height: 20px;\n margin-top: 1px;\n}\n.syntra-toast-icon[data-type=\"success\"] { color: var(--syntra-color-green-500); }\n.syntra-toast-icon[data-type=\"error\"] { color: var(--syntra-color-red-500); }\n.syntra-toast-icon[data-type=\"warning\"] { color: var(--syntra-color-orange-500); }\n.syntra-toast-icon[data-type=\"info\"] { color: var(--syntra-color-blue-500); }\n\n/* \u2500\u2500 Content \u2500\u2500 */\n.syntra-toast-content {\n flex: 1;\n min-width: 0;\n line-height: 1.5;\n padding-top: 1px;\n}\n\n/* \u2500\u2500 Close \u2500\u2500 */\n.syntra-toast-close {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n border: none;\n background: none;\n padding: 0;\n cursor: pointer;\n color: var(--syntra-color-foreground-subtle);\n border-radius: 6px;\n margin-top: -1px;\n transition: background 100ms ease, color 100ms ease;\n}\n.syntra-toast-close:hover {\n background: var(--syntra-color-background-emphasis);\n color: var(--syntra-color-foreground-default);\n}\n.syntra-toast-close:active {\n transform: scale(0.9);\n}\n";
|
|
4
|
+
export { TOAST_CSS };
|
|
5
|
+
export type { ToastType, ToastPosition };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { TooltipPosition } from './tooltip.styles';
|
|
3
|
+
interface TooltipProps {
|
|
4
|
+
label: ReactNode;
|
|
5
|
+
position?: TooltipPosition;
|
|
6
|
+
delay?: number;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
declare function Tooltip({ label, position, delay, disabled, children }: TooltipProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
declare namespace Tooltip {
|
|
12
|
+
var displayName: string;
|
|
13
|
+
}
|
|
14
|
+
export { Tooltip };
|
|
15
|
+
export type { TooltipProps };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';
|
|
2
|
+
declare const TOOLTIP_CSS = "\n.syntra-tooltip-wrapper {\n display: inline-flex;\n position: relative;\n}\n.syntra-tooltip {\n position: fixed;\n z-index: 99999;\n padding: 6px 10px;\n border-radius: 8px;\n background: var(--syntra-color-foreground-default);\n color: var(--syntra-color-background-default);\n font-family: inherit;\n font-size: 12px;\n font-weight: 500;\n letter-spacing: -0.01em;\n line-height: 1.35;\n white-space: nowrap;\n pointer-events: none;\n max-width: 280px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n animation: syntra-tooltip-in 150ms cubic-bezier(0.2, 0, 0, 1);\n}\n@keyframes syntra-tooltip-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n}\n";
|
|
3
|
+
export { TOOLTIP_CSS };
|
|
4
|
+
export type { TooltipPosition };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useControllableState<T>(controlledValue: T | undefined, defaultValue: T, onChange?: (value: T) => void): [T, (value: T | ((prev: T) => T)) => void];
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ export { useSyntra } from './hooks/useSyntra';
|
|
|
4
4
|
export { useSyntraMode } from './hooks/useSyntraMode';
|
|
5
5
|
export { Box, Text, Heading, Flex, Stack, Grid, Divider, VisuallyHidden, resolveStyleProps, extractStyleProps, } from './primitives';
|
|
6
6
|
export type { BoxOwnProps, TextOwnProps, HeadingOwnProps, HeadingLevel, FlexOwnProps, StackOwnProps, GridOwnProps, DividerOwnProps, VisuallyHiddenOwnProps, SyntraStyleProps, SpaceProp, RadiusProp, ShadowProp, PolymorphicProps, PolymorphicPropsWithRef, PolymorphicComponent, } from './primitives';
|
|
7
|
-
export { Button, Input, Spinner } from './components';
|
|
8
|
-
export type { ButtonOwnProps, ButtonVariant, ButtonSize, ButtonColorScheme, InputOwnProps, InputProps, InputVariant, InputSize, SpinnerProps, } from './components';
|
|
7
|
+
export { Button, Input, Spinner, Select, Tabs, TabList, Tab, TabPanel, Toaster, toast, Modal, ModalHeader, ModalBody, ModalFooter, Checkbox, Switch, Badge, Avatar, AvatarGroup, Textarea, Tooltip, } from './components';
|
|
8
|
+
export type { ButtonOwnProps, ButtonVariant, ButtonSize, ButtonColorScheme, InputOwnProps, InputProps, InputVariant, InputSize, SpinnerProps, SelectOwnProps, SelectOption, SelectVariant, SelectSize, TabsOwnProps, TabListOwnProps, TabOwnProps, TabPanelOwnProps, TabsVariant, TabsSize, TabsOrientation, ToasterProps, ToastType, ToastPosition, ToastOptions, ModalOwnProps, ModalSize, CheckboxOwnProps, CheckboxProps, CheckboxSize, SwitchOwnProps, SwitchProps, SwitchSize, BadgeOwnProps, BadgeProps, BadgeVariant, BadgeSize, BadgeColorScheme, AvatarOwnProps, AvatarProps, AvatarGroupProps, AvatarSize, TextareaOwnProps, TextareaProps, TextareaVariant, TextareaSize, TooltipProps, TooltipPosition, } from './components';
|
|
9
9
|
export { cn } from './utils/cn';
|
|
10
10
|
export { createSyntraTheme } from './utils/createSyntraTheme';
|
|
11
11
|
export { generateColorScale } from './utils/colorScale';
|