A design system in a box. hip-ui.tngl.io/docs/introduction
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

invalid/valid/warning states

+5117 -846
+1
README.md
··· 7 7 - [ ] Add Virtualizer 8 8 - [ ] add borderless variant for input fields 9 9 - [ ] perfect inset border radii 10 + - [ ] Number field validation state styling 10 11 11 12 ### Components 12 13
+93 -27
apps/docs/src/components/color-field/index.tsx
··· 10 10 11 11 import { SizeContext } from "../context"; 12 12 import { Description, FieldErrorMessage, Label } from "../label"; 13 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 13 + import { SuffixIcon } from "../suffix-icon"; 14 + import { 15 + InputVariant, 16 + InputValidationState, 17 + Size, 18 + StyleXComponentProps, 19 + } from "../theme/types"; 14 20 import { useInputStyles } from "../theme/useInputStyles"; 15 21 22 + interface ColorFieldContentProps { 23 + label?: React.ReactNode; 24 + description?: string; 25 + errorMessage?: string | ((validation: ValidationResult) => string); 26 + size: Size; 27 + variant: InputVariant | undefined; 28 + validationState: InputValidationState | undefined; 29 + isInvalid: boolean; 30 + prefix?: React.ReactNode; 31 + suffix?: React.ReactNode; 32 + placeholder?: string; 33 + } 34 + 35 + function ColorFieldContent({ 36 + label, 37 + description, 38 + errorMessage, 39 + size, 40 + variant, 41 + validationState, 42 + isInvalid, 43 + prefix, 44 + suffix, 45 + placeholder, 46 + }: ColorFieldContentProps) { 47 + const inputRef = useRef<HTMLInputElement>(null); 48 + const inputStyles = useInputStyles({ 49 + size, 50 + variant, 51 + validationState: isInvalid ? "invalid" : validationState, 52 + }); 53 + 54 + return ( 55 + <> 56 + <Label>{label}</Label> 57 + {/* 58 + This onClick is specifically for mouse users not clicking directly on the input. 59 + A keyboard user would not encounter the same issue. 60 + */} 61 + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 62 + <div 63 + {...stylex.props(inputStyles.wrapper)} 64 + onClick={() => inputRef.current?.focus()} 65 + > 66 + {prefix != null && ( 67 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 68 + )} 69 + <Input 70 + placeholder={placeholder} 71 + ref={inputRef} 72 + {...stylex.props(inputStyles.input)} 73 + /> 74 + <SuffixIcon 75 + suffix={suffix} 76 + style={inputStyles.addon} 77 + validationIconStyle={inputStyles.validationIcon} 78 + validationState={validationState} 79 + /> 80 + </div> 81 + <Description>{description}</Description> 82 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 83 + </> 84 + ); 85 + } 86 + 16 87 export interface ColorFieldProps 17 - extends StyleXComponentProps<AriaColorFieldProps>, 88 + extends StyleXComponentProps<Omit<AriaColorFieldProps, "isInvalid">>, 18 89 Pick<InputProps, "placeholder"> { 19 90 label?: React.ReactNode; 20 91 description?: string; 21 92 errorMessage?: string | ((validation: ValidationResult) => string); 22 93 size?: Size; 23 94 variant?: InputVariant; 95 + validationState?: InputValidationState; 24 96 prefix?: React.ReactNode; 25 97 suffix?: React.ReactNode; 26 98 } ··· 32 104 style, 33 105 size: sizeProp, 34 106 variant, 107 + validationState, 35 108 prefix, 36 109 suffix, 37 110 placeholder, 38 111 ...props 39 112 }: ColorFieldProps) { 40 113 const size = sizeProp || use(SizeContext); 41 - const inputRef = useRef<HTMLInputElement>(null); 42 - const inputStyles = useInputStyles({ size, variant }); 114 + const inputStyles = useInputStyles({ size, variant, validationState }); 43 115 44 116 return ( 45 117 <SizeContext value={size}> 46 - <AriaColorField {...props} {...stylex.props(inputStyles.field, style)}> 47 - <Label>{label}</Label> 48 - {/* 49 - This onClick is specifically for mouse users not clicking directly on the input. 50 - A keyboard user would not encounter the same issue. 51 - */} 52 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 53 - <div 54 - {...stylex.props(inputStyles.wrapper)} 55 - onClick={() => inputRef.current?.focus()} 56 - > 57 - {prefix != null && ( 58 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 59 - )} 60 - <Input 118 + <AriaColorField 119 + {...props} 120 + isInvalid={validationState ? validationState === "invalid" : undefined} 121 + {...stylex.props(inputStyles.field, style)} 122 + > 123 + {({ isInvalid }) => ( 124 + <ColorFieldContent 125 + label={label} 126 + description={description} 127 + errorMessage={errorMessage} 128 + size={size} 129 + variant={variant} 130 + validationState={validationState} 131 + isInvalid={isInvalid} 132 + prefix={prefix} 133 + suffix={suffix} 61 134 placeholder={placeholder} 62 - ref={inputRef} 63 - {...stylex.props(inputStyles.input)} 64 135 /> 65 - {suffix != null && ( 66 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 67 - )} 68 - </div> 69 - <Description>{description}</Description> 70 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 136 + )} 71 137 </AriaColorField> 72 138 </SizeContext> 73 139 );
+128 -42
apps/docs/src/components/combobox/index.tsx
··· 13 13 } from "react-aria-components"; 14 14 15 15 import { SizeContext } from "../context"; 16 - import { IconButton } from "../icon-button"; 17 16 import { Description, FieldErrorMessage, Label } from "../label"; 18 17 import { ListBox } from "../listbox"; 18 + import { SuffixIcon } from "../suffix-icon"; 19 19 import { spacing } from "../theme/spacing.stylex"; 20 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 20 + import { 21 + InputVariant, 22 + InputValidationState, 23 + Size, 24 + StyleXComponentProps, 25 + } from "../theme/types"; 21 26 import { useInputStyles } from "../theme/useInputStyles"; 22 27 import { usePopoverStyles } from "../theme/usePopoverStyles"; 23 28 import { SmallBody } from "../typography"; ··· 27 32 width: "var(--trigger-width)", 28 33 }, 29 34 emptyState: { 35 + padding: spacing["4"], 30 36 display: "flex", 31 37 justifyContent: "center", 32 - padding: spacing["4"], 33 38 }, 34 39 }); 35 40 ··· 41 46 ); 42 47 } 43 48 49 + interface ComboBoxContentProps<T extends object> { 50 + label?: string; 51 + description?: string; 52 + errorMessage?: string | ((validation: ValidationResult) => string); 53 + size: Size; 54 + variant: InputVariant | undefined; 55 + validationState: InputValidationState | undefined; 56 + isInvalid: boolean; 57 + placeholder: string; 58 + prefix?: React.ReactNode; 59 + suffix?: React.ReactNode; 60 + items?: Iterable<T>; 61 + children: React.ReactNode | ((item: T) => React.ReactNode); 62 + shouldCloseOnInteractOutside?: ((element: Element) => boolean) | undefined; 63 + shouldFlip?: boolean; 64 + shouldUpdatePosition?: boolean; 65 + placement?: PopoverProps["placement"]; 66 + renderEmptyState?: ListBoxProps<T>["renderEmptyState"]; 67 + } 68 + 69 + function ComboBoxContent<T extends object>({ 70 + label, 71 + description, 72 + errorMessage, 73 + size, 74 + variant, 75 + validationState, 76 + isInvalid: _isInvalid, 77 + placeholder, 78 + prefix, 79 + suffix, 80 + items, 81 + children, 82 + shouldCloseOnInteractOutside, 83 + shouldFlip, 84 + shouldUpdatePosition, 85 + placement, 86 + renderEmptyState, 87 + }: ComboBoxContentProps<T>) { 88 + const inputStyles = useInputStyles({ 89 + size, 90 + variant, 91 + validationState: _isInvalid ? "invalid" : validationState, 92 + }); 93 + const popoverStyles = usePopoverStyles(); 94 + 95 + return ( 96 + <> 97 + <Label>{label}</Label> 98 + <Button {...stylex.props(inputStyles.wrapper)}> 99 + {prefix != null && ( 100 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 101 + )} 102 + <Input {...stylex.props(inputStyles.input)} placeholder={placeholder} /> 103 + <SuffixIcon 104 + suffix={ 105 + <> 106 + {suffix} 107 + <ChevronDown size={16} aria-hidden="true" /> 108 + </> 109 + } 110 + style={inputStyles.addon} 111 + validationIconStyle={inputStyles.validationIcon} 112 + validationState={validationState} 113 + /> 114 + </Button> 115 + <Description>{description}</Description> 116 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 117 + <Popover 118 + containerPadding={8} 119 + shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 120 + shouldFlip={shouldFlip} 121 + shouldUpdatePosition={shouldUpdatePosition} 122 + placement={placement} 123 + {...stylex.props( 124 + popoverStyles.wrapper, 125 + popoverStyles.animation, 126 + styles.matchWidth, 127 + )} 128 + > 129 + <ListBox 130 + items={items} 131 + renderEmptyState={renderEmptyState || EmptyState} 132 + > 133 + {children} 134 + </ListBox> 135 + </Popover> 136 + </> 137 + ); 138 + } 139 + 44 140 export interface ComboBoxProps<T extends object> 45 - extends StyleXComponentProps<Omit<AriaComboBoxProps<T>, "children">>, 141 + extends StyleXComponentProps< 142 + Omit<AriaComboBoxProps<T>, "children" | "isInvalid"> 143 + >, 46 144 Pick< 47 145 PopoverProps, 48 146 | "shouldCloseOnInteractOutside" ··· 58 156 children: React.ReactNode | ((item: T) => React.ReactNode); 59 157 size?: Size; 60 158 variant?: InputVariant; 159 + validationState?: InputValidationState; 61 160 placeholder?: string; 62 161 prefix?: React.ReactNode; 63 162 suffix?: React.ReactNode; ··· 72 171 style, 73 172 size: sizeProp, 74 173 variant, 174 + validationState, 75 175 shouldCloseOnInteractOutside, 76 176 shouldFlip, 77 177 shouldUpdatePosition, ··· 83 183 ...props 84 184 }: ComboBoxProps<T>) { 85 185 const size = sizeProp || use(SizeContext); 86 - const inputStyles = useInputStyles({ size, variant }); 87 - const popoverStyles = usePopoverStyles(); 186 + const inputStyles = useInputStyles({ size, variant, validationState }); 88 187 89 188 return ( 90 189 <SizeContext value={size}> 91 - <AriaComboBox {...props} {...stylex.props(inputStyles.field, style)}> 92 - <Label>{label}</Label> 93 - <Button {...stylex.props(inputStyles.wrapper)}> 94 - {prefix != null && ( 95 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 96 - )} 97 - <Input 98 - {...stylex.props(inputStyles.input)} 190 + <AriaComboBox 191 + {...props} 192 + isInvalid={validationState ? validationState === "invalid" : undefined} 193 + {...stylex.props(inputStyles.field, style)} 194 + > 195 + {({ isInvalid }) => ( 196 + <ComboBoxContent 197 + label={label} 198 + description={description} 199 + errorMessage={errorMessage} 200 + size={size} 201 + variant={variant} 202 + validationState={validationState} 203 + isInvalid={isInvalid} 99 204 placeholder={placeholder} 100 - /> 101 - {suffix != null && ( 102 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 103 - )} 104 - <div {...stylex.props(inputStyles.addon)}> 105 - <IconButton size="sm" variant="secondary" label="Open combobox"> 106 - <ChevronDown size={16} aria-hidden="true" /> 107 - </IconButton> 108 - </div> 109 - </Button> 110 - <Description>{description}</Description> 111 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 112 - <Popover 113 - containerPadding={8} 114 - shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 115 - shouldFlip={shouldFlip} 116 - shouldUpdatePosition={shouldUpdatePosition} 117 - placement={placement} 118 - {...stylex.props( 119 - popoverStyles.wrapper, 120 - popoverStyles.animation, 121 - styles.matchWidth, 122 - )} 123 - > 124 - <ListBox 205 + prefix={prefix} 206 + suffix={suffix} 125 207 items={items} 126 - renderEmptyState={renderEmptyState || EmptyState} 208 + shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 209 + shouldFlip={shouldFlip} 210 + shouldUpdatePosition={shouldUpdatePosition} 211 + placement={placement} 212 + renderEmptyState={renderEmptyState} 127 213 > 128 214 {children} 129 - </ListBox> 130 - </Popover> 215 + </ComboBoxContent> 216 + )} 131 217 </AriaComboBox> 132 218 </SizeContext> 133 219 );
+90 -27
apps/docs/src/components/date-field/index.tsx
··· 11 11 12 12 import { SizeContext } from "../context"; 13 13 import { Description, FieldErrorMessage, Label } from "../label"; 14 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 14 + import { SuffixIcon } from "../suffix-icon"; 15 + import { 16 + InputVariant, 17 + InputValidationState, 18 + Size, 19 + StyleXComponentProps, 20 + } from "../theme/types"; 15 21 import { useInputStyles } from "../theme/useInputStyles"; 16 22 23 + interface DateFieldContentProps { 24 + label?: React.ReactNode; 25 + description?: string; 26 + errorMessage?: string | ((validation: ValidationResult) => string); 27 + size: Size; 28 + variant: InputVariant | undefined; 29 + validationState: InputValidationState | undefined; 30 + isInvalid: boolean; 31 + prefix?: React.ReactNode; 32 + suffix?: React.ReactNode; 33 + } 34 + 35 + function DateFieldContent({ 36 + label, 37 + description, 38 + errorMessage, 39 + size, 40 + variant, 41 + validationState, 42 + isInvalid, 43 + prefix, 44 + suffix, 45 + }: DateFieldContentProps) { 46 + const inputRef = useRef<HTMLInputElement>(null); 47 + const inputStyles = useInputStyles({ 48 + size, 49 + variant, 50 + validationState: isInvalid ? "invalid" : validationState, 51 + }); 52 + 53 + return ( 54 + <> 55 + <Label>{label}</Label> 56 + {/* 57 + This onClick is specifically for mouse users not clicking directly on the input. 58 + A keyboard user would not encounter the same issue. 59 + */} 60 + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 61 + <div 62 + {...stylex.props(inputStyles.wrapper)} 63 + onClick={() => inputRef.current?.focus()} 64 + > 65 + {prefix != null && ( 66 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 67 + )} 68 + <DateInput {...stylex.props(inputStyles.input)} ref={inputRef}> 69 + {(segment) => <DateSegment segment={segment} />} 70 + </DateInput> 71 + <SuffixIcon 72 + suffix={suffix} 73 + style={inputStyles.addon} 74 + validationIconStyle={inputStyles.validationIcon} 75 + validationState={validationState} 76 + /> 77 + </div> 78 + <Description>{description}</Description> 79 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 80 + </> 81 + ); 82 + } 83 + 17 84 export interface DateFieldProps<T extends DateValue> 18 - extends StyleXComponentProps<AriaDateFieldProps<T>> { 85 + extends StyleXComponentProps<Omit<AriaDateFieldProps<T>, "isInvalid">> { 19 86 label?: React.ReactNode; 20 87 description?: string; 21 88 errorMessage?: string | ((validation: ValidationResult) => string); 22 89 size?: Size; 23 90 variant?: InputVariant; 91 + validationState?: InputValidationState; 24 92 prefix?: React.ReactNode; 25 93 suffix?: React.ReactNode; 26 94 } ··· 32 100 style, 33 101 size: sizeProp, 34 102 variant, 103 + validationState, 35 104 prefix, 36 105 suffix, 37 106 ...props 38 107 }: DateFieldProps<T>) { 39 108 const size = sizeProp || use(SizeContext); 40 - const inputRef = useRef<HTMLInputElement>(null); 41 - const inputStyles = useInputStyles({ size, variant }); 109 + const inputStyles = useInputStyles({ size, variant, validationState }); 42 110 43 111 return ( 44 112 <SizeContext value={size}> 45 - <AriaDateField {...props} {...stylex.props(inputStyles.field, style)}> 46 - <Label>{label}</Label> 47 - {/* 48 - This onClick is specifically for mouse users not clicking directly on the input. 49 - A keyboard user would not encounter the same issue. 50 - */} 51 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 52 - <div 53 - {...stylex.props(inputStyles.wrapper)} 54 - onClick={() => inputRef.current?.focus()} 55 - > 56 - {prefix != null && ( 57 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 58 - )} 59 - <DateInput {...stylex.props(inputStyles.input)} ref={inputRef}> 60 - {(segment) => <DateSegment segment={segment} />} 61 - </DateInput> 62 - {suffix != null && ( 63 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 64 - )} 65 - </div> 66 - <Description>{description}</Description> 67 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 113 + <AriaDateField 114 + {...props} 115 + isInvalid={validationState ? validationState === "invalid" : undefined} 116 + {...stylex.props(inputStyles.field, style)} 117 + > 118 + {({ isInvalid }) => ( 119 + <DateFieldContent 120 + label={label} 121 + description={description} 122 + errorMessage={errorMessage} 123 + size={size} 124 + variant={variant} 125 + validationState={validationState} 126 + isInvalid={isInvalid} 127 + prefix={prefix} 128 + suffix={suffix} 129 + /> 130 + )} 68 131 </AriaDateField> 69 132 </SizeContext> 70 133 );
+85 -30
apps/docs/src/components/date-picker/index.tsx
··· 17 17 import { IconButton } from "../icon-button"; 18 18 import { Description, FieldErrorMessage, Label } from "../label"; 19 19 import { spacing } from "../theme/spacing.stylex"; 20 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 20 + import { 21 + InputVariant, 22 + InputValidationState, 23 + Size, 24 + StyleXComponentProps, 25 + } from "../theme/types"; 21 26 import { useInputStyles } from "../theme/useInputStyles"; 22 27 import { usePopoverStyles } from "../theme/usePopoverStyles"; 23 28 24 29 export interface DatePickerProps<T extends DateValue> 25 - extends StyleXComponentProps<AriaDatePickerProps<T>>, 30 + extends StyleXComponentProps<Omit<AriaDatePickerProps<T>, "isInvalid">>, 26 31 Pick<CalendarProps<T>, "weekdayStyle" | "visibleDuration"> { 27 32 label?: React.ReactNode; 28 33 description?: string; 29 34 errorMessage?: string | ((validation: ValidationResult) => string); 30 35 size?: Size; 31 36 variant?: InputVariant; 37 + validationState?: InputValidationState; 32 38 } 33 39 34 40 const styles = stylex.create({ ··· 37 43 }, 38 44 }); 39 45 46 + interface DatePickerContentProps<T extends DateValue> { 47 + label?: React.ReactNode; 48 + description?: string; 49 + errorMessage?: string | ((validation: ValidationResult) => string); 50 + size: Size; 51 + variant: InputVariant | undefined; 52 + validationState: InputValidationState | undefined; 53 + isInvalid: boolean; 54 + weekdayStyle?: CalendarProps<T>["weekdayStyle"]; 55 + visibleDuration?: CalendarProps<T>["visibleDuration"]; 56 + } 57 + 58 + function DatePickerContent<T extends DateValue>({ 59 + label, 60 + description, 61 + errorMessage, 62 + size: _size, 63 + variant, 64 + validationState, 65 + isInvalid: _isInvalid, 66 + weekdayStyle, 67 + visibleDuration, 68 + }: DatePickerContentProps<T>) { 69 + const popoverStyles = usePopoverStyles(); 70 + 71 + return ( 72 + <> 73 + <Label>{label}</Label> 74 + <Group> 75 + <DateField 76 + variant={variant} 77 + validationState={validationState} 78 + suffix={ 79 + <IconButton 80 + size="sm" 81 + aria-label="Open date picker" 82 + variant="tertiary" 83 + > 84 + <CalendarIcon /> 85 + </IconButton> 86 + } 87 + /> 88 + </Group> 89 + <Description>{description}</Description> 90 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 91 + <AriaPopover 92 + {...stylex.props(popoverStyles.wrapper, popoverStyles.animation)} 93 + > 94 + <Dialog {...stylex.props(styles.popoverContent)}> 95 + <Calendar 96 + weekdayStyle={weekdayStyle} 97 + visibleDuration={visibleDuration} 98 + /> 99 + </Dialog> 100 + </AriaPopover> 101 + </> 102 + ); 103 + } 104 + 40 105 export function DatePicker<T extends DateValue>({ 41 106 label, 42 107 description, ··· 46 111 weekdayStyle, 47 112 visibleDuration, 48 113 variant, 114 + validationState, 49 115 ...props 50 116 }: DatePickerProps<T>) { 51 117 const size = sizeProp || use(SizeContext); 52 - const inputStyles = useInputStyles({ size, variant }); 53 - const popoverStyles = usePopoverStyles(); 118 + const inputStyles = useInputStyles({ size, variant, validationState }); 54 119 55 120 return ( 56 121 <SizeContext value={size}> 57 - <AriaDatePicker {...props} {...stylex.props(inputStyles.field, style)}> 58 - <Label>{label}</Label> 59 - <Group> 60 - <DateField 122 + <AriaDatePicker 123 + {...props} 124 + isInvalid={validationState ? validationState === "invalid" : undefined} 125 + {...stylex.props(inputStyles.field, style)} 126 + > 127 + {({ isInvalid }) => ( 128 + <DatePickerContent 129 + label={label} 130 + description={description} 131 + errorMessage={errorMessage} 132 + size={size} 61 133 variant={variant} 62 - suffix={ 63 - <IconButton 64 - size="sm" 65 - aria-label="Open date picker" 66 - variant="tertiary" 67 - > 68 - <CalendarIcon /> 69 - </IconButton> 70 - } 134 + validationState={validationState} 135 + isInvalid={isInvalid} 136 + weekdayStyle={weekdayStyle} 137 + visibleDuration={visibleDuration} 71 138 /> 72 - </Group> 73 - <Description>{description}</Description> 74 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 75 - <AriaPopover 76 - {...stylex.props(popoverStyles.wrapper, popoverStyles.animation)} 77 - > 78 - <Dialog {...stylex.props(styles.popoverContent)}> 79 - <Calendar 80 - weekdayStyle={weekdayStyle} 81 - visibleDuration={visibleDuration} 82 - /> 83 - </Dialog> 84 - </AriaPopover> 139 + )} 85 140 </AriaDatePicker> 86 141 </SizeContext> 87 142 );
+114 -56
apps/docs/src/components/date-range-picker/index.tsx
··· 17 17 import { IconButton } from "../icon-button"; 18 18 import { Description, FieldErrorMessage, Label } from "../label"; 19 19 import { RangeCalendar, RangeCalendarProps } from "../range-calendar"; 20 + import { SuffixIcon } from "../suffix-icon"; 20 21 import { uiColor } from "../theme/semantic-color.stylex"; 21 22 import { spacing } from "../theme/spacing.stylex"; 22 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 23 + import { 24 + InputVariant, 25 + InputValidationState, 26 + Size, 27 + StyleXComponentProps, 28 + } from "../theme/types"; 23 29 import { fontSize } from "../theme/typography.stylex"; 24 30 import { useInputStyles } from "../theme/useInputStyles"; 25 31 import { usePopoverStyles } from "../theme/usePopoverStyles"; 26 32 27 33 export interface DateRangePickerProps<T extends DateValue> 28 - extends StyleXComponentProps<AriaDateRangePickerProps<T>>, 34 + extends StyleXComponentProps<Omit<AriaDateRangePickerProps<T>, "isInvalid">>, 29 35 Pick<RangeCalendarProps<T>, "weekdayStyle" | "visibleDuration"> { 30 36 label?: React.ReactNode; 31 37 description?: string; 32 38 errorMessage?: string | ((validation: ValidationResult) => string); 33 39 size?: Size; 34 40 variant?: InputVariant; 41 + validationState?: InputValidationState; 35 42 } 36 43 37 44 const styles = stylex.create({ 38 45 group: { 46 + gap: spacing["1"], 39 47 alignItems: "center", 40 48 display: "flex", 41 - gap: spacing["1"], 42 49 43 50 fontSize: { 44 - ":is([data-size=sm])": fontSize["xs"], 51 + ":is([data-size=lg])": fontSize["base"], 45 52 ":is([data-size=md])": fontSize["sm"], 46 - ":is([data-size=lg])": fontSize["base"], 53 + ":is([data-size=sm])": fontSize["xs"], 47 54 }, 48 55 }, 49 56 popoverContent: { ··· 51 58 }, 52 59 separator: { 53 60 paddingRight: { 54 - ":is([data-size=sm] *)": spacing["1"], 55 - ":is([data-size=md] *)": spacing["2"], 56 61 ":is([data-size=lg] *)": spacing["1"], 62 + ":is([data-size=md] *)": spacing["2"], 63 + ":is([data-size=sm] *)": spacing["1"], 57 64 }, 58 65 }, 59 66 lastInput: { ··· 66 73 }, 67 74 }); 68 75 76 + interface DateRangePickerContentProps<T extends DateValue> { 77 + label?: React.ReactNode; 78 + description?: string; 79 + errorMessage?: string | ((validation: ValidationResult) => string); 80 + size: Size; 81 + variant: InputVariant | undefined; 82 + validationState: InputValidationState | undefined; 83 + isInvalid: boolean; 84 + weekdayStyle?: RangeCalendarProps<T>["weekdayStyle"]; 85 + visibleDuration?: RangeCalendarProps<T>["visibleDuration"]; 86 + } 87 + 88 + function DateRangePickerContent<T extends DateValue>({ 89 + label, 90 + description, 91 + errorMessage, 92 + size, 93 + variant, 94 + validationState, 95 + isInvalid, 96 + weekdayStyle, 97 + visibleDuration, 98 + }: DateRangePickerContentProps<T>) { 99 + const inputStyles = useInputStyles({ 100 + size, 101 + variant, 102 + validationState: isInvalid ? "invalid" : validationState, 103 + }); 104 + const popoverStyles = usePopoverStyles(); 105 + 106 + return ( 107 + <> 108 + <Label>{label}</Label> 109 + <Group 110 + data-size={size} 111 + {...stylex.props(inputStyles.wrapper, styles.group)} 112 + > 113 + <DateInput slot="start" {...stylex.props(inputStyles.input)}> 114 + {(segment) => ( 115 + <DateSegment segment={segment} {...stylex.props(styles.segment)} /> 116 + )} 117 + </DateInput> 118 + <div aria-hidden="true" {...stylex.props(styles.separator)}> 119 + - 120 + </div> 121 + <DateInput 122 + slot="end" 123 + {...stylex.props(inputStyles.input, styles.lastInput)} 124 + > 125 + {(segment) => ( 126 + <DateSegment segment={segment} {...stylex.props(styles.segment)} /> 127 + )} 128 + </DateInput> 129 + <SuffixIcon 130 + suffix={ 131 + <IconButton 132 + size="sm" 133 + aria-label="Open date picker" 134 + variant="tertiary" 135 + > 136 + <CalendarIcon /> 137 + </IconButton> 138 + } 139 + style={inputStyles.addon} 140 + validationIconStyle={inputStyles.validationIcon} 141 + validationState={validationState} 142 + /> 143 + </Group> 144 + <Description>{description}</Description> 145 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 146 + <AriaPopover 147 + {...stylex.props(popoverStyles.wrapper, popoverStyles.animation)} 148 + > 149 + <Dialog {...stylex.props(styles.popoverContent)}> 150 + <RangeCalendar 151 + weekdayStyle={weekdayStyle} 152 + visibleDuration={visibleDuration} 153 + /> 154 + </Dialog> 155 + </AriaPopover> 156 + </> 157 + ); 158 + } 159 + 69 160 export function DateRangePicker<T extends DateValue>({ 70 161 label, 71 162 description, ··· 75 166 weekdayStyle, 76 167 visibleDuration, 77 168 variant, 169 + validationState, 78 170 ...props 79 171 }: DateRangePickerProps<T>) { 80 172 const size = sizeProp || use(SizeContext); 81 - const inputStyles = useInputStyles({ size, variant }); 82 - const popoverStyles = usePopoverStyles(); 173 + const inputStyles = useInputStyles({ size, variant, validationState }); 83 174 84 175 return ( 85 176 <SizeContext value={size}> 86 177 <AriaDateRangePicker 87 178 {...props} 179 + isInvalid={validationState ? validationState === "invalid" : undefined} 88 180 {...stylex.props(inputStyles.field, style)} 89 181 > 90 - <Label>{label}</Label> 91 - <Group 92 - data-size={size} 93 - {...stylex.props(inputStyles.wrapper, styles.group)} 94 - > 95 - <DateInput slot="start" {...stylex.props(inputStyles.input)}> 96 - {(segment) => ( 97 - <DateSegment 98 - segment={segment} 99 - {...stylex.props(styles.segment)} 100 - /> 101 - )} 102 - </DateInput> 103 - <div aria-hidden="true" {...stylex.props(styles.separator)}> 104 - - 105 - </div> 106 - <DateInput 107 - slot="end" 108 - {...stylex.props(inputStyles.input, styles.lastInput)} 109 - > 110 - {(segment) => ( 111 - <DateSegment 112 - segment={segment} 113 - {...stylex.props(styles.segment)} 114 - /> 115 - )} 116 - </DateInput> 117 - <IconButton 118 - size="sm" 119 - aria-label="Open date picker" 120 - variant="tertiary" 121 - > 122 - <CalendarIcon /> 123 - </IconButton> 124 - </Group> 125 - <Description>{description}</Description> 126 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 127 - <AriaPopover 128 - {...stylex.props(popoverStyles.wrapper, popoverStyles.animation)} 129 - > 130 - <Dialog {...stylex.props(styles.popoverContent)}> 131 - <RangeCalendar 132 - weekdayStyle={weekdayStyle} 133 - visibleDuration={visibleDuration} 134 - /> 135 - </Dialog> 136 - </AriaPopover> 182 + {({ isInvalid }) => ( 183 + <DateRangePickerContent 184 + label={label} 185 + description={description} 186 + errorMessage={errorMessage} 187 + size={size} 188 + variant={variant} 189 + validationState={validationState} 190 + isInvalid={isInvalid} 191 + weekdayStyle={weekdayStyle} 192 + visibleDuration={visibleDuration} 193 + /> 194 + )} 137 195 </AriaDateRangePicker> 138 196 </SizeContext> 139 197 );
+117 -46
apps/docs/src/components/number-field/index.tsx
··· 17 17 18 18 import { SizeContext } from "../context"; 19 19 import { Description, FieldErrorMessage, Label } from "../label"; 20 + import { SuffixIcon } from "../suffix-icon"; 20 21 import { ui, uiColor } from "../theme/semantic-color.stylex"; 21 22 import { spacing } from "../theme/spacing.stylex"; 22 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 23 + import { 24 + InputVariant, 25 + InputValidationState, 26 + Size, 27 + StyleXComponentProps, 28 + } from "../theme/types"; 23 29 import { useInputStyles } from "../theme/useInputStyles"; 24 30 import { usePointerLock } from "./usePointerLock"; 25 31 ··· 81 87 display: "flex", 82 88 }, 83 89 button: { 90 + borderWidth: 0, 84 91 alignItems: "center", 92 + display: "flex", 93 + flexGrow: 1, 94 + justifyContent: "center", 85 95 borderBottomWidth: 0, 86 96 borderLeftStyle: "solid", 87 97 borderLeftWidth: 1, 88 98 borderRightWidth: 0, 89 99 borderTopWidth: 0, 90 - borderWidth: 0, 91 - display: "flex", 92 - flexGrow: 1, 93 - justifyContent: "center", 94 100 minHeight: 0, 95 101 96 102 // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 97 103 ":is(*) svg": { 98 104 flexShrink: 0, 105 + pointerEvents: "none", 99 106 height: spacing["4"], 100 - pointerEvents: "none", 101 107 width: spacing["4"], 102 108 }, 103 109 ··· 108 114 }, 109 115 }); 110 116 117 + interface NumberFieldContentProps { 118 + label?: React.ReactNode; 119 + description?: string; 120 + errorMessage?: string | ((validation: ValidationResult) => string); 121 + size: Size; 122 + variant: InputVariant | undefined; 123 + validationState: InputValidationState | undefined; 124 + isInvalid: boolean; 125 + prefix?: React.ReactNode; 126 + suffix?: React.ReactNode; 127 + placeholder?: string; 128 + hideStepper: boolean; 129 + } 130 + 131 + function NumberFieldContent({ 132 + label, 133 + description, 134 + errorMessage, 135 + size, 136 + variant, 137 + validationState, 138 + isInvalid, 139 + prefix, 140 + suffix, 141 + placeholder, 142 + hideStepper, 143 + }: NumberFieldContentProps) { 144 + const inputRef = useRef<HTMLInputElement>(null); 145 + const inputStyles = useInputStyles({ 146 + size, 147 + variant, 148 + validationState: isInvalid ? "invalid" : validationState, 149 + }); 150 + const buttonStyles = stylex.props( 151 + styles.button, 152 + ui.borderInteractive, 153 + ui.bgAction, 154 + ); 155 + 156 + return ( 157 + <> 158 + <Label>{label}</Label> 159 + {/* 160 + This onClick is specifically for mouse users not clicking directly on the input. 161 + A keyboard user would not encounter the same issue. 162 + */} 163 + <NumberInputWrapper 164 + style={inputStyles.wrapper} 165 + onClick={() => inputRef.current?.focus()} 166 + > 167 + {prefix != null && ( 168 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 169 + )} 170 + <Input 171 + placeholder={placeholder} 172 + ref={inputRef} 173 + {...stylex.props(styles.input, inputStyles.input)} 174 + /> 175 + <SuffixIcon 176 + suffix={suffix} 177 + style={inputStyles.addon} 178 + validationIconStyle={inputStyles.validationIcon} 179 + validationState={validationState} 180 + /> 181 + {!hideStepper && ( 182 + <Group {...stylex.props(styles.buttons)}> 183 + <Button slot="decrement" {...buttonStyles}> 184 + <Minus /> 185 + </Button> 186 + <Button slot="increment" {...buttonStyles}> 187 + <Plus /> 188 + </Button> 189 + </Group> 190 + )} 191 + </NumberInputWrapper> 192 + <Description>{description}</Description> 193 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 194 + </> 195 + ); 196 + } 197 + 111 198 export interface NumberFieldProps 112 - extends StyleXComponentProps<Omit<AriaNumberFieldProps, "children">>, 199 + extends StyleXComponentProps< 200 + Omit<AriaNumberFieldProps, "children" | "isInvalid"> 201 + >, 113 202 Pick<InputProps, "placeholder"> { 114 203 label?: React.ReactNode; 115 204 description?: string; 116 205 errorMessage?: string | ((validation: ValidationResult) => string); 117 206 size?: Size; 118 207 variant?: InputVariant; 208 + validationState?: InputValidationState; 119 209 prefix?: React.ReactNode; 120 210 suffix?: React.ReactNode; 121 211 hideStepper?: boolean; ··· 128 218 style, 129 219 size: sizeProp, 130 220 variant, 221 + validationState, 131 222 prefix, 132 223 suffix, 133 224 placeholder, ··· 135 226 ...props 136 227 }: NumberFieldProps) { 137 228 const size = sizeProp || use(SizeContext); 138 - const inputRef = useRef<HTMLInputElement>(null); 139 - const inputStyles = useInputStyles({ size, variant }); 140 - const buttonStyles = stylex.props( 141 - styles.button, 142 - ui.borderInteractive, 143 - ui.bgAction, 144 - ); 229 + const inputStyles = useInputStyles({ size, variant, validationState }); 145 230 146 231 return ( 147 232 <SizeContext value={size}> 148 - <AriaNumberField {...props} {...stylex.props(inputStyles.field, style)}> 149 - <Label>{label}</Label> 150 - {/* 151 - This onClick is specifically for mouse users not clicking directly on the input. 152 - A keyboard user would not encounter the same issue. 153 - */} 154 - <NumberInputWrapper 155 - style={inputStyles.wrapper} 156 - onClick={() => inputRef.current?.focus()} 157 - > 158 - {prefix != null && ( 159 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 160 - )} 161 - <Input 233 + <AriaNumberField 234 + {...props} 235 + isInvalid={validationState ? validationState === "invalid" : undefined} 236 + {...stylex.props(inputStyles.field, style)} 237 + > 238 + {({ isInvalid }) => ( 239 + <NumberFieldContent 240 + label={label} 241 + description={description} 242 + errorMessage={errorMessage} 243 + size={size} 244 + variant={variant} 245 + validationState={validationState} 246 + isInvalid={isInvalid} 247 + prefix={prefix} 248 + suffix={suffix} 162 249 placeholder={placeholder} 163 - ref={inputRef} 164 - {...stylex.props(styles.input, inputStyles.input)} 250 + hideStepper={hideStepper} 165 251 /> 166 - {suffix != null && ( 167 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 168 - )} 169 - {!hideStepper && ( 170 - <Group {...stylex.props(styles.buttons)}> 171 - <Button slot="decrement" {...buttonStyles}> 172 - <Minus /> 173 - </Button> 174 - <Button slot="increment" {...buttonStyles}> 175 - <Plus /> 176 - </Button> 177 - </Group> 178 - )} 179 - </NumberInputWrapper> 180 - <Description>{description}</Description> 181 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 252 + )} 182 253 </AriaNumberField> 183 254 </SizeContext> 184 255 );
+109 -50
apps/docs/src/components/search-field/index.tsx
··· 12 12 import { SizeContext } from "../context"; 13 13 import { IconButton } from "../icon-button"; 14 14 import { Description, FieldErrorMessage, Label } from "../label"; 15 + import { SuffixIcon } from "../suffix-icon"; 15 16 import { spacing } from "../theme/spacing.stylex"; 16 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 17 + import { 18 + InputVariant, 19 + InputValidationState, 20 + Size, 21 + StyleXComponentProps, 22 + } from "../theme/types"; 17 23 import { useInputStyles } from "../theme/useInputStyles"; 18 24 19 25 const styles = stylex.create({ ··· 22 28 }, 23 29 clearButton: { 24 30 position: "absolute", 31 + transform: "translateY(-50%)", 25 32 right: 0, 26 33 top: "50%", 27 - transform: "translateY(-50%)", 28 34 }, 29 35 clearButtonPadding: { 30 36 paddingRight: spacing["8"], 31 37 }, 32 38 }); 33 39 40 + interface SearchFieldContentProps { 41 + label?: React.ReactNode; 42 + description?: string; 43 + errorMessage?: string | ((validation: ValidationResult) => string); 44 + size: Size; 45 + variant: InputVariant | undefined; 46 + validationState: InputValidationState | undefined; 47 + isInvalid: boolean; 48 + prefix?: React.ReactNode; 49 + suffix?: React.ReactNode; 50 + placeholder?: string; 51 + isEmpty: boolean; 52 + } 53 + 54 + function SearchFieldContent({ 55 + label, 56 + description, 57 + errorMessage, 58 + size, 59 + variant, 60 + validationState, 61 + isInvalid, 62 + prefix, 63 + suffix, 64 + placeholder, 65 + isEmpty, 66 + }: SearchFieldContentProps) { 67 + const inputRef = useRef<HTMLInputElement>(null); 68 + const inputStyles = useInputStyles({ 69 + size, 70 + variant, 71 + validationState: isInvalid ? "invalid" : validationState, 72 + }); 73 + 74 + return ( 75 + <> 76 + <Label>{label}</Label> 77 + {/* 78 + This onClick is specifically for mouse users not clicking directly on the input. 79 + A keyboard user would not encounter the same issue. 80 + */} 81 + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 82 + <div 83 + {...stylex.props(inputStyles.wrapper, styles.wrapper)} 84 + onClick={() => inputRef.current?.focus()} 85 + > 86 + {prefix != null && ( 87 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 88 + )} 89 + <Input 90 + placeholder={placeholder} 91 + ref={inputRef} 92 + {...stylex.props( 93 + inputStyles.input, 94 + !isEmpty && styles.clearButtonPadding, 95 + )} 96 + /> 97 + <SuffixIcon 98 + suffix={suffix} 99 + style={inputStyles.addon} 100 + validationIconStyle={inputStyles.validationIcon} 101 + validationState={validationState} 102 + /> 103 + {!isEmpty && ( 104 + <div {...stylex.props(inputStyles.addon, styles.clearButton)}> 105 + <IconButton label="Clear search" size="sm" variant="secondary"> 106 + <X /> 107 + </IconButton> 108 + </div> 109 + )} 110 + </div> 111 + <Description>{description}</Description> 112 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 113 + </> 114 + ); 115 + } 116 + 34 117 export interface SearchFieldProps 35 - extends StyleXComponentProps<AriaSearchFieldProps>, 118 + extends StyleXComponentProps<Omit<AriaSearchFieldProps, "isInvalid">>, 36 119 Pick<InputProps, "placeholder"> { 37 120 label?: React.ReactNode; 38 121 description?: string; 39 122 errorMessage?: string | ((validation: ValidationResult) => string); 40 123 size?: Size; 41 124 variant?: InputVariant; 125 + validationState?: InputValidationState; 42 126 prefix?: React.ReactNode; 43 127 suffix?: React.ReactNode; 44 128 } ··· 52 136 style, 53 137 size: sizeProp, 54 138 variant, 139 + validationState, 55 140 prefix = defaultPrefix, 56 141 suffix, 57 142 placeholder, 58 143 ...props 59 144 }: SearchFieldProps) { 60 145 const size = sizeProp || use(SizeContext); 61 - const inputRef = useRef<HTMLInputElement>(null); 62 - const inputStyles = useInputStyles({ size, variant }); 146 + const inputStyles = useInputStyles({ size, variant, validationState }); 63 147 64 148 return ( 65 149 <SizeContext value={size}> 66 - <AriaSearchField {...props} {...stylex.props(inputStyles.field, style)}> 67 - {({ isEmpty }) => { 68 - return ( 69 - <> 70 - <Label>{label}</Label> 71 - {/* 72 - This onClick is specifically for mouse users not clicking directly on the input. 73 - A keyboard user would not encounter the same issue. 74 - */} 75 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 76 - <div 77 - {...stylex.props(inputStyles.wrapper, styles.wrapper)} 78 - onClick={() => inputRef.current?.focus()} 79 - > 80 - {prefix != null && ( 81 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 82 - )} 83 - <Input 84 - placeholder={placeholder} 85 - ref={inputRef} 86 - {...stylex.props( 87 - inputStyles.input, 88 - !isEmpty && styles.clearButtonPadding, 89 - )} 90 - /> 91 - {suffix != null && ( 92 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 93 - )} 94 - {!isEmpty && ( 95 - <div {...stylex.props(inputStyles.addon, styles.clearButton)}> 96 - <IconButton 97 - label="Clear search" 98 - size="sm" 99 - variant="secondary" 100 - > 101 - <X /> 102 - </IconButton> 103 - </div> 104 - )} 105 - </div> 106 - <Description>{description}</Description> 107 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 108 - </> 109 - ); 110 - }} 150 + <AriaSearchField 151 + {...props} 152 + isInvalid={validationState ? validationState === "invalid" : undefined} 153 + {...stylex.props(inputStyles.field, style)} 154 + > 155 + {({ isInvalid, isEmpty }) => ( 156 + <SearchFieldContent 157 + label={label} 158 + description={description} 159 + errorMessage={errorMessage} 160 + size={size} 161 + variant={variant} 162 + validationState={validationState} 163 + isInvalid={isInvalid} 164 + prefix={prefix} 165 + suffix={suffix} 166 + placeholder={placeholder} 167 + isEmpty={isEmpty} 168 + /> 169 + )} 111 170 </AriaSearchField> 112 171 </SizeContext> 113 172 );
+140 -51
apps/docs/src/components/select/index.tsx
··· 18 18 import { Description, FieldErrorMessage, Label } from "../label"; 19 19 import { ListBox, ListBoxSeparator } from "../listbox"; 20 20 import { SearchField } from "../search-field"; 21 + import { SuffixIcon } from "../suffix-icon"; 21 22 import { spacing } from "../theme/spacing.stylex"; 22 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 23 + import { 24 + InputVariant, 25 + InputValidationState, 26 + Size, 27 + StyleXComponentProps, 28 + } from "../theme/types"; 23 29 import { useInputStyles } from "../theme/useInputStyles"; 24 30 import { usePopoverStyles } from "../theme/usePopoverStyles"; 25 31 ··· 33 39 }, 34 40 }); 35 41 42 + interface SelectContentProps<T extends object> { 43 + label?: string; 44 + description?: string; 45 + errorMessage?: string | ((validation: ValidationResult) => string); 46 + size: Size; 47 + variant: InputVariant | undefined; 48 + validationState: InputValidationState | undefined; 49 + isInvalid: boolean; 50 + placeholder: string; 51 + prefix?: React.ReactNode; 52 + suffix?: React.ReactNode; 53 + isSearchable: boolean; 54 + items?: Iterable<T>; 55 + children: React.ReactNode | ((item: T) => React.ReactNode); 56 + shouldCloseOnInteractOutside?: ((element: Element) => boolean) | undefined; 57 + shouldFlip?: boolean; 58 + shouldUpdatePosition?: boolean; 59 + placement?: PopoverProps["placement"]; 60 + } 61 + 62 + function SelectContent<T extends object>({ 63 + label, 64 + description, 65 + errorMessage, 66 + size, 67 + variant, 68 + validationState, 69 + isInvalid, 70 + placeholder, 71 + prefix, 72 + suffix, 73 + isSearchable, 74 + items, 75 + children, 76 + shouldCloseOnInteractOutside, 77 + shouldFlip, 78 + shouldUpdatePosition, 79 + placement, 80 + }: SelectContentProps<T>) { 81 + const inputStyles = useInputStyles({ 82 + size, 83 + variant, 84 + validationState: isInvalid ? "invalid" : validationState, 85 + }); 86 + const popoverStyles = usePopoverStyles(); 87 + const { contains } = useFilter({ sensitivity: "base" }); 88 + 89 + return ( 90 + <> 91 + <Label>{label}</Label> 92 + <Button {...stylex.props(inputStyles.wrapper)}> 93 + {prefix != null && ( 94 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 95 + )} 96 + <SelectValue {...stylex.props(inputStyles.input)}> 97 + {({ selectedText, isPlaceholder, defaultChildren }) => { 98 + if (isPlaceholder) return placeholder; 99 + if (selectedText) return selectedText; 100 + 101 + return defaultChildren; 102 + }} 103 + </SelectValue> 104 + <SuffixIcon 105 + suffix={ 106 + <> 107 + {suffix} 108 + <ChevronDown size={16} aria-hidden="true" /> 109 + </> 110 + } 111 + style={inputStyles.addon} 112 + validationIconStyle={inputStyles.validationIcon} 113 + validationState={validationState} 114 + /> 115 + </Button> 116 + <Description>{description}</Description> 117 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 118 + <Popover 119 + containerPadding={8} 120 + shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 121 + shouldFlip={shouldFlip} 122 + shouldUpdatePosition={shouldUpdatePosition} 123 + placement={placement} 124 + {...stylex.props( 125 + popoverStyles.wrapper, 126 + popoverStyles.animation, 127 + styles.matchWidth, 128 + )} 129 + > 130 + {isSearchable ? ( 131 + <Autocomplete filter={contains}> 132 + <div {...stylex.props(styles.searchField)}> 133 + <SearchField placeholder="Search" variant="secondary" /> 134 + </div> 135 + <ListBoxSeparator /> 136 + <ListBox items={items}>{children}</ListBox> 137 + </Autocomplete> 138 + ) : ( 139 + <ListBox items={items}>{children}</ListBox> 140 + )} 141 + </Popover> 142 + </> 143 + ); 144 + } 145 + 36 146 export interface SelectProps<T extends object, M extends "single" | "multiple"> 37 - extends StyleXComponentProps<Omit<AriaSelectProps<T, M>, "children">>, 147 + extends StyleXComponentProps< 148 + Omit<AriaSelectProps<T, M>, "children" | "isInvalid"> 149 + >, 38 150 Pick< 39 151 PopoverProps, 40 152 | "shouldCloseOnInteractOutside" ··· 49 161 children: React.ReactNode | ((item: T) => React.ReactNode); 50 162 size?: Size; 51 163 variant?: InputVariant; 164 + validationState?: InputValidationState; 52 165 placeholder?: string; 53 166 prefix?: React.ReactNode; 54 167 suffix?: React.ReactNode; ··· 67 180 style, 68 181 size: sizeProp, 69 182 variant, 183 + validationState, 70 184 shouldCloseOnInteractOutside, 71 185 shouldFlip, 72 186 shouldUpdatePosition, ··· 78 192 ...props 79 193 }: SelectProps<T, M>) { 80 194 const size = sizeProp || use(SizeContext); 81 - const inputStyles = useInputStyles({ size, variant }); 82 - const popoverStyles = usePopoverStyles(); 83 - const { contains } = useFilter({ sensitivity: "base" }); 195 + const inputStyles = useInputStyles({ size, variant, validationState }); 84 196 85 197 return ( 86 198 <SizeContext value={size}> 87 199 <AriaSelect 88 200 {...props} 201 + isInvalid={validationState ? validationState === "invalid" : undefined} 89 202 {...stylex.props(inputStyles.field, style)} 90 203 placeholder={placeholder} 91 204 > 92 - <Label>{label}</Label> 93 - <Button {...stylex.props(inputStyles.wrapper)}> 94 - {prefix != null && ( 95 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 96 - )} 97 - <SelectValue {...stylex.props(inputStyles.input)}> 98 - {({ selectedText, isPlaceholder, defaultChildren }) => { 99 - if (isPlaceholder) return placeholder; 100 - if (selectedText) return selectedText; 101 - 102 - return defaultChildren; 103 - }} 104 - </SelectValue> 105 - {suffix != null && ( 106 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 107 - )} 108 - <div {...stylex.props(inputStyles.addon)}> 109 - <ChevronDown size={16} aria-hidden="true" /> 110 - </div> 111 - </Button> 112 - <Description>{description}</Description> 113 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 114 - <Popover 115 - containerPadding={8} 116 - shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 117 - shouldFlip={shouldFlip} 118 - shouldUpdatePosition={shouldUpdatePosition} 119 - placement={placement} 120 - {...stylex.props( 121 - popoverStyles.wrapper, 122 - popoverStyles.animation, 123 - styles.matchWidth, 124 - )} 125 - > 126 - {isSearchable ? ( 127 - <Autocomplete filter={contains}> 128 - <div {...stylex.props(styles.searchField)}> 129 - <SearchField placeholder="Search" variant="secondary" /> 130 - </div> 131 - <ListBoxSeparator /> 132 - <ListBox items={items}>{children}</ListBox> 133 - </Autocomplete> 134 - ) : ( 135 - <ListBox items={items}>{children}</ListBox> 136 - )} 137 - </Popover> 205 + {({ isInvalid }) => ( 206 + <SelectContent 207 + label={label} 208 + description={description} 209 + errorMessage={errorMessage} 210 + size={size} 211 + variant={variant} 212 + validationState={validationState} 213 + isInvalid={isInvalid} 214 + placeholder={placeholder} 215 + prefix={prefix} 216 + suffix={suffix} 217 + isSearchable={isSearchable} 218 + items={items} 219 + shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 220 + shouldFlip={shouldFlip} 221 + shouldUpdatePosition={shouldUpdatePosition} 222 + placement={placement} 223 + > 224 + {children} 225 + </SelectContent> 226 + )} 138 227 </AriaSelect> 139 228 </SizeContext> 140 229 );
+44
apps/docs/src/components/suffix-icon/index.tsx
··· 1 + import * as stylex from "@stylexjs/stylex"; 2 + import { AlertTriangle, Check, CircleX } from "lucide-react"; 3 + import { use } from "react"; 4 + import { FieldErrorContext } from "react-aria-components"; 5 + 6 + import { InputValidationState } from "../theme/types"; 7 + 8 + export interface SuffixIconProps { 9 + suffix: React.ReactNode | undefined; 10 + style?: stylex.StyleXStyles; 11 + validationIconStyle: stylex.StyleXStyles; 12 + validationState: InputValidationState | undefined; 13 + } 14 + 15 + export function SuffixIcon({ 16 + suffix, 17 + validationState, 18 + style, 19 + validationIconStyle, 20 + }: SuffixIconProps) { 21 + const state = use(FieldErrorContext); 22 + const isVisible = state?.isInvalid || validationState || suffix != null; 23 + 24 + if (!isVisible) { 25 + return null; 26 + } 27 + 28 + return ( 29 + <div {...stylex.props(style)}> 30 + {suffix} 31 + {state?.isInvalid || validationState ? ( 32 + <div {...stylex.props(validationIconStyle)}> 33 + {state?.isInvalid || validationState === "invalid" ? ( 34 + <CircleX /> 35 + ) : validationState === "valid" ? ( 36 + <Check /> 37 + ) : ( 38 + <AlertTriangle /> 39 + )} 40 + </div> 41 + ) : null} 42 + </div> 43 + ); 44 + }
+103 -34
apps/docs/src/components/text-field/index.tsx
··· 13 13 import { SizeContext } from "../context"; 14 14 import { IconButton } from "../icon-button"; 15 15 import { Description, FieldErrorMessage, Label } from "../label"; 16 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 16 + import { SuffixIcon } from "../suffix-icon"; 17 + import { 18 + InputValidationState, 19 + InputVariant, 20 + Size, 21 + StyleXComponentProps, 22 + } from "../theme/types"; 17 23 import { useInputStyles } from "../theme/useInputStyles"; 18 24 19 25 function PasswordToggle({ ··· 45 51 ); 46 52 } 47 53 54 + interface TextFieldContentProps { 55 + label?: React.ReactNode; 56 + description?: string; 57 + errorMessage?: string | ((validation: ValidationResult) => string); 58 + size: Size; 59 + variant: InputVariant | undefined; 60 + validationState: InputValidationState | undefined; 61 + isInvalid: boolean; 62 + prefix?: React.ReactNode; 63 + suffix?: React.ReactNode; 64 + placeholder?: string; 65 + type: TextFieldProps["type"]; 66 + setType: (type: TextFieldProps["type"]) => void; 67 + } 68 + 69 + function TextFieldContent({ 70 + label, 71 + description, 72 + errorMessage, 73 + size, 74 + variant, 75 + validationState, 76 + isInvalid, 77 + prefix, 78 + suffix, 79 + placeholder, 80 + type, 81 + setType, 82 + }: TextFieldContentProps) { 83 + const inputRef = useRef<HTMLInputElement>(null); 84 + const isPasswordInput = type === "password"; 85 + const inputStyles = useInputStyles({ 86 + size, 87 + variant, 88 + validationState: isInvalid ? "invalid" : validationState, 89 + }); 90 + 91 + return ( 92 + <> 93 + <Label>{label}</Label> 94 + {/* 95 + This onClick is specifically for mouse users not clicking directly on the input. 96 + A keyboard user would not encounter the same issue. 97 + */} 98 + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 99 + <div 100 + {...stylex.props(inputStyles.wrapper)} 101 + onClick={() => inputRef.current?.focus()} 102 + > 103 + {prefix != null && ( 104 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 105 + )} 106 + <Input 107 + {...stylex.props(inputStyles.input)} 108 + ref={inputRef} 109 + placeholder={placeholder} 110 + /> 111 + {isPasswordInput && ( 112 + <PasswordToggle 113 + type={type} 114 + setType={setType} 115 + style={inputStyles.addon} 116 + /> 117 + )} 118 + <SuffixIcon 119 + suffix={suffix} 120 + style={inputStyles.addon} 121 + validationIconStyle={inputStyles.validationIcon} 122 + validationState={validationState} 123 + /> 124 + </div> 125 + <Description>{description}</Description> 126 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 127 + </> 128 + ); 129 + } 130 + 48 131 export interface TextFieldProps 49 - extends StyleXComponentProps<AriaTextFieldProps>, 132 + extends StyleXComponentProps<Omit<AriaTextFieldProps, "isInvalid">>, 50 133 Pick<InputProps, "placeholder"> { 51 134 label?: React.ReactNode; 52 135 description?: string; 53 136 errorMessage?: string | ((validation: ValidationResult) => string); 54 137 size?: Size; 55 138 variant?: InputVariant; 139 + validationState?: InputValidationState; 56 140 prefix?: React.ReactNode; 57 141 suffix?: React.ReactNode; 58 142 } ··· 64 148 style, 65 149 size: sizeProp, 66 150 variant, 151 + validationState, 67 152 prefix, 68 153 suffix, 69 154 placeholder, 70 155 ...props 71 156 }: TextFieldProps) { 72 157 const size = sizeProp || use(SizeContext); 73 - const inputRef = useRef<HTMLInputElement>(null); 74 158 const [type, setType] = useState<TextFieldProps["type"]>( 75 159 props.type || "text", 76 160 ); 77 - const isPasswordInput = props.type === "password"; 78 - const inputStyles = useInputStyles({ size, variant }); 161 + const inputStyles = useInputStyles({ size, variant, validationState }); 79 162 80 163 return ( 81 164 <SizeContext value={size}> 82 165 <AriaTextField 83 166 {...props} 167 + isInvalid={validationState ? validationState === "invalid" : undefined} 84 168 type={type} 85 169 {...stylex.props(inputStyles.field, style)} 86 170 > 87 - <Label>{label}</Label> 88 - {/* 89 - This onClick is specifically for mouse users not clicking directly on the input. 90 - A keyboard user would not encounter the same issue. 91 - */} 92 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 93 - <div 94 - {...stylex.props(inputStyles.wrapper)} 95 - onClick={() => inputRef.current?.focus()} 96 - > 97 - {prefix != null && ( 98 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 99 - )} 100 - <Input 101 - {...stylex.props(inputStyles.input)} 102 - ref={inputRef} 171 + {({ isInvalid }) => ( 172 + <TextFieldContent 173 + label={label} 174 + description={description} 175 + errorMessage={errorMessage} 176 + size={size} 177 + variant={variant} 178 + validationState={validationState} 179 + isInvalid={isInvalid} 180 + prefix={prefix} 181 + suffix={suffix} 103 182 placeholder={placeholder} 183 + type={type} 184 + setType={setType} 104 185 /> 105 - {suffix != null && ( 106 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 107 - )} 108 - {isPasswordInput && ( 109 - <PasswordToggle 110 - type={type} 111 - setType={setType} 112 - style={inputStyles.addon} 113 - /> 114 - )} 115 - </div> 116 - <Description>{description}</Description> 117 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 186 + )} 118 187 </AriaTextField> 119 188 </SizeContext> 120 189 );
+1
apps/docs/src/components/theme/types.ts
··· 12 12 | "critical" 13 13 | "critical-outline"; 14 14 export type InputVariant = "primary" | "secondary" | "tertiary"; 15 + export type InputValidationState = "valid" | "invalid" | "warning"; 15 16 export type ButtonGroupVariant = "grouped" | "separate"; 16 17 export type TextVariant = "primary" | "secondary" | "critical"; 17 18 export type MeterVariant =
+232 -16
apps/docs/src/components/theme/useInputStyles.ts
··· 2 2 import { use } from "react"; 3 3 4 4 import { SizeContext } from "../context"; 5 - import { InputVariant, Size } from "../theme/types"; 5 + import { InputValidationState, InputVariant, Size } from "../theme/types"; 6 + import { animationDuration } from "./animations-duration.stylex"; 6 7 import { radius } from "./radius.stylex"; 7 - import { criticalColor, ui, uiColor } from "./semantic-color.stylex"; 8 + import { 9 + criticalColor, 10 + successColor, 11 + ui, 12 + uiColor, 13 + warningColor, 14 + } from "./semantic-color.stylex"; 8 15 import { spacing } from "./spacing.stylex"; 9 16 import { lineHeight, fontSize } from "./typography.stylex"; 10 17 ··· 15 22 flexDirection: "column", 16 23 }, 17 24 addon: { 25 + boxSizing: "border-box", 18 26 color: ui.textDim, 19 27 flexShrink: 0, 20 28 height: "100%", 21 - minWidth: spacing["8"], 22 - paddingLeft: { ":first-child": spacing["0.5"] }, 29 + paddingLeft: { ":first-child": spacing["2.5"] }, 23 30 paddingRight: { 24 - ":last-child:has(svg)": spacing["0.5"], 25 - ":last-child": spacing["2"], 31 + ":first-child": spacing["2"], 32 + ":last-child": spacing["2.5"], 26 33 }, 27 34 28 - gap: spacing["0.5"], 35 + gap: spacing["2"], 29 36 alignItems: "center", 30 37 display: "flex", 31 38 justifyContent: "center", ··· 38 45 width: spacing["4"], 39 46 }, 40 47 }, 48 + validationIcon: { 49 + alignItems: "center", 50 + display: "flex", 51 + justifyContent: "center", 52 + }, 53 + invalidIcon: { 54 + color: criticalColor.text1, 55 + }, 56 + validIcon: { 57 + color: successColor.text1, 58 + }, 59 + warningIcon: { 60 + color: warningColor.text1, 61 + }, 41 62 inputWrapper: { 42 63 // eslint-disable-next-line @stylexjs/valid-styles 43 64 cornerShape: "squircle", ··· 59 80 backgroundColor: "transparent", 60 81 boxSizing: "border-box", 61 82 color: { 83 + default: "inherit", 62 84 ":is(::placeholder,[data-placeholder])": uiColor.text1, 63 85 }, 64 86 display: "flex", ··· 74 96 primary: { 75 97 borderColor: { 76 98 default: uiColor.border2, 77 - ":has([data-hovered]):not([data-invalid])": uiColor.border3, 78 - ":has([data-invalid])": criticalColor.border2, 99 + ":has([data-hovered]):not(:has([data-invalid]))": uiColor.border3, 79 100 ":focus": uiColor.solid1, 80 101 }, 81 102 borderStyle: "solid", 82 103 borderWidth: 1, 104 + backgroundColor: { 105 + default: "transparent", 106 + ":hover:not(:has(* button:hover)):not(:disabled)": uiColor.component2, 107 + ":is(:active,[data-pressed=true]):not(:disabled)": uiColor.component3, 108 + ":disabled": "transparent", 109 + }, 110 + boxShadow: { 111 + ":has([data-invalid])": `0 0 0 2px ${criticalColor.component1}`, 112 + }, 113 + transitionDuration: animationDuration.fast, 83 114 transitionProperty: "background-color, border-color", 115 + transitionTimingFunction: "ease-in-out", 116 + }, 117 + primaryInvalid: { 118 + borderColor: { 119 + default: criticalColor.border2, 120 + ":has([data-hovered])": criticalColor.border3, 121 + ":focus": uiColor.solid1, 122 + }, 123 + backgroundColor: { 124 + default: criticalColor.bgSubtle, 125 + ":hover:not(:has(* button:hover)):not(:disabled)": 126 + criticalColor.component2, 127 + ":disabled": "transparent", 128 + }, 129 + boxShadow: `0 0 0 2px ${criticalColor.component1}`, 130 + color: criticalColor.text2, 131 + }, 132 + primaryWarning: { 133 + borderColor: { 134 + default: warningColor.border2, 135 + ":has([data-hovered])": warningColor.border3, 136 + ":focus": uiColor.solid1, 137 + }, 138 + backgroundColor: { 139 + default: warningColor.bgSubtle, 140 + ":hover:not(:has(* button:hover)):not(:disabled)": 141 + warningColor.component2, 142 + ":disabled": "transparent", 143 + }, 144 + boxShadow: `0 0 0 2px ${warningColor.component1}`, 145 + color: warningColor.text2, 146 + }, 147 + primaryValid: { 148 + borderColor: { 149 + default: successColor.border2, 150 + ":has([data-hovered])": successColor.border3, 151 + ":focus": uiColor.solid1, 152 + }, 153 + backgroundColor: { 154 + default: successColor.bgSubtle, 155 + ":hover:not(:has(* button:hover)):not(:disabled)": 156 + successColor.component2, 157 + ":disabled": "transparent", 158 + }, 159 + boxShadow: `0 0 0 2px ${successColor.component1}`, 160 + color: successColor.text2, 84 161 }, 85 162 secondary: { 86 163 borderColor: { 87 164 default: uiColor.component1, 88 - ":has([data-invalid])": criticalColor.border2, 165 + ":hover:not(:has(* button:hover)):not(:disabled)": uiColor.component2, 166 + ":is(:active,[data-pressed=true]):not(:disabled)": uiColor.component3, 167 + ":disabled": uiColor.component1, 89 168 }, 90 169 borderStyle: "solid", 91 170 borderWidth: 1, 171 + backgroundColor: { 172 + default: uiColor.component1, 173 + ":hover:not(:has(* button:hover)):not(:disabled)": uiColor.component2, 174 + ":is(:active,[data-pressed=true]):not(:disabled)": uiColor.component3, 175 + ":disabled": uiColor.component1, 176 + }, 177 + transitionDuration: animationDuration.fast, 92 178 transitionProperty: "background-color, border-color", 179 + transitionTimingFunction: "ease-in-out", 180 + }, 181 + secondaryInvalid: { 182 + borderColor: { 183 + default: criticalColor.component1, 184 + ":hover:not(:has(* button:hover)):not(:disabled)": 185 + criticalColor.component2, 186 + }, 187 + backgroundColor: { 188 + default: criticalColor.component1, 189 + ":hover:not(:has(* button:hover)):not(:disabled)": 190 + criticalColor.component2, 191 + }, 192 + }, 193 + secondaryWarning: { 194 + borderColor: { 195 + default: warningColor.component1, 196 + ":hover:not(:has(* button:hover)):not(:disabled)": 197 + warningColor.component2, 198 + }, 199 + backgroundColor: { 200 + default: warningColor.component1, 201 + ":hover:not(:has(* button:hover)):not(:disabled)": 202 + warningColor.component2, 203 + }, 204 + color: warningColor.text2, 205 + }, 206 + secondaryValid: { 207 + borderColor: { 208 + default: successColor.component1, 209 + ":hover:not(:has(* button:hover)):not(:disabled)": 210 + successColor.component2, 211 + }, 212 + backgroundColor: { 213 + default: successColor.component1, 214 + ":hover:not(:has(* button:hover)):not(:disabled)": 215 + successColor.component2, 216 + }, 217 + color: successColor.text2, 93 218 }, 94 219 tertiary: { 95 220 borderColor: { 96 221 default: "transparent", 97 - ":has([data-invalid])": criticalColor.border2, 222 + ":hover:not(:has(* button:hover)):not(:disabled)": uiColor.component2, 223 + ":is(:active,[data-pressed=true]):not(:disabled)": uiColor.component3, 224 + ":disabled": "transparent", 98 225 }, 99 226 borderStyle: "solid", 100 227 borderWidth: 1, 228 + backgroundColor: { 229 + default: "transparent", 230 + ":hover:not(:has(* button:hover)):not(:disabled)": uiColor.component2, 231 + ":is(:active,[data-pressed=true]):not(:disabled)": uiColor.component3, 232 + ":disabled": "transparent", 233 + }, 234 + transitionDuration: animationDuration.fast, 101 235 transitionProperty: "background-color, border-color", 236 + transitionTimingFunction: "ease-in-out", 102 237 }, 238 + tertiaryInvalid: { 239 + borderColor: { 240 + default: "transparent", 241 + ":hover:not(:has(* button:hover)):not(:disabled)": 242 + criticalColor.component1, 243 + ":is(:active,[data-pressed=true]):not(:disabled)": 244 + criticalColor.component2, 245 + ":disabled": "transparent", 246 + }, 247 + backgroundColor: { 248 + default: "transparent", 249 + ":hover:not(:has(* button:hover)):not(:disabled)": 250 + criticalColor.component1, 251 + ":is(:active,[data-pressed=true]):not(:disabled)": 252 + criticalColor.component2, 253 + ":disabled": "transparent", 254 + }, 255 + color: criticalColor.text2, 256 + }, 257 + tertiaryWarning: { 258 + borderColor: { 259 + default: "transparent", 260 + ":hover:not(:has(* button:hover)):not(:disabled)": 261 + warningColor.component1, 262 + ":is(:active,[data-pressed=true]):not(:disabled)": 263 + warningColor.component2, 264 + ":disabled": "transparent", 265 + }, 266 + backgroundColor: { 267 + default: "transparent", 268 + ":hover:not(:has(* button:hover)):not(:disabled)": 269 + warningColor.component1, 270 + ":is(:active,[data-pressed=true]):not(:disabled)": 271 + warningColor.component2, 272 + ":disabled": "transparent", 273 + }, 274 + color: warningColor.text1, 275 + }, 276 + tertiaryValid: { 277 + borderColor: { 278 + default: "transparent", 279 + ":hover:not(:has(* button:hover)):not(:disabled)": 280 + successColor.component1, 281 + ":is(:active,[data-pressed=true]):not(:disabled)": 282 + successColor.component2, 283 + ":disabled": "transparent", 284 + }, 285 + backgroundColor: { 286 + default: "transparent", 287 + ":hover:not(:has(* button:hover)):not(:disabled)": 288 + successColor.component1, 289 + ":is(:active,[data-pressed=true]):not(:disabled)": 290 + successColor.component2, 291 + ":disabled": "transparent", 292 + }, 293 + color: successColor.text1, 294 + }, 295 + 103 296 inputSize: (size: Size) => ({ 104 297 fontSize: 105 298 size === "sm" ··· 113 306 ? spacing["1"] 114 307 : size === "md" 115 308 ? spacing["2"] 116 - : spacing["1"], 309 + : spacing["3"], 117 310 }, 118 311 paddingRight: 119 312 size === "sm" 120 313 ? spacing["1"] 121 314 : size === "md" 122 315 ? spacing["2"] 123 - : spacing["2"], 316 + : spacing["3"], 124 317 }), 125 318 wrapperSize: (size: Size) => ({ 126 319 height: ··· 135 328 export function useInputStyles({ 136 329 size: sizeProp, 137 330 variant = "primary", 331 + validationState, 138 332 }: { 139 333 size: Size | undefined; 140 334 variant: InputVariant | undefined; 335 + validationState: InputValidationState | undefined; 141 336 }) { 142 337 const size = sizeProp || use(SizeContext); 143 338 ··· 145 340 field: [styles.field], 146 341 wrapper: [ 147 342 styles.inputWrapper, 148 - variant === "primary" && [ui.bgGhost, styles.primary], 149 - variant === "secondary" && [ui.bgUi, styles.secondary], 150 - variant === "tertiary" && [ui.bgGhost, styles.tertiary], 151 343 ui.text, 344 + variant === "primary" && [ 345 + styles.primary, 346 + validationState === "invalid" && [styles.primaryInvalid], 347 + validationState === "warning" && [styles.primaryWarning], 348 + validationState === "valid" && [styles.primaryValid], 349 + ], 350 + variant === "secondary" && [ 351 + styles.secondary, 352 + validationState === "invalid" && [styles.secondaryInvalid], 353 + validationState === "warning" && [styles.secondaryWarning], 354 + validationState === "valid" && [styles.secondaryValid], 355 + ], 356 + variant === "tertiary" && [ 357 + styles.tertiary, 358 + validationState === "invalid" && [styles.tertiaryInvalid], 359 + validationState === "warning" && [styles.tertiaryWarning], 360 + validationState === "valid" && [styles.tertiaryValid], 361 + ], 152 362 styles.wrapperSize(size), 153 363 ], 154 364 input: [styles.input, styles.inputSize(size)], 155 365 addon: styles.addon as unknown as stylex.StyleXStyles, 366 + validationIcon: [ 367 + styles.validationIcon, 368 + validationState === "invalid" && [styles.invalidIcon], 369 + validationState === "valid" && [styles.validIcon], 370 + validationState === "warning" && [styles.warningIcon], 371 + ], 156 372 }; 157 373 }
+90 -27
apps/docs/src/components/time-field/index.tsx
··· 11 11 12 12 import { SizeContext } from "../context"; 13 13 import { Description, FieldErrorMessage, Label } from "../label"; 14 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 14 + import { SuffixIcon } from "../suffix-icon"; 15 + import { 16 + InputVariant, 17 + InputValidationState, 18 + Size, 19 + StyleXComponentProps, 20 + } from "../theme/types"; 15 21 import { useInputStyles } from "../theme/useInputStyles"; 16 22 23 + interface TimeFieldContentProps { 24 + label?: React.ReactNode; 25 + description?: string; 26 + errorMessage?: string | ((validation: ValidationResult) => string); 27 + size: Size; 28 + variant: InputVariant | undefined; 29 + validationState: InputValidationState | undefined; 30 + isInvalid: boolean; 31 + prefix?: React.ReactNode; 32 + suffix?: React.ReactNode; 33 + } 34 + 35 + function TimeFieldContent({ 36 + label, 37 + description, 38 + errorMessage, 39 + size, 40 + variant, 41 + validationState, 42 + isInvalid, 43 + prefix, 44 + suffix, 45 + }: TimeFieldContentProps) { 46 + const inputRef = useRef<HTMLInputElement>(null); 47 + const inputStyles = useInputStyles({ 48 + size, 49 + variant, 50 + validationState: isInvalid ? "invalid" : validationState, 51 + }); 52 + 53 + return ( 54 + <> 55 + <Label>{label}</Label> 56 + {/* 57 + This onClick is specifically for mouse users not clicking directly on the input. 58 + A keyboard user would not encounter the same issue. 59 + */} 60 + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 61 + <div 62 + {...stylex.props(inputStyles.wrapper)} 63 + onClick={() => inputRef.current?.focus()} 64 + > 65 + {prefix != null && ( 66 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 67 + )} 68 + <DateInput {...stylex.props(inputStyles.input)} ref={inputRef}> 69 + {(segment) => <DateSegment segment={segment} />} 70 + </DateInput> 71 + <SuffixIcon 72 + suffix={suffix} 73 + style={inputStyles.addon} 74 + validationIconStyle={inputStyles.validationIcon} 75 + validationState={validationState} 76 + /> 77 + </div> 78 + <Description>{description}</Description> 79 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 80 + </> 81 + ); 82 + } 83 + 17 84 export interface TimeFieldProps<T extends TimeValue> 18 - extends StyleXComponentProps<AriaTimeFieldProps<T>> { 85 + extends StyleXComponentProps<Omit<AriaTimeFieldProps<T>, "isInvalid">> { 19 86 label?: React.ReactNode; 20 87 description?: string; 21 88 errorMessage?: string | ((validation: ValidationResult) => string); 22 89 size?: Size; 23 90 variant?: InputVariant; 91 + validationState?: InputValidationState; 24 92 prefix?: React.ReactNode; 25 93 suffix?: React.ReactNode; 26 94 } ··· 32 100 style, 33 101 size: sizeProp, 34 102 variant, 103 + validationState, 35 104 prefix, 36 105 suffix, 37 106 ...props 38 107 }: TimeFieldProps<T>) { 39 108 const size = sizeProp || use(SizeContext); 40 - const inputRef = useRef<HTMLInputElement>(null); 41 - const inputStyles = useInputStyles({ size, variant }); 109 + const inputStyles = useInputStyles({ size, variant, validationState }); 42 110 43 111 return ( 44 112 <SizeContext value={size}> 45 - <AriaTimeField {...props} {...stylex.props(inputStyles.field, style)}> 46 - <Label>{label}</Label> 47 - {/* 48 - This onClick is specifically for mouse users not clicking directly on the input. 49 - A keyboard user would not encounter the same issue. 50 - */} 51 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 52 - <div 53 - {...stylex.props(inputStyles.wrapper)} 54 - onClick={() => inputRef.current?.focus()} 55 - > 56 - {prefix != null && ( 57 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 58 - )} 59 - <DateInput {...stylex.props(inputStyles.input)} ref={inputRef}> 60 - {(segment) => <DateSegment segment={segment} />} 61 - </DateInput> 62 - {suffix != null && ( 63 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 64 - )} 65 - </div> 66 - <Description>{description}</Description> 67 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 113 + <AriaTimeField 114 + {...props} 115 + isInvalid={validationState ? validationState === "invalid" : undefined} 116 + {...stylex.props(inputStyles.field, style)} 117 + > 118 + {({ isInvalid }) => ( 119 + <TimeFieldContent 120 + label={label} 121 + description={description} 122 + errorMessage={errorMessage} 123 + size={size} 124 + variant={variant} 125 + validationState={validationState} 126 + isInvalid={isInvalid} 127 + prefix={prefix} 128 + suffix={suffix} 129 + /> 130 + )} 68 131 </AriaTimeField> 69 132 </SizeContext> 70 133 );
+20
apps/docs/src/docs/components/color-field.mdx
··· 6 6 import { PropDocs } from '../../lib/PropDocs' 7 7 import { Example } from '../../lib/Example' 8 8 import { Basic } from '../../examples/color-field/basic' 9 + import { Validation } from '../../examples/color-field/validation' 10 + import { ValidationWarning } from '../../examples/color-field/validation-warning' 11 + import { ValidationSuccess } from '../../examples/color-field/validation-success' 9 12 10 13 <Example src={Basic} /> 11 14 ··· 22 25 This component is built using the [React Aria ColorField](https://react-spectrum.adobe.com/react-aria/ColorField.html). 23 26 24 27 <PropDocs components={["ColorField"]} /> 28 + 29 + ## Features 30 + 31 + ### Validation 32 + 33 + Use the `validationState` prop to indicate when a field has validation errors. 34 + Set `validationState="invalid"` along with an `errorMessage` to display error states. 35 + 36 + <Example src={Validation} /> 37 + 38 + Set `validationState="warning"` to show a warning state with a description. 39 + 40 + <Example src={ValidationWarning} /> 41 + 42 + Set `validationState="valid"` to show a success state with a description. 43 + 44 + <Example src={ValidationSuccess} /> 25 45 26 46 ## Related Components 27 47
+20
apps/docs/src/docs/components/combobox.mdx
··· 6 6 import { PropDocs } from '../../lib/PropDocs' 7 7 import { Example } from '../../lib/Example' 8 8 import { Basic } from '../../examples/combobox/basic' 9 + import { Validation } from '../../examples/combobox/validation' 10 + import { ValidationWarning } from '../../examples/combobox/validation-warning' 11 + import { ValidationSuccess } from '../../examples/combobox/validation-success' 9 12 10 13 <Example src={Basic} /> 11 14 ··· 22 25 This component is built using the [React Aria ComboBox](https://react-spectrum.adobe.com/react-aria/ComboBox.html). 23 26 24 27 <PropDocs components={["ComboBox", "ComboBoxItem", "ComboBoxSection", "ComboBoxSectionHeader", "ComboBoxSeparator"]} /> 28 + 29 + ## Features 30 + 31 + ### Validation 32 + 33 + Use the `validationState` prop to indicate when a field has validation errors. 34 + Set `validationState="invalid"` along with an `errorMessage` to display error states. 35 + 36 + <Example src={Validation} /> 37 + 38 + Set `validationState="warning"` to show a warning state with a description. 39 + 40 + <Example src={ValidationWarning} /> 41 + 42 + Set `validationState="valid"` to show a success state with a description. 43 + 44 + <Example src={ValidationSuccess} /> 25 45 26 46 ## Related Components 27 47
+20
apps/docs/src/docs/components/date-field.mdx
··· 6 6 import { PropDocs } from '../../lib/PropDocs' 7 7 import { Example } from '../../lib/Example' 8 8 import { Basic } from '../../examples/date-field/basic' 9 + import { Validation } from '../../examples/date-field/validation' 10 + import { ValidationWarning } from '../../examples/date-field/validation-warning' 11 + import { ValidationSuccess } from '../../examples/date-field/validation-success' 9 12 10 13 <Example src={Basic} /> 11 14 ··· 22 25 This component is built using the [React Aria DateField](https://react-spectrum.adobe.com/react-aria/DateField.html). 23 26 24 27 <PropDocs components={["DateField"]} /> 28 + 29 + ## Features 30 + 31 + ### Validation 32 + 33 + Use the `validationState` prop to indicate when a field has validation errors. 34 + Set `validationState="invalid"` along with an `errorMessage` to display error states. 35 + 36 + <Example src={Validation} /> 37 + 38 + Set `validationState="warning"` to show a warning state with a description. 39 + 40 + <Example src={ValidationWarning} /> 41 + 42 + Set `validationState="valid"` to show a success state with a description. 43 + 44 + <Example src={ValidationSuccess} /> 25 45 26 46 ## Related Components 27 47
+20
apps/docs/src/docs/components/date-picker.mdx
··· 6 6 import { PropDocs } from '../../lib/PropDocs' 7 7 import { Example } from '../../lib/Example' 8 8 import { Basic } from '../../examples/date-picker/basic' 9 + import { Validation } from '../../examples/date-picker/validation' 10 + import { ValidationWarning } from '../../examples/date-picker/validation-warning' 11 + import { ValidationSuccess } from '../../examples/date-picker/validation-success' 9 12 10 13 <Example src={Basic} /> 11 14 ··· 22 25 This component is built using the [React Aria DatePicker](https://react-spectrum.adobe.com/react-aria/DatePicker.html). 23 26 24 27 <PropDocs components={["DatePicker"]} /> 28 + 29 + ## Features 30 + 31 + ### Validation 32 + 33 + Use the `validationState` prop to indicate when a field has validation errors. 34 + Set `validationState="invalid"` along with an `errorMessage` to display error states. 35 + 36 + <Example src={Validation} /> 37 + 38 + Set `validationState="warning"` to show a warning state with a description. 39 + 40 + <Example src={ValidationWarning} /> 41 + 42 + Set `validationState="valid"` to show a success state with a description. 43 + 44 + <Example src={ValidationSuccess} /> 25 45 26 46 ## Related Components 27 47
+20
apps/docs/src/docs/components/date-range-picker.mdx
··· 6 6 import { PropDocs } from '../../lib/PropDocs' 7 7 import { Example } from '../../lib/Example' 8 8 import { Basic } from '../../examples/date-range-picker/basic' 9 + import { Validation } from '../../examples/date-range-picker/validation' 10 + import { ValidationWarning } from '../../examples/date-range-picker/validation-warning' 11 + import { ValidationSuccess } from '../../examples/date-range-picker/validation-success' 9 12 10 13 <Example src={Basic} /> 11 14 ··· 22 25 This component is built using the [React Aria DateRangePicker](https://react-spectrum.adobe.com/react-aria/DateRangePicker.html). 23 26 24 27 <PropDocs components={["DateRangePicker"]} /> 28 + 29 + ## Features 30 + 31 + ### Validation 32 + 33 + Use the `validationState` prop to indicate when a field has validation errors. 34 + Set `validationState="invalid"` along with an `errorMessage` to display error states. 35 + 36 + <Example src={Validation} /> 37 + 38 + Set `validationState="warning"` to show a warning state with a description. 39 + 40 + <Example src={ValidationWarning} /> 41 + 42 + Set `validationState="valid"` to show a success state with a description. 43 + 44 + <Example src={ValidationSuccess} /> 25 45 26 46 ## Related Components 27 47
+20
apps/docs/src/docs/components/number-field.mdx
··· 6 6 import { PropDocs } from '../../lib/PropDocs' 7 7 import { Example } from '../../lib/Example' 8 8 import { Basic } from '../../examples/number-field/basic' 9 + import { Validation } from '../../examples/number-field/validation' 10 + import { ValidationWarning } from '../../examples/number-field/validation-warning' 11 + import { ValidationSuccess } from '../../examples/number-field/validation-success' 9 12 10 13 <Example src={Basic} /> 11 14 ··· 22 25 This component is built using the [React Aria NumberField](https://react-spectrum.adobe.com/react-aria/NumberField.html). 23 26 24 27 <PropDocs components={["NumberField"]} /> 28 + 29 + ## Features 30 + 31 + ### Validation 32 + 33 + Use the `validationState` prop to indicate when a field has validation errors. 34 + Set `validationState="invalid"` along with an `errorMessage` to display error states. 35 + 36 + <Example src={Validation} /> 37 + 38 + Set `validationState="warning"` to show a warning state with a description. 39 + 40 + <Example src={ValidationWarning} /> 41 + 42 + Set `validationState="valid"` to show a success state with a description. 43 + 44 + <Example src={ValidationSuccess} /> 25 45 26 46 ## Related Components 27 47
+20
apps/docs/src/docs/components/search-field.mdx
··· 6 6 import { PropDocs } from '../../lib/PropDocs' 7 7 import { Example } from '../../lib/Example' 8 8 import { Basic } from '../../examples/search-field/basic' 9 + import { Validation } from '../../examples/search-field/validation' 10 + import { ValidationWarning } from '../../examples/search-field/validation-warning' 11 + import { ValidationSuccess } from '../../examples/search-field/validation-success' 9 12 10 13 <Example src={Basic} /> 11 14 ··· 22 25 This component is built using the [React Aria SearchField](https://react-spectrum.adobe.com/react-aria/SearchField.html). 23 26 24 27 <PropDocs components={["SearchField"]} /> 28 + 29 + ## Features 30 + 31 + ### Validation 32 + 33 + Use the `validationState` prop to indicate when a field has validation errors. 34 + Set `validationState="invalid"` along with an `errorMessage` to display error states. 35 + 36 + <Example src={Validation} /> 37 + 38 + Set `validationState="warning"` to show a warning state with a description. 39 + 40 + <Example src={ValidationWarning} /> 41 + 42 + Set `validationState="valid"` to show a success state with a description. 43 + 44 + <Example src={ValidationSuccess} /> 25 45 26 46 ## Related Components 27 47
+18
apps/docs/src/docs/components/select.mdx
··· 8 8 import { Basic } from '../../examples/select/basic' 9 9 import { SelectWithDescription } from '../../examples/select/with-description' 10 10 import { SelectSizes } from '../../examples/select/sizes' 11 + import { Validation } from '../../examples/select/validation' 12 + import { ValidationWarning } from '../../examples/select/validation-warning' 13 + import { ValidationSuccess } from '../../examples/select/validation-success' 11 14 12 15 <Example src={Basic} /> 13 16 ··· 38 41 Select components support different sizes for various use cases. 39 42 40 43 <Example src={SelectSizes} /> 44 + 45 + ### Validation 46 + 47 + Use the `validationState` prop to indicate when a field has validation errors. 48 + Set `validationState="invalid"` along with an `errorMessage` to display error states. 49 + 50 + <Example src={Validation} /> 51 + 52 + Set `validationState="warning"` to show a warning state with a description. 53 + 54 + <Example src={ValidationWarning} /> 55 + 56 + Set `validationState="valid"` to show a success state with a description. 57 + 58 + <Example src={ValidationSuccess} /> 41 59 42 60 ## Related Components 43 61
+18
apps/docs/src/docs/components/text-field.mdx
··· 10 10 import { TextFieldSizes } from '../../examples/text-field/sizes' 11 11 import { PasswordField } from '../../examples/text-field/password' 12 12 import { PrefixAndSuffix } from '../../examples/text-field/prefix-and-suffix' 13 + import { Validation } from '../../examples/text-field/validation' 14 + import { ValidationWarning } from '../../examples/text-field/validation-warning' 15 + import { ValidationSuccess } from '../../examples/text-field/validation-success' 13 16 14 17 <Example src={Basic} /> 15 18 ··· 52 55 Text fields automatically include password visibility toggle when type is set to "password". 53 56 54 57 <Example src={PasswordField} /> 58 + 59 + ### Validation 60 + 61 + Use the `validationState` prop to indicate when a field has validation errors. 62 + Set `validationState="invalid"` along with an `errorMessage` to display error states. 63 + 64 + <Example src={Validation} /> 65 + 66 + Set `validationState="warning"` to show a warning state with a description. 67 + 68 + <Example src={ValidationWarning} /> 69 + 70 + Set `validationState="valid"` to show a success state with a description. 71 + 72 + <Example src={ValidationSuccess} /> 55 73 56 74 ## Related Components 57 75
+18
apps/docs/src/docs/components/time-field.mdx
··· 10 10 import { Variants } from '../../examples/time-field/variants' 11 11 import { Description } from '../../examples/time-field/description' 12 12 import { PrefixAndSuffix } from '../../examples/time-field/prefix-and-suffix' 13 + import { Validation } from '../../examples/time-field/validation' 14 + import { ValidationWarning } from '../../examples/time-field/validation-warning' 15 + import { ValidationSuccess } from '../../examples/time-field/validation-success' 13 16 14 17 <Example src={Basic} /> 15 18 ··· 46 49 The time field component supports a description. 47 50 48 51 <Example src={Description} /> 52 + 53 + ### Validation 54 + 55 + Use the `validationState` prop to indicate when a field has validation errors. 56 + Set `validationState="invalid"` along with an `errorMessage` to display error states. 57 + 58 + <Example src={Validation} /> 59 + 60 + Set `validationState="warning"` to show a warning state with a description. 61 + 62 + <Example src={ValidationWarning} /> 63 + 64 + Set `validationState="valid"` to show a success state with a description. 65 + 66 + <Example src={ValidationSuccess} /> 49 67 50 68 ## Props 51 69
+31
apps/docs/src/examples/color-field/validation-success.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { ColorField } from "@/components/color-field"; 3 + 4 + export function ValidationSuccess() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <ColorField 8 + label="Background Color" 9 + defaultValue="#3B82F6" 10 + validationState="valid" 11 + variant="primary" 12 + description="Color is valid and accessible" 13 + /> 14 + <ColorField 15 + label="Background Color" 16 + defaultValue="#3B82F6" 17 + validationState="valid" 18 + variant="secondary" 19 + description="Color is valid and accessible" 20 + /> 21 + <ColorField 22 + label="Background Color" 23 + defaultValue="#3B82F6" 24 + validationState="valid" 25 + variant="tertiary" 26 + description="Color is valid and accessible" 27 + /> 28 + </Flex> 29 + ); 30 + } 31 +
+31
apps/docs/src/examples/color-field/validation-warning.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { ColorField } from "@/components/color-field"; 3 + 4 + export function ValidationWarning() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <ColorField 8 + label="Background Color" 9 + defaultValue="#FF0000" 10 + validationState="warning" 11 + variant="primary" 12 + description="This color may be too bright for text readability" 13 + /> 14 + <ColorField 15 + label="Background Color" 16 + defaultValue="#FF0000" 17 + validationState="warning" 18 + variant="secondary" 19 + description="This color may be too bright for text readability" 20 + /> 21 + <ColorField 22 + label="Background Color" 23 + defaultValue="#FF0000" 24 + validationState="warning" 25 + variant="tertiary" 26 + description="This color may be too bright for text readability" 27 + /> 28 + </Flex> 29 + ); 30 + } 31 +
+31
apps/docs/src/examples/color-field/validation.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { ColorField } from "@/components/color-field"; 3 + 4 + export function Validation() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <ColorField 8 + label="Background Color" 9 + defaultValue="#invalid" 10 + validationState="invalid" 11 + variant="primary" 12 + errorMessage="Please enter a valid hex color code" 13 + /> 14 + <ColorField 15 + label="Background Color" 16 + defaultValue="#invalid" 17 + validationState="invalid" 18 + variant="secondary" 19 + errorMessage="Please enter a valid hex color code" 20 + /> 21 + <ColorField 22 + label="Background Color" 23 + defaultValue="#invalid" 24 + validationState="invalid" 25 + variant="tertiary" 26 + errorMessage="Please enter a valid hex color code" 27 + /> 28 + </Flex> 29 + ); 30 + } 31 +
+40
apps/docs/src/examples/combobox/validation-success.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { ComboBox, ComboBoxItem } from "@/components/combobox"; 3 + 4 + export function ValidationSuccess() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <ComboBox 8 + label="Country" 9 + validationState="valid" 10 + variant="primary" 11 + description="Selection is valid" 12 + > 13 + <ComboBoxItem id="us">United States</ComboBoxItem> 14 + <ComboBoxItem id="uk">United Kingdom</ComboBoxItem> 15 + <ComboBoxItem id="ca">Canada</ComboBoxItem> 16 + </ComboBox> 17 + <ComboBox 18 + label="Country" 19 + validationState="valid" 20 + variant="secondary" 21 + description="Selection is valid" 22 + > 23 + <ComboBoxItem id="us">United States</ComboBoxItem> 24 + <ComboBoxItem id="uk">United Kingdom</ComboBoxItem> 25 + <ComboBoxItem id="ca">Canada</ComboBoxItem> 26 + </ComboBox> 27 + <ComboBox 28 + label="Country" 29 + validationState="valid" 30 + variant="tertiary" 31 + description="Selection is valid" 32 + > 33 + <ComboBoxItem id="us">United States</ComboBoxItem> 34 + <ComboBoxItem id="uk">United Kingdom</ComboBoxItem> 35 + <ComboBoxItem id="ca">Canada</ComboBoxItem> 36 + </ComboBox> 37 + </Flex> 38 + ); 39 + } 40 +
+40
apps/docs/src/examples/combobox/validation-warning.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { ComboBox, ComboBoxItem } from "@/components/combobox"; 3 + 4 + export function ValidationWarning() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <ComboBox 8 + label="Region" 9 + validationState="warning" 10 + variant="primary" 11 + description="This region may have limited availability" 12 + > 13 + <ComboBoxItem id="us">United States</ComboBoxItem> 14 + <ComboBoxItem id="uk">United Kingdom</ComboBoxItem> 15 + <ComboBoxItem id="ca">Canada</ComboBoxItem> 16 + </ComboBox> 17 + <ComboBox 18 + label="Region" 19 + validationState="warning" 20 + variant="secondary" 21 + description="This region may have limited availability" 22 + > 23 + <ComboBoxItem id="us">United States</ComboBoxItem> 24 + <ComboBoxItem id="uk">United Kingdom</ComboBoxItem> 25 + <ComboBoxItem id="ca">Canada</ComboBoxItem> 26 + </ComboBox> 27 + <ComboBox 28 + label="Region" 29 + validationState="warning" 30 + variant="tertiary" 31 + description="This region may have limited availability" 32 + > 33 + <ComboBoxItem id="us">United States</ComboBoxItem> 34 + <ComboBoxItem id="uk">United Kingdom</ComboBoxItem> 35 + <ComboBoxItem id="ca">Canada</ComboBoxItem> 36 + </ComboBox> 37 + </Flex> 38 + ); 39 + } 40 +
+40
apps/docs/src/examples/combobox/validation.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { ComboBox, ComboBoxItem } from "@/components/combobox"; 3 + 4 + export function Validation() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <ComboBox 8 + label="Country" 9 + validationState="invalid" 10 + variant="primary" 11 + errorMessage="Please select a country" 12 + > 13 + <ComboBoxItem id="us">United States</ComboBoxItem> 14 + <ComboBoxItem id="uk">United Kingdom</ComboBoxItem> 15 + <ComboBoxItem id="ca">Canada</ComboBoxItem> 16 + </ComboBox> 17 + <ComboBox 18 + label="Country" 19 + validationState="invalid" 20 + variant="secondary" 21 + errorMessage="Please select a country" 22 + > 23 + <ComboBoxItem id="us">United States</ComboBoxItem> 24 + <ComboBoxItem id="uk">United Kingdom</ComboBoxItem> 25 + <ComboBoxItem id="ca">Canada</ComboBoxItem> 26 + </ComboBox> 27 + <ComboBox 28 + label="Country" 29 + validationState="invalid" 30 + variant="tertiary" 31 + errorMessage="Please select a country" 32 + > 33 + <ComboBoxItem id="us">United States</ComboBoxItem> 34 + <ComboBoxItem id="uk">United Kingdom</ComboBoxItem> 35 + <ComboBoxItem id="ca">Canada</ComboBoxItem> 36 + </ComboBox> 37 + </Flex> 38 + ); 39 + } 40 +
+28
apps/docs/src/examples/date-field/validation-success.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { DateField } from "@/components/date-field"; 3 + 4 + export function ValidationSuccess() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <DateField 8 + label="Event Date" 9 + validationState="valid" 10 + variant="primary" 11 + description="Date is valid and available" 12 + /> 13 + <DateField 14 + label="Event Date" 15 + validationState="valid" 16 + variant="secondary" 17 + description="Date is valid and available" 18 + /> 19 + <DateField 20 + label="Event Date" 21 + validationState="valid" 22 + variant="tertiary" 23 + description="Date is valid and available" 24 + /> 25 + </Flex> 26 + ); 27 + } 28 +
+28
apps/docs/src/examples/date-field/validation-warning.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { DateField } from "@/components/date-field"; 3 + 4 + export function ValidationWarning() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <DateField 8 + label="Event Date" 9 + validationState="warning" 10 + variant="primary" 11 + description="This date is in the past" 12 + /> 13 + <DateField 14 + label="Event Date" 15 + validationState="warning" 16 + variant="secondary" 17 + description="This date is in the past" 18 + /> 19 + <DateField 20 + label="Event Date" 21 + validationState="warning" 22 + variant="tertiary" 23 + description="This date is in the past" 24 + /> 25 + </Flex> 26 + ); 27 + } 28 +
+27
apps/docs/src/examples/date-field/validation.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { DateField } from "@/components/date-field"; 3 + 4 + export function Validation() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <DateField 8 + label="Birth Date" 9 + validationState="invalid" 10 + variant="primary" 11 + errorMessage="Please enter a valid date" 12 + /> 13 + <DateField 14 + label="Birth Date" 15 + validationState="invalid" 16 + variant="secondary" 17 + errorMessage="Please enter a valid date" 18 + /> 19 + <DateField 20 + label="Birth Date" 21 + validationState="invalid" 22 + variant="tertiary" 23 + errorMessage="Please enter a valid date" 24 + /> 25 + </Flex> 26 + ); 27 + }
+28
apps/docs/src/examples/date-picker/validation-success.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { DatePicker } from "@/components/date-picker"; 3 + 4 + export function ValidationSuccess() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <DatePicker 8 + label="Event Date" 9 + validationState="valid" 10 + variant="primary" 11 + description="Date is valid and available" 12 + /> 13 + <DatePicker 14 + label="Event Date" 15 + validationState="valid" 16 + variant="secondary" 17 + description="Date is valid and available" 18 + /> 19 + <DatePicker 20 + label="Event Date" 21 + validationState="valid" 22 + variant="tertiary" 23 + description="Date is valid and available" 24 + /> 25 + </Flex> 26 + ); 27 + } 28 +
+28
apps/docs/src/examples/date-picker/validation-warning.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { DatePicker } from "@/components/date-picker"; 3 + 4 + export function ValidationWarning() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <DatePicker 8 + label="Event Date" 9 + validationState="warning" 10 + variant="primary" 11 + description="This date is in the past" 12 + /> 13 + <DatePicker 14 + label="Event Date" 15 + validationState="warning" 16 + variant="secondary" 17 + description="This date is in the past" 18 + /> 19 + <DatePicker 20 + label="Event Date" 21 + validationState="warning" 22 + variant="tertiary" 23 + description="This date is in the past" 24 + /> 25 + </Flex> 26 + ); 27 + } 28 +
+28
apps/docs/src/examples/date-picker/validation.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { DatePicker } from "@/components/date-picker"; 3 + 4 + export function Validation() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <DatePicker 8 + label="Event Date" 9 + validationState="invalid" 10 + variant="primary" 11 + errorMessage="Please select a valid date" 12 + /> 13 + <DatePicker 14 + label="Event Date" 15 + validationState="invalid" 16 + variant="secondary" 17 + errorMessage="Please select a valid date" 18 + /> 19 + <DatePicker 20 + label="Event Date" 21 + validationState="invalid" 22 + variant="tertiary" 23 + errorMessage="Please select a valid date" 24 + /> 25 + </Flex> 26 + ); 27 + } 28 +
+28
apps/docs/src/examples/date-range-picker/validation-success.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { DateRangePicker } from "@/components/date-range-picker"; 3 + 4 + export function ValidationSuccess() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <DateRangePicker 8 + label="Date Range" 9 + validationState="valid" 10 + variant="primary" 11 + description="Date range is valid and available" 12 + /> 13 + <DateRangePicker 14 + label="Date Range" 15 + validationState="valid" 16 + variant="secondary" 17 + description="Date range is valid and available" 18 + /> 19 + <DateRangePicker 20 + label="Date Range" 21 + validationState="valid" 22 + variant="tertiary" 23 + description="Date range is valid and available" 24 + /> 25 + </Flex> 26 + ); 27 + } 28 +
+28
apps/docs/src/examples/date-range-picker/validation-warning.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { DateRangePicker } from "@/components/date-range-picker"; 3 + 4 + export function ValidationWarning() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <DateRangePicker 8 + label="Date Range" 9 + validationState="warning" 10 + variant="primary" 11 + description="This date range may conflict with existing events" 12 + /> 13 + <DateRangePicker 14 + label="Date Range" 15 + validationState="warning" 16 + variant="secondary" 17 + description="This date range may conflict with existing events" 18 + /> 19 + <DateRangePicker 20 + label="Date Range" 21 + validationState="warning" 22 + variant="tertiary" 23 + description="This date range may conflict with existing events" 24 + /> 25 + </Flex> 26 + ); 27 + } 28 +
+28
apps/docs/src/examples/date-range-picker/validation.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { DateRangePicker } from "@/components/date-range-picker"; 3 + 4 + export function Validation() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <DateRangePicker 8 + label="Date Range" 9 + validationState="invalid" 10 + variant="primary" 11 + errorMessage="Please select a valid date range" 12 + /> 13 + <DateRangePicker 14 + label="Date Range" 15 + validationState="invalid" 16 + variant="secondary" 17 + errorMessage="Please select a valid date range" 18 + /> 19 + <DateRangePicker 20 + label="Date Range" 21 + validationState="invalid" 22 + variant="tertiary" 23 + errorMessage="Please select a valid date range" 24 + /> 25 + </Flex> 26 + ); 27 + } 28 +
+37
apps/docs/src/examples/number-field/validation-success.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { NumberField } from "@/components/number-field"; 3 + 4 + export function ValidationSuccess() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <NumberField 8 + label="Quantity" 9 + defaultValue={50} 10 + validationState="valid" 11 + variant="primary" 12 + description="Quantity is within the valid range" 13 + minValue={0} 14 + maxValue={100} 15 + /> 16 + <NumberField 17 + label="Quantity" 18 + defaultValue={50} 19 + validationState="valid" 20 + variant="secondary" 21 + description="Quantity is within the valid range" 22 + minValue={0} 23 + maxValue={100} 24 + /> 25 + <NumberField 26 + label="Quantity" 27 + defaultValue={50} 28 + validationState="valid" 29 + variant="tertiary" 30 + description="Quantity is within the valid range" 31 + minValue={0} 32 + maxValue={100} 33 + /> 34 + </Flex> 35 + ); 36 + } 37 +
+37
apps/docs/src/examples/number-field/validation-warning.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { NumberField } from "@/components/number-field"; 3 + 4 + export function ValidationWarning() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <NumberField 8 + label="Quantity" 9 + defaultValue={85} 10 + validationState="warning" 11 + variant="primary" 12 + description="Quantity is approaching the maximum limit" 13 + minValue={0} 14 + maxValue={100} 15 + /> 16 + <NumberField 17 + label="Quantity" 18 + defaultValue={85} 19 + validationState="warning" 20 + variant="secondary" 21 + description="Quantity is approaching the maximum limit" 22 + minValue={0} 23 + maxValue={100} 24 + /> 25 + <NumberField 26 + label="Quantity" 27 + defaultValue={85} 28 + validationState="warning" 29 + variant="tertiary" 30 + description="Quantity is approaching the maximum limit" 31 + minValue={0} 32 + maxValue={100} 33 + /> 34 + </Flex> 35 + ); 36 + } 37 +
+37
apps/docs/src/examples/number-field/validation.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { NumberField } from "@/components/number-field"; 3 + 4 + export function Validation() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <NumberField 8 + label="Quantity" 9 + defaultValue={150} 10 + validationState="invalid" 11 + variant="primary" 12 + errorMessage="Quantity must be between 0 and 100" 13 + minValue={0} 14 + maxValue={100} 15 + /> 16 + <NumberField 17 + label="Quantity" 18 + defaultValue={150} 19 + validationState="invalid" 20 + variant="secondary" 21 + errorMessage="Quantity must be between 0 and 100" 22 + minValue={0} 23 + maxValue={100} 24 + /> 25 + <NumberField 26 + label="Quantity" 27 + defaultValue={150} 28 + validationState="invalid" 29 + variant="tertiary" 30 + errorMessage="Quantity must be between 0 and 100" 31 + minValue={0} 32 + maxValue={100} 33 + /> 34 + </Flex> 35 + ); 36 + } 37 +
+31
apps/docs/src/examples/search-field/validation-success.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { SearchField } from "@/components/search-field"; 3 + 4 + export function ValidationSuccess() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <SearchField 8 + label="Search" 9 + defaultValue="valid search query" 10 + validationState="valid" 11 + variant="primary" 12 + description="Search query is valid" 13 + /> 14 + <SearchField 15 + label="Search" 16 + defaultValue="valid search query" 17 + validationState="valid" 18 + variant="secondary" 19 + description="Search query is valid" 20 + /> 21 + <SearchField 22 + label="Search" 23 + defaultValue="valid search query" 24 + validationState="valid" 25 + variant="tertiary" 26 + description="Search query is valid" 27 + /> 28 + </Flex> 29 + ); 30 + } 31 +
+31
apps/docs/src/examples/search-field/validation-warning.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { SearchField } from "@/components/search-field"; 3 + 4 + export function ValidationWarning() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <SearchField 8 + label="Search" 9 + defaultValue="test" 10 + validationState="warning" 11 + variant="primary" 12 + description="Search query is too short, try a longer phrase" 13 + /> 14 + <SearchField 15 + label="Search" 16 + defaultValue="test" 17 + validationState="warning" 18 + variant="secondary" 19 + description="Search query is too short, try a longer phrase" 20 + /> 21 + <SearchField 22 + label="Search" 23 + defaultValue="test" 24 + validationState="warning" 25 + variant="tertiary" 26 + description="Search query is too short, try a longer phrase" 27 + /> 28 + </Flex> 29 + ); 30 + } 31 +
+31
apps/docs/src/examples/search-field/validation.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { SearchField } from "@/components/search-field"; 3 + 4 + export function Validation() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <SearchField 8 + label="Search" 9 + defaultValue="invalid search" 10 + validationState="invalid" 11 + variant="primary" 12 + errorMessage="Search query contains invalid characters" 13 + /> 14 + <SearchField 15 + label="Search" 16 + defaultValue="invalid search" 17 + validationState="invalid" 18 + variant="secondary" 19 + errorMessage="Search query contains invalid characters" 20 + /> 21 + <SearchField 22 + label="Search" 23 + defaultValue="invalid search" 24 + validationState="invalid" 25 + variant="tertiary" 26 + errorMessage="Search query contains invalid characters" 27 + /> 28 + </Flex> 29 + ); 30 + } 31 +
+2 -2
apps/docs/src/examples/select/basic.tsx
··· 1 - import { Select } from "@/components/select"; 1 + import { Select, SelectItem } from "@/components/select"; 2 2 3 3 const options = [ 4 4 { id: "option1", name: "Option 1" }, ··· 13 13 placeholder="Select an option" 14 14 items={options} 15 15 > 16 - {(item) => item.name} 16 + {(item) => <SelectItem id={item.id}>{item.name}</SelectItem>} 17 17 </Select> 18 18 ); 19 19 }
+7 -22
apps/docs/src/examples/select/sizes.tsx
··· 1 1 import { Flex } from "@/components/flex"; 2 - import { Select } from "@/components/select"; 2 + import { Select, SelectItem } from "@/components/select"; 3 3 4 4 const sizes = [ 5 5 { id: "xs", name: "Extra Small" }, ··· 12 12 export function SelectSizes() { 13 13 return ( 14 14 <Flex direction="column" gap="4"> 15 - <Select 16 - label="Small" 17 - size="sm" 18 - placeholder="Select size" 19 - items={sizes} 20 - > 21 - {(item) => item.name} 15 + <Select label="Small" size="sm" placeholder="Select size" items={sizes}> 16 + {(item) => <SelectItem id={item.id}>{item.name}</SelectItem>} 22 17 </Select> 23 - <Select 24 - label="Medium" 25 - size="md" 26 - placeholder="Select size" 27 - items={sizes} 28 - > 29 - {(item) => item.name} 18 + <Select label="Medium" size="md" placeholder="Select size" items={sizes}> 19 + {(item) => <SelectItem id={item.id}>{item.name}</SelectItem>} 30 20 </Select> 31 - <Select 32 - label="Large" 33 - size="lg" 34 - placeholder="Select size" 35 - items={sizes} 36 - > 37 - {(item) => item.name} 21 + <Select label="Large" size="lg" placeholder="Select size" items={sizes}> 22 + {(item) => <SelectItem id={item.id}>{item.name}</SelectItem>} 38 23 </Select> 39 24 </Flex> 40 25 );
+40
apps/docs/src/examples/select/validation-success.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { Select, SelectItem } from "@/components/select"; 3 + 4 + export function ValidationSuccess() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <Select 8 + label="Country" 9 + validationState="valid" 10 + variant="primary" 11 + description="Selection is valid" 12 + > 13 + <SelectItem id="us">United States</SelectItem> 14 + <SelectItem id="uk">United Kingdom</SelectItem> 15 + <SelectItem id="ca">Canada</SelectItem> 16 + </Select> 17 + <Select 18 + label="Country" 19 + validationState="valid" 20 + variant="secondary" 21 + description="Selection is valid" 22 + > 23 + <SelectItem id="us">United States</SelectItem> 24 + <SelectItem id="uk">United Kingdom</SelectItem> 25 + <SelectItem id="ca">Canada</SelectItem> 26 + </Select> 27 + <Select 28 + label="Country" 29 + validationState="valid" 30 + variant="tertiary" 31 + description="Selection is valid" 32 + > 33 + <SelectItem id="us">United States</SelectItem> 34 + <SelectItem id="uk">United Kingdom</SelectItem> 35 + <SelectItem id="ca">Canada</SelectItem> 36 + </Select> 37 + </Flex> 38 + ); 39 + } 40 +
+40
apps/docs/src/examples/select/validation-warning.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { Select, SelectItem } from "@/components/select"; 3 + 4 + export function ValidationWarning() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <Select 8 + label="Region" 9 + validationState="warning" 10 + variant="primary" 11 + description="This region may have limited availability" 12 + > 13 + <SelectItem id="us">United States</SelectItem> 14 + <SelectItem id="uk">United Kingdom</SelectItem> 15 + <SelectItem id="ca">Canada</SelectItem> 16 + </Select> 17 + <Select 18 + label="Region" 19 + validationState="warning" 20 + variant="secondary" 21 + description="This region may have limited availability" 22 + > 23 + <SelectItem id="us">United States</SelectItem> 24 + <SelectItem id="uk">United Kingdom</SelectItem> 25 + <SelectItem id="ca">Canada</SelectItem> 26 + </Select> 27 + <Select 28 + label="Region" 29 + validationState="warning" 30 + variant="tertiary" 31 + description="This region may have limited availability" 32 + > 33 + <SelectItem id="us">United States</SelectItem> 34 + <SelectItem id="uk">United Kingdom</SelectItem> 35 + <SelectItem id="ca">Canada</SelectItem> 36 + </Select> 37 + </Flex> 38 + ); 39 + } 40 +
+39
apps/docs/src/examples/select/validation.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { Select, SelectItem } from "@/components/select"; 3 + 4 + export function Validation() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <Select 8 + label="Country" 9 + validationState="invalid" 10 + variant="primary" 11 + errorMessage="Please select a country" 12 + > 13 + <SelectItem id="us">United States</SelectItem> 14 + <SelectItem id="uk">United Kingdom</SelectItem> 15 + <SelectItem id="ca">Canada</SelectItem> 16 + </Select> 17 + <Select 18 + label="Country" 19 + validationState="invalid" 20 + variant="secondary" 21 + errorMessage="Please select a country" 22 + > 23 + <SelectItem id="us">United States</SelectItem> 24 + <SelectItem id="uk">United Kingdom</SelectItem> 25 + <SelectItem id="ca">Canada</SelectItem> 26 + </Select> 27 + <Select 28 + label="Country" 29 + validationState="invalid" 30 + variant="tertiary" 31 + errorMessage="Please select a country" 32 + > 33 + <SelectItem id="us">United States</SelectItem> 34 + <SelectItem id="uk">United Kingdom</SelectItem> 35 + <SelectItem id="ca">Canada</SelectItem> 36 + </Select> 37 + </Flex> 38 + ); 39 + }
+3 -10
apps/docs/src/examples/select/with-description.tsx
··· 1 1 import { Flex } from "@/components/flex"; 2 - import { Select } from "@/components/select"; 2 + import { Select, SelectItem } from "@/components/select"; 3 3 4 4 const countries = [ 5 5 { id: "us", name: "United States", code: "US" }, ··· 12 12 export function SelectWithDescription() { 13 13 return ( 14 14 <Flex direction="column" gap="4"> 15 - <Select 15 + <Select 16 16 label="Country" 17 17 placeholder="Select your country" 18 18 description="Choose the country where you live" 19 19 items={countries} 20 20 > 21 - {(item) => ( 22 - <div> 23 - <div>{item.name}</div> 24 - <div style={{ fontSize: "0.875rem", color: "#666" }}> 25 - {item.code} 26 - </div> 27 - </div> 28 - )} 21 + {(item) => <SelectItem id={item.id}>{item.name}</SelectItem>} 29 22 </Select> 30 23 </Flex> 31 24 );
+30
apps/docs/src/examples/text-field/validation-success.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { TextField } from "@/components/text-field"; 3 + 4 + export function ValidationSuccess() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <TextField 8 + label="Email" 9 + defaultValue="test@example.com" 10 + validationState="valid" 11 + variant="primary" 12 + description="Email address is valid" 13 + /> 14 + <TextField 15 + label="Email" 16 + defaultValue="test@example.com" 17 + validationState="valid" 18 + variant="secondary" 19 + description="Email address is valid" 20 + /> 21 + <TextField 22 + label="Email" 23 + defaultValue="test@example.com" 24 + validationState="valid" 25 + variant="tertiary" 26 + description="Email address is valid" 27 + /> 28 + </Flex> 29 + ); 30 + }
+30
apps/docs/src/examples/text-field/validation-warning.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { TextField } from "@/components/text-field"; 3 + 4 + export function ValidationWarning() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <TextField 8 + label="Username" 9 + defaultValue="xXx_test_xXx" 10 + validationState="warning" 11 + variant="primary" 12 + description="Username should be at least 6 characters" 13 + /> 14 + <TextField 15 + label="Username" 16 + defaultValue="xXx_test_xXx" 17 + validationState="warning" 18 + variant="secondary" 19 + description="Username should be at least 6 characters" 20 + /> 21 + <TextField 22 + label="Username" 23 + defaultValue="xXx_test_xXx" 24 + validationState="warning" 25 + variant="tertiary" 26 + description="Username should be at least 6 characters" 27 + /> 28 + </Flex> 29 + ); 30 + }
+30
apps/docs/src/examples/text-field/validation.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { TextField } from "@/components/text-field"; 3 + 4 + export function Validation() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <TextField 8 + label="Email" 9 + defaultValue="test@example" 10 + validationState="invalid" 11 + variant="primary" 12 + errorMessage="Please enter a valid email" 13 + /> 14 + <TextField 15 + label="Email" 16 + defaultValue="test@example" 17 + validationState="invalid" 18 + variant="secondary" 19 + errorMessage="Please enter a valid email" 20 + /> 21 + <TextField 22 + label="Email" 23 + defaultValue="test@example" 24 + validationState="invalid" 25 + variant="tertiary" 26 + errorMessage="Please enter a valid email" 27 + /> 28 + </Flex> 29 + ); 30 + }
+28
apps/docs/src/examples/time-field/validation-success.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { TimeField } from "@/components/time-field"; 3 + 4 + export function ValidationSuccess() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <TimeField 8 + label="Meeting Time" 9 + validationState="valid" 10 + variant="primary" 11 + description="Time is valid and available" 12 + /> 13 + <TimeField 14 + label="Meeting Time" 15 + validationState="valid" 16 + variant="secondary" 17 + description="Time is valid and available" 18 + /> 19 + <TimeField 20 + label="Meeting Time" 21 + validationState="valid" 22 + variant="tertiary" 23 + description="Time is valid and available" 24 + /> 25 + </Flex> 26 + ); 27 + } 28 +
+28
apps/docs/src/examples/time-field/validation-warning.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { TimeField } from "@/components/time-field"; 3 + 4 + export function ValidationWarning() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <TimeField 8 + label="Meeting Time" 9 + validationState="warning" 10 + variant="primary" 11 + description="This time is outside business hours" 12 + /> 13 + <TimeField 14 + label="Meeting Time" 15 + validationState="warning" 16 + variant="secondary" 17 + description="This time is outside business hours" 18 + /> 19 + <TimeField 20 + label="Meeting Time" 21 + validationState="warning" 22 + variant="tertiary" 23 + description="This time is outside business hours" 24 + /> 25 + </Flex> 26 + ); 27 + } 28 +
+28
apps/docs/src/examples/time-field/validation.tsx
··· 1 + import { Flex } from "@/components/flex"; 2 + import { TimeField } from "@/components/time-field"; 3 + 4 + export function Validation() { 5 + return ( 6 + <Flex gap="4" direction="column"> 7 + <TimeField 8 + label="Start Time" 9 + validationState="invalid" 10 + variant="primary" 11 + errorMessage="Please enter a valid time" 12 + /> 13 + <TimeField 14 + label="Start Time" 15 + validationState="invalid" 16 + variant="secondary" 17 + errorMessage="Please enter a valid time" 18 + /> 19 + <TimeField 20 + label="Start Time" 21 + validationState="invalid" 22 + variant="tertiary" 23 + errorMessage="Please enter a valid time" 24 + /> 25 + </Flex> 26 + ); 27 + } 28 +
+1256
apps/docs/stylex.css
··· 1 + @property --x-boxShadow { syntax: "*"; inherits: false;} 2 + @property --x-gridTemplateRows { syntax: "*"; inherits: false;} 3 + @property --x-gridTemplateColumns { syntax: "*"; inherits: false;} 4 + @property --x-gridColumnStart { syntax: "*"; inherits: false;} 5 + @property --x-gridColumnEnd { syntax: "*"; inherits: false;} 6 + @property --x-gridRowStart { syntax: "*"; inherits: false;} 7 + @property --x-gridRowEnd { syntax: "*"; inherits: false;} 8 + @property --x-aspectRatio { syntax: "*"; inherits: false;} 9 + @property --x-width { syntax: "*"; inherits: false;} 10 + @property --x-paddingLeft { syntax: "*"; inherits: false;} 11 + @property --x-fontSize { syntax: "*"; inherits: false;} 12 + @property --x-1gfbyet { syntax: "*"; inherits: false;} 13 + @property --x-paddingRight { syntax: "*"; inherits: false;} 14 + @property --x-height { syntax: "*"; inherits: false;} 15 + @property --x---items-per-row { syntax: "*"; inherits: false;} 16 + @property --x-transform { syntax: "*"; inherits: false;} 17 + @property --thin-xk6k0je { syntax: "<number>"; inherits: true; initial-value: 100 } 18 + @property --extralight-x12edb6v { syntax: "<number>"; inherits: true; initial-value: 200 } 19 + @property --light-x1xrohu8 { syntax: "<number>"; inherits: true; initial-value: 300 } 20 + @property --normal-xi6lnv8 { syntax: "<number>"; inherits: true; initial-value: 400 } 21 + @property --medium-x1tobmye { syntax: "<number>"; inherits: true; initial-value: 500 } 22 + @property --semibold-x1vekvjh { syntax: "<number>"; inherits: true; initial-value: 600 } 23 + @property --bold-x1nz9syw { syntax: "<number>"; inherits: true; initial-value: 700 } 24 + @property --extrabold-x70wtui { syntax: "<number>"; inherits: true; initial-value: 800 } 25 + @property --black-xdj5g3 { syntax: "<number>"; inherits: true; initial-value: 900 } 26 + @keyframes x1wc8ddo-B{from{transform:rotate(0deg);}to{transform:rotate(360deg);}} 27 + @keyframes x1yo5mx1-B{0%{transform:translate(-50%,-50%) scale(0);}100%{transform:translate(-50%,-50%) scale(1);}} 28 + @keyframes x1yf9xd4-B{0%{transform:translateX(-65%);}100%{transform:translateX(0%);}} 29 + @keyframes x72inym-B{from{transform:translateX(-1.86%);}to{transform:translateX(0%);}} 30 + :root, .x15x7s49{--_0-xcffliq:0px;--_1-x1plbop:0.25rem;--_2-xsow7ju:0.5rem;--_3-x1a1riub:0.75rem;--_4-xgvn2um:1rem;--_5-x1pn3ufh:1.25rem;--_6-x109877l:1.5rem;--_7-x3ogwq2:1.75rem;--_8-x1do95gr:2rem;--_9-x58vtwt:2.25rem;--_10-xyoqvup:2.5rem;--_11-x11x3va4:2.75rem;--_12-xaxip2l:3rem;--_14-x18pvp2c:3.5rem;--_16-xnqsi2d:4rem;--_20-xbgtkw8:5rem;--_24-x8uq83j:6rem;--_28-x3c8utc:7rem;--_32-xxeew7j:8rem;--_36-x9ro48l:9rem;--_40-xlhyjhi:10rem;--_44-x4oqk9o:11rem;--_48-xc3zl6e:12rem;--_52-x66e183:13rem;--_56-x1k96jyh:14rem;--_60-xf930e:15rem;--_64-xhz114r:16rem;--_72-xgbkc4t:18rem;--_80-x12r4f45:20rem;--_96-x1mf07nc:24rem;--px-x1rrl3u8:1px;--_0_5-x1bnlq1y:0.125rem;--_1_5-x1llymyc:0.375rem;--_2_5-xmuc480:0.625rem;--_3_5-x1gotxl7:0.875rem;} 31 + :root, .x1rvy3a9{--_2xs-x1xzzr5o:0 1px rgb(0 0 0 / 0.05);--xs-x1e2w8h4:0 1px 2px 0 rgb(0 0 0 / 0.05);--sm-xeboudq:0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);--md-xf59ov0:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);--lg-xgilsvr:0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);--xl-x1azhb21:0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);--_2xl-x1nhun0f:0 25px 50px -12px rgb(0 0 0 / 0.25);--none-xgllz1r:0 0 #0000;--inset-xe4eu4o:inset 0 0 4px 0 rgb(0 0 0 / 0.1);--insetSm-xio3qbh:inset 0 0 4px 0 rgb(0 0 0 / 0.05);--insetMd-xx48ebj:inset 0 0 4px 0 rgb(0 0 0 / 0.1);--insetLg-x19q2zjg:inset 0 0 8px 0 rgb(0 0 0 / 0.15);} 32 + :root, .x1vqb0uf{--bg-x11hz5ne:light-dark(#fcfcfd, #fcfcfd);--bgSubtle-xk6jaqm:light-dark(#f9f9fb, #f9f9fb);--component1-x14nyoj8:light-dark(#f0f0f3, #f0f0f3);--component2-xx984p:light-dark(#e8e8ec, #e8e8ec);--component3-x1frjuvu:light-dark(#e0e1e6, #e0e1e6);--border1-x1xf4476:light-dark(#d9d9e0, #d9d9e0);--border2-x10iw3tt:light-dark(#cdced6, #cdced6);--border3-xq0e6t4:light-dark(#b9bbc6, #b9bbc6);--solid1-x1rohqqu:light-dark(#8b8d98, #8b8d98);--solid2-x27t3df:light-dark(#80838d, #80838d);--text1-x1340um9:light-dark(#60646c, #60646c);--text2-x19kn33k:light-dark(#1c2024, #1c2024);} 33 + :root, .x192maez{--bg-x151sc8w:var(--bg-x1gphzf2);--bgSubtle-x8mr634:var(--bgSubtle-x1jplh2x);--component1-x1rae15s:var(--component1-xrknle9);--component2-x1a2uij6:var(--component2-x12ntf8);--component3-x1g6ykoq:var(--component3-x1qvqun4);--border1-xs1aqk6:var(--border1-xdv3dhm);--border2-xdphg4n:var(--border2-xwn3lmr);--border3-xy1d7zd:var(--border3-xwig6mx);--solid1-xdodexi:var(--solid1-xp35zam);--solid2-xzgmc89:var(--solid2-xi399qe);--text1-xccyl1g:var(--text1-x1blb29e);--text2-x8ycaw:var(--text2-xx3kex6);--textContrast-xxxqvdi:white;} 34 + :root, .xxwjb7h{--bg-x175608s:var(--bg-xyifsjz);--bgSubtle-x1y9leuq:var(--bgSubtle-x2tkz45);--component1-x1sghgg8:var(--component1-xaivliz);--component2-x124xhl6:var(--component2-xgxkwj6);--component3-x1ejz5cj:var(--component3-x3872c4);--border1-xm7eg2j:var(--border1-x51i60m);--border2-x1kmnglg:var(--border2-x1lnuyuh);--border3-x1afn5qd:var(--border3-xqf689p);--solid1-x2pkv20:var(--solid1-x1m6a25n);--solid2-x4985y2:var(--solid2-x1o05zwi);--text1-xjn2lxg:var(--text1-x3r7y46);--text2-x1drysnq:var(--text2-x11v4dhp);--textContrast-x116zh0m:white;} 35 + :root, .x1nacpgj{--bg-x18rimo7:light-dark(#00c04004, #00de4505);--bgSubtle-x1qpayca:light-dark(#00a32f0b, #29f99d0b);--component1-xkt0b0i:light-dark(#00a43319, #22ff991e);--component2-x13zpfk5:light-dark(#00a83829, #11ff992d);--component3-x3c1f4h:light-dark(#019c393b, #2bffa23c);--border1-xmsez:light-dark(#00963c52, #44ffaa4b);--border2-x6ry4fz:light-dark(#00914071, #50fdac5e);--border3-x1xr1aty:light-dark(#00924ba4, #54ffad73);--solid1-xtnx0yx:light-dark(#008f4acf, #44ffa49e);--solid2-x1vqfbnw:light-dark(#008647d4, #43fea4ab);--text1-xkuh3uh:light-dark(#00713fde, #46fea5d4);--text2-x1i4rdgx:light-dark(#002616e6, #bbffd7f0);} 36 + :root, .x1ghv51{--bg-x1gphzf2:light-dark(#fcfcfd, #fcfcfd);--bgSubtle-x1jplh2x:light-dark(#f9f9fb, #f9f9fb);--component1-xrknle9:light-dark(#f0f0f3, #f0f0f3);--component2-x12ntf8:light-dark(#e8e8ec, #e8e8ec);--component3-x1qvqun4:light-dark(#e0e1e6, #e0e1e6);--border1-xdv3dhm:light-dark(#d9d9e0, #d9d9e0);--border2-xwn3lmr:light-dark(#cdced6, #cdced6);--border3-xwig6mx:light-dark(#b9bbc6, #b9bbc6);--solid1-xp35zam:light-dark(#8b8d98, #8b8d98);--solid2-xi399qe:light-dark(#80838d, #80838d);--text1-x1blb29e:light-dark(#60646c, #60646c);--text2-xx3kex6:light-dark(#1c2024, #1c2024);} 37 + :root, .x1hdqnv5{--bg-x1jmar6b:var(--bg-x6re758);--bgSubtle-xvpzc41:var(--bgSubtle-x415v6g);--component1-x1gg3jrv:var(--component1-xp4d679);--component2-x1q29jlu:var(--component2-xk9ahtj);--component3-x3nfkm8:var(--component3-x4u0l1k);--border1-xdz3kzl:var(--border1-x1rbpmds);--border2-x7rqvo0:var(--border2-xfem4zx);--border3-x16mdiod:var(--border3-x1hu3pnx);--solid1-xnhvmlu:var(--solid1-x162hmff);--solid2-xlw47ga:var(--solid2-x1dlve8z);--text1-x1pj8xh0:var(--text1-x13j7ndk);--text2-xcv02bb:var(--text2-xpa4mfl);--textContrast-x1gt1e58:black;} 38 + :root, .x1eqhwi5{--bg-x1l89o2a:light-dark(#fbfefc, #fbfefc);--bgSubtle-xlq589s:light-dark(#f4fbf6, #f4fbf6);--component1-xoam46d:light-dark(#e6f6eb, #e6f6eb);--component2-xptpg9x:light-dark(#d6f1df, #d6f1df);--component3-x1bpgk6h:light-dark(#c4e8d1, #c4e8d1);--border1-x1m6eoqc:light-dark(#adddc0, #adddc0);--border2-x1s07flx:light-dark(#8eceaa, #8eceaa);--border3-x3z2k3q:light-dark(#5bb98b, #5bb98b);--solid1-x10d61hv:light-dark(#30a46c, #30a46c);--solid2-x1ks7zzp:light-dark(#2b9a66, #2b9a66);--text1-x1hos2s0:light-dark(#218358, #218358);--text2-xasqimf:light-dark(#193b2d, #193b2d);} 39 + :root, .x1jciiue{--bg-x1oix42s:var(--bg-x1l89o2a);--bgSubtle-x1eogh41:var(--bgSubtle-xlq589s);--component1-x1ui28u3:var(--component1-xoam46d);--component2-x1hhltqf:var(--component2-xptpg9x);--component3-x3irpq9:var(--component3-x1bpgk6h);--border1-x46gdic:var(--border1-x1m6eoqc);--border2-x1k67xy2:var(--border2-x1s07flx);--border3-x1kngkfb:var(--border3-x3z2k3q);--solid1-xmemhk6:var(--solid1-x10d61hv);--solid2-x1dbywqs:var(--solid2-x1ks7zzp);--text1-x253p4m:var(--text1-x1hos2s0);--text2-x1ew83cn:var(--text2-xasqimf);--textContrast-x1xz901g:white;} 40 + :root, .x1lw1t95{--bg-x1rxyl4a:var(--bg-x1sw4zc8);--bgSubtle-xmjz13d:var(--bgSubtle-x16ilu94);--component1-x43o0oh:var(--component1-xeaj9e7);--component2-xzjwbwe:var(--component2-x8ir5ts);--component3-xvwaia1:var(--component3-xdklm5y);--border1-x1d0hf4b:var(--border1-x6y5na3);--border2-x130p4o0:var(--border2-x9cla9k);--border3-x1lhdl2z:var(--border3-x1g5crwn);--solid1-x6o1eyi:var(--solid1-x1jiy1i7);--solid2-x1rgzn25:var(--solid2-x1lcgbx5);--text1-xc56m6b:var(--text1-x1g3lydx);--text2-x6gkmtf:var(--text2-x649ojl);--textContrast-xmd31bd:white;} 41 + :root, .x1tahuoi{--bg-x1sw4zc8:light-dark(#fefcfb, #fefcfb);--bgSubtle-x16ilu94:light-dark(#fff7ed, #fff7ed);--component1-xeaj9e7:light-dark(#ffefd6, #ffefd6);--component2-x8ir5ts:light-dark(#ffdfb5, #ffdfb5);--component3-xdklm5y:light-dark(#ffd19a, #ffd19a);--border1-x6y5na3:light-dark(#ffc182, #ffc182);--border2-x9cla9k:light-dark(#f5ae73, #f5ae73);--border3-x1g5crwn:light-dark(#ec9455, #ec9455);--solid1-x1jiy1i7:light-dark(#f76b15, #f76b15);--solid2-x1lcgbx5:light-dark(#ef5f00, #ef5f00);--text1-x1g3lydx:light-dark(#cc4e00, #cc4e00);--text2-x649ojl:light-dark(#582d1d, #582d1d);} 42 + :root, .xyxmmhb{--bg-x6qb2y7:light-dark(#00000000, #00005503);--bgSubtle-xz52aqz:light-dark(#d8f4f609, #00005506);--component1-x1ootxdk:light-dark(#ddeaf814, #0000330f);--component2-x1x5bo14:light-dark(#d3edf81d, #00002d17);--component3-x8x5exd:light-dark(#d9edfe25, #0009321f);--border1-xl5c3qb:light-dark(#d6ebfd30, #00002f26);--border2-x1snns10:light-dark(#d9edff40, #00062e32);--border3-x1b5487t:light-dark(#d9edff5d, #00083046);--solid1-xw7lcsf:light-dark(#dfebfd6d, #00051d74);--solid2-x1vuts7a:light-dark(#e5edfd7b, #00071b7f);--text1-x1qacqzu:light-dark(#f1f7feb5, #0007149f);--text2-x7xxkp7:light-dark(#fcfdffef, #000509e3);} 43 + :root, .x9qo77k{--bg-x6re758:light-dark(#fdfdf9, #fdfdf9);--bgSubtle-x415v6g:light-dark(#fefce9, #fefce9);--component1-xp4d679:light-dark(#fffab8, #fffab8);--component2-xk9ahtj:light-dark(#fff394, #fff394);--component3-x4u0l1k:light-dark(#ffe770, #ffe770);--border1-x1rbpmds:light-dark(#f3d768, #f3d768);--border2-xfem4zx:light-dark(#e4c767, #e4c767);--border3-x1hu3pnx:light-dark(#d5ae39, #d5ae39);--solid1-x162hmff:light-dark(#ffe629, #ffe629);--solid2-x1dlve8z:light-dark(#ffdc00, #ffdc00);--text1-x13j7ndk:light-dark(#9e6c00, #9e6c00);--text2-xpa4mfl:light-dark(#473b1f, #473b1f);} 44 + :root, .xxq1yzn{--bg-xa4n1ix:light-dark(#ff000003, #f4121209);--bgSubtle-xjwgibg:light-dark(#ff000008, #f22f3e11);--component1-x18qyhc9:light-dark(#f3000d14, #ff173f2d);--component2-x1532e8q:light-dark(#ff000824, #fe0a3b44);--component3-x1pajzzf:light-dark(#ff000632, #ff204756);--border1-xovqzn1:light-dark(#f8000442, #ff3e5668);--border2-xphtnsk:light-dark(#df000356, #ff536184);--border3-x16n4bma:light-dark(#d2000571, #ff5d61b0);--solid1-x1iik73w:light-dark(#db0007b7, #fe4e54e4);--solid2-x1j1wfyr:light-dark(#d10005c1, #ff6465eb);--text1-x8esa8k:light-dark(#c40006d3, #ff9592);--text2-x1bvq9d8:light-dark(#55000de8, #ffd1d9);} 45 + :root, .x4hfvnt{--bg-xde63gs:light-dark(#c0400004, #ec360007);--bgSubtle-x1jdsv4g:light-dark(#ff8e0012, #fe6d000e);--component1-xxoq9mm:light-dark(#ff9c0029, #fb6a0025);--component2-x1os2gnc:light-dark(#ff91014a, #ff590039);--component3-x1becyrv:light-dark(#ff8b0065, #ff61004a);--border1-xb79avr:light-dark(#ff81007d, #fd75045c);--border2-xq7p22b:light-dark(#ed6c008c, #ff832c75);--border3-x1jpklpn:light-dark(#e35f00aa, #fe84389d);--solid1-x1uqiz8q:light-dark(#f65e00ea, #fe6d15f7);--solid2-x1f48cqm:light-dark(#ef5f00, #ff801f);--text1-xqn6ccr:light-dark(#cc4e00, #ffa057);--text2-x143oi4e:light-dark(#431200e2, #ffe0c2);} 46 + :root, .x1sicsqz{--bg-xl687un:var(--bg-x11hz5ne);--bgSubtle-xi821rj:var(--bgSubtle-xk6jaqm);--component1-x11poo5x:var(--component1-x14nyoj8);--component2-x18xhj12:var(--component2-xx984p);--component3-x1isc7sq:var(--component3-x1frjuvu);--border1-x1en7ut4:var(--border1-x1xf4476);--border2-xavwyw3:var(--border2-x10iw3tt);--border3-xm42ywm:var(--border3-xq0e6t4);--solid1-x1yanih7:var(--solid1-x1rohqqu);--solid2-x1ba3nh8:var(--solid2-x27t3df);--text1-xb5nrd9:var(--text1-x1340um9);--text2-x1ztxw:var(--text2-x19kn33k);--textContrast-xk9atbi:white;} 47 + :root, .xv3w7a0{--bg-xo9m2b4:light-dark(#aaaa0006, #d1510004);--bgSubtle-xpnscu7:light-dark(#f4dd0016, #f9b4000b);--component1-xq65tlw:light-dark(#ffee0047, #ffaa001e);--component2-x1ujsea2:light-dark(#ffe3016b, #fdb70028);--component3-x1njakr4:light-dark(#ffd5008f, #febb0036);--border1-xgpgkv2:light-dark(#ebbc0097, #fec40046);--border2-xfy5k6m:light-dark(#d2a10098, #fdcb225c);--border3-x1bakgjo:light-dark(#c99700c6, #fdca327b);--solid1-xffo9u0:light-dark(#ffe100d6, #ffe629);--solid2-x10kpuhz:light-dark(#ffdc00, #ffff57);--text1-x1arwxzo:light-dark(#9e6c00, #fee949f5);--text2-x1330fsk:light-dark(#2e2000e0, #fef6baf6);} 48 + :root, .x1qw93q1{--bg-xvz4l1d:light-dark(#00005503, #00000000);--bgSubtle-x11wv3u2:light-dark(#00005506, #d8f4f609);--component1-xq1n77x:light-dark(#0000330f, #ddeaf814);--component2-x1pcqosl:light-dark(#00002d17, #d3edf81d);--component3-x2i1291:light-dark(#0009321f, #d9edfe25);--border1-xqh3mvu:light-dark(#00002f26, #d6ebfd30);--border2-xk8cw7k:light-dark(#00062e32, #d9edff40);--border3-x1aygav0:light-dark(#00083046, #d9edff5d);--solid1-xxfkrpm:light-dark(#00051d74, #dfebfd6d);--solid2-x1u1gfxn:light-dark(#00071b7f, #e5edfd7b);--text1-ximjy2m:light-dark(#0007149f, #f1f7feb5);--text2-x1tsbbhh:light-dark(#000509e3, #fcfdffef);} 49 + :root, .x1dct8vy{--bg-xyifsjz:light-dark(#fffcfc, #fffcfc);--bgSubtle-x2tkz45:light-dark(#fff7f7, #fff7f7);--component1-xaivliz:light-dark(#feebec, #feebec);--component2-xgxkwj6:light-dark(#ffdbdc, #ffdbdc);--component3-x3872c4:light-dark(#ffcdce, #ffcdce);--border1-x51i60m:light-dark(#fdbdbe, #fdbdbe);--border2-x1lnuyuh:light-dark(#f4a9aa, #f4a9aa);--border3-xqf689p:light-dark(#eb8e90, #eb8e90);--solid1-x1m6a25n:light-dark(#e5484d, #e5484d);--solid2-x1o05zwi:light-dark(#dc3e42, #dc3e42);--text1-x3r7y46:light-dark(#ce2c31, #ce2c31);--text2-x11v4dhp:light-dark(#641723, #641723);} 50 + :root, .x10ailbr{--none-x7rich4:1;--xs-xg4a8ug:0.8;--sm-x4pl0dv:1.25;--base-x17a3wz2:1.75;--lg-x1nt92rq:2;--xl-xyq6gpo:2.5;--_2xl-xnhvph2:3;--_3xl-x11fa68j:3.5;} 51 + :root, .x1hwhxn{--sans-x1htm3rl:'Inter', sans-serif;--serif-x9eavc5:Georgia, serif;--mono-x1tvxhun:Monaco, monospace;} 52 + :root, .xzy7lqw{--thin-xk6k0je:100;--extralight-x12edb6v:200;--light-x1xrohu8:300;--normal-xi6lnv8:400;--medium-x1tobmye:500;--semibold-x1vekvjh:600;--bold-x1nz9syw:700;--extrabold-x70wtui:800;--black-xdj5g3:900;} 53 + :root, .x668sbw{--tighter-x1x2i330:-0.05em;--tight-x18yt8gk:-0.025em;--normal-xb40a8v:0em;--wide-x143nt7w:0.025em;--wider-x1v3fezh:0.05em;--widest-xihocmh:0.1em;} 54 + :root, .x1ea6woo{--xs-x1vaen13:0.75rem;--sm-x1w27pzf:0.85rem;--base-xidomu0:1rem;--lg-x1hevvyd:1.125rem;--xl-x1vzl7l6:1.25rem;--_2xl-xq985z6:1.5rem;--_3xl-x1lstm7v:1.875rem;--_4xl-x4z03mz:2.25rem;--_5xl-x17lnkj2:3rem;--_6xl-x1m2s84k:3.75rem;--_7xl-xir39hh:4.5rem;--_8xl-xt70kky:6rem;--_9xl-xpyewce:8rem;} 55 + :root, .x12296y5{--xs-x1y0v5dr:0.125rem;--sm-xp4zkua:0.25rem;--md-x1o51v3i:0.375rem;--lg-x1011bts:0.5rem;--xl-x195otgw:0.75rem;--_2xl-xzsum9y:1rem;--_3xl-x1bwjc12:1.5rem;--_4xl-x1okofp6:2rem;--full-xmpdjt5:calc(infinity * 1px);} 56 + @media (color-gamut: p3){:root, .x1vqb0uf{--bg-x11hz5ne:light-dark(color(display-p3 0.988 0.988 0.992), color(display-p3 0.067 0.067 0.074));--bgSubtle-xk6jaqm:light-dark(color(display-p3 0.976 0.976 0.984), color(display-p3 0.095 0.098 0.105));--component1-x14nyoj8:light-dark(color(display-p3 0.94 0.941 0.953), color(display-p3 0.13 0.135 0.145));--component2-xx984p:light-dark(color(display-p3 0.908 0.909 0.925), color(display-p3 0.156 0.163 0.176));--component3-x1frjuvu:light-dark(color(display-p3 0.88 0.881 0.901), color(display-p3 0.183 0.191 0.206));--border1-x1xf4476:light-dark(color(display-p3 0.85 0.852 0.876), color(display-p3 0.215 0.226 0.244));--border2-x10iw3tt:light-dark(color(display-p3 0.805 0.808 0.838), color(display-p3 0.265 0.28 0.302));--border3-xq0e6t4:light-dark(color(display-p3 0.727 0.733 0.773), color(display-p3 0.357 0.381 0.409));--solid1-x1rohqqu:light-dark(color(display-p3 0.547 0.553 0.592), color(display-p3 0.415 0.431 0.463));--solid2-x27t3df:light-dark(color(display-p3 0.503 0.512 0.549), color(display-p3 0.469 0.483 0.514));--text1-x1340um9:light-dark(color(display-p3 0.379 0.392 0.421), color(display-p3 0.692 0.704 0.728));--text2-x19kn33k:light-dark(color(display-p3 0.113 0.125 0.14), color(display-p3 0.93 0.933 0.94));}} 57 + @media (color-gamut: p3){:root, .x1nacpgj{--bg-x18rimo7:light-dark(color(display-p3 0.024 0.757 0.267 / 0.016), color(display-p3 0 0.992 0.298 / 0.017));--bgSubtle-x1qpayca:light-dark(color(display-p3 0.024 0.565 0.129 / 0.036), color(display-p3 0.341 0.98 0.616 / 0.043));--component1-xkt0b0i:light-dark(color(display-p3 0.012 0.596 0.145 / 0.087), color(display-p3 0.376 0.996 0.655 / 0.114));--component2-x13zpfk5:light-dark(color(display-p3 0.008 0.588 0.145 / 0.142), color(display-p3 0.341 0.996 0.635 / 0.173));--component3-x3c1f4h:light-dark(color(display-p3 0.004 0.541 0.157 / 0.204), color(display-p3 0.408 1 0.678 / 0.232));--border1-xmsez:light-dark(color(display-p3 0.004 0.518 0.157 / 0.283), color(display-p3 0.475 1 0.706 / 0.29));--border2-x6ry4fz:light-dark(color(display-p3 0.004 0.486 0.165 / 0.389), color(display-p3 0.514 1 0.706 / 0.362));--border3-x1xr1aty:light-dark(color(display-p3 0 0.478 0.2 / 0.55), color(display-p3 0.529 1 0.718 / 0.442));--solid1-xtnx0yx:light-dark(color(display-p3 0 0.455 0.165 / 0.667), color(display-p3 0.502 0.996 0.682 / 0.61));--solid2-x1vqfbnw:light-dark(color(display-p3 0 0.416 0.153 / 0.691), color(display-p3 0.506 1 0.682 / 0.66));--text1-xkuh3uh:light-dark(color(display-p3 0.19 0.5 0.32), color(display-p3 0.434 0.828 0.573));--text2-x1i4rdgx:light-dark(color(display-p3 0.132 0.228 0.18), color(display-p3 0.747 0.938 0.807));}} 58 + @media (color-gamut: p3){:root, .x1ghv51{--bg-x1gphzf2:light-dark(color(display-p3 0.067 0.067 0.074), color(display-p3 0.988 0.988 0.992));--bgSubtle-x1jplh2x:light-dark(color(display-p3 0.095 0.098 0.105), color(display-p3 0.976 0.976 0.984));--component1-xrknle9:light-dark(color(display-p3 0.13 0.135 0.145), color(display-p3 0.94 0.941 0.953));--component2-x12ntf8:light-dark(color(display-p3 0.156 0.163 0.176), color(display-p3 0.908 0.909 0.925));--component3-x1qvqun4:light-dark(color(display-p3 0.183 0.191 0.206), color(display-p3 0.88 0.881 0.901));--border1-xdv3dhm:light-dark(color(display-p3 0.215 0.226 0.244), color(display-p3 0.85 0.852 0.876));--border2-xwn3lmr:light-dark(color(display-p3 0.265 0.28 0.302), color(display-p3 0.805 0.808 0.838));--border3-xwig6mx:light-dark(color(display-p3 0.357 0.381 0.409), color(display-p3 0.727 0.733 0.773));--solid1-xp35zam:light-dark(color(display-p3 0.415 0.431 0.463), color(display-p3 0.547 0.553 0.592));--solid2-xi399qe:light-dark(color(display-p3 0.469 0.483 0.514), color(display-p3 0.503 0.512 0.549));--text1-x1blb29e:light-dark(color(display-p3 0.692 0.704 0.728), color(display-p3 0.379 0.392 0.421));--text2-xx3kex6:light-dark(color(display-p3 0.93 0.933 0.94), color(display-p3 0.113 0.125 0.14));}} 59 + @media (color-gamut: p3){:root, .x1eqhwi5{--bg-x1l89o2a:light-dark(color(display-p3 0.986 0.996 0.989), color(display-p3 0.062 0.083 0.071));--bgSubtle-xlq589s:light-dark(color(display-p3 0.963 0.983 0.967), color(display-p3 0.079 0.106 0.09));--component1-xoam46d:light-dark(color(display-p3 0.913 0.964 0.925), color(display-p3 0.1 0.173 0.133));--component2-xptpg9x:light-dark(color(display-p3 0.859 0.94 0.879), color(display-p3 0.115 0.229 0.166));--component3-x1bpgk6h:light-dark(color(display-p3 0.796 0.907 0.826), color(display-p3 0.147 0.282 0.206));--border1-x1m6eoqc:light-dark(color(display-p3 0.718 0.863 0.761), color(display-p3 0.185 0.338 0.25));--border2-x1s07flx:light-dark(color(display-p3 0.61 0.801 0.675), color(display-p3 0.227 0.403 0.298));--border3-x3z2k3q:light-dark(color(display-p3 0.451 0.715 0.559), color(display-p3 0.27 0.479 0.351));--solid1-x10d61hv:light-dark(color(display-p3 0.332 0.634 0.442), color(display-p3 0.332 0.634 0.442));--solid2-x1ks7zzp:light-dark(color(display-p3 0.308 0.595 0.417), color(display-p3 0.357 0.682 0.474));--text1-x1hos2s0:light-dark(color(display-p3 0.19 0.5 0.32), color(display-p3 0.434 0.828 0.573));--text2-xasqimf:light-dark(color(display-p3 0.132 0.228 0.18), color(display-p3 0.747 0.938 0.807));}} 60 + @media (color-gamut: p3){:root, .x1tahuoi{--bg-x1sw4zc8:light-dark(color(display-p3 0.995 0.988 0.985), color(display-p3 0.088 0.07 0.057));--bgSubtle-x16ilu94:light-dark(color(display-p3 0.994 0.968 0.934), color(display-p3 0.113 0.089 0.061));--component1-xeaj9e7:light-dark(color(display-p3 0.989 0.938 0.85), color(display-p3 0.189 0.12 0.056));--component2-x8ir5ts:light-dark(color(display-p3 1 0.874 0.687), color(display-p3 0.262 0.132 0));--component3-xdklm5y:light-dark(color(display-p3 1 0.821 0.583), color(display-p3 0.315 0.168 0.016));--border1-x6y5na3:light-dark(color(display-p3 0.975 0.767 0.545), color(display-p3 0.376 0.219 0.088));--border2-x9cla9k:light-dark(color(display-p3 0.919 0.693 0.486), color(display-p3 0.465 0.283 0.147));--border3-x1g5crwn:light-dark(color(display-p3 0.877 0.597 0.379), color(display-p3 0.601 0.359 0.201));--solid1-x1jiy1i7:light-dark(color(display-p3 0.9 0.45 0.2), color(display-p3 0.9 0.45 0.2));--solid2-x1lcgbx5:light-dark(color(display-p3 0.87 0.409 0.164), color(display-p3 0.98 0.51 0.23));--text1-x1g3lydx:light-dark(color(display-p3 0.76 0.34 0), color(display-p3 1 0.63 0.38));--text2-x649ojl:light-dark(color(display-p3 0.323 0.185 0.127), color(display-p3 0.98 0.883 0.775));}} 61 + @media (color-gamut: p3){:root, .xyxmmhb{--bg-x6qb2y7:light-dark(color(display-p3 0 0 0 / 0), color(display-p3 0.024 0.024 0.349 / 0.012));--bgSubtle-xz52aqz:light-dark(color(display-p3 0.875 0.992 1 / 0.034), color(display-p3 0.024 0.024 0.349 / 0.024));--component1-x1ootxdk:light-dark(color(display-p3 0.882 0.933 0.992 / 0.077), color(display-p3 0.004 0.004 0.204 / 0.059));--component2-x1x5bo14:light-dark(color(display-p3 0.882 0.953 0.996 / 0.111), color(display-p3 0.012 0.012 0.184 / 0.091));--component3-x8x5exd:light-dark(color(display-p3 0.878 0.929 0.996 / 0.145), color(display-p3 0.004 0.039 0.2 / 0.122));--border1-xl5c3qb:light-dark(color(display-p3 0.882 0.949 0.996 / 0.183), color(display-p3 0.008 0.008 0.165 / 0.15));--border2-x1snns10:light-dark(color(display-p3 0.882 0.929 1 / 0.246), color(display-p3 0.008 0.027 0.184 / 0.197));--border3-x1b5487t:light-dark(color(display-p3 0.871 0.937 1 / 0.361), color(display-p3 0.004 0.031 0.176 / 0.275));--solid1-xw7lcsf:light-dark(color(display-p3 0.898 0.937 1 / 0.42), color(display-p3 0.004 0.02 0.106 / 0.455));--solid2-x1vuts7a:light-dark(color(display-p3 0.918 0.945 1 / 0.475), color(display-p3 0.004 0.027 0.098 / 0.499));--text1-x1qacqzu:light-dark(color(display-p3 0.949 0.969 0.996 / 0.708), color(display-p3 0 0.02 0.063 / 0.62));--text2-x7xxkp7:light-dark(color(display-p3 0.988 0.992 1 / 0.937), color(display-p3 0 0.012 0.031 / 0.887));}} 62 + @media (color-gamut: p3){:root, .x9qo77k{--bg-x6re758:light-dark(color(display-p3 0.992 0.992 0.978), color(display-p3 0.078 0.069 0.047));--bgSubtle-x415v6g:light-dark(color(display-p3 0.995 0.99 0.922), color(display-p3 0.103 0.094 0.063));--component1-xp4d679:light-dark(color(display-p3 0.997 0.982 0.749), color(display-p3 0.168 0.137 0.039));--component2-xk9ahtj:light-dark(color(display-p3 0.992 0.953 0.627), color(display-p3 0.209 0.169 0));--component3-x4u0l1k:light-dark(color(display-p3 0.984 0.91 0.51), color(display-p3 0.255 0.209 0));--border1-x1rbpmds:light-dark(color(display-p3 0.934 0.847 0.474), color(display-p3 0.31 0.261 0.07));--border2-xfem4zx:light-dark(color(display-p3 0.876 0.785 0.46), color(display-p3 0.389 0.331 0.135));--border3-x1hu3pnx:light-dark(color(display-p3 0.811 0.689 0.313), color(display-p3 0.497 0.42 0.182));--solid1-x162hmff:light-dark(color(display-p3 1 0.92 0.22), color(display-p3 1 0.92 0.22));--solid2-x1dlve8z:light-dark(color(display-p3 0.977 0.868 0.291), color(display-p3 1 1 0.456));--text1-x13j7ndk:light-dark(color(display-p3 0.6 0.44 0), color(display-p3 0.948 0.885 0.392));--text2-xpa4mfl:light-dark(color(display-p3 0.271 0.233 0.137), color(display-p3 0.959 0.934 0.731));}} 63 + @media (color-gamut: p3){:root, .xxq1yzn{--bg-xa4n1ix:light-dark(color(display-p3 0.675 0.024 0.024 / 0.012), color(display-p3 0.984 0.071 0.071 / 0.03));--bgSubtle-xjwgibg:light-dark(color(display-p3 0.863 0.024 0.024 / 0.028), color(display-p3 0.996 0.282 0.282 / 0.055));--component1-x18qyhc9:light-dark(color(display-p3 0.792 0.008 0.008 / 0.075), color(display-p3 1 0.169 0.271 / 0.156));--component2-x1532e8q:light-dark(color(display-p3 1 0.008 0.008 / 0.134), color(display-p3 1 0.118 0.267 / 0.236));--component3-x1pajzzf:light-dark(color(display-p3 0.918 0.008 0.008 / 0.189), color(display-p3 1 0.212 0.314 / 0.303));--border1-xovqzn1:light-dark(color(display-p3 0.831 0.02 0.004 / 0.251), color(display-p3 1 0.318 0.38 / 0.374));--border2-xphtnsk:light-dark(color(display-p3 0.741 0.016 0.004 / 0.33), color(display-p3 1 0.4 0.424 / 0.475));--border3-x16n4bma:light-dark(color(display-p3 0.698 0.012 0.004 / 0.428), color(display-p3 1 0.431 0.431 / 0.635));--solid1-x1iik73w:light-dark(color(display-p3 0.749 0.008 0 / 0.675), color(display-p3 1 0.388 0.384 / 0.82));--solid2-x1j1wfyr:light-dark(color(display-p3 0.714 0.012 0 / 0.714), color(display-p3 1 0.463 0.447 / 0.853));--text1-x8esa8k:light-dark(color(display-p3 0.744 0.234 0.222), color(display-p3 1 0.57 0.55));--text2-x1bvq9d8:light-dark(color(display-p3 0.36 0.115 0.143), color(display-p3 0.971 0.826 0.852));}} 64 + @media (color-gamut: p3){:root, .x4hfvnt{--bg-xde63gs:light-dark(color(display-p3 0.757 0.267 0.024 / 0.016), color(display-p3 0.961 0.247 0 / 0.022));--bgSubtle-x1jdsv4g:light-dark(color(display-p3 0.886 0.533 0.008 / 0.067), color(display-p3 0.992 0.529 0 / 0.051));--component1-xxoq9mm:light-dark(color(display-p3 0.922 0.584 0.008 / 0.15), color(display-p3 0.996 0.486 0 / 0.131));--component2-x1os2gnc:light-dark(color(display-p3 1 0.604 0.004 / 0.314), color(display-p3 0.996 0.384 0 / 0.211));--component3-x1becyrv:light-dark(color(display-p3 1 0.569 0.004 / 0.416), color(display-p3 1 0.455 0 / 0.265));--border1-xb79avr:light-dark(color(display-p3 0.949 0.494 0.004 / 0.455), color(display-p3 1 0.529 0.129 / 0.332));--border2-xq7p22b:light-dark(color(display-p3 0.839 0.408 0 / 0.514), color(display-p3 1 0.569 0.251 / 0.429));--border3-x1jpklpn:light-dark(color(display-p3 0.804 0.349 0 / 0.62), color(display-p3 1 0.584 0.302 / 0.572));--solid1-x1uqiz8q:light-dark(color(display-p3 0.878 0.314 0 / 0.8), color(display-p3 1 0.494 0.216 / 0.895));--solid2-x1f48cqm:light-dark(color(display-p3 0.843 0.29 0 / 0.836), color(display-p3 1 0.522 0.235 / 0.979));--text1-xqn6ccr:light-dark(color(display-p3 0.76 0.34 0), color(display-p3 1 0.63 0.38));--text2-x143oi4e:light-dark(color(display-p3 0.323 0.185 0.127), color(display-p3 0.98 0.883 0.775));}} 65 + @media (color-gamut: p3){:root, .xv3w7a0{--bg-xo9m2b4:light-dark(color(display-p3 0.675 0.675 0.024 / 0.024), color(display-p3 0.973 0.369 0 / 0.013));--bgSubtle-xpnscu7:light-dark(color(display-p3 0.953 0.855 0.008 / 0.079), color(display-p3 0.996 0.792 0 / 0.038));--component1-xq65tlw:light-dark(color(display-p3 0.988 0.925 0.004 / 0.251), color(display-p3 0.996 0.71 0 / 0.11));--component2-x1ujsea2:light-dark(color(display-p3 0.98 0.875 0.004 / 0.373), color(display-p3 0.996 0.741 0 / 0.152));--component3-x1njakr4:light-dark(color(display-p3 0.969 0.816 0.004 / 0.491), color(display-p3 0.996 0.765 0 / 0.202));--border1-xgpgkv2:light-dark(color(display-p3 0.875 0.71 0 / 0.526), color(display-p3 0.996 0.816 0.082 / 0.261));--border2-xfy5k6m:light-dark(color(display-p3 0.769 0.604 0 / 0.542), color(display-p3 1 0.831 0.263 / 0.345));--border3-x1bakgjo:light-dark(color(display-p3 0.725 0.549 0 / 0.687), color(display-p3 1 0.831 0.314 / 0.463));--solid1-xffo9u0:light-dark(color(display-p3 1 0.898 0 / 0.781), color(display-p3 1 0.922 0.22));--solid2-x10kpuhz:light-dark(color(display-p3 0.969 0.812 0 / 0.71), color(display-p3 1 1 0.455));--text1-x1arwxzo:light-dark(color(display-p3 0.6 0.44 0), color(display-p3 0.948 0.885 0.392));--text2-x1330fsk:light-dark(color(display-p3 0.271 0.233 0.137), color(display-p3 0.959 0.934 0.731));}} 66 + @media (color-gamut: p3){:root, .x1qw93q1{--bg-xvz4l1d:light-dark(color(display-p3 0.024 0.024 0.349 / 0.012), color(display-p3 0 0 0 / 0));--bgSubtle-x11wv3u2:light-dark(color(display-p3 0.024 0.024 0.349 / 0.024), color(display-p3 0.875 0.992 1 / 0.034));--component1-xq1n77x:light-dark(color(display-p3 0.004 0.004 0.204 / 0.059), color(display-p3 0.882 0.933 0.992 / 0.077));--component2-x1pcqosl:light-dark(color(display-p3 0.012 0.012 0.184 / 0.091), color(display-p3 0.882 0.953 0.996 / 0.111));--component3-x2i1291:light-dark(color(display-p3 0.004 0.039 0.2 / 0.122), color(display-p3 0.878 0.929 0.996 / 0.145));--border1-xqh3mvu:light-dark(color(display-p3 0.008 0.008 0.165 / 0.15), color(display-p3 0.882 0.949 0.996 / 0.183));--border2-xk8cw7k:light-dark(color(display-p3 0.008 0.027 0.184 / 0.197), color(display-p3 0.882 0.929 1 / 0.246));--border3-x1aygav0:light-dark(color(display-p3 0.004 0.031 0.176 / 0.275), color(display-p3 0.871 0.937 1 / 0.361));--solid1-xxfkrpm:light-dark(color(display-p3 0.004 0.02 0.106 / 0.455), color(display-p3 0.898 0.937 1 / 0.42));--solid2-x1u1gfxn:light-dark(color(display-p3 0.004 0.027 0.098 / 0.499), color(display-p3 0.918 0.945 1 / 0.475));--text1-ximjy2m:light-dark(color(display-p3 0 0.02 0.063 / 0.62), color(display-p3 0.949 0.969 0.996 / 0.708));--text2-x1tsbbhh:light-dark(color(display-p3 0 0.012 0.031 / 0.887), color(display-p3 0.988 0.992 1 / 0.937));}} 67 + @media (color-gamut: p3){:root, .x1dct8vy{--bg-xyifsjz:light-dark(color(display-p3 0.998 0.989 0.988), color(display-p3 0.093 0.068 0.067));--bgSubtle-x2tkz45:light-dark(color(display-p3 0.995 0.971 0.971), color(display-p3 0.118 0.077 0.079));--component1-xaivliz:light-dark(color(display-p3 0.985 0.925 0.925), color(display-p3 0.211 0.081 0.099));--component2-xgxkwj6:light-dark(color(display-p3 0.999 0.866 0.866), color(display-p3 0.287 0.079 0.113));--component3-x3872c4:light-dark(color(display-p3 0.984 0.812 0.811), color(display-p3 0.348 0.11 0.142));--border1-x51i60m:light-dark(color(display-p3 0.955 0.751 0.749), color(display-p3 0.414 0.16 0.183));--border2-x1lnuyuh:light-dark(color(display-p3 0.915 0.675 0.672), color(display-p3 0.508 0.224 0.236));--border3-xqf689p:light-dark(color(display-p3 0.872 0.575 0.572), color(display-p3 0.659 0.298 0.297));--solid1-x1m6a25n:light-dark(color(display-p3 0.83 0.329 0.324), color(display-p3 0.83 0.329 0.324));--solid2-x1o05zwi:light-dark(color(display-p3 0.798 0.294 0.285), color(display-p3 0.861 0.403 0.387));--text1-x3r7y46:light-dark(color(display-p3 0.744 0.234 0.222), color(display-p3 1 0.57 0.55));--text2-x11v4dhp:light-dark(color(display-p3 0.36 0.115 0.143), color(display-p3 0.971 0.826 0.852));}} 68 + .--items-per-row-x1bgwy09{--items-per-row:var(--x---items-per-row)} 69 + .--progress-border-width-x1b7fzij{--progress-border-width:var(--_1-x1plbop)} 70 + .--toggle-button-group-gap-xpqjrd2{--toggle-button-group-gap:var(--_2-xsow7ju)} 71 + .--card-gap-x1w9yjgu:is([data-card-size=sm]){--card-gap:var(--_2-xsow7ju)} 72 + .--card-gap-x1nabd30:is([data-card-size=md]){--card-gap:var(--_6-x109877l)} 73 + .--card-gap-x1l22kzu:is([data-card-size=lg]){--card-gap:var(--_9-x58vtwt)} 74 + .--card-x-padding-x2nykd4:is([data-card-size=sm]){--card-x-padding:var(--_2-xsow7ju)} 75 + .--card-x-padding-xyoqhrw:is([data-card-size=md]){--card-x-padding:var(--_6-x109877l)} 76 + .--card-x-padding-xeqfs28:is([data-card-size=lg]){--card-x-padding:var(--_9-x58vtwt)} 77 + .--card-y-padding-x1s63jwo:is([data-card-size=lg]){--card-y-padding:var(--_10-xyoqvup)} 78 + .--card-y-padding-xmmjuso:is([data-card-size=sm]){--card-y-padding:var(--_2-xsow7ju)} 79 + .--card-y-padding-x1d9o89m:is([data-card-size=md]){--card-y-padding:var(--_7-x3ogwq2)} 80 + .--origin-x-x1b8bcs2:is([data-placement=right],[data-placement=right] > *){--origin-x:calc(var(--_4-xgvn2um) * -1)} 81 + .--origin-x-x11jamwj:is([data-placement=left],[data-placement=left] > *){--origin-x:var(--_4-xgvn2um)} 82 + .--origin-y-xkt5zg6:is([data-placement=bottom],[data-placement=bottom] > *){--origin-y:calc(var(--_4-xgvn2um) * -1)} 83 + .--origin-y-x1qkz1vz:is([data-placement=top],[data-placement=top] > *){--origin-y:var(--_4-xgvn2um)} 84 + .--origin-xp3o6i3:is([data-placement=right]){--origin:translateX(-4px)} 85 + .--origin-x1wfptxb:is([data-placement=left]){--origin:translateX(4px)} 86 + .--origin-x1gg9rhx:is([data-placement=bottom]){--origin:translateY(-4px)} 87 + .--origin-xqt2xo2:is([data-placement=top]){--origin:translateY(4px)} 88 + .--progress-size-xzv23kb:is([data-size=lg] *){--progress-size:var(--_10-xyoqvup)} 89 + .--progress-size-x1mc7m0b:is([data-size=sm] *){--progress-size:var(--_4-xgvn2um)} 90 + .--progress-size-xbwumww:is([data-size=md] *){--progress-size:var(--_8-x1do95gr)} 91 + .gridArea-x19dv8yz:not(#\#){grid-area:action} 92 + .gridArea-x1iynvfu:not(#\#){grid-area:bar} 93 + .gridArea-x19tbii3:not(#\#){grid-area:description} 94 + .gridArea-xxwd7sb:not(#\#){grid-area:label} 95 + .gridArea-xnyuz70:not(#\#){grid-area:title} 96 + .gridArea-xo3lhmp:not(#\#){grid-area:track} 97 + .gridArea-xilv4yv:not(#\#){grid-area:value-label} 98 + .gridTemplate-x1a6ub5m:not(#\#){grid-template:'title action'} 99 + .inset-x10a8y8t:not(#\#){inset:0} 100 + .margin-x1ghz6dp:not(#\#){margin:0} 101 + .padding-x7gbtqy:not(#\#){padding:.5rem} 102 + .padding-x1717udv:not(#\#){padding:0} 103 + .padding-x1tamke2:not(#\#){padding:16px} 104 + .padding-x1uz70x1:not(#\#){padding:1rem} 105 + .padding-x1uktvz8:not(#\#){padding:var(--_1-x1plbop)} 106 + .padding-x1mus72z:not(#\#){padding:var(--_2-xsow7ju)} 107 + .padding-x11nodoc:not(#\#){padding:var(--_3-x1a1riub)} 108 + .padding-xymjty3:not(#\#){padding:var(--_4-xgvn2um)} 109 + .padding-x1yao562:not(#\#){padding:var(--_6-x109877l)} 110 + .padding-xv88oc5:not(#\#){padding:var(--_8-x1do95gr)} 111 + .margin-xzcrhhs:is(*) pre:not(#\#){margin:0} 112 + .padding-x1fp8jo2:is(*) pre:not(#\#){padding:var(--_1-x1plbop)} 113 + .padding-x1stei55:is([data-size=sm] *):not(#\#){padding:var(--_2-xsow7ju) var(--_2_5-xmuc480)} 114 + .padding-xvljzth:is([data-size=sm] *):not(#\#){padding:var(--_2-xsow7ju) var(--_2-xsow7ju)} 115 + .padding-xdd3en7:is([data-size=md] *):not(#\#){padding:var(--_3-x1a1riub) var(--_3-x1a1riub)} 116 + .padding-xpe9v1p:is([data-size=md] *):not(#\#){padding:var(--_3-x1a1riub) var(--_4-xgvn2um)} 117 + .padding-xokpq8m:is([data-size=sm] *):not(#\#){padding:var(--_3-x1a1riub)} 118 + .padding-x1eixeqh:is([data-size=lg] *):not(#\#){padding:var(--_4-xgvn2um) var(--_4-xgvn2um)} 119 + .padding-x1462qbg:is([data-size=lg] *):not(#\#){padding:var(--_4-xgvn2um) var(--_5-x1pn3ufh)} 120 + .padding-xsz7bkx:is(*) pre:not(#\#){padding:var(--_4-xgvn2um)} 121 + .padding-xowlro6:is([data-size=md] *):not(#\#){padding:var(--_4-xgvn2um)} 122 + .padding-x11kw06r:is([data-size=lg] *):not(#\#){padding:var(--_5-x1pn3ufh)} 123 + .gridTemplate-xznk9rs:has([data-card-header-description]):not(#\#){grid-template:'title action' 'description action'} 124 + .borderColor-x9r1u3d:not(#\#):not(#\#){border-color:transparent} 125 + .borderColor-x1k39n6z:not(#\#):not(#\#){border-color:var(--border1-x1d0hf4b)} 126 + .borderColor-x1py3wlq:not(#\#):not(#\#){border-color:var(--border1-x1en7ut4)} 127 + .borderColor-xc465ie:not(#\#):not(#\#){border-color:var(--border1-x46gdic)} 128 + .borderColor-xfxcto8:not(#\#):not(#\#){border-color:var(--border1-xdz3kzl)} 129 + .borderColor-x13kk5ga:not(#\#):not(#\#){border-color:var(--border1-xm7eg2j)} 130 + .borderColor-xfo4zru:not(#\#):not(#\#){border-color:var(--border2-x130p4o0)} 131 + .borderColor-xs06tsl:not(#\#):not(#\#){border-color:var(--border2-x1k67xy2)} 132 + .borderColor-x10awtix:not(#\#):not(#\#){border-color:var(--border2-x1kmnglg)} 133 + .borderColor-xqcsr7z:not(#\#):not(#\#){border-color:var(--border2-x7rqvo0)} 134 + .borderColor-x1gsw6mb:not(#\#):not(#\#){border-color:var(--border2-xavwyw3)} 135 + .borderColor-xa6stqc:not(#\#):not(#\#){border-color:var(--border3-xm42ywm)} 136 + .borderColor-x2xmkrc:not(#\#):not(#\#){border-color:var(--component1-x11poo5x)} 137 + .borderColor-x11wpsl:not(#\#):not(#\#){border-color:var(--component1-x1gg3jrv)} 138 + .borderColor-x13lxkxy:not(#\#):not(#\#){border-color:var(--component1-x1sghgg8)} 139 + .borderColor-xty6efl:not(#\#):not(#\#){border-color:var(--component1-x1ui28u3)} 140 + .borderColor-x6txe1r:not(#\#):not(#\#){border-color:var(--solid1-x6o1eyi)} 141 + .borderColor-x1e8wf2f:not(#\#):not(#\#){border-color:var(--solid2-x1rgzn25)} 142 + .borderColor-x1nvupfo:not(#\#):not(#\#){border-color:white} 143 + .borderRadius-x2u8bby:not(#\#):not(#\#){border-radius:0} 144 + .borderRadius-x16rqkct:not(#\#):not(#\#){border-radius:50%} 145 + .borderRadius-x1gb8ofl:not(#\#):not(#\#){border-radius:var(--full-xmpdjt5)} 146 + .borderRadius-xuoujax:not(#\#):not(#\#){border-radius:var(--lg-x1011bts)} 147 + .borderRadius-x1i993ju:not(#\#):not(#\#){border-radius:var(--md-x1o51v3i)} 148 + .borderRadius-xf80l99:not(#\#):not(#\#){border-radius:var(--sm-xp4zkua)} 149 + .borderStyle-xbsl7fq:not(#\#):not(#\#){border-style:dashed} 150 + .borderStyle-x1y0btm7:not(#\#):not(#\#){border-style:solid} 151 + .borderWidth-xc342km:not(#\#):not(#\#){border-width:0} 152 + .borderWidth-xmkeg23:not(#\#):not(#\#){border-width:1px} 153 + .borderWidth-xdh2fpr:not(#\#):not(#\#){border-width:2px} 154 + .borderWidth-x1dixmfi:not(#\#):not(#\#){border-width:var(--progress-border-width)} 155 + .flex-x12lumcd:not(#\#):not(#\#){flex:1 1 auto} 156 + .gap-xou54vl:not(#\#):not(#\#){gap:16px} 157 + .gap-x1h4iudz:not(#\#):not(#\#){gap:2rem} 158 + .gap-x1rzw5jd:not(#\#):not(#\#){gap:32px} 159 + .gap-x167g77z:not(#\#):not(#\#){gap:8px} 160 + .gap-x1bb112x:not(#\#):not(#\#){gap:var(--_0_5-x1bnlq1y)} 161 + .gap-x2waoly:not(#\#):not(#\#){gap:var(--_1_5-x1llymyc)} 162 + .gap-x1k9mv0v:not(#\#):not(#\#){gap:var(--_1-x1plbop)} 163 + .gap-x1ywmbtt:not(#\#):not(#\#){gap:var(--_10-xyoqvup)} 164 + .gap-x1boramg:not(#\#):not(#\#){gap:var(--_11-x11x3va4)} 165 + .gap-xjd99v6:not(#\#):not(#\#){gap:var(--_12-xaxip2l)} 166 + .gap-xndfpl2:not(#\#):not(#\#){gap:var(--_14-x18pvp2c)} 167 + .gap-x1911wsy:not(#\#):not(#\#){gap:var(--_16-xnqsi2d)} 168 + .gap-xedfus0:not(#\#):not(#\#){gap:var(--_2_5-xmuc480)} 169 + .gap-x1j4zcgc:not(#\#):not(#\#){gap:var(--_2-xsow7ju)} 170 + .gap-x8jda87:not(#\#):not(#\#){gap:var(--_20-xbgtkw8)} 171 + .gap-xtpq9fc:not(#\#):not(#\#){gap:var(--_24-x8uq83j)} 172 + .gap-x1wnq7ln:not(#\#):not(#\#){gap:var(--_28-x3c8utc)} 173 + .gap-x1ytesra:not(#\#):not(#\#){gap:var(--_3_5-x1gotxl7)} 174 + .gap-x1vor5f1:not(#\#):not(#\#){gap:var(--_3-x1a1riub)} 175 + .gap-x9x6ubb:not(#\#):not(#\#){gap:var(--_32-xxeew7j)} 176 + .gap-xp7vuhs:not(#\#):not(#\#){gap:var(--_36-x9ro48l)} 177 + .gap-xre4se3:not(#\#):not(#\#){gap:var(--_4-xgvn2um)} 178 + .gap-xek65v7:not(#\#):not(#\#){gap:var(--_40-xlhyjhi)} 179 + .gap-x1blu1u1:not(#\#):not(#\#){gap:var(--_44-x4oqk9o)} 180 + .gap-x1qoym1l:not(#\#):not(#\#){gap:var(--_48-xc3zl6e)} 181 + .gap-x1ewgtkp:not(#\#):not(#\#){gap:var(--_5-x1pn3ufh)} 182 + .gap-x1e2g7u1:not(#\#):not(#\#){gap:var(--_52-x66e183)} 183 + .gap-xxv4kv0:not(#\#):not(#\#){gap:var(--_56-x1k96jyh)} 184 + .gap-x4upvg0:not(#\#):not(#\#){gap:var(--_6-x109877l)} 185 + .gap-x1460p1j:not(#\#):not(#\#){gap:var(--_60-xf930e)} 186 + .gap-xuvm9qt:not(#\#):not(#\#){gap:var(--_64-xhz114r)} 187 + .gap-x11mtbcp:not(#\#):not(#\#){gap:var(--_7-x3ogwq2)} 188 + .gap-x1id0tnk:not(#\#):not(#\#){gap:var(--_72-xgbkc4t)} 189 + .gap-x6foxyh:not(#\#):not(#\#){gap:var(--_8-x1do95gr)} 190 + .gap-x1no0ltn:not(#\#):not(#\#){gap:var(--_80-x12r4f45)} 191 + .gap-x1mlfgta:not(#\#):not(#\#){gap:var(--_9-x58vtwt)} 192 + .gap-x1erfctr:not(#\#):not(#\#){gap:var(--_96-x1mf07nc)} 193 + .gap-x8fwt5u:not(#\#):not(#\#){gap:var(--card-gap)} 194 + .gap-x19e0sr3:not(#\#):not(#\#){gap:var(--toggle-button-group-gap)} 195 + .gridTemplateAreas-x1syeyrc:not(#\#):not(#\#){grid-template-areas:'label value-label' 'bar bar'} 196 + .gridTemplateAreas-xynonu2:not(#\#):not(#\#){grid-template-areas:'label value-label' 'track track'} 197 + .gridTemplateAreas-x1vftqdq:not(#\#):not(#\#){grid-template-areas:'track'} 198 + .listStyle-xe8uvvx:not(#\#):not(#\#){list-style:none} 199 + .outline-x1a2a7pz:not(#\#):not(#\#){outline:none} 200 + .overflow-xysyzu8:not(#\#):not(#\#){overflow:auto} 201 + .overflow-x7giv3:not(#\#):not(#\#){overflow:clip} 202 + .overflow-xb3r6kr:not(#\#):not(#\#){overflow:hidden} 203 + .overscrollBehavior-xish69e:not(#\#):not(#\#){overscroll-behavior:contain} 204 + .textDecoration-x1r8a4m5:not(#\#):not(#\#){text-decoration:inherit} 205 + .textDecoration-xmqliwb:not(#\#):not(#\#){text-decoration:line-through} 206 + .textDecoration-x1hl2dhg:not(#\#):not(#\#){text-decoration:none} 207 + .transition-x1hhud1w:not(#\#):not(#\#){transition:height .25s} 208 + .transition-xkxqpla:not(#\#):not(#\#){transition:rotate .25s} 209 + .transition-xr2178u:not(#\#):not(#\#){transition:rotate .2s ease-in-out} 210 + @supports (corner-shape: squircle){.borderRadius-x1lluddf.borderRadius-x1lluddf:not(#\#):not(#\#){border-radius:var(--_2xl-xzsum9y)}} 211 + @supports (corner-shape: squircle){.borderRadius-xrrq4d1.borderRadius-xrrq4d1:not(#\#):not(#\#){border-radius:var(--_3xl-x1bwjc12)}} 212 + @supports (corner-shape: squircle){.borderRadius-xw9u2bx.borderRadius-xw9u2bx:not(#\#):not(#\#){border-radius:var(--_4xl-x1okofp6)}} 213 + @supports (corner-shape: squircle){.borderRadius-x6qlbny.borderRadius-x6qlbny:not(#\#):not(#\#){border-radius:var(--full-xmpdjt5)}} 214 + .borderColor-x13lu68w:is(*) pre:not(#\#):not(#\#){border-color:var(--border1-x1en7ut4)} 215 + .borderColor-x3f55jo:is([data-selected]):not(#\#):not(#\#){border-color:var(--border3-x1lhdl2z)} 216 + .borderColor-x1eiwmf5:is([data-hovered]):not(#\#):not(#\#){border-color:var(--border3-xm42ywm)} 217 + .borderColor-xqq6sos:is([data-selected]):not(#\#):not(#\#)::after{border-color:var(--border3-xm42ywm)} 218 + .borderColor-x1sy93ik:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#){border-color:var(--component1-x1gg3jrv)} 219 + .borderColor-x14yyjta:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#){border-color:var(--component1-x1sghgg8)} 220 + .borderColor-x1cdleqb:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#){border-color:var(--component1-x1ui28u3)} 221 + .borderColor-x7uwspx:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#){border-color:var(--component2-x124xhl6)} 222 + .borderColor-x1hjdiz4:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#){border-color:var(--component2-x124xhl6)} 223 + .borderColor-x1u7xhzo:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#){border-color:var(--component2-x18xhj12)} 224 + .borderColor-x12xzem2:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#){border-color:var(--component2-x1hhltqf)} 225 + .borderColor-x1norvzd:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#){border-color:var(--component2-x1hhltqf)} 226 + .borderColor-x18bsdji:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#){border-color:var(--component2-x1q29jlu)} 227 + .borderColor-x1hn2oy6:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#){border-color:var(--component2-x1q29jlu)} 228 + .borderColor-xrto6f1:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#){border-color:var(--component3-x1isc7sq)} 229 + .borderColor-xh16ylw:is([data-drop-target]):not(#\#):not(#\#){border-color:var(--solid1-x6o1eyi)} 230 + .borderRadius-x1t92zbi:is([data-size=lg]):not(#\#):not(#\#){border-radius:var(--lg-x1011bts)} 231 + .borderRadius-xebk0zn:is([data-size=lg] *):not(#\#):not(#\#){border-radius:var(--lg-x1011bts)} 232 + .borderRadius-x1yuwfv0:is(*) pre:not(#\#):not(#\#){border-radius:var(--md-x1o51v3i)} 233 + .borderRadius-xsj6ar2:is([data-size=md]):not(#\#):not(#\#){border-radius:var(--md-x1o51v3i)} 234 + .borderRadius-xaojaxi:is([data-size=md] *):not(#\#):not(#\#){border-radius:var(--md-x1o51v3i)} 235 + .borderRadius-x1xma92x:is([data-size=sm]):not(#\#):not(#\#){border-radius:var(--sm-xp4zkua)} 236 + .borderRadius-x1rz1h0l:is([data-size=sm] *):not(#\#):not(#\#){border-radius:var(--sm-xp4zkua)} 237 + .borderRadius-xerymwo:is([data-size=xl]):not(#\#):not(#\#){border-radius:var(--xl-x195otgw)} 238 + .borderStyle-xqya0cv:is(*) pre:not(#\#):not(#\#){border-style:solid} 239 + .borderStyle-x1d6f3g8:is([data-drop-target]):not(#\#):not(#\#){border-style:solid} 240 + .borderStyle-xwciwry:is([data-selected]):not(#\#):not(#\#)::after{border-style:solid} 241 + .borderWidth-x175w7g3:is(*) pre:not(#\#):not(#\#){border-width:0} 242 + .borderWidth-x1h53ki7:is(*) pre:not(#\#):not(#\#){border-width:1px} 243 + .borderWidth-xqwsx7m:is([data-selected]):not(#\#):not(#\#)::after{border-width:1px} 244 + .gap-x3qxcbn:is([data-size=sm]):not(#\#):not(#\#){gap:var(--_1-x1plbop)} 245 + .gap-x1i12q1p:is([data-orientation=vertical]):not(#\#):not(#\#){gap:var(--_2-xsow7ju)} 246 + .outline-x1wayld1:is([data-focus-visible] *):not(#\#):not(#\#){outline:2px solid var(--solid1-x1yanih7)} 247 + .textDecoration-x1meiurb:is([data-unavailable]):not(#\#):not(#\#){text-decoration:line-through} 248 + .textDecoration-x17pbne7:is([data-breadcrumb] *):not(#\#):not(#\#){text-decoration:none} 249 + .textDecoration-x1fyv82c:is([data-hovered]):not(#\#):not(#\#){text-decoration:underline} 250 + .borderColor-x1vqnz6b:has([data-hovered]):not(#\#):not(#\#){border-color:var(--border3-x16mdiod)} 251 + .borderColor-xlfq6zh:has([data-hovered]):not(#\#):not(#\#){border-color:var(--border3-x1afn5qd)} 252 + .borderColor-xbu3y6y:has([data-hovered]):not(#\#):not(#\#){border-color:var(--border3-x1kngkfb)} 253 + .borderColor-x1fywe2t:has([data-hovered]):not(:has([data-invalid])):not(#\#):not(#\#){border-color:var(--border3-xm42ywm)} 254 + .gridTemplateAreas-xx842gn:has(label,[data-slider-output]):not(#\#):not(#\#){grid-template-areas:'label value-label' 'track track'} 255 + @supports (corner-shape: squircle){.borderRadius-xdq5phb.borderRadius-xdq5phb:is(*) pre:not(#\#):not(#\#){border-radius:var(--_3xl-x1bwjc12)}} 256 + @supports (corner-shape: squircle){.borderRadius-xydlxy0.borderRadius-xydlxy0:is([data-size=lg]):not(#\#):not(#\#){border-radius:var(--_3xl-x1bwjc12)}} 257 + @supports (corner-shape: squircle){.borderRadius-x1sctp66.borderRadius-x1sctp66:is([data-size=md]):not(#\#):not(#\#){border-radius:var(--_3xl-x1bwjc12)}} 258 + @supports (corner-shape: squircle){.borderRadius-x4arbgl.borderRadius-x4arbgl:is([data-size=sm]):not(#\#):not(#\#){border-radius:var(--_3xl-x1bwjc12)}} 259 + @supports (corner-shape: squircle){.borderRadius-x1w2x00y.borderRadius-x1w2x00y:is([data-size=xl]):not(#\#):not(#\#){border-radius:var(--_3xl-x1bwjc12)}} 260 + .borderColor-x17yyxzj:disabled:not(#\#):not(#\#){border-color:transparent} 261 + .borderColor-xwl4gkf:disabled:not(#\#):not(#\#){border-color:var(--component1-x11poo5x)} 262 + .borderColor-x10hl8ol:hover:not(#\#):not(#\#){border-color:var(--border2-xavwyw3)} 263 + .borderColor-x1jy64qq:hover:not(#\#):not(#\#){border-color:var(--border3-x16mdiod)} 264 + .borderColor-x1dprclh:hover:not(#\#):not(#\#){border-color:var(--border3-x1lhdl2z)} 265 + .borderColor-x8vuplx:hover:not(#\#):not(#\#){border-color:var(--border3-x3z2k3q)} 266 + .borderColor-x1nnb4vk:hover:not(#\#):not(#\#){border-color:var(--border3-xm42ywm)} 267 + .borderColor-x9035ti:hover:not(#\#):not(#\#){border-color:var(--border3-xqf689p)} 268 + .borderColor-xlq0dt:hover:not(#\#):not(#\#){border-color:var(--component2-x18xhj12)} 269 + .borderColor-x1v4kup2:focus:not(#\#):not(#\#){border-color:var(--solid1-x1yanih7)} 270 + .outline-x1uvtmcs:focus:not(#\#):not(#\#){outline:none} 271 + .borderColor-xr9x1gx:active:not(#\#):not(#\#){border-color:var(--border3-xm42ywm)} 272 + .borderColor-xzr5fyu:active:not(#\#):not(#\#){border-color:var(--component3-x1isc7sq)} 273 + @media (prefers-reduced-motion: reduce){.transition-x9kvfbb.transition-x9kvfbb:not(#\#):not(#\#){transition:none}} 274 + .alignContent-xc26acl:not(#\#):not(#\#):not(#\#){align-content:center} 275 + .alignContent-x4465f1:not(#\#):not(#\#):not(#\#){align-content:end} 276 + .alignContent-x1jpljmv:not(#\#):not(#\#):not(#\#){align-content:space-around} 277 + .alignContent-xcdzlcm:not(#\#):not(#\#):not(#\#){align-content:space-between} 278 + .alignContent-xmsuk3y:not(#\#):not(#\#):not(#\#){align-content:space-evenly} 279 + .alignContent-x10ukxgv:not(#\#):not(#\#):not(#\#){align-content:start} 280 + .alignItems-x1pha0wt:not(#\#):not(#\#):not(#\#){align-items:baseline} 281 + .alignItems-x6s0dn4:not(#\#):not(#\#):not(#\#){align-items:center} 282 + .alignItems-xuk3077:not(#\#):not(#\#):not(#\#){align-items:flex-end} 283 + .alignItems-x1cy8zhl:not(#\#):not(#\#):not(#\#){align-items:flex-start} 284 + .alignItems-x1qjc9v5:not(#\#):not(#\#):not(#\#){align-items:stretch} 285 + .animationDuration-xvjg3zp:not(#\#):not(#\#):not(#\#){animation-duration:1.7s} 286 + .animationDuration-x1q3qbx4:not(#\#):not(#\#):not(#\#){animation-duration:1s} 287 + .animationDuration-xaft12t:not(#\#):not(#\#):not(#\#){animation-duration:var(--default-x1seeabg)} 288 + .animationDuration-xzfl22l:not(#\#):not(#\#):not(#\#){animation-duration:var(--fast-x1gssecm)} 289 + .animationDuration-xry2d85:not(#\#):not(#\#):not(#\#){animation-duration:var(--slow-xghckaq)} 290 + .animationFillMode-x10e4vud:not(#\#):not(#\#):not(#\#){animation-fill-mode:forwards} 291 + .animationIterationCount-xa4qsjk:not(#\#):not(#\#):not(#\#){animation-iteration-count:infinite} 292 + .animationName-x1aerksh:not(#\#):not(#\#):not(#\#){animation-name:x1wc8ddo-B} 293 + .animationName-x19gekol:not(#\#):not(#\#):not(#\#){animation-name:x1yf9xd4-B} 294 + .animationName-x1exzhgm:not(#\#):not(#\#):not(#\#){animation-name:x1yo5mx1-B} 295 + .animationName-x1e4sq93:not(#\#):not(#\#):not(#\#){animation-name:x72inym-B} 296 + .animationTimingFunction-x4hg4is:not(#\#):not(#\#):not(#\#){animation-timing-function:ease-in-out} 297 + .animationTimingFunction-xn0cd8s:not(#\#):not(#\#):not(#\#){animation-timing-function:ease-in} 298 + .animationTimingFunction-x1esw782:not(#\#):not(#\#):not(#\#){animation-timing-function:linear} 299 + .aspectRatio-x10y9f9r:not(#\#):not(#\#):not(#\#){aspect-ratio:var(--x-aspectRatio)} 300 + .backgroundColor-x1esc4pq:not(#\#):not(#\#):not(#\#){background-color:#14b8a6} 301 + .backgroundColor-xcpsgoo:not(#\#):not(#\#):not(#\#){background-color:rgba(0,0,0,.5)} 302 + .backgroundColor-xjbqb8w:not(#\#):not(#\#):not(#\#){background-color:transparent} 303 + .backgroundColor-xpt24m0:not(#\#):not(#\#):not(#\#){background-color:var(--bg-x151sc8w)} 304 + .backgroundColor-x1k29844:not(#\#):not(#\#):not(#\#){background-color:var(--bg-x175608s)} 305 + .backgroundColor-x1l4czcd:not(#\#):not(#\#):not(#\#){background-color:var(--bg-x1jmar6b)} 306 + .backgroundColor-x1cxuv9w:not(#\#):not(#\#):not(#\#){background-color:var(--bg-x1oix42s)} 307 + .backgroundColor-x63xxpn:not(#\#):not(#\#):not(#\#){background-color:var(--bg-x1rxyl4a)} 308 + .backgroundColor-x1r9drjd:not(#\#):not(#\#):not(#\#){background-color:var(--bg-xl687un)} 309 + .backgroundColor-x1p10r6x:not(#\#):not(#\#):not(#\#){background-color:var(--bgSubtle-x1eogh41)} 310 + .backgroundColor-xg427dp:not(#\#):not(#\#):not(#\#){background-color:var(--bgSubtle-x1y9leuq)} 311 + .backgroundColor-x1tez0uk:not(#\#):not(#\#):not(#\#){background-color:var(--bgSubtle-xi821rj)} 312 + .backgroundColor-x1s411yl:not(#\#):not(#\#):not(#\#){background-color:var(--bgSubtle-xmjz13d)} 313 + .backgroundColor-x11zz5ef:not(#\#):not(#\#):not(#\#){background-color:var(--bgSubtle-xvpzc41)} 314 + .backgroundColor-x7nz34z:not(#\#):not(#\#):not(#\#){background-color:var(--border1-x1en7ut4)} 315 + .backgroundColor-x1vh6gzx:not(#\#):not(#\#):not(#\#){background-color:var(--border2-xavwyw3)} 316 + .backgroundColor-xvf7uj2:not(#\#):not(#\#):not(#\#){background-color:var(--component1-x11poo5x)} 317 + .backgroundColor-x1a2iaau:not(#\#):not(#\#):not(#\#){background-color:var(--component1-x1gg3jrv)} 318 + .backgroundColor-x1fv4v9l:not(#\#):not(#\#):not(#\#){background-color:var(--component1-x1sghgg8)} 319 + .backgroundColor-x1nx5pi8:not(#\#):not(#\#):not(#\#){background-color:var(--component1-x1ui28u3)} 320 + .backgroundColor-xyz3se4:not(#\#):not(#\#):not(#\#){background-color:var(--component1-x43o0oh)} 321 + .backgroundColor-xy55pl3:not(#\#):not(#\#):not(#\#){background-color:var(--component2-x124xhl6)} 322 + .backgroundColor-x1kr21eg:not(#\#):not(#\#):not(#\#){background-color:var(--component2-x18xhj12)} 323 + .backgroundColor-xclalfi:not(#\#):not(#\#):not(#\#){background-color:var(--component2-x1hhltqf)} 324 + .backgroundColor-xwxmetc:not(#\#):not(#\#):not(#\#){background-color:var(--component2-x1q29jlu)} 325 + .backgroundColor-xw3eyx6:not(#\#):not(#\#):not(#\#){background-color:var(--component2-xzjwbwe)} 326 + .backgroundColor-x74tuy1:not(#\#):not(#\#):not(#\#){background-color:var(--component3-x1ejz5cj)} 327 + .backgroundColor-xkpi630:not(#\#):not(#\#):not(#\#){background-color:var(--component3-x1isc7sq)} 328 + .backgroundColor-xmiexp3:not(#\#):not(#\#):not(#\#){background-color:var(--component3-x3irpq9)} 329 + .backgroundColor-x1wopwzl:not(#\#):not(#\#):not(#\#){background-color:var(--component3-x3nfkm8)} 330 + .backgroundColor-xxm6bgo:not(#\#):not(#\#):not(#\#){background-color:var(--component3-xvwaia1)} 331 + .backgroundColor-xyxz66h:not(#\#):not(#\#):not(#\#){background-color:var(--solid1-x1yanih7)} 332 + .backgroundColor-x1uus1jj:not(#\#):not(#\#):not(#\#){background-color:var(--solid1-x2pkv20)} 333 + .backgroundColor-xkg05a4:not(#\#):not(#\#):not(#\#){background-color:var(--solid1-x6o1eyi)} 334 + .backgroundColor-x1ou224l:not(#\#):not(#\#):not(#\#){background-color:var(--solid1-xmemhk6)} 335 + .backgroundColor-xi0jere:not(#\#):not(#\#):not(#\#){background-color:var(--solid1-xnhvmlu)} 336 + .backgroundColor-x267pdx:not(#\#):not(#\#):not(#\#){background-color:var(--solid2-x1ba3nh8)} 337 + .backgroundColor-x5yh9jm:not(#\#):not(#\#):not(#\#){background-color:var(--solid2-x1dbywqs)} 338 + .backgroundColor-x1vti4om:not(#\#):not(#\#):not(#\#){background-color:var(--solid2-x1rgzn25)} 339 + .backgroundColor-xms3029:not(#\#):not(#\#):not(#\#){background-color:var(--solid2-x4985y2)} 340 + .backgroundColor-x1hn9kz4:not(#\#):not(#\#):not(#\#){background-color:var(--solid2-xlw47ga)} 341 + .backgroundColor-x12peec7:not(#\#):not(#\#):not(#\#){background-color:white} 342 + .backgroundImage-x1bl8eps:not(#\#):not(#\#):not(#\#){background-image:linear-gradient(-80deg,transparent 0%,transparent 30%,var(--component3-x1isc7sq) 50%,transparent 70%,transparent 100%)} 343 + .backgroundImage-xs7eep8:not(#\#):not(#\#):not(#\#){background-image:linear-gradient(135deg,var(--solid2-x1rgzn25) 0%,var(--text1-xc56m6b) 100%)} 344 + .backgroundImage-x1kafqu6:not(#\#):not(#\#):not(#\#){background-image:repeating-linear-gradient(45deg,var(--solid1-x6o1eyi),var(--solid1-x6o1eyi) 20px,var(--border2-x130p4o0) 20px,var(--border2-x130p4o0) 40px)} 345 + .backgroundRepeat-xiy17q3:not(#\#):not(#\#):not(#\#){background-repeat:no-repeat} 346 + .backgroundSize-x25l62i:not(#\#):not(#\#):not(#\#){background-size:100%} 347 + .backgroundSize-x12z9qec:not(#\#):not(#\#):not(#\#){background-size:20%} 348 + .borderCollapse-x1mwwwfo:not(#\#):not(#\#):not(#\#){border-collapse:collapse} 349 + .borderSpacing-x1gukg7c:not(#\#):not(#\#):not(#\#){border-spacing:0} 350 + .boxShadow-xa2943:not(#\#):not(#\#):not(#\#){box-shadow:0 0 0 1px black,inset 0 0 0 1px black} 351 + .boxShadow-x1uv2y6h:not(#\#):not(#\#):not(#\#){box-shadow:0 0 0 2px var(--component1-x1gg3jrv)} 352 + .boxShadow-xy8646n:not(#\#):not(#\#):not(#\#){box-shadow:0 0 0 2px var(--component1-x1sghgg8)} 353 + .boxShadow-xlf2e38:not(#\#):not(#\#):not(#\#){box-shadow:0 0 0 2px var(--component1-x1ui28u3)} 354 + .boxShadow-x85lyh1:not(#\#):not(#\#):not(#\#){box-shadow:inset 0 0 10px 1px rgba(0,0,0,.1)} 355 + .boxShadow-xkc5vb6:not(#\#):not(#\#):not(#\#){box-shadow:inset 0 0 8px 1px rgba(0,0,0,.2)} 356 + .boxShadow-x1gnnqk1:not(#\#):not(#\#):not(#\#){box-shadow:none} 357 + .boxShadow-x1fguj3b:not(#\#):not(#\#):not(#\#){box-shadow:var(--insetSm-xio3qbh)} 358 + .boxShadow-xidusqm:not(#\#):not(#\#):not(#\#){box-shadow:var(--lg-xgilsvr)} 359 + .boxShadow-x19jlxt2:not(#\#):not(#\#):not(#\#){box-shadow:var(--md-xf59ov0)} 360 + .boxShadow-xt4x5a2:not(#\#):not(#\#):not(#\#){box-shadow:var(--sm-xeboudq)} 361 + .boxShadow-x1iotiob:not(#\#):not(#\#):not(#\#){box-shadow:var(--x-boxShadow)} 362 + .boxShadow-x160cbv3:not(#\#):not(#\#):not(#\#){box-shadow:var(--xs-x1e2w8h4)} 363 + .boxSizing-x9f619:not(#\#):not(#\#):not(#\#){box-sizing:border-box} 364 + .color-x1heor9g:not(#\#):not(#\#):not(#\#){color:inherit} 365 + .color-x1g041ww:not(#\#):not(#\#):not(#\#){color:light-dark(white,black)} 366 + .color-x13p24mn:not(#\#):not(#\#):not(#\#){color:var(--solid1-x6o1eyi)} 367 + .color-xrykz3h:not(#\#):not(#\#):not(#\#){color:var(--solid2-x1dbywqs)} 368 + .color-x1ji32hz:not(#\#):not(#\#):not(#\#){color:var(--solid2-x1rgzn25)} 369 + .color-xvqu39i:not(#\#):not(#\#):not(#\#){color:var(--text1-x1pj8xh0)} 370 + .color-xyxuv7z:not(#\#):not(#\#):not(#\#){color:var(--text1-x253p4m)} 371 + .color-x17eu1j6:not(#\#):not(#\#):not(#\#){color:var(--text1-xb5nrd9)} 372 + .color-xqle7yb:not(#\#):not(#\#):not(#\#){color:var(--text1-xc56m6b)} 373 + .color-xbhoie5:not(#\#):not(#\#):not(#\#){color:var(--text1-xccyl1g)} 374 + .color-x1t52da2:not(#\#):not(#\#):not(#\#){color:var(--text1-xjn2lxg)} 375 + .color-xc1cpzf:not(#\#):not(#\#):not(#\#){color:var(--text2-x1drysnq)} 376 + .color-x1a78sfz:not(#\#):not(#\#):not(#\#){color:var(--text2-x1ew83cn)} 377 + .color-x1x394q5:not(#\#):not(#\#):not(#\#){color:var(--text2-x1ztxw)} 378 + .color-x1vmc86j:not(#\#):not(#\#):not(#\#){color:var(--text2-x6gkmtf)} 379 + .color-xlv6qze:not(#\#):not(#\#):not(#\#){color:var(--text2-xcv02bb)} 380 + .color-x1n45ymj:not(#\#):not(#\#):not(#\#){color:var(--textContrast-x1gt1e58)} 381 + .color-x5xs1dj:not(#\#):not(#\#):not(#\#){color:var(--textContrast-x1xz901g)} 382 + .color-x1dc14gg:not(#\#):not(#\#):not(#\#){color:var(--textContrast-xk9atbi)} 383 + .color-x1pz8lci:not(#\#):not(#\#):not(#\#){color:var(--textContrast-xmd31bd)} 384 + .color-xfru5vu:not(#\#):not(#\#):not(#\#){color:var(--textDim-x17ce2fr)} 385 + .color-xagf5oq:not(#\#):not(#\#):not(#\#){color:var(--textDim-x1v8eiz3)} 386 + .color-x1awj2ng:not(#\#):not(#\#):not(#\#){color:white} 387 + .columnGap-xe2rson:not(#\#):not(#\#):not(#\#){column-gap:var(--_1_5-x1llymyc)} 388 + .containerType-x12h1iku:not(#\#):not(#\#):not(#\#){container-type:inline-size} 389 + .content-x14obwa1:not(#\#):not(#\#):not(#\#){content:''} 390 + .cornerShape-xa22041:not(#\#):not(#\#):not(#\#){corner-shape:squircle} 391 + .cursor-xicojor:not(#\#):not(#\#):not(#\#){cursor:col-resize} 392 + .cursor-xt0e3qv:not(#\#):not(#\#):not(#\#){cursor:default} 393 + .cursor-x7eptgl:not(#\#):not(#\#):not(#\#){cursor:ew-resize} 394 + .cursor-x1ypdohk:not(#\#):not(#\#):not(#\#){cursor:pointer} 395 + .cursor-x1ed109x:not(#\#):not(#\#):not(#\#){cursor:text} 396 + .display-x1lliihq:not(#\#):not(#\#):not(#\#){display:block} 397 + .display-xjp7ctv:not(#\#):not(#\#):not(#\#){display:contents} 398 + .display-x78zum5:not(#\#):not(#\#):not(#\#){display:flex} 399 + .display-xrvj5dj:not(#\#):not(#\#):not(#\#){display:grid} 400 + .display-x1rg5ohu:not(#\#):not(#\#):not(#\#){display:inline-block} 401 + .display-x3nfvp2:not(#\#):not(#\#):not(#\#){display:inline-flex} 402 + .display-x1s85apg:not(#\#):not(#\#):not(#\#){display:none} 403 + .fill-x9d69u1:not(#\#):not(#\#):not(#\#){fill:var(--bg-x151sc8w)} 404 + .fill-x1b0arvy:not(#\#):not(#\#):not(#\#){fill:var(--solid1-x6o1eyi)} 405 + .filter-x1j01woz:not(#\#):not(#\#):not(#\#){filter:drop-shadow(-0.5px -0.5px 0 var(--border2-xavwyw3)) drop-shadow(.5px -0.5px 0 var(--border2-xavwyw3)) drop-shadow(.5px .5px 0 var(--border2-xavwyw3)) drop-shadow(-0.5px .5px 0 var(--border2-xavwyw3)) drop-shadow(0px 1px 3px rgb(0 0 0 / .1)) drop-shadow(0 -1px 3px rgb(0 0 0 / .1))} 406 + .flexBasis-x1t1x2f9:not(#\#):not(#\#):not(#\#){flex-basis:0%} 407 + .flexBasis-xdl72j9:not(#\#):not(#\#):not(#\#){flex-basis:auto} 408 + .flexBasis-x199s2q5:not(#\#):not(#\#):not(#\#){flex-basis:calc((1 / var(--items-per-row)) * (100% - (var(--toggle-button-group-gap) * (var(--items-per-row) - 1))))} 409 + .flexDirection-x3ieub6:not(#\#):not(#\#):not(#\#){flex-direction:column-reverse} 410 + .flexDirection-xdt5ytf:not(#\#):not(#\#):not(#\#){flex-direction:column} 411 + .flexDirection-x15zctf7:not(#\#):not(#\#):not(#\#){flex-direction:row-reverse} 412 + .flexDirection-x1q0g3np:not(#\#):not(#\#):not(#\#){flex-direction:row} 413 + .flexGrow-xo60xuc:not(#\#):not(#\#):not(#\#){flex-grow:.5} 414 + .flexGrow-x8m4toh:not(#\#):not(#\#):not(#\#){flex-grow:.75} 415 + .flexGrow-x1c4vz4f:not(#\#):not(#\#):not(#\#){flex-grow:0} 416 + .flexGrow-x1iyjqo2:not(#\#):not(#\#):not(#\#){flex-grow:1} 417 + .flexShrink-x2lah0s:not(#\#):not(#\#):not(#\#){flex-shrink:0} 418 + .flexShrink-xs83m0k:not(#\#):not(#\#):not(#\#){flex-shrink:1} 419 + .flexWrap-x8hhl5t:not(#\#):not(#\#):not(#\#){flex-wrap:wrap-reverse} 420 + .flexWrap-x1a02dak:not(#\#):not(#\#):not(#\#){flex-wrap:wrap} 421 + .fontFamily-xjb2p0i:not(#\#):not(#\#):not(#\#){font-family:inherit} 422 + .fontFamily-x2ttkn5:not(#\#):not(#\#):not(#\#){font-family:var(--mono-x1tvxhun)} 423 + .fontFamily-x11qb04y:not(#\#):not(#\#):not(#\#){font-family:var(--sans-x1htm3rl)} 424 + .fontFamily-x1w7yfx3:not(#\#):not(#\#):not(#\#){font-family:var(--serif-x9eavc5)} 425 + .fontSize-x9wccx5:not(#\#):not(#\#):not(#\#){font-size:.95em} 426 + .fontSize-x1qlqyl8:not(#\#):not(#\#):not(#\#){font-size:inherit} 427 + .fontSize-xakty5g:not(#\#):not(#\#):not(#\#){font-size:var(--_2xl-xq985z6)} 428 + .fontSize-x6jg0rf:not(#\#):not(#\#):not(#\#){font-size:var(--_3xl-x1lstm7v)} 429 + .fontSize-x150pmqa:not(#\#):not(#\#):not(#\#){font-size:var(--_4xl-x4z03mz)} 430 + .fontSize-x1ftte9y:not(#\#):not(#\#):not(#\#){font-size:var(--_5xl-x17lnkj2)} 431 + .fontSize-xxlv6v8:not(#\#):not(#\#):not(#\#){font-size:var(--_6xl-x1m2s84k)} 432 + .fontSize-xhxc9j7:not(#\#):not(#\#):not(#\#){font-size:var(--_7xl-xir39hh)} 433 + .fontSize-x1e2b9oe:not(#\#):not(#\#):not(#\#){font-size:var(--_8xl-xt70kky)} 434 + .fontSize-xbd8w88:not(#\#):not(#\#):not(#\#){font-size:var(--_9xl-xpyewce)} 435 + .fontSize-x2nmluw:not(#\#):not(#\#):not(#\#){font-size:var(--base-xidomu0)} 436 + .fontSize-x1a9pdt8:not(#\#):not(#\#):not(#\#){font-size:var(--lg-x1hevvyd)} 437 + .fontSize-x1m1vj2o:not(#\#):not(#\#):not(#\#){font-size:var(--sm-x1w27pzf)} 438 + .fontSize-xdmh292:not(#\#):not(#\#):not(#\#){font-size:var(--x-fontSize)} 439 + .fontSize-xoa44ge:not(#\#):not(#\#):not(#\#){font-size:var(--xl-x1vzl7l6)} 440 + .fontSize-xcd8l7k:not(#\#):not(#\#):not(#\#){font-size:var(--xs-x1vaen13)} 441 + .fontVariantNumeric-xss6m8b:not(#\#):not(#\#):not(#\#){font-variant-numeric:tabular-nums} 442 + .fontWeight-x1s688f:not(#\#):not(#\#):not(#\#){font-weight:600} 443 + .fontWeight-x1pd3egz:not(#\#):not(#\#):not(#\#){font-weight:inherit} 444 + .fontWeight-xydkh8a:not(#\#):not(#\#):not(#\#){font-weight:var(--black-xdj5g3)} 445 + .fontWeight-xckyxiw:not(#\#):not(#\#):not(#\#){font-weight:var(--bold-x1nz9syw)} 446 + .fontWeight-x1gitv93:not(#\#):not(#\#):not(#\#){font-weight:var(--extrabold-x70wtui)} 447 + .fontWeight-xg3dpo2:not(#\#):not(#\#):not(#\#){font-weight:var(--extralight-x12edb6v)} 448 + .fontWeight-x152fs08:not(#\#):not(#\#):not(#\#){font-weight:var(--light-x1xrohu8)} 449 + .fontWeight-x1mggaxd:not(#\#):not(#\#):not(#\#){font-weight:var(--medium-x1tobmye)} 450 + .fontWeight-xq9zzvo:not(#\#):not(#\#):not(#\#){font-weight:var(--normal-xi6lnv8)} 451 + .fontWeight-xotd7ge:not(#\#):not(#\#):not(#\#){font-weight:var(--semibold-x1vekvjh)} 452 + .fontWeight-x1v3qfzj:not(#\#):not(#\#):not(#\#){font-weight:var(--thin-xk6k0je)} 453 + .forcedColorAdjust-x1kzknox:not(#\#):not(#\#):not(#\#){forced-color-adjust:none} 454 + .gridColumnEnd-x5ha1vm:not(#\#):not(#\#):not(#\#){grid-column-end:var(--x-gridColumnEnd)} 455 + .gridColumnStart-x15kxzb9:not(#\#):not(#\#):not(#\#){grid-column-start:var(--x-gridColumnStart)} 456 + .gridRowEnd-x1f5yvw1:not(#\#):not(#\#):not(#\#){grid-row-end:var(--x-gridRowEnd)} 457 + .gridRowStart-x1cjrry:not(#\#):not(#\#):not(#\#){grid-row-start:var(--x-gridRowStart)} 458 + .gridTemplateColumns-xqketvx:not(#\#):not(#\#):not(#\#){grid-template-columns:var(--x-gridTemplateColumns)} 459 + .gridTemplateRows-x1xxtoay:not(#\#):not(#\#):not(#\#){grid-template-rows:var(--x-gridTemplateRows)} 460 + .justifyContent-xl56j7k:not(#\#):not(#\#):not(#\#){justify-content:center} 461 + .justifyContent-x13a6bvl:not(#\#):not(#\#):not(#\#){justify-content:flex-end} 462 + .justifyContent-x1nhvcw1:not(#\#):not(#\#):not(#\#){justify-content:flex-start} 463 + .justifyContent-x1l1ennw:not(#\#):not(#\#):not(#\#){justify-content:space-around} 464 + .justifyContent-x1qughib:not(#\#):not(#\#):not(#\#){justify-content:space-between} 465 + .justifyContent-xaw8158:not(#\#):not(#\#):not(#\#){justify-content:space-evenly} 466 + .justifyItems-x1o2pa38:not(#\#):not(#\#):not(#\#){justify-items:center} 467 + .justifyItems-x4xo5sw:not(#\#):not(#\#):not(#\#){justify-items:end} 468 + .justifyItems-x619ttb:not(#\#):not(#\#):not(#\#){justify-items:start} 469 + .justifySelf-x15bdqvn:not(#\#):not(#\#):not(#\#){justify-self:flex-end} 470 + .letterSpacing-x4gjf66:not(#\#):not(#\#):not(#\#){letter-spacing:inherit} 471 + .letterSpacing-x7gaq66:not(#\#):not(#\#):not(#\#){letter-spacing:var(--normal-xb40a8v)} 472 + .letterSpacing-xl7fe40:not(#\#):not(#\#):not(#\#){letter-spacing:var(--tight-x18yt8gk)} 473 + .letterSpacing-x1tjqt9o:not(#\#):not(#\#):not(#\#){letter-spacing:var(--tighter-x1x2i330)} 474 + .letterSpacing-xvt0q65:not(#\#):not(#\#):not(#\#){letter-spacing:var(--wide-x143nt7w)} 475 + .letterSpacing-x4dkgjf:not(#\#):not(#\#):not(#\#){letter-spacing:var(--wider-x1v3fezh)} 476 + .letterSpacing-x13wu9bi:not(#\#):not(#\#):not(#\#){letter-spacing:var(--widest-xihocmh)} 477 + .lineHeight-x15bjb6t:not(#\#):not(#\#):not(#\#){line-height:inherit} 478 + .lineHeight-x1otes00:not(#\#):not(#\#):not(#\#){line-height:var(--_2xl-xnhvph2)} 479 + .lineHeight-x1djwuob:not(#\#):not(#\#):not(#\#){line-height:var(--_3xl-x11fa68j)} 480 + .lineHeight-xpteji4:not(#\#):not(#\#):not(#\#){line-height:var(--_8-x1do95gr)} 481 + .lineHeight-x1fj13bc:not(#\#):not(#\#):not(#\#){line-height:var(--base-x17a3wz2)} 482 + .lineHeight-xcui70o:not(#\#):not(#\#):not(#\#){line-height:var(--lg-x1nt92rq)} 483 + .lineHeight-x2wzbrm:not(#\#):not(#\#):not(#\#){line-height:var(--none-x7rich4)} 484 + .lineHeight-x1iix7l:not(#\#):not(#\#):not(#\#){line-height:var(--sm-x4pl0dv)} 485 + .lineHeight-x1ygbb9r:not(#\#):not(#\#):not(#\#){line-height:var(--xl-xyq6gpo)} 486 + .lineHeight-x46yr4d:not(#\#):not(#\#):not(#\#){line-height:var(--xs-xg4a8ug)} 487 + .listStyleType-x3yw8vx:not(#\#):not(#\#):not(#\#){list-style-type:decimal} 488 + .listStyleType-xtaz4m5:not(#\#):not(#\#):not(#\#){list-style-type:disc} 489 + .listStyleType-x3ct3a4:not(#\#):not(#\#):not(#\#){list-style-type:none} 490 + .objectFit-xl1xv1r:not(#\#):not(#\#):not(#\#){object-fit:cover} 491 + .objectPosition-x115dhu7:not(#\#):not(#\#):not(#\#){object-position:center} 492 + .opacity-xbyyjgo:not(#\#):not(#\#):not(#\#){opacity:.5} 493 + .opacity-xg01cxk:not(#\#):not(#\#):not(#\#){opacity:0} 494 + .opacity-x1hc1fzr:not(#\#):not(#\#):not(#\#){opacity:1} 495 + .outlineColor-x1vjhitx:not(#\#):not(#\#):not(#\#){outline-color:blue} 496 + .outlineColor-x1lu3twc:not(#\#):not(#\#):not(#\#){outline-color:var(--solid1-x6o1eyi)} 497 + .outlineOffset-x1hl8ikr:not(#\#):not(#\#):not(#\#){outline-offset:2px} 498 + .outlineStyle-xaatb59:not(#\#):not(#\#):not(#\#){outline-style:solid} 499 + .outlineWidth-x1k57tk5:not(#\#):not(#\#):not(#\#){outline-width:0} 500 + .outlineWidth-x1qgsegg:not(#\#):not(#\#):not(#\#){outline-width:1px} 501 + .pointerEvents-x47corl:not(#\#):not(#\#):not(#\#){pointer-events:none} 502 + .position-x10l6tqk:not(#\#):not(#\#):not(#\#){position:absolute} 503 + .position-xixxii4:not(#\#):not(#\#):not(#\#){position:fixed} 504 + .position-x1n2onr6:not(#\#):not(#\#):not(#\#){position:relative} 505 + .position-x7wzq59:not(#\#):not(#\#):not(#\#){position:sticky} 506 + .resize-x8za3yd:not(#\#):not(#\#):not(#\#){resize:both} 507 + .resize-xtt52l0:not(#\#):not(#\#):not(#\#){resize:none} 508 + .rotate-x1gcftaf:not(#\#):not(#\#):not(#\#){rotate:0deg} 509 + .rowGap-xj49xfw:not(#\#):not(#\#):not(#\#){row-gap:var(--_2_5-xmuc480)} 510 + .shadow-xi4h4sd:not(#\#):not(#\#):not(#\#){shadow:var(--md-xf59ov0)} 511 + .textAlign-x2b8uid:not(#\#):not(#\#):not(#\#){text-align:center} 512 + .textAlign-x16tdsg8:not(#\#):not(#\#):not(#\#){text-align:inherit} 513 + .textAlign-xdpxx8g:not(#\#):not(#\#):not(#\#){text-align:left} 514 + .textAlign-x1hr2gdg:not(#\#):not(#\#):not(#\#){text-align:right} 515 + .textDecorationLine-xujl8zx:not(#\#):not(#\#):not(#\#){text-decoration-line:underline} 516 + .textOverflow-xlyipyv:not(#\#):not(#\#):not(#\#){text-overflow:ellipsis} 517 + .textTransform-x5ftkge:not(#\#):not(#\#):not(#\#){text-transform:inherit} 518 + .textUnderlineOffset-x1qlg3mc:not(#\#):not(#\#):not(#\#){text-underline-offset:var(--_1-x1plbop)} 519 + .touchAction-x5ve5x3:not(#\#):not(#\#):not(#\#){touch-action:none} 520 + .transformOrigin-xcz5yhc:not(#\#):not(#\#):not(#\#){transform-origin:100%} 521 + .transformOrigin-xee5nap:not(#\#):not(#\#):not(#\#){transform-origin:right} 522 + .transform-x7p49u4:not(#\#):not(#\#):not(#\#){transform:rotate(0deg)} 523 + .transform-x19jd1h0:not(#\#):not(#\#):not(#\#){transform:rotate(180deg)} 524 + .transform-x5c49eg:not(#\#):not(#\#):not(#\#){transform:translate(-100%,-50%)} 525 + .transform-x11lhmoz:not(#\#):not(#\#):not(#\#){transform:translate(-50%,-50%)} 526 + .transform-x5i6ehr:not(#\#):not(#\#):not(#\#){transform:translateX(-100%)} 527 + .transform-xuuh30:not(#\#):not(#\#):not(#\#){transform:translateX(-50%)} 528 + .transform-x1cb1t30:not(#\#):not(#\#):not(#\#){transform:translateY(-50%)} 529 + .transform-xsqj5wx:not(#\#):not(#\#):not(#\#){transform:var(--x-transform)} 530 + .transitionDuration-x1g2r6go:not(#\#):not(#\#):not(#\#){transition-duration:.1s} 531 + .transitionDuration-xpfv6me:not(#\#):not(#\#):not(#\#){transition-duration:var(--default-x1seeabg)} 532 + .transitionDuration-xx08pzc:not(#\#):not(#\#):not(#\#){transition-duration:var(--fast-x1gssecm)} 533 + .transitionDuration-x85ithh:not(#\#):not(#\#):not(#\#){transition-duration:var(--fast-x6ual6w)} 534 + .transitionDuration-xjfzak9:not(#\#):not(#\#):not(#\#){transition-duration:var(--slow-xc0p8py)} 535 + .transitionDuration-xzr5fb6:not(#\#):not(#\#):not(#\#){transition-duration:var(--slow-xghckaq)} 536 + .transitionProperty-xfagghw:not(#\#):not(#\#):not(#\#){transition-property:all} 537 + .transitionProperty-x1eaenvl:not(#\#):not(#\#):not(#\#){transition-property:background-color,border-color,color} 538 + .transitionProperty-xts7igz:not(#\#):not(#\#):not(#\#){transition-property:background-color,border-color} 539 + .transitionProperty-x15406qy:not(#\#):not(#\#):not(#\#){transition-property:background-color} 540 + .transitionProperty-xghmlwh:not(#\#):not(#\#):not(#\#){transition-property:color,border-left-color} 541 + .transitionProperty-xt3l3uh:not(#\#):not(#\#):not(#\#){transition-property:color} 542 + .transitionProperty-xua3uq3:not(#\#):not(#\#):not(#\#){transition-property:height} 543 + .transitionProperty-x13b0p5u:not(#\#):not(#\#):not(#\#){transition-property:none} 544 + .transitionProperty-x19991ni:not(#\#):not(#\#):not(#\#){transition-property:opacity} 545 + .transitionProperty-xwcsmn1:not(#\#):not(#\#):not(#\#){transition-property:transform,opacity} 546 + .transitionProperty-x11xpdln:not(#\#):not(#\#):not(#\#){transition-property:transform} 547 + .transitionProperty-xkznf9o:not(#\#):not(#\#):not(#\#){transition-property:translate,width,height} 548 + .transitionProperty-x1mnhl27:not(#\#):not(#\#):not(#\#){transition-property:translate,width} 549 + .transitionTimingFunction-xz4gly6:not(#\#):not(#\#):not(#\#){transition-timing-function:ease-in-out} 550 + .transitionTimingFunction-xcj1dhv:not(#\#):not(#\#):not(#\#){transition-timing-function:linear} 551 + .translate-x113ijq:not(#\#):not(#\#):not(#\#){translate:-50% -50%} 552 + .translate-xh1e3oa:not(#\#):not(#\#):not(#\#){translate:unset} 553 + .userSelect-x87ps6o:not(#\#):not(#\#):not(#\#){user-select:none} 554 + .visibility-xlshs6z:not(#\#):not(#\#):not(#\#){visibility:hidden} 555 + .whiteSpace-xuxw1ft:not(#\#):not(#\#):not(#\#){white-space:nowrap} 556 + .zIndex-x8knxv4:not(#\#):not(#\#):not(#\#){z-index:-1} 557 + .zIndex-x1ja2u2z:not(#\#):not(#\#):not(#\#){z-index:0} 558 + .zIndex-x1vjfegm:not(#\#):not(#\#):not(#\#){z-index:1} 559 + .zIndex-x11uqc5h:not(#\#):not(#\#):not(#\#){z-index:100} 560 + .zIndex-x1q2oy4v:not(#\#):not(#\#):not(#\#){z-index:9999} 561 + .alignItems-xoun3hd:is([data-orientation=vertical]):not(#\#):not(#\#):not(#\#){align-items:center} 562 + .alignItems-x1wjcwka:is([data-orientation=horizontal]):not(#\#):not(#\#):not(#\#){align-items:flex-start} 563 + .alignItems-xtpdso8:is([data-orientation=vertical]):not(#\#):not(#\#):not(#\#){align-items:stretch} 564 + .animationDuration-xs2en9u:is([data-entering]):not(#\#):not(#\#):not(#\#){animation-duration:.3s} 565 + .animationName-x1i605ls:is([data-entering]):not(#\#):not(#\#):not(#\#){animation-name:var(--fadeIn-x1jmpvsz)} 566 + .animationName-x4i2j9k:is([data-direction=bottom][data-entering]):not(#\#):not(#\#):not(#\#){animation-name:var(--slideInBottom-xe54f9n)} 567 + .animationName-x1ogfgie:is([data-direction=left][data-entering]):not(#\#):not(#\#):not(#\#){animation-name:var(--slideInLeft-xijpfl)} 568 + .animationName-xhx8o8z:is([data-direction=right][data-entering]):not(#\#):not(#\#):not(#\#){animation-name:var(--slideInRight-x1otygbt)} 569 + .animationName-xedw4zo:is([data-direction=top][data-entering]):not(#\#):not(#\#):not(#\#){animation-name:var(--slideInTop-x1q5efi)} 570 + .animationName-x1sllcvh:is([data-direction=bottom][data-exiting]):not(#\#):not(#\#):not(#\#){animation-name:var(--slideOutBottom-x1hjek28)} 571 + .animationName-x1phx78d:is([data-direction=left][data-exiting]):not(#\#):not(#\#):not(#\#){animation-name:var(--slideOutLeft-x18nztzn)} 572 + .animationName-x1slukww:is([data-direction=right][data-exiting]):not(#\#):not(#\#):not(#\#){animation-name:var(--slideOutRight-xft8bi2)} 573 + .animationName-x1tlo8ge:is([data-direction=top][data-exiting]):not(#\#):not(#\#):not(#\#){animation-name:var(--slideOutTop-xi8gqyr)} 574 + .animationName-xfv8cg2:is([data-entering]):not(#\#):not(#\#):not(#\#){animation-name:var(--zoomIn-xe8tyo6)} 575 + .animationTimingFunction-xyfghb2:is([data-entering]):not(#\#):not(#\#):not(#\#){animation-timing-function:cubic-bezier(.175,.885,.32,1.275)} 576 + .backgroundColor-x6yz6ea:is(*):not(#\#):not(#\#):not(#\#)::before{background-color:transparent} 577 + .backgroundColor-x7yv93o:is([data-state='dragging']):not(#\#):not(#\#):not(#\#){background-color:var(--border2-x130p4o0)} 578 + .backgroundColor-x1ccbx3t:is([data-hovered=true] *):not(#\#):not(#\#):not(#\#){background-color:var(--border2-xavwyw3)} 579 + .backgroundColor-x1xgxvzy:is([data-resizing=true] *):not(#\#):not(#\#):not(#\#){background-color:var(--border3-xm42ywm)} 580 + .backgroundColor-x1bwnevv:is([data-disabled=true] *):not(#\#):not(#\#):not(#\#){background-color:var(--border3-xm42ywm)} 581 + .backgroundColor-xvlnlln:hover:not([data-state='dragging']):not(#\#):not(#\#):not(#\#){background-color:var(--border3-xm42ywm)} 582 + .backgroundColor-x1ymmlfe:is([data-hovered]):not(#\#):not(#\#):not(#\#){background-color:var(--component1-x11poo5x)} 583 + .backgroundColor-x9mfpjm:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component1-x1gg3jrv)} 584 + .backgroundColor-x5c6nzi:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component1-x1sghgg8)} 585 + .backgroundColor-x1d3hb8j:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component1-x1ui28u3)} 586 + .backgroundColor-xty7e01:is([data-drop-target]):not(#\#):not(#\#):not(#\#){background-color:var(--component1-x43o0oh)} 587 + .backgroundColor-x1p3054l:is([data-selected]):not(#\#):not(#\#):not(#\#){background-color:var(--component1-x43o0oh)} 588 + .backgroundColor-x1azejus:is([data-selected]):not([data-selection-start],[data-selection-end]):not([data-unavailable]):not(#\#):not(#\#):not(#\#)::before{background-color:var(--component1-x43o0oh)} 589 + .backgroundColor-xhd8mbf:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x124xhl6)} 590 + .backgroundColor-x1hjp71x:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x124xhl6)} 591 + .backgroundColor-xzckxse:is([data-variant=critical] *):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x124xhl6)} 592 + .backgroundColor-xj1svf1:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x18xhj12)} 593 + .backgroundColor-x1a4xmkr:is([data-hovered=true]):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x18xhj12)} 594 + .backgroundColor-x3iekxc:is([data-react-aria-pressable=true]:hover:not([data-disabled]) *):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x18xhj12)} 595 + .backgroundColor-x15ownq4:is([data-hovered]):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x18xhj12)} 596 + .backgroundColor-x1xa9zv7:is([data-variant=secondary] *):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x18xhj12)} 597 + .backgroundColor-xh32jup:is([data-pressed]):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x18xhj12)} 598 + .backgroundColor-x2jfmnu:is([data-hovered]):not([data-unavailable]):not(#\#):not(#\#):not(#\#)::before{background-color:var(--component2-x18xhj12)} 599 + .backgroundColor-xsd57se:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x1hhltqf)} 600 + .backgroundColor-x1akb97j:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x1hhltqf)} 601 + .backgroundColor-xtgxwrx:is([data-variant=success] *):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x1hhltqf)} 602 + .backgroundColor-x1u4j5me:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x1q29jlu)} 603 + .backgroundColor-x3h62z9:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x1q29jlu)} 604 + .backgroundColor-x6d30c2:is([data-variant=warning] *):not(#\#):not(#\#):not(#\#){background-color:var(--component2-x1q29jlu)} 605 + .backgroundColor-xllbmhp:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component2-xzjwbwe)} 606 + .backgroundColor-x1q7fcaw:is([data-hovered=true]):not(#\#):not(#\#):not(#\#){background-color:var(--component2-xzjwbwe)} 607 + .backgroundColor-xfnscv6:is([data-variant=primary] *):not(#\#):not(#\#):not(#\#){background-color:var(--component2-xzjwbwe)} 608 + .backgroundColor-xk7lcje:is([data-selected]):not([data-unavailable]):not(#\#):not(#\#):not(#\#)::before{background-color:var(--component2-xzjwbwe)} 609 + .backgroundColor-x1l0anta:is([data-selection-start],[data-selection-end]):not([data-unavailable]):not(#\#):not(#\#):not(#\#)::before{background-color:var(--component2-xzjwbwe)} 610 + .backgroundColor-xkhw87q:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x1ejz5cj)} 611 + .backgroundColor-x174ku2b:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x1ejz5cj)} 612 + .backgroundColor-xbmc7h8:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x1isc7sq)} 613 + .backgroundColor-xibgg82:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x1isc7sq)} 614 + .backgroundColor-x1n9l9xn:is([data-pressed=true]):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x1isc7sq)} 615 + .backgroundColor-x18u3sjz:is([data-dragging=true]):is([data-dragging=true]):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x1isc7sq)} 616 + .backgroundColor-xvke1tl:is([data-react-aria-pressable=true]:not([data-disabled]):active *):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x1isc7sq)} 617 + .backgroundColor-x1w0eppo:is([data-pressed]):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x1isc7sq)} 618 + .backgroundColor-x11hzcxw:is([data-pressed]):not([data-unavailable]):not(#\#):not(#\#):not(#\#)::before{background-color:var(--component3-x1isc7sq)} 619 + .backgroundColor-xfj0oy5:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x3irpq9)} 620 + .backgroundColor-xlnddd4:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x3irpq9)} 621 + .backgroundColor-x1qt1x9y:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x3nfkm8)} 622 + .backgroundColor-x127wlr:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x3nfkm8)} 623 + .backgroundColor-xfm9g3v:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component3-x4u0l1k)} 624 + .backgroundColor-x120yizm:is(:active,[data-pressed=true]):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component3-xvwaia1)} 625 + .backgroundColor-xgaer2l:is(:active,[data-pressed=true]):not(#\#):not(#\#):not(#\#){background-color:var(--component3-xvwaia1)} 626 + .backgroundColor-x9pex8s:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--component3-xvwaia1)} 627 + .backgroundColor-xbhw3a7:is([data-pressed=true]):not(#\#):not(#\#):not(#\#){background-color:var(--component3-xvwaia1)} 628 + .backgroundColor-x10vob7d:is([data-selected]):not([data-unavailable]):hover:not(#\#):not(#\#):not(#\#)::before{background-color:var(--component3-xvwaia1)} 629 + .backgroundColor-x1e0gckj:is([data-selection-start],[data-selection-end]):not([data-unavailable]):hover:not(#\#):not(#\#):not(#\#)::before{background-color:var(--component3-xvwaia1)} 630 + .backgroundColor-xzrhb8f:is([data-variant=secondary] *):not(#\#):not(#\#):not(#\#){background-color:var(--solid1-x1yanih7)} 631 + .backgroundColor-x17491x2:is([data-variant=critical] *):not(#\#):not(#\#):not(#\#){background-color:var(--solid1-x2pkv20)} 632 + .backgroundColor-x1ck3tfv:hover:not(#\#):not(#\#):not(#\#)::before{background-color:var(--solid1-x6o1eyi)} 633 + .backgroundColor-x1aw4n5j:is([data-selected=true] *):not(#\#):not(#\#):not(#\#){background-color:var(--solid1-x6o1eyi)} 634 + .backgroundColor-x61hwtc:is([data-variant=primary] *):not(#\#):not(#\#):not(#\#){background-color:var(--solid1-x6o1eyi)} 635 + .backgroundColor-xxpmrhf:is([data-variant=success] *):not(#\#):not(#\#):not(#\#){background-color:var(--solid1-xmemhk6)} 636 + .backgroundColor-x2bbucx:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--solid2-x1ba3nh8)} 637 + .backgroundColor-xdx23yb:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--solid2-x1dbywqs)} 638 + .backgroundColor-x1ukug4a:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--solid2-x1rgzn25)} 639 + .backgroundColor-x8b2kiq:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--solid2-x4985y2)} 640 + .backgroundColor-xsfl4k6:hover:not(:has(* button:hover)):not(:disabled):not(#\#):not(#\#):not(#\#){background-color:var(--solid2-xlw47ga)} 641 + .backgroundColor-x1anma2h:is([data-variant=warning] *):not(#\#):not(#\#):not(#\#){background-color:var(--solid2-xlw47ga)} 642 + .backgroundImage-x1beqnot:is([data-disabled]):not(#\#):not(#\#):not(#\#){background-image:linear-gradient(var(--component2-x18xhj12),var(--component2-x18xhj12))!important} 643 + .borderBottomLeftWidth-xti2wqi:is(:not(:first-child)) *:not(#\#):not(#\#):not(#\#){border-bottom-left-width:0} 644 + .boxShadow-x19pap68:is([data-variant=critical] *):not(#\#):not(#\#):not(#\#){box-shadow:inset 0 0 2px 1px rgba(0,0,0,.2)} 645 + .boxShadow-xf34dur:is([data-variant=primary] *):not(#\#):not(#\#):not(#\#){box-shadow:inset 0 0 2px 1px rgba(0,0,0,.2)} 646 + .boxShadow-xe1oxu5:is([data-variant=secondary] *):not(#\#):not(#\#):not(#\#){box-shadow:inset 0 0 2px 1px rgba(0,0,0,.2)} 647 + .boxShadow-xdsxzvj:is([data-variant=success] *):not(#\#):not(#\#):not(#\#){box-shadow:inset 0 0 2px 1px rgba(0,0,0,.2)} 648 + .boxShadow-x10iyi2d:is([data-variant=warning] *):not(#\#):not(#\#):not(#\#){box-shadow:inset 0 0 2px 1px rgba(0,0,0,.2)} 649 + .color-x1rssh9o:is([data-react-aria-pressable=true][data-disabled] *):not(#\#):not(#\#):not(#\#){color:var(--border3-xm42ywm)} 650 + .color-x1e3r2xt:is([data-variant=warning] *):not(#\#):not(#\#):not(#\#){color:var(--text1-x1pj8xh0)} 651 + .color-x17661w7:is([data-variant=success] *):not(#\#):not(#\#):not(#\#){color:var(--text1-x253p4m)} 652 + .color-x18y9v2v:is([data-breadcrumb] *):not(#\#):not(#\#):not(#\#){color:var(--text1-xb5nrd9)} 653 + .color-xnfuzeh:is(:not(#\#):not(#\#):not(#\#)::placeholder,[data-placeholder]){color:var(--text1-xb5nrd9)} 654 + .color-xl7gfqg:is([data-placeholder]):not(#\#):not(#\#):not(#\#){color:var(--text1-xb5nrd9)} 655 + .color-xr273q8:is([data-current]):not(#\#):not(#\#):not(#\#){color:var(--text1-xb5nrd9)} 656 + .color-x3dk8ss:is([data-variant=destructive] *):not(#\#):not(#\#):not(#\#){color:var(--text1-xjn2lxg)} 657 + .color-x15gqzh4:is([data-variant=critical] *):not(#\#):not(#\#):not(#\#){color:var(--text1-xjn2lxg)} 658 + .color-xfg0ta2:is([data-breadcrumb][data-current] *):not(#\#):not(#\#):not(#\#){color:var(--text2-x1ztxw)} 659 + .color-x1gaf1qe:is([data-hovered]):not(#\#):not(#\#):not(#\#){color:var(--text2-x1ztxw)} 660 + .color-xis98h5:is([data-selected]):not(#\#):not(#\#):not(#\#){color:var(--text2-x1ztxw)} 661 + .color-xjka5tq:is([data-hovered],[data-focused],[data-selected]):not(#\#):not(#\#):not(#\#){color:var(--text2-x1ztxw)} 662 + .color-xat45n7:is([data-hovered]):not([data-unavailable]):not(#\#):not(#\#):not(#\#){color:var(--text2-x1ztxw)} 663 + .color-x8zdt5v:is([data-selected]):not(#\#):not(#\#):not(#\#){color:var(--text2-x6gkmtf)} 664 + .color-x16entun:is([data-selection-start],[data-selection-end]):not(#\#):not(#\#):not(#\#){color:var(--text2-x6gkmtf)} 665 + .color-x1v12cwp:is([data-variant=warning] *):not(#\#):not(#\#):not(#\#){color:var(--text2-xcv02bb)} 666 + .color-x1cw8dt2:is([data-variant=critical] *):not(#\#):not(#\#):not(#\#){color:var(--textContrast-x116zh0m)} 667 + .color-x1juwwod:is([data-variant=success] *):not(#\#):not(#\#):not(#\#){color:var(--textContrast-x1xz901g)} 668 + .cornerShape-x12tbmpm:is(*) pre:not(#\#):not(#\#):not(#\#){corner-shape:squircle} 669 + .cursor-x1w11t6e:is([data-resizable-direction=left]):not(#\#):not(#\#):not(#\#){cursor:e-resize} 670 + .cursor-x1oooc6o:is([data-resizable-direction=both]):not(#\#):not(#\#):not(#\#){cursor:ew-resize} 671 + .cursor-x77jxow:is([data-hovered]):not(#\#):not(#\#):not(#\#){cursor:pointer} 672 + .cursor-x11wow30:is([data-panel-group-direction=vertical]):not(#\#):not(#\#):not(#\#){cursor:row-resize} 673 + .cursor-xewnasn:is([data-resizable-direction=right]):not(#\#):not(#\#):not(#\#){cursor:w-resize} 674 + .display-x16mfbck:is([data-splitter-type='handle']:hover > *):not(#\#):not(#\#):not(#\#){display:block} 675 + .display-x1h6jewf:is([data-orientation=vertical]):not(#\#):not(#\#):not(#\#){display:flex} 676 + .display-x126me4j:is([data-breadcrumb]:last-child *):not(#\#):not(#\#):not(#\#){display:none} 677 + .filter-xece8kz:is([data-disabled]):not(#\#):not(#\#):not(#\#){filter:grayscale(1)} 678 + .flexDirection-x18ko33d:is([data-orientation=vertical]):not(#\#):not(#\#):not(#\#){flex-direction:column} 679 + .flexDirection-xb5kijp:is([data-layout=stack]):not(#\#):not(#\#):not(#\#){flex-direction:column} 680 + .flexDirection-x158tx91:is([data-orientation=horizontal]):not(#\#):not(#\#):not(#\#){flex-direction:row} 681 + .flexGrow-xmzpm4q:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#){flex-grow:1} 682 + .flexShrink-x1vnanun:is(*) svg:not(#\#):not(#\#):not(#\#){flex-shrink:0} 683 + .fontSize-xdi2y9l:is([data-card-size='lg'] *):not(#\#):not(#\#):not(#\#){font-size:var(--_2xl-xq985z6)} 684 + .fontSize-x1h5ralm:is([data-size=md] *):not(#\#):not(#\#):not(#\#){font-size:var(--base-xidomu0)} 685 + .fontSize-x1a19hz7:is([data-size=lg]):not(#\#):not(#\#):not(#\#){font-size:var(--base-xidomu0)} 686 + .fontSize-x175ohug:is([data-size=lg] *):not(#\#):not(#\#):not(#\#){font-size:var(--base-xidomu0)} 687 + .fontSize-x1py6ykt:is([data-size=lg] *):not(#\#):not(#\#):not(#\#){font-size:var(--lg-x1hevvyd)} 688 + .fontSize-x1fkmo1y:is([data-card-size='sm'] *):not(#\#):not(#\#):not(#\#){font-size:var(--lg-x1hevvyd)} 689 + .fontSize-xiceyaw:is([data-size=sm] *):not(#\#):not(#\#):not(#\#){font-size:var(--sm-x1w27pzf)} 690 + .fontSize-x1bzifm9:is([data-size=md]):not(#\#):not(#\#):not(#\#){font-size:var(--sm-x1w27pzf)} 691 + .fontSize-x1ya0evx:is([data-size=md] *):not(#\#):not(#\#):not(#\#){font-size:var(--sm-x1w27pzf)} 692 + .fontSize-xonwjwx:is([data-size=xl] *):not(#\#):not(#\#):not(#\#){font-size:var(--xl-x1vzl7l6)} 693 + .fontSize-xujovw0:is([data-card-size='md'] *):not(#\#):not(#\#):not(#\#){font-size:var(--xl-x1vzl7l6)} 694 + .fontSize-x1w3w1z:is([data-size=sm]):not(#\#):not(#\#):not(#\#){font-size:var(--xs-x1vaen13)} 695 + .fontSize-x14nmpad:is([data-size=sm] *):not(#\#):not(#\#):not(#\#){font-size:var(--xs-x1vaen13)} 696 + .fontWeight-x12f8piz:is([data-react-aria-pressable=true][data-selected=true]):not(#\#):not(#\#):not(#\#){font-weight:var(--medium-x1tobmye)} 697 + .fontWeight-x6i2wo5:is([data-current]):not(#\#):not(#\#):not(#\#){font-weight:var(--medium-x1tobmye)} 698 + .lineHeight-xx24gj9:is(li *):not(#\#):not(#\#):not(#\#){line-height:var(--base-x17a3wz2)} 699 + .lineHeight-x1qqnixq:is(blockquote *):not(#\#):not(#\#):not(#\#){line-height:var(--base-x17a3wz2)} 700 + .lineHeight-x1g66cck:is([data-size=lg]):not(#\#):not(#\#):not(#\#){line-height:var(--base-x17a3wz2)} 701 + .lineHeight-xygti73:is([data-size=lg] *):not(#\#):not(#\#):not(#\#){line-height:var(--base-x17a3wz2)} 702 + .lineHeight-x5ejvnn:is([data-size=md]):not(#\#):not(#\#):not(#\#){line-height:var(--sm-x4pl0dv)} 703 + .lineHeight-x1scf232:is([data-size=md] *):not(#\#):not(#\#):not(#\#){line-height:var(--sm-x4pl0dv)} 704 + .lineHeight-xnvsck6:is([data-size=sm]):not(#\#):not(#\#):not(#\#){line-height:var(--xs-xg4a8ug)} 705 + .lineHeight-x47360v:is([data-size=sm] *):not(#\#):not(#\#):not(#\#){line-height:var(--xs-xg4a8ug)} 706 + .opacity-x1lxkrgy:is([disabled]):not(#\#):not(#\#):not(#\#){opacity:.3} 707 + .opacity-xxh3kiz:is([data-disabled]):not(#\#):not(#\#):not(#\#){opacity:.5} 708 + .opacity-xz45kkc:is([aria-disabled=true] *):not(#\#):not(#\#):not(#\#){opacity:.5} 709 + .opacity-x78oxnk:is([data-disabled=true] *):not(#\#):not(#\#):not(#\#){opacity:.5} 710 + .opacity-xc6n1n6:is([data-outside-visible-range],[data-unavailable]):not(#\#):not(#\#):not(#\#){opacity:.5} 711 + .opacity-xo3lgda:is([data-entering]):not(#\#):not(#\#):not(#\#){opacity:0} 712 + .opacity-x1y3ytew:is([data-exiting]):not(#\#):not(#\#):not(#\#){opacity:0} 713 + .opacity-x1xlq6hu:is([data-entering], [data-entering] > *):not(#\#):not(#\#):not(#\#){opacity:0} 714 + .opacity-x15h3uk9:is([data-exiting], [data-exiting] > *):not(#\#):not(#\#):not(#\#){opacity:0} 715 + .opacity-xdwziqs:is([data-heading-link]:hover *):not(#\#):not(#\#):not(#\#){opacity:1} 716 + .opacity-x127iuxr:is([data-focus-visible]):not(#\#):not(#\#):not(#\#){opacity:1} 717 + .opacity-x1f9km8m:is([data-react-aria-pressable=true]:hover:not([data-disabled]) *):not(#\#):not(#\#):not(#\#){opacity:1} 718 + .outlineColor-xyr3coy:is([data-selected]):not(#\#):not(#\#):not(#\#)::after{outline-color:white} 719 + .outlineOffset-x1goi28a:is([data-selected]):not(#\#):not(#\#):not(#\#)::after{outline-offset:-2px} 720 + .outlineStyle-xzo6rw9:is([data-selected]):not(#\#):not(#\#):not(#\#)::after{outline-style:solid} 721 + .outlineWidth-x1pxrnyt:is([data-selected]):not(#\#):not(#\#):not(#\#)::after{outline-width:2px} 722 + .pointerEvents-x19fw6na:is(*) svg:not(#\#):not(#\#):not(#\#){pointer-events:none} 723 + .pointerEvents-x19hqv7w:is([data-exiting], [data-exiting] > *):not(#\#):not(#\#):not(#\#){pointer-events:none} 724 + .rotate-xufvh4u:is([aria-expanded=true] *):not(#\#):not(#\#):not(#\#){rotate:180deg} 725 + .rotate-x18ellfx:is([aria-expanded=true] *):not(#\#):not(#\#):not(#\#){rotate:90deg} 726 + .transform-x140extk:is([data-placement=right] *):not(#\#):not(#\#):not(#\#){transform:rotate(-90deg)} 727 + .transform-x1s861hk:is([data-placement=top] *):not(#\#):not(#\#):not(#\#){transform:rotate(0deg)} 728 + .transform-xr9p1a1:is([data-placement=bottom] *):not(#\#):not(#\#):not(#\#){transform:rotate(180deg)} 729 + .transform-x1pjk68:is([data-placement=left] *):not(#\#):not(#\#):not(#\#){transform:rotate(90deg)} 730 + .transform-xk6zm71:is([aria-expanded=true] *):not(#\#):not(#\#):not(#\#){transform:rotate(90deg)} 731 + .transform-x1ha5ii1:is([data-entering]):not(#\#):not(#\#):not(#\#){transform:scale(.9) var(--origin)} 732 + .transform-xfdjxlr:is([data-exiting]):not(#\#):not(#\#):not(#\#){transform:scale(.9) var(--origin)} 733 + .transform-x1ilsqch:is([data-entering], [data-entering] > *):not(#\#):not(#\#):not(#\#){transform:scale(.95) translate(var(--origin-x,0),var(--origin-y,0))} 734 + .transform-xxucve0:is([data-exiting], [data-exiting] > *):not(#\#):not(#\#):not(#\#){transform:scale(.95) translate(var(--origin-x,0),var(--origin-y,0))} 735 + .transform-x1a19u22:is([data-selected=true] *):not(#\#):not(#\#):not(#\#){transform:translate(100%,-50%)} 736 + .transform-xet38jj:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#)::before{transform:translateX(-50%)} 737 + .transform-xvyvk38:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#){transform:translateX(-50%)} 738 + .transform-xikjbfy:is([data-handle-orientation='horizontal'] *):not(#\#):not(#\#):not(#\#){transform:translateX(-50%)} 739 + .transform-x19lgda6:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#)::before{transform:translateY(-50%)} 740 + .transform-x174hktb:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#){transform:translateY(-50%)} 741 + .transform-xa746um:is([data-handle-orientation='vertical'] *):not(#\#):not(#\#):not(#\#){transform:translateY(-50%)} 742 + .transform-xm5um24:is([data-placement=top] *):not(#\#):not(#\#):not(#\#){transform:tranuiColorY(-50%) rotate(-45deg)} 743 + .transitionDuration-xgggp24:is([data-exiting]):not(#\#):not(#\#):not(#\#){transition-duration:var(--fast-x1gssecm)} 744 + .zIndex-xikqtj0:is([data-selected]):not(#\#):not(#\#):not(#\#){z-index:0} 745 + .alignItems-xkjcc5q:has(p):not(#\#):not(#\#):not(#\#){align-items:flex-start} 746 + .backgroundColor-x1ywip0:has(td:hover):not(#\#):not(#\#):not(#\#){background-color:var(--bgSubtle-xi821rj)} 747 + .boxShadow-xqd9uwx:has([data-invalid]):not(#\#):not(#\#):not(#\#){box-shadow:0 0 0 2px var(--component1-x1sghgg8)} 748 + .color-x17u1pav:is([data-variant=critical] *):is(*) svg:not(#\#):not(#\#):not(#\#){color:var(--solid1-x2pkv20)} 749 + .color-x1ok210x:is([data-variant=success] *):is(*) svg:not(#\#):not(#\#):not(#\#){color:var(--solid1-xmemhk6)} 750 + .color-x1af8a7e:is([data-variant=warning] *):is(*) svg:not(#\#):not(#\#):not(#\#){color:var(--solid1-xnhvmlu)} 751 + .backgroundColor-x1oqui1x:disabled:not(#\#):not(#\#):not(#\#){background-color:transparent} 752 + .backgroundColor-xcvjdaz:disabled:not(#\#):not(#\#):not(#\#){background-color:var(--component1-x11poo5x)} 753 + .backgroundColor-xhe8pwl:disabled:not(#\#):not(#\#):not(#\#){background-color:var(--component1-x1gg3jrv)} 754 + .backgroundColor-x9ustey:disabled:not(#\#):not(#\#):not(#\#){background-color:var(--component1-x1sghgg8)} 755 + .backgroundColor-x1dfs8j4:disabled:not(#\#):not(#\#):not(#\#){background-color:var(--component1-x1ui28u3)} 756 + .backgroundColor-x1snhj8a:disabled:not(#\#):not(#\#):not(#\#){background-color:var(--component1-x43o0oh)} 757 + .color-xnxeckx:disabled:not(#\#):not(#\#):not(#\#){color:var(--text1-xb5nrd9)} 758 + .opacity-xijokvz:disabled:not(#\#):not(#\#):not(#\#){opacity:.5} 759 + .pointerEvents-xaqnwrm:disabled:not(#\#):not(#\#):not(#\#){pointer-events:none} 760 + .backgroundColor-x1byop2d:hover:not(#\#):not(#\#):not(#\#){background-color:rgba(255,255,255,.3)} 761 + .backgroundColor-x1tett1n:hover:not(#\#):not(#\#):not(#\#){background-color:var(--border2-xavwyw3)} 762 + .backgroundColor-x1jqod2p:hover:not(#\#):not(#\#):not(#\#){background-color:var(--component1-x11poo5x)} 763 + .backgroundColor-xow2hbl:hover:not(#\#):not(#\#):not(#\#){background-color:var(--component2-x18xhj12)} 764 + .backgroundColor-x151gwij:hover:not(#\#):not(#\#):not(#\#){background-color:var(--component2-xzjwbwe)} 765 + .backgroundColor-x11aw7u0:hover:not(#\#):not(#\#):not(#\#){background-color:var(--component3-xvwaia1)} 766 + .backgroundColor-xp87xln:hover:not(#\#):not(#\#):not(#\#){background-color:var(--solid2-x1rgzn25)} 767 + .color-xjrurd6:hover:not(#\#):not(#\#):not(#\#){color:var(--text2-x1ztxw)} 768 + .opacity-x1o7uuvo:hover:not(#\#):not(#\#):not(#\#){opacity:1} 769 + .outlineWidth-xat8dtc:focus:not(#\#):not(#\#):not(#\#){outline-width:1px} 770 + .backgroundColor-x174fhsx:active:not(#\#):not(#\#):not(#\#){background-color:var(--border3-xm42ywm)} 771 + .backgroundColor-x13w91gl:active:not(#\#):not(#\#):not(#\#){background-color:var(--component3-x1isc7sq)} 772 + .backgroundColor-x1jjjnae:active:not(#\#):not(#\#):not(#\#){background-color:var(--text1-xc56m6b)} 773 + @media (prefers-reduced-motion: reduce){.animationName-x1aquc0h.animationName-x1aquc0h:not(#\#):not(#\#):not(#\#){animation-name:none}} 774 + @media (min-width: 48rem){.fontSize-x1em9g14.fontSize-x1em9g14:not(#\#):not(#\#):not(#\#){font-size:var(--_4xl-x4z03mz)}} 775 + @media (min-width: 48rem){.fontSize-xd8xfak.fontSize-xd8xfak:not(#\#):not(#\#):not(#\#){font-size:var(--_5xl-x17lnkj2)}} 776 + @media (prefers-reduced-motion: reduce){.transitionProperty-x4wkmsb.transitionProperty-x4wkmsb:not(#\#):not(#\#):not(#\#){transition-property:none}} 777 + @container (min-width: 400px){.display-x1b4ekcc.display-x1b4ekcc:not(#\#):not(#\#):not(#\#){display:flex}} 778 + @container (min-width: 400px){.display-xr91lqn.display-xr91lqn:not(#\#):not(#\#):not(#\#){display:none}} 779 + .borderBottomColor-x16stqrj:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-color:transparent} 780 + .borderBottomColor-x4zo83h:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-color:var(--border1-x1en7ut4)} 781 + .borderBottomColor-xc7lc1u:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-color:var(--border2-xavwyw3)} 782 + .borderBottomLeftRadius-xfrllxf:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-left-radius:0} 783 + .borderBottomLeftRadius-x19y7gkx:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-left-radius:var(--md-x1o51v3i)} 784 + .borderBottomRightRadius-xjppbhk:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-right-radius:0} 785 + .borderBottomRightRadius-x1ww4vys:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-right-radius:var(--md-x1o51v3i)} 786 + .borderBottomStyle-x1q0q8m5:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-style:solid} 787 + .borderBottomWidth-x1qhh985:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-width:0} 788 + .borderBottomWidth-xso031l:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-width:1px} 789 + .borderLeftColor-x80kmbg:not(#\#):not(#\#):not(#\#):not(#\#){border-left-color:var(--border1-x1en7ut4)} 790 + .borderLeftColor-x1nbwh4f:not(#\#):not(#\#):not(#\#):not(#\#){border-left-color:var(--border2-xavwyw3)} 791 + .borderLeftColor-xicfvt9:not(#\#):not(#\#):not(#\#):not(#\#){border-left-color:var(--borderDim-x1j89upv)} 792 + .borderLeftColor-x1iy1ygf:not(#\#):not(#\#):not(#\#):not(#\#){border-left-color:var(--solid1-x6o1eyi)} 793 + .borderLeftStyle-x19ypqd9:not(#\#):not(#\#):not(#\#):not(#\#){border-left-style:solid} 794 + .borderLeftWidth-xyj58a3:not(#\#):not(#\#):not(#\#):not(#\#){border-left-width:0} 795 + .borderLeftWidth-xe0pwq:not(#\#):not(#\#):not(#\#):not(#\#){border-left-width:1px} 796 + .borderRightColor-xm0m5e5:not(#\#):not(#\#):not(#\#):not(#\#){border-right-color:var(--border2-xavwyw3)} 797 + .borderRightStyle-x32b0ac:not(#\#):not(#\#):not(#\#):not(#\#){border-right-style:solid} 798 + .borderRightWidth-xgfja2r:not(#\#):not(#\#):not(#\#):not(#\#){border-right-width:0} 799 + .borderRightWidth-xs1s249:not(#\#):not(#\#):not(#\#):not(#\#){border-right-width:1px} 800 + .borderTopColor-xdo11qm:not(#\#):not(#\#):not(#\#):not(#\#){border-top-color:var(--border1-x1en7ut4)} 801 + .borderTopColor-x1unxl75:not(#\#):not(#\#):not(#\#):not(#\#){border-top-color:var(--border2-xavwyw3)} 802 + .borderTopLeftRadius-x1ia1hqs:not(#\#):not(#\#):not(#\#):not(#\#){border-top-left-radius:0} 803 + .borderTopLeftRadius-xkvr9zc:not(#\#):not(#\#):not(#\#):not(#\#){border-top-left-radius:var(--md-x1o51v3i)} 804 + .borderTopRightRadius-x1a2w583:not(#\#):not(#\#):not(#\#):not(#\#){border-top-right-radius:0} 805 + .borderTopRightRadius-xpiszqg:not(#\#):not(#\#):not(#\#):not(#\#){border-top-right-radius:var(--md-x1o51v3i)} 806 + .borderTopStyle-x13fuv20:not(#\#):not(#\#):not(#\#):not(#\#){border-top-style:solid} 807 + .borderTopWidth-x972fbf:not(#\#):not(#\#):not(#\#):not(#\#){border-top-width:0} 808 + .borderTopWidth-x178xt8z:not(#\#):not(#\#):not(#\#):not(#\#){border-top-width:1px} 809 + .bottom-x1ey2m1c:not(#\#):not(#\#):not(#\#):not(#\#){bottom:0} 810 + .bottom-x19qnocw:not(#\#):not(#\#):not(#\#):not(#\#){bottom:var(--_3-x1a1riub)} 811 + .bottom-x10yiizf:not(#\#):not(#\#):not(#\#):not(#\#){bottom:var(--_4-xgvn2um)} 812 + .height-x5yr21d:not(#\#):not(#\#):not(#\#):not(#\#){height:100%} 813 + .height-x1dr59a3:not(#\#):not(#\#):not(#\#):not(#\#){height:100vh} 814 + .height-xjm9jq1:not(#\#):not(#\#):not(#\#):not(#\#){height:1px} 815 + .height-x1vd4hg5:not(#\#):not(#\#):not(#\#):not(#\#){height:300px} 816 + .height-x16nrsnc:not(#\#):not(#\#):not(#\#):not(#\#){height:400px} 817 + .height-xdd8jsf:not(#\#):not(#\#):not(#\#):not(#\#){height:52px} 818 + .height-x1xa6b72:not(#\#):not(#\#):not(#\#):not(#\#){height:700px} 819 + .height-x3urnb8:not(#\#):not(#\#):not(#\#):not(#\#){height:800px} 820 + .height-xt7dq6l:not(#\#):not(#\#):not(#\#):not(#\#){height:auto} 821 + .height-xfc2vd1:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_10-xyoqvup)} 822 + .height-xrkkcas:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_12-xaxip2l)} 823 + .height-x140y8s0:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_16-xnqsi2d)} 824 + .height-x1gek4bg:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_2_5-xmuc480)} 825 + .height-x1tdiqgn:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_2-xsow7ju)} 826 + .height-x1tmjr0p:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_32-xxeew7j)} 827 + .height-x1h8rqws:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_4-xgvn2um)} 828 + .height-xlwbodq:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_40-xlhyjhi)} 829 + .height-xsi1db0:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_5-x1pn3ufh)} 830 + .height-x6bhkw4:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_6-x109877l)} 831 + .height-xuupj4z:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_7-x3ogwq2)} 832 + .height-xk310vn:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_72-xgbkc4t)} 833 + .height-xcky1rk:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_8-x1do95gr)} 834 + .height-xxdp216:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--disclosure-panel-height)} 835 + .height-x11shy6x:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--page-height)} 836 + .height-x166ztde:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--progress-size)} 837 + .height-x16ye13r:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--x-height)} 838 + .left-xu96u03:not(#\#):not(#\#):not(#\#):not(#\#){left:0} 839 + .left-x1nrll8i:not(#\#):not(#\#):not(#\#):not(#\#){left:50%} 840 + .left-xnacogl:not(#\#):not(#\#):not(#\#):not(#\#){left:var(--_1-x1plbop)} 841 + .left-xz72ev6:not(#\#):not(#\#):not(#\#):not(#\#){left:var(--_2-xsow7ju)} 842 + .marginBottom-xat24cr:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:0} 843 + .marginBottom-xyi6m4r:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:1rem} 844 + .marginBottom-xubxldh:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:calc(var(--_1-x1plbop) * -1)} 845 + .marginBottom-x1yuevv8:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:calc(var(--_2-xsow7ju) * -1)} 846 + .marginBottom-x153mvl1:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--_1_5-x1llymyc)} 847 + .marginBottom-xuzbrib:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--_12-xaxip2l)} 848 + .marginBottom-x3s77m2:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--_4-xgvn2um)} 849 + .marginBottom-x1p6xj8o:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--_5-x1pn3ufh)} 850 + .marginBottom-x11n9ykl:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--_6-x109877l)} 851 + .marginBottom-x2ali7v:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--_8-x1do95gr)} 852 + .marginLeft-x16jtila:not(#\#):not(#\#):not(#\#):not(#\#){margin-left:calc(var(--_0_5-x1bnlq1y) * -1)} 853 + .marginLeft-xbxdmyg:not(#\#):not(#\#):not(#\#):not(#\#){margin-left:calc(var(--_2_5-xmuc480) * -1)} 854 + .marginLeft-x140u6kw:not(#\#):not(#\#):not(#\#):not(#\#){margin-left:calc(var(--_2-xsow7ju) * -1)} 855 + .marginLeft-xtib8b6:not(#\#):not(#\#):not(#\#):not(#\#){margin-left:calc(var(--_3-x1a1riub) * -1)} 856 + .marginLeft-xvmb2fk:not(#\#):not(#\#):not(#\#):not(#\#){margin-left:var(--_1-x1plbop)} 857 + .marginLeft-xy28nsv:not(#\#):not(#\#):not(#\#):not(#\#){margin-left:var(--_2-xsow7ju)} 858 + .marginRight-x1yf7rl7:not(#\#):not(#\#):not(#\#):not(#\#){margin-right:0} 859 + .marginRight-x94flzf:not(#\#):not(#\#):not(#\#):not(#\#){margin-right:calc(var(--_0_5-x1bnlq1y) * -1)} 860 + .marginRight-xkx2q80:not(#\#):not(#\#):not(#\#):not(#\#){margin-right:calc(var(--_2-xsow7ju) * -1)} 861 + .marginRight-x1qg4v5a:not(#\#):not(#\#):not(#\#):not(#\#){margin-right:calc(var(--_3-x1a1riub) * -1)} 862 + .marginRight-x1051q95:not(#\#):not(#\#):not(#\#):not(#\#){margin-right:var(--_1-x1plbop)} 863 + .marginRight-x1nx9lg9:not(#\#):not(#\#):not(#\#):not(#\#){margin-right:var(--_4-xgvn2um)} 864 + .marginTop-xdj266r:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:0} 865 + .marginTop-xr1yuqi:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:auto} 866 + .marginTop-x1x4oqzj:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:calc(var(--_1-x1plbop) * -1)} 867 + .marginTop-x1xcu83e:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:calc(var(--_2-xsow7ju) * -1)} 868 + .marginTop-xxugbsv:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--_1_5-x1llymyc)} 869 + .marginTop-xj26ot3:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--_12-xaxip2l)} 870 + .marginTop-xsjbwxm:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--_16-xnqsi2d)} 871 + .marginTop-xkeb37j:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--_4-xgvn2um)} 872 + .marginTop-x15z9wlt:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--_5-x1pn3ufh)} 873 + .marginTop-x1u5uhqf:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--_8-x1do95gr)} 874 + .maxHeight-x1oh82ff:not(#\#):not(#\#):not(#\#):not(#\#){max-height:calc(var(--visual-viewport-height) * .8)} 875 + .maxWidth-x1mqrghp:not(#\#):not(#\#):not(#\#):not(#\#){max-width:100ch} 876 + .minHeight-x2lwn1j:not(#\#):not(#\#):not(#\#):not(#\#){min-height:0} 877 + .minHeight-x6uqey6:not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--_12-xaxip2l)} 878 + .minHeight-x1bgdama:not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--_40-xlhyjhi)} 879 + .minHeight-xlqy7cr:not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--_7-x3ogwq2)} 880 + .minHeight-x1btrftn:not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--_8-x1do95gr)} 881 + .minHeight-x4fvrxy:not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--_9-x58vtwt)} 882 + .minWidth-xeuugli:not(#\#):not(#\#):not(#\#):not(#\#){min-width:0} 883 + .minWidth-x1sn4fs6:not(#\#):not(#\#):not(#\#):not(#\#){min-width:var(--_4-xgvn2um)} 884 + .minWidth-x75xjn4:not(#\#):not(#\#):not(#\#):not(#\#){min-width:var(--_60-xf930e)} 885 + .minWidth-xxqemk0:not(#\#):not(#\#):not(#\#):not(#\#){min-width:var(--_8-x1do95gr)} 886 + .overflowY-x1odjw0f:not(#\#):not(#\#):not(#\#):not(#\#){overflow-y:auto} 887 + .paddingBottom-x18d9i69:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:0} 888 + .paddingBottom-xkcyk3g:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_0_5-x1bnlq1y)} 889 + .paddingBottom-x1o6k5y8:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_1-x1plbop)} 890 + .paddingBottom-x16qb4in:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_12-xaxip2l)} 891 + .paddingBottom-x1o314:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_2-xsow7ju)} 892 + .paddingBottom-xbfpk89:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_20-xbgtkw8)} 893 + .paddingBottom-x1xi39lx:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_3-x1a1riub)} 894 + .paddingBottom-xnfycaw:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_4-xgvn2um)} 895 + .paddingBottom-x1p08vyf:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_6-x109877l)} 896 + .paddingLeft-x1uhho1l:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:0} 897 + .paddingLeft-x1bbsik7:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_0_5-x1bnlq1y)} 898 + .paddingLeft-x1kmr12f:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_1_5-x1llymyc)} 899 + .paddingLeft-x115zygv:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_1-x1plbop)} 900 + .paddingLeft-xlcfnap:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_10-xyoqvup)} 901 + .paddingLeft-x1b1v5c0:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_16-xnqsi2d)} 902 + .paddingLeft-x11rlpl4:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_2_5-xmuc480)} 903 + .paddingLeft-x18qrpd6:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_2-xsow7ju)} 904 + .paddingLeft-x16j2j4g:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_3-x1a1riub)} 905 + .paddingLeft-x8smes1:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_4-xgvn2um)} 906 + .paddingLeft-x15ntmvy:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_6-x109877l)} 907 + .paddingLeft-x81jyg:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_8-x1do95gr)} 908 + .paddingLeft-xbc5pgh:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--card-x-padding)} 909 + .paddingLeft-x13e46o5:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--x-paddingLeft)} 910 + .paddingRight-x1xpa7k:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:0} 911 + .paddingRight-x1k8k2k7:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_1_5-x1llymyc)} 912 + .paddingRight-x19p030x:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_1-x1plbop)} 913 + .paddingRight-x1o9lhx6:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_16-xnqsi2d)} 914 + .paddingRight-x17i3xln:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_2_5-xmuc480)} 915 + .paddingRight-x181basc:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_2-xsow7ju)} 916 + .paddingRight-x6cyeea:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_3-x1a1riub)} 917 + .paddingRight-x13a2dg3:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_4-xgvn2um)} 918 + .paddingRight-x1scv0vq:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_6-x109877l)} 919 + .paddingRight-x15wkd4u:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_8-x1do95gr)} 920 + .paddingRight-x1u8e7yt:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--card-x-padding)} 921 + .paddingRight-xwsd3xy:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--x-paddingRight)} 922 + .paddingTop-xexx8yu:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:0} 923 + .paddingTop-x159zdv2:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_0_5-x1bnlq1y)} 924 + .paddingTop-x1n2t9di:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_1_5-x1llymyc)} 925 + .paddingTop-xevm68z:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_1-x1plbop)} 926 + .paddingTop-xks1qye:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_12-xaxip2l)} 927 + .paddingTop-x1h4xhff:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_2-xsow7ju)} 928 + .paddingTop-x104xgb4:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_20-xbgtkw8)} 929 + .paddingTop-x1s6vlbb:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_3-x1a1riub)} 930 + .paddingTop-x1noqrsl:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_4-xgvn2um)} 931 + .paddingTop-x1k7s7hd:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_5-x1pn3ufh)} 932 + .paddingTop-xz418gm:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_6-x109877l)} 933 + .right-x3m8u43:not(#\#):not(#\#):not(#\#):not(#\#){right:0} 934 + .right-x1e3uvw1:not(#\#):not(#\#):not(#\#):not(#\#){right:var(--_3-x1a1riub)} 935 + .right-xjqvg7w:not(#\#):not(#\#):not(#\#):not(#\#){right:var(--_4-xgvn2um)} 936 + .scrollMarginTop-x16864uc:not(#\#):not(#\#):not(#\#):not(#\#){scroll-margin-top:var(--_20-xbgtkw8)} 937 + .top-x13dri30:not(#\#):not(#\#):not(#\#):not(#\#){top:-0.01em} 938 + .top-x13vifvy:not(#\#):not(#\#):not(#\#):not(#\#){top:0} 939 + .top-xwa60dl:not(#\#):not(#\#):not(#\#):not(#\#){top:50%} 940 + .top-x1drkmrx:not(#\#):not(#\#):not(#\#):not(#\#){top:calc(var(--visual-viewport-height) / 2)} 941 + .top-x18vgj00:not(#\#):not(#\#):not(#\#):not(#\#){top:var(--_1-x1plbop)} 942 + .top-x3l5brz:not(#\#):not(#\#):not(#\#):not(#\#){top:var(--_2_5-xmuc480)} 943 + .top-x1fcu2lf:not(#\#):not(#\#):not(#\#):not(#\#){top:var(--_3-x1a1riub)} 944 + .width-xh8yej3:not(#\#):not(#\#):not(#\#):not(#\#){width:100%} 945 + .width-x1udut9i:not(#\#):not(#\#):not(#\#):not(#\#){width:1000%} 946 + .width-xn9wirt:not(#\#):not(#\#):not(#\#):not(#\#){width:100vw} 947 + .width-x1y43apy:not(#\#):not(#\#):not(#\#):not(#\#){width:1200px} 948 + .width-x1lmkilm:not(#\#):not(#\#):not(#\#):not(#\#){width:1600px} 949 + .width-x13esg8c:not(#\#):not(#\#):not(#\#):not(#\#){width:2000px} 950 + .width-x16grhtn:not(#\#):not(#\#):not(#\#):not(#\#){width:220px} 951 + .width-xafpxmx:not(#\#):not(#\#):not(#\#):not(#\#){width:240px} 952 + .width-xfo62xy:not(#\#):not(#\#):not(#\#):not(#\#){width:2px} 953 + .width-x103aznp:not(#\#):not(#\#):not(#\#):not(#\#){width:300%} 954 + .width-xdzyupr:not(#\#):not(#\#):not(#\#):not(#\#){width:300px} 955 + .width-x1m258z3:not(#\#):not(#\#):not(#\#):not(#\#){width:320px} 956 + .width-xi55695:not(#\#):not(#\#):not(#\#):not(#\#){width:328px} 957 + .width-x1cvmir6:not(#\#):not(#\#):not(#\#):not(#\#){width:360px} 958 + .width-x1l2rt3b:not(#\#):not(#\#):not(#\#):not(#\#){width:400px} 959 + .width-x3hqpx7:not(#\#):not(#\#):not(#\#):not(#\#){width:50%} 960 + .width-xvue9z:not(#\#):not(#\#):not(#\#):not(#\#){width:500px} 961 + .width-xvni27:not(#\#):not(#\#):not(#\#):not(#\#){width:52px} 962 + .width-xycev2y:not(#\#):not(#\#):not(#\#):not(#\#){width:60%} 963 + .width-xhh3r5d:not(#\#):not(#\#):not(#\#):not(#\#){width:calc((var(--tree-item-level,0) - 1) * var(--_3-x1a1riub))} 964 + .width-x1unzbce:not(#\#):not(#\#):not(#\#):not(#\#){width:calc(100% + var(--_2-xsow7ju) * 2)} 965 + .width-xeq5yr9:not(#\#):not(#\#):not(#\#):not(#\#){width:fit-content} 966 + .width-xzrvom6:not(#\#):not(#\#):not(#\#):not(#\#){width:min(100%,300px)} 967 + .width-x45bhuy:not(#\#):not(#\#):not(#\#):not(#\#){width:min(300px,60%)} 968 + .width-x1gvrpfw:not(#\#):not(#\#):not(#\#):not(#\#){width:min(300px,80%)} 969 + .width-x1dznjnj:not(#\#):not(#\#):not(#\#):not(#\#){width:min(80%,300px)} 970 + .width-xrn72xf:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_0_5-x1bnlq1y)} 971 + .width-xe35rg9:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_10-xyoqvup)} 972 + .width-x1ut46fo:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_12-xaxip2l)} 973 + .width-x1cyjp46:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_16-xnqsi2d)} 974 + .width-xae9cqk:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_2_5-xmuc480)} 975 + .width-xnum6w6:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_2-xsow7ju)} 976 + .width-x3v7y2w:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_3-x1a1riub)} 977 + .width-x5aj043:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_32-xxeew7j)} 978 + .width-x1iobu0p:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_4-xgvn2um)} 979 + .width-x1ywvk1j:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_64-xhz114r)} 980 + .width-x9tbrr9:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_8-x1do95gr)} 981 + .width-xrstr7j:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--progress-size)} 982 + .width-xlvufjm:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--trigger-width)} 983 + .width-x5lhr3w:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--x-width)} 984 + @supports (corner-shape: squircle){.borderBottomLeftRadius-x126c7c0.borderBottomLeftRadius-x126c7c0:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-left-radius:var(--_3xl-x1bwjc12)}} 985 + @supports (corner-shape: squircle){.borderBottomRightRadius-xcyha5d.borderBottomRightRadius-xcyha5d:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-right-radius:var(--_3xl-x1bwjc12)}} 986 + @supports (corner-shape: squircle){.borderTopLeftRadius-x8lfnw4.borderTopLeftRadius-x8lfnw4:not(#\#):not(#\#):not(#\#):not(#\#){border-top-left-radius:var(--_3xl-x1bwjc12)}} 987 + @supports (corner-shape: squircle){.borderTopRightRadius-xzsfayr.borderTopRightRadius-xzsfayr:not(#\#):not(#\#):not(#\#):not(#\#){border-top-right-radius:var(--_3xl-x1bwjc12)}} 988 + .borderBottomColor-xd1ie4z:is([data-orientation=vertical]):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-color:transparent} 989 + .borderBottomColor-x1utxzx2:not(:last-child):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-color:var(--border2-xavwyw3)} 990 + .borderBottomColor-x12b2rmk:is([data-orientation=horizontal]):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-color:var(--border2-xavwyw3)} 991 + .borderBottomColor-x94w7c5:is([data-orientation=horizontal] > [data-selected] > *):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-color:var(--solid1-x6o1eyi)} 992 + .borderBottomLeftRadius-x7efh69:not(:first-child):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-left-radius:0} 993 + .borderBottomLeftRadius-x1l931rc:not(:last-child):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-left-radius:0} 994 + .borderBottomLeftRadius-x11hkhd3:is(:not(:first-child)) *:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-left-radius:0} 995 + .borderBottomLeftRadius-x10fm8ce:is(*) pre:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-left-radius:var(--lg-x1011bts)} 996 + .borderBottomLeftRadius-xwoh6l1:is([data-selection-start],td:first-child > *):not(#\#):not(#\#):not(#\#):not(#\#)::before{border-bottom-left-radius:var(--md-x1o51v3i)} 997 + .borderBottomRightRadius-xsmum3n:not(:last-child):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-right-radius:0} 998 + .borderBottomRightRadius-xio9zp4:is(:not(:last-child)) *:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-right-radius:0} 999 + .borderBottomRightRadius-xn3byd1:is(*) pre:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-right-radius:var(--lg-x1011bts)} 1000 + .borderBottomRightRadius-x10l6qm4:is([data-selection-end],td:last-child > *):not(#\#):not(#\#):not(#\#):not(#\#)::before{border-bottom-right-radius:var(--md-x1o51v3i)} 1001 + .borderBottomStyle-xc9ovlk:is([data-orientation=vertical]):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-style:none} 1002 + .borderBottomStyle-xeedzij:is([data-orientation=horizontal]):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-style:solid} 1003 + .borderBottomStyle-x1n9d4a3:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-style:solid} 1004 + .borderBottomWidth-x15l4pgt:is([role=row]:last-child *):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-width:0} 1005 + .borderBottomWidth-x1vqyp8j:is(:not(:last-child)) *:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-width:0} 1006 + .borderBottomWidth-x7dc8i6:is([data-orientation=vertical]):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-width:0} 1007 + .borderBottomWidth-x1ed0nfq:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-width:0} 1008 + .borderBottomWidth-xyn800g:is([data-orientation=horizontal]):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-width:1px} 1009 + .borderBottomWidth-x1t94y08:is([data-direction=top]):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-width:1px} 1010 + .borderBottomWidth-x1t21ho3:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-width:3px} 1011 + .borderLeftWidth-x8b28c3:not(:first-child):not(#\#):not(#\#):not(#\#):not(#\#){border-left-width:0} 1012 + .borderLeftWidth-x7e6zi8:is(:not(:first-child)) *:not(#\#):not(#\#):not(#\#):not(#\#){border-left-width:0} 1013 + .borderLeftWidth-x1g606n3:is([data-direction=right]):not(#\#):not(#\#):not(#\#):not(#\#){border-left-width:1px} 1014 + .borderRightColor-xkuxz9x:is([data-orientation=horizontal]):not(#\#):not(#\#):not(#\#):not(#\#){border-right-color:transparent} 1015 + .borderRightColor-xz94i59:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){border-right-color:transparent} 1016 + .borderRightColor-x8t59l0:not(:last-child):not(#\#):not(#\#):not(#\#):not(#\#){border-right-color:var(--border2-xavwyw3)} 1017 + .borderRightColor-x8pcx9o:is([data-orientation=vertical]):not(#\#):not(#\#):not(#\#):not(#\#){border-right-color:var(--border2-xavwyw3)} 1018 + .borderRightColor-xrs3to8:is([data-orientation=vertical] > [data-selected] > *):not(#\#):not(#\#):not(#\#):not(#\#){border-right-color:var(--solid1-x6o1eyi)} 1019 + .borderRightStyle-x11n44ol:is([data-orientation=horizontal]):not(#\#):not(#\#):not(#\#):not(#\#){border-right-style:none} 1020 + .borderRightStyle-x43d2xm:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){border-right-style:none} 1021 + .borderRightStyle-x1ep6zql:is([data-orientation=vertical]):not(#\#):not(#\#):not(#\#):not(#\#){border-right-style:solid} 1022 + .borderRightStyle-x1n7zma2:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){border-right-style:solid} 1023 + .borderRightWidth-xgzzm7r:is(:not(:last-child)) *:not(#\#):not(#\#):not(#\#):not(#\#){border-right-width:0} 1024 + .borderRightWidth-x13nsbtr:is([data-orientation=horizontal]):not(#\#):not(#\#):not(#\#):not(#\#){border-right-width:0} 1025 + .borderRightWidth-x14zibg8:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){border-right-width:0} 1026 + .borderRightWidth-xmzihwk:is([data-orientation=vertical]):not(#\#):not(#\#):not(#\#):not(#\#){border-right-width:1px} 1027 + .borderRightWidth-xpx03pi:is([data-direction=left]):not(#\#):not(#\#):not(#\#):not(#\#){border-right-width:1px} 1028 + .borderRightWidth-x1n82x8c:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){border-right-width:3px} 1029 + .borderTopLeftRadius-x1jrxlk3:not(:first-child):not(#\#):not(#\#):not(#\#):not(#\#){border-top-left-radius:0} 1030 + .borderTopLeftRadius-x10dxjnd:is(:not(:first-child)) *:not(#\#):not(#\#):not(#\#):not(#\#){border-top-left-radius:0} 1031 + .borderTopLeftRadius-x14erhs3:is([data-selection-start],td:first-child > *):not(#\#):not(#\#):not(#\#):not(#\#)::before{border-top-left-radius:var(--md-x1o51v3i)} 1032 + .borderTopRightRadius-xt1km4f:not(:last-child):not(#\#):not(#\#):not(#\#):not(#\#){border-top-right-radius:0} 1033 + .borderTopRightRadius-x18bx6q4:not(:first-child):not(#\#):not(#\#):not(#\#):not(#\#){border-top-right-radius:0} 1034 + .borderTopRightRadius-xl3d9s7:is(:not(:last-child)) *:not(#\#):not(#\#):not(#\#):not(#\#){border-top-right-radius:0} 1035 + .borderTopRightRadius-x1sj05a8:is(:not(:first-child)) *:not(#\#):not(#\#):not(#\#):not(#\#){border-top-right-radius:0} 1036 + .borderTopRightRadius-x1pgoo9o:is([data-selection-end],td:last-child > *):not(#\#):not(#\#):not(#\#):not(#\#)::before{border-top-right-radius:var(--md-x1o51v3i)} 1037 + .borderTopWidth-x1fuzw2w:not(:first-child):not(#\#):not(#\#):not(#\#):not(#\#){border-top-width:0} 1038 + .borderTopWidth-xe4pvmi:is(:not(:first-child)) *:not(#\#):not(#\#):not(#\#):not(#\#){border-top-width:0} 1039 + .borderTopWidth-xk32l79:is([data-direction=bottom]):not(#\#):not(#\#):not(#\#):not(#\#){border-top-width:1px} 1040 + .bottom-xkg4vtl:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#)::before{bottom:0} 1041 + .bottom-x1fk7w57:is([data-handle-orientation='horizontal'] *):not(#\#):not(#\#):not(#\#):not(#\#){bottom:0} 1042 + .bottom-x1s1o4wi:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){bottom:0} 1043 + .bottom-x1w0y3cq:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){bottom:0} 1044 + .bottom-x1tkpfsv:is([data-direction=bottom]):not(#\#):not(#\#):not(#\#):not(#\#){bottom:0} 1045 + .bottom-x1ey2r4m:is([data-direction=left]):not(#\#):not(#\#):not(#\#):not(#\#){bottom:0} 1046 + .bottom-xslbvph:is([data-direction=right]):not(#\#):not(#\#):not(#\#):not(#\#){bottom:0} 1047 + .height-xmu6b7u:is(*) pre:not(#\#):not(#\#):not(#\#):not(#\#){height:100%} 1048 + .height-xfajk90:is([aria-orientation=vertical]):not(#\#):not(#\#):not(#\#):not(#\#){height:100%} 1049 + .height-x15y5qw9:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){height:100%} 1050 + .height-x1e29dhg:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#)::before{height:100%} 1051 + .height-x1ujwaxl:is([data-handle-orientation='horizontal'] *):not(#\#):not(#\#):not(#\#):not(#\#){height:100%} 1052 + .height-xa6wk7n:is([data-direction=right], [data-direction=left]):not(#\#):not(#\#):not(#\#):not(#\#){height:100vh} 1053 + .height-xa90ixn:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){height:1px} 1054 + .height-xgfdyuw:is([data-direction=top], [data-direction=bottom]):is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){height:320px} 1055 + .height-xjwgx98:is([data-direction=top], [data-direction=bottom]):is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){height:600px} 1056 + .height-x1i0w0n8:is([data-direction=top], [data-direction=bottom]):is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){height:800px} 1057 + .height-x4isadb:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){height:calc(attr(data-progress number) * 1%)} 1058 + .height-xqr7z5w:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){height:calc(attr(data-progress-end number) * 1% - attr(data-progress-start number) * 1%)} 1059 + .height-xdwu4s3:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#)::before{height:var(--_1-x1plbop)} 1060 + .height-xnn4vh6:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_1-x1plbop)} 1061 + .height-xdjr7hi:is([data-size=sm] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_1-x1plbop)} 1062 + .height-xvgowgr:is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_10-xyoqvup)} 1063 + .height-x1bj8b9x:is([data-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_10-xyoqvup)} 1064 + .height-x104b1j8:is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_11-x11x3va4)} 1065 + .height-x1k9a9im:is([data-size=xl]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_14-x18pvp2c)} 1066 + .height-xe43mij:is([data-handle-orientation='vertical'] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_2-xsow7ju)} 1067 + .height-x11nvpuc:is([data-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_2-xsow7ju)} 1068 + .height-x1dwj4yq:is(*) svg:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_3_5-x1gotxl7)} 1069 + .height-xepgdy3:is(*) svg:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_3-x1a1riub)} 1070 + .height-x6cp08u:is([data-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_3-x1a1riub)} 1071 + .height-x1fju72f:is([data-size=sm] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_3-x1a1riub)} 1072 + .height-x1nk0t4g:is(*) svg:not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_4-xgvn2um)} 1073 + .height-x1ejewa8:is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_4-xgvn2um)} 1074 + .height-xzmxqe9:is([data-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_4-xgvn2um)} 1075 + .height-x1ckmk8u:is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_6-x109877l)} 1076 + .height-x413wr7:is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_6-x109877l)} 1077 + .height-x1900l2r:is([data-size=sm] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_6-x109877l)} 1078 + .height-xuw6t6g:is([data-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_6-x109877l)} 1079 + .height-x1f99l0e:is([data-focus-visible]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_6-x109877l)} 1080 + .height-xflfpla:is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_7-x3ogwq2)} 1081 + .height-x8h21d:is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_7-x3ogwq2)} 1082 + .height-xbkx42m:is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_8-x1do95gr)} 1083 + .height-xl931vt:is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_8-x1do95gr)} 1084 + .height-xwcq22m:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_8-x1do95gr)} 1085 + .height-xawfzw8:is([data-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_8-x1do95gr)} 1086 + .height-x1ym6ln2:is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_9-x58vtwt)} 1087 + .height-xz9j5pl:is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){height:var(--_9-x58vtwt)} 1088 + .left-x12bf3xg:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#)::before{left:0} 1089 + .left-xu15ax8:is([data-handle-orientation='vertical'] *):not(#\#):not(#\#):not(#\#):not(#\#){left:0} 1090 + .left-x1vbnr6c:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){left:0} 1091 + .left-x15qd2tb:is([data-direction=bottom]):not(#\#):not(#\#):not(#\#):not(#\#){left:0} 1092 + .left-x1958hiq:is([data-direction=left]):not(#\#):not(#\#):not(#\#):not(#\#){left:0} 1093 + .left-xz1wair:is([data-direction=top]):not(#\#):not(#\#):not(#\#):not(#\#){left:0} 1094 + .left-x13m0n2z:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#)::before{left:50%} 1095 + .left-x1ff65kx:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){left:50%} 1096 + .left-xhiwlwb:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){left:calc(attr(data-progress-start number) * 1%)} 1097 + .left-xjed1bz:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){left:unset} 1098 + .marginBottom-x9c2n64:is([data-table-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:calc(var(--_2-xsow7ju) * -1)} 1099 + .marginBottom-x1acpxd3:is([data-table-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:calc(var(--_3-x1a1riub) * -1)} 1100 + .marginBottom-x1yqwghl:is(li *):not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--_0-xcffliq)} 1101 + .marginBottom-x10hd0vl:is(blockquote *):not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--_0-xcffliq)} 1102 + .marginBottom-xqvk9lr:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--_1-x1plbop)} 1103 + .marginBottom-xwmxh6r:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--_2-xsow7ju)} 1104 + .marginLeft-x1drdkdw:is(td:not(:first-child) > [data-selected]):not([data-selection-start],[data-selection-end]):not(#\#):not(#\#):not(#\#):not(#\#)::before{margin-left:calc(var(--_2-xsow7ju) * -1)} 1105 + .marginLeft-x1mvsmej:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-left:var(--_1-x1plbop)} 1106 + .marginLeft-xbzrfa7:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-left:var(--_2-xsow7ju)} 1107 + .marginRight-x1v6vlb2:is(td:not(:last-child) > [data-selected]):not([data-selection-start],[data-selection-end]):not(#\#):not(#\#):not(#\#):not(#\#)::before{margin-right:calc(var(--_2-xsow7ju) * -1)} 1108 + .marginRight-xsrj4lo:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-right:var(--_1-x1plbop)} 1109 + .marginRight-x3neje5:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-right:var(--_2-xsow7ju)} 1110 + .marginTop-xvatmk5:is([data-table-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-top:calc(var(--_2-xsow7ju) * -1)} 1111 + .marginTop-x13lbpgh:is([data-table-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-top:calc(var(--_3-x1a1riub) * -1)} 1112 + .marginTop-x1wxs10r:is(li *):not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--_0-xcffliq)} 1113 + .marginTop-x16lzv0x:is(blockquote *):not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--_0-xcffliq)} 1114 + .marginTop-xgh7tvm:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--_1-x1plbop)} 1115 + .marginTop-xfg1sq8:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--_2-xsow7ju)} 1116 + .maxHeight-x1ettal:is([data-direction=right], [data-direction=left]):not(#\#):not(#\#):not(#\#):not(#\#){max-height:100vh} 1117 + .maxHeight-x1aybang:is([data-direction=top], [data-direction=bottom]):not(#\#):not(#\#):not(#\#):not(#\#){max-height:calc(100vh - var(--_8-x1do95gr))} 1118 + .maxWidth-x601bgv:is([data-direction=top], [data-direction=bottom]):not(#\#):not(#\#):not(#\#):not(#\#){max-width:100vw} 1119 + .maxWidth-x1xioav0:is([data-direction=right], [data-direction=left]):not(#\#):not(#\#):not(#\#):not(#\#){max-width:calc(100vw - var(--_8-x1do95gr))} 1120 + .minHeight-xmvt6du:is([data-table-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--_10-xyoqvup)} 1121 + .minHeight-xfhokl8:is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--_10-xyoqvup)} 1122 + .minHeight-x99y9gj:is([data-table-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--_12-xaxip2l)} 1123 + .minHeight-xg061xe:is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--_6-x109877l)} 1124 + .minHeight-xl99ybt:is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--_8-x1do95gr)} 1125 + .paddingBottom-x6sjm68:is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_1-x1plbop)} 1126 + .paddingBottom-xniqjlh:is([data-table-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_2-xsow7ju)} 1127 + .paddingBottom-xn17ysx:is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_2-xsow7ju)} 1128 + .paddingBottom-xljj8os:is([data-table-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_3-x1a1riub)} 1129 + .paddingBottom-xdhqxmq:is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_3-x1a1riub)} 1130 + .paddingBottom-x16hjl5o:is(*) pre:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--_4-xgvn2um)} 1131 + .paddingLeft-x6qsi07:is(:first-child):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:0} 1132 + .paddingLeft-xv7dtq0:is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_1-x1plbop)} 1133 + .paddingLeft-xkluz58:is([data-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_2_5-xmuc480)} 1134 + .paddingLeft-xgc1uv4:is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_2-xsow7ju)} 1135 + .paddingLeft-xck0eub:is([data-size=sm] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_2-xsow7ju)} 1136 + .paddingLeft-x13txke7:is([data-table-size=md] *:not(:first-child)):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_3-x1a1riub)} 1137 + .paddingLeft-x1izh1lq:is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_3-x1a1riub)} 1138 + .paddingLeft-x1yv1bkc:is([data-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_3-x1a1riub)} 1139 + .paddingLeft-xhpkq72:is(*) pre:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_4-xgvn2um)} 1140 + .paddingLeft-x1remayf:is([data-table-size=lg] *:not(:first-child)):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_4-xgvn2um)} 1141 + .paddingRight-x1ovgblk:last-child:has(svg):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_0_5-x1bnlq1y)} 1142 + .paddingRight-xt1a0pi:is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_1-x1plbop)} 1143 + .paddingRight-x1l70bhl:is([data-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_1-x1plbop)} 1144 + .paddingRight-xuusv2y:is([data-size=sm] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_1-x1plbop)} 1145 + .paddingRight-x1wn3puj:is([data-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_2_5-xmuc480)} 1146 + .paddingRight-xhqis6d:is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_2-xsow7ju)} 1147 + .paddingRight-xyc92g7:is([data-size=sm] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_2-xsow7ju)} 1148 + .paddingRight-xooq7vc:is([data-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_2-xsow7ju)} 1149 + .paddingRight-xzl3pht:is([data-table-size=md] *:not(:last-child)):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_3-x1a1riub)} 1150 + .paddingRight-x1w258yr:is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_3-x1a1riub)} 1151 + .paddingRight-xmwtj4t:is([data-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_3-x1a1riub)} 1152 + .paddingRight-x1er5lt3:is(*) pre:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_4-xgvn2um)} 1153 + .paddingRight-x1aw6fwa:is([data-table-size=lg] *:not(:last-child)):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_4-xgvn2um)} 1154 + .paddingTop-x18kutu2:is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_1-x1plbop)} 1155 + .paddingTop-x1tzt7i6:is([data-table-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_2-xsow7ju)} 1156 + .paddingTop-x1xomi29:is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_2-xsow7ju)} 1157 + .paddingTop-x1xre27a:is([data-table-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_3-x1a1riub)} 1158 + .paddingTop-x1xm6zre:is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_3-x1a1riub)} 1159 + .paddingTop-x1pdtiu9:is(*) pre:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_4-xgvn2um)} 1160 + .right-x8z6mx6:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#)::before{right:0} 1161 + .right-xdsir5g:is([data-handle-orientation='vertical'] *):not(#\#):not(#\#):not(#\#):not(#\#){right:0} 1162 + .right-x1pbrn0l:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){right:0} 1163 + .right-xxlim67:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){right:0} 1164 + .right-x1hu1b0q:is([data-direction=bottom]):not(#\#):not(#\#):not(#\#):not(#\#){right:0} 1165 + .right-x1edtlyo:is([data-direction=right]):not(#\#):not(#\#):not(#\#):not(#\#){right:0} 1166 + .right-xp6x2dd:is([data-direction=top]):not(#\#):not(#\#):not(#\#):not(#\#){right:0} 1167 + .top-x1v5ec6b:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#)::before{top:0} 1168 + .top-xbwnylk:is([data-handle-orientation='horizontal'] *):not(#\#):not(#\#):not(#\#):not(#\#){top:0} 1169 + .top-xdod2xa:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){top:0} 1170 + .top-xi4gtk3:is([data-direction=left]):not(#\#):not(#\#):not(#\#):not(#\#){top:0} 1171 + .top-x1m4vouk:is([data-direction=right]):not(#\#):not(#\#):not(#\#):not(#\#){top:0} 1172 + .top-xck6qwh:is([data-direction=top]):not(#\#):not(#\#):not(#\#):not(#\#){top:0} 1173 + .top-xzpubj3:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#)::before{top:50%} 1174 + .top-xdpxmfp:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){top:50%} 1175 + .top-x7u6t2g:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){top:auto} 1176 + .top-xl8t2ac:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){top:calc(100% - attr(data-progress-end number) * 1%)} 1177 + .width-xucb16f:is(*) pre:not(#\#):not(#\#):not(#\#):not(#\#){width:100%} 1178 + .width-x1j0uice:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){width:100%} 1179 + .width-xhqp866:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#)::before{width:100%} 1180 + .width-x1d46ikq:is([data-handle-orientation='vertical'] *):not(#\#):not(#\#):not(#\#):not(#\#){width:100%} 1181 + .width-x67hbu9:is([data-direction=top], [data-direction=bottom]):not(#\#):not(#\#):not(#\#):not(#\#){width:100vw} 1182 + .width-xdip0o1:is([aria-orientation=vertical]):not(#\#):not(#\#):not(#\#):not(#\#){width:1px} 1183 + .width-xebvyi3:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){width:1px} 1184 + .width-x3jquih:is([data-direction=left], [data-direction=right]):is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){width:320px} 1185 + .width-x1ak4868:is([data-direction=left], [data-direction=right]):is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){width:600px} 1186 + .width-x11sbvg8:is([data-direction=left], [data-direction=right]):is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){width:800px} 1187 + .width-x16ouo39:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){width:auto} 1188 + .width-x19s274e:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){width:calc(attr(data-progress number) * 1%)} 1189 + .width-xbu4jqu:is([data-orientation=horizontal] *):not(#\#):not(#\#):not(#\#):not(#\#){width:calc(attr(data-progress-end number) * 1% - attr(data-progress-start number) * 1%)} 1190 + .width-x16wso6y:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#)::before{width:var(--_1-x1plbop)} 1191 + .width-xk4ult:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_1-x1plbop)} 1192 + .width-x3sirbn:is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_10-xyoqvup)} 1193 + .width-xjnrrc6:is([data-size=xl]):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_14-x18pvp2c)} 1194 + .width-x88fgpr:is([data-handle-orientation='horizontal'] *):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_2-xsow7ju)} 1195 + .width-xpxfstr:is(*) svg:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_3_5-x1gotxl7)} 1196 + .width-x5dfxfh:is(*) svg:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_3-x1a1riub)} 1197 + .width-x1f1f7ci:is([data-size=sm] *):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_3-x1a1riub)} 1198 + .width-x9pq8ax:is(*) svg:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_4-xgvn2um)} 1199 + .width-x1ika010:is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_4-xgvn2um)} 1200 + .width-xx5h5ec:is([data-size=md] *):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_4-xgvn2um)} 1201 + .width-x1vjoq73:is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_6-x109877l)} 1202 + .width-xw8vdjb:is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_6-x109877l)} 1203 + .width-x17jvw3h:is([data-focus-visible]):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_6-x109877l)} 1204 + .width-x9c0q0b:is([data-size=lg] *):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_6-x109877l)} 1205 + .width-x10ou3qj:is([data-size=sm]):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_7-x3ogwq2)} 1206 + .width-xn3cxqo:is([data-size=md]):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_8-x1do95gr)} 1207 + .width-x1lby93s:is([data-size=lg]):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_8-x1do95gr)} 1208 + .width-xo8awbe:is([data-orientation=vertical] *):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_8-x1do95gr)} 1209 + .paddingLeft-xu53kqt:has(svg+*):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_2_5-xmuc480)} 1210 + .paddingLeft-xe3k1bx:has(> * + *, > *:not(svg):only-child):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_2-xsow7ju)} 1211 + .paddingLeft-xizjdfb:has(svg+*):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_3-x1a1riub)} 1212 + .paddingLeft-x22gwoe:has(> * + *, > *:not(svg):only-child):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_3-x1a1riub)} 1213 + .paddingLeft-x1qm54lp:has(> * + *, > *:not(svg):only-child):not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_4-xgvn2um)} 1214 + .paddingRight-xkvdgk:has(button):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_1_5-x1llymyc)} 1215 + .paddingRight-x95aa3d:has(> * + *, > *:not(svg):only-child):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_2-xsow7ju)} 1216 + .paddingRight-xbfp5r9:has(> * + *, > *:not(svg):only-child):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_3-x1a1riub)} 1217 + .paddingRight-xgqucqf:has(> * + *, > *:not(svg):only-child):not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_4-xgvn2um)} 1218 + .width-x15vyqus:has(svg:only-child):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_10-xyoqvup)} 1219 + .width-xfmdrng:has(svg:only-child):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_7-x3ogwq2)} 1220 + .width-x1nm162b:has(svg:only-child):not(#\#):not(#\#):not(#\#):not(#\#){width:var(--_8-x1do95gr)} 1221 + .borderTopLeftRadius-xqfgiaj:first-child:not(#\#):not(#\#):not(#\#):not(#\#){border-top-left-radius:var(--md-x1o51v3i)} 1222 + .borderTopRightRadius-xq6bztk:first-child:not(#\#):not(#\#):not(#\#):not(#\#){border-top-right-radius:var(--md-x1o51v3i)} 1223 + .paddingLeft-x1k9nibj:first-child:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_0_5-x1bnlq1y)} 1224 + .paddingLeft-x1n6d1z9:first-child:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--_2_5-xmuc480)} 1225 + .paddingLeft-xok9p14:first-child:not(#\#):not(#\#):not(#\#):not(#\#){padding-left:var(--x-1gfbyet)} 1226 + .paddingRight-xgequa0:first-child:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_2-xsow7ju)} 1227 + .paddingTop-x17g1skl:first-child:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--_4-xgvn2um)} 1228 + .paddingTop-xzc7y64:first-child:not(#\#):not(#\#):not(#\#):not(#\#){padding-top:var(--card-y-padding)} 1229 + .borderBottomLeftRadius-x9jr2fx:last-child:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-left-radius:var(--md-x1o51v3i)} 1230 + .borderBottomRightRadius-x1ug12hw:last-child:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-right-radius:var(--md-x1o51v3i)} 1231 + .paddingBottom-xmampw0:last-child:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:var(--card-y-padding)} 1232 + .paddingRight-x11r64v7:last-child:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_2_5-xmuc480)} 1233 + .paddingRight-x1ycezwp:last-child:not(#\#):not(#\#):not(#\#):not(#\#){padding-right:var(--_2-xsow7ju)} 1234 + .inset-xarstr8:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{inset:0} 1235 + .inset-xeqgs30:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{inset:var(--_1-x1plbop)} 1236 + .borderRadius-x1k48kgn:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{border-radius:inherit} 1237 + .borderRadius-xnpr4at:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{border-radius:var(--full-xmpdjt5)} 1238 + .borderRadius-x1a44610:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{border-radius:var(--md-x1o51v3i)} 1239 + .appearance-x1ad04t7:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::-webkit-search-cancel-button{appearance:none} 1240 + .appearance-x1glnyev:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::-webkit-search-decoration{appearance:none} 1241 + .backgroundColor-x1og98oj:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{background-color:var(--border1-x1en7ut4)} 1242 + .backgroundColor-x2ydo77:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{background-color:var(--solid1-x6o1eyi)} 1243 + .boxSizing-xx38sju:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{box-sizing:border-box} 1244 + .color-x17pfzbs:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::placeholder{color:var(--text1-xb5nrd9)} 1245 + .content-x10tli2e:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{content:''} 1246 + .content-x1s928wv:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{content:""} 1247 + .position-x1hmns74:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{position:absolute} 1248 + .position-x1j6awrg:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{position:absolute} 1249 + .transitionDuration-xy2prys:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{transition-duration:var(--fast-x1gssecm)} 1250 + .transitionProperty-xxcwgru:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{transition-property:background-color} 1251 + .transitionTimingFunction-xn05597:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{transition-timing-function:ease-in-out} 1252 + .zIndex-xy5mcqj:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{z-index:-1} 1253 + .bottom-xhq5o37:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{bottom:0} 1254 + .left-x1wlytlt:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{left:0} 1255 + .top-x1y3wzot:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{top:0} 1256 + .width-x1vgi0k:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{width:1px}
+93 -27
packages/hip-ui/src/components/color-field/index.tsx
··· 10 10 11 11 import { SizeContext } from "../context"; 12 12 import { Description, FieldErrorMessage, Label } from "../label"; 13 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 13 + import { SuffixIcon } from "../suffix-icon"; 14 + import { 15 + InputVariant, 16 + InputValidationState, 17 + Size, 18 + StyleXComponentProps, 19 + } from "../theme/types"; 14 20 import { useInputStyles } from "../theme/useInputStyles"; 15 21 22 + interface ColorFieldContentProps { 23 + label?: React.ReactNode; 24 + description?: string; 25 + errorMessage?: string | ((validation: ValidationResult) => string); 26 + size: Size; 27 + variant: InputVariant | undefined; 28 + validationState: InputValidationState | undefined; 29 + isInvalid: boolean; 30 + prefix?: React.ReactNode; 31 + suffix?: React.ReactNode; 32 + placeholder?: string; 33 + } 34 + 35 + function ColorFieldContent({ 36 + label, 37 + description, 38 + errorMessage, 39 + size, 40 + variant, 41 + validationState, 42 + isInvalid, 43 + prefix, 44 + suffix, 45 + placeholder, 46 + }: ColorFieldContentProps) { 47 + const inputRef = useRef<HTMLInputElement>(null); 48 + const inputStyles = useInputStyles({ 49 + size, 50 + variant, 51 + validationState: isInvalid ? "invalid" : validationState, 52 + }); 53 + 54 + return ( 55 + <> 56 + <Label>{label}</Label> 57 + {/* 58 + This onClick is specifically for mouse users not clicking directly on the input. 59 + A keyboard user would not encounter the same issue. 60 + */} 61 + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 62 + <div 63 + {...stylex.props(inputStyles.wrapper)} 64 + onClick={() => inputRef.current?.focus()} 65 + > 66 + {prefix != null && ( 67 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 68 + )} 69 + <Input 70 + placeholder={placeholder} 71 + ref={inputRef} 72 + {...stylex.props(inputStyles.input)} 73 + /> 74 + <SuffixIcon 75 + suffix={suffix} 76 + style={inputStyles.addon} 77 + validationIconStyle={inputStyles.validationIcon} 78 + validationState={validationState} 79 + /> 80 + </div> 81 + <Description>{description}</Description> 82 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 83 + </> 84 + ); 85 + } 86 + 16 87 export interface ColorFieldProps 17 - extends StyleXComponentProps<AriaColorFieldProps>, 88 + extends StyleXComponentProps<Omit<AriaColorFieldProps, "isInvalid">>, 18 89 Pick<InputProps, "placeholder"> { 19 90 label?: React.ReactNode; 20 91 description?: string; 21 92 errorMessage?: string | ((validation: ValidationResult) => string); 22 93 size?: Size; 23 94 variant?: InputVariant; 95 + validationState?: InputValidationState; 24 96 prefix?: React.ReactNode; 25 97 suffix?: React.ReactNode; 26 98 } ··· 32 104 style, 33 105 size: sizeProp, 34 106 variant, 107 + validationState, 35 108 prefix, 36 109 suffix, 37 110 placeholder, 38 111 ...props 39 112 }: ColorFieldProps) { 40 113 const size = sizeProp || use(SizeContext); 41 - const inputRef = useRef<HTMLInputElement>(null); 42 - const inputStyles = useInputStyles({ size, variant }); 114 + const inputStyles = useInputStyles({ size, variant, validationState }); 43 115 44 116 return ( 45 117 <SizeContext value={size}> 46 - <AriaColorField {...props} {...stylex.props(inputStyles.field, style)}> 47 - <Label>{label}</Label> 48 - {/* 49 - This onClick is specifically for mouse users not clicking directly on the input. 50 - A keyboard user would not encounter the same issue. 51 - */} 52 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 53 - <div 54 - {...stylex.props(inputStyles.wrapper)} 55 - onClick={() => inputRef.current?.focus()} 56 - > 57 - {prefix != null && ( 58 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 59 - )} 60 - <Input 118 + <AriaColorField 119 + {...props} 120 + isInvalid={validationState ? validationState === "invalid" : undefined} 121 + {...stylex.props(inputStyles.field, style)} 122 + > 123 + {({ isInvalid }) => ( 124 + <ColorFieldContent 125 + label={label} 126 + description={description} 127 + errorMessage={errorMessage} 128 + size={size} 129 + variant={variant} 130 + validationState={validationState} 131 + isInvalid={isInvalid} 132 + prefix={prefix} 133 + suffix={suffix} 61 134 placeholder={placeholder} 62 - ref={inputRef} 63 - {...stylex.props(inputStyles.input)} 64 135 /> 65 - {suffix != null && ( 66 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 67 - )} 68 - </div> 69 - <Description>{description}</Description> 70 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 136 + )} 71 137 </AriaColorField> 72 138 </SizeContext> 73 139 );
+128 -42
packages/hip-ui/src/components/combobox/index.tsx
··· 13 13 } from "react-aria-components"; 14 14 15 15 import { SizeContext } from "../context"; 16 - import { IconButton } from "../icon-button"; 17 16 import { Description, FieldErrorMessage, Label } from "../label"; 18 17 import { ListBox } from "../listbox"; 18 + import { SuffixIcon } from "../suffix-icon"; 19 19 import { spacing } from "../theme/spacing.stylex"; 20 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 20 + import { 21 + InputVariant, 22 + InputValidationState, 23 + Size, 24 + StyleXComponentProps, 25 + } from "../theme/types"; 21 26 import { useInputStyles } from "../theme/useInputStyles"; 22 27 import { usePopoverStyles } from "../theme/usePopoverStyles"; 23 28 import { SmallBody } from "../typography"; ··· 27 32 width: "var(--trigger-width)", 28 33 }, 29 34 emptyState: { 35 + padding: spacing["4"], 30 36 display: "flex", 31 37 justifyContent: "center", 32 - padding: spacing["4"], 33 38 }, 34 39 }); 35 40 ··· 41 46 ); 42 47 } 43 48 49 + interface ComboBoxContentProps<T extends object> { 50 + label?: string; 51 + description?: string; 52 + errorMessage?: string | ((validation: ValidationResult) => string); 53 + size: Size; 54 + variant: InputVariant | undefined; 55 + validationState: InputValidationState | undefined; 56 + isInvalid: boolean; 57 + placeholder: string; 58 + prefix?: React.ReactNode; 59 + suffix?: React.ReactNode; 60 + items?: Iterable<T>; 61 + children: React.ReactNode | ((item: T) => React.ReactNode); 62 + shouldCloseOnInteractOutside?: ((element: Element) => boolean) | undefined; 63 + shouldFlip?: boolean; 64 + shouldUpdatePosition?: boolean; 65 + placement?: PopoverProps["placement"]; 66 + renderEmptyState?: ListBoxProps<T>["renderEmptyState"]; 67 + } 68 + 69 + function ComboBoxContent<T extends object>({ 70 + label, 71 + description, 72 + errorMessage, 73 + size, 74 + variant, 75 + validationState, 76 + isInvalid: _isInvalid, 77 + placeholder, 78 + prefix, 79 + suffix, 80 + items, 81 + children, 82 + shouldCloseOnInteractOutside, 83 + shouldFlip, 84 + shouldUpdatePosition, 85 + placement, 86 + renderEmptyState, 87 + }: ComboBoxContentProps<T>) { 88 + const inputStyles = useInputStyles({ 89 + size, 90 + variant, 91 + validationState: _isInvalid ? "invalid" : validationState, 92 + }); 93 + const popoverStyles = usePopoverStyles(); 94 + 95 + return ( 96 + <> 97 + <Label>{label}</Label> 98 + <Button {...stylex.props(inputStyles.wrapper)}> 99 + {prefix != null && ( 100 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 101 + )} 102 + <Input {...stylex.props(inputStyles.input)} placeholder={placeholder} /> 103 + <SuffixIcon 104 + suffix={ 105 + <> 106 + {suffix} 107 + <ChevronDown size={16} aria-hidden="true" /> 108 + </> 109 + } 110 + style={inputStyles.addon} 111 + validationIconStyle={inputStyles.validationIcon} 112 + validationState={validationState} 113 + /> 114 + </Button> 115 + <Description>{description}</Description> 116 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 117 + <Popover 118 + containerPadding={8} 119 + shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 120 + shouldFlip={shouldFlip} 121 + shouldUpdatePosition={shouldUpdatePosition} 122 + placement={placement} 123 + {...stylex.props( 124 + popoverStyles.wrapper, 125 + popoverStyles.animation, 126 + styles.matchWidth, 127 + )} 128 + > 129 + <ListBox 130 + items={items} 131 + renderEmptyState={renderEmptyState || EmptyState} 132 + > 133 + {children} 134 + </ListBox> 135 + </Popover> 136 + </> 137 + ); 138 + } 139 + 44 140 export interface ComboBoxProps<T extends object> 45 - extends StyleXComponentProps<Omit<AriaComboBoxProps<T>, "children">>, 141 + extends StyleXComponentProps< 142 + Omit<AriaComboBoxProps<T>, "children" | "isInvalid"> 143 + >, 46 144 Pick< 47 145 PopoverProps, 48 146 | "shouldCloseOnInteractOutside" ··· 58 156 children: React.ReactNode | ((item: T) => React.ReactNode); 59 157 size?: Size; 60 158 variant?: InputVariant; 159 + validationState?: InputValidationState; 61 160 placeholder?: string; 62 161 prefix?: React.ReactNode; 63 162 suffix?: React.ReactNode; ··· 72 171 style, 73 172 size: sizeProp, 74 173 variant, 174 + validationState, 75 175 shouldCloseOnInteractOutside, 76 176 shouldFlip, 77 177 shouldUpdatePosition, ··· 83 183 ...props 84 184 }: ComboBoxProps<T>) { 85 185 const size = sizeProp || use(SizeContext); 86 - const inputStyles = useInputStyles({ size, variant }); 87 - const popoverStyles = usePopoverStyles(); 186 + const inputStyles = useInputStyles({ size, variant, validationState }); 88 187 89 188 return ( 90 189 <SizeContext value={size}> 91 - <AriaComboBox {...props} {...stylex.props(inputStyles.field, style)}> 92 - <Label>{label}</Label> 93 - <Button {...stylex.props(inputStyles.wrapper)}> 94 - {prefix != null && ( 95 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 96 - )} 97 - <Input 98 - {...stylex.props(inputStyles.input)} 190 + <AriaComboBox 191 + {...props} 192 + isInvalid={validationState ? validationState === "invalid" : undefined} 193 + {...stylex.props(inputStyles.field, style)} 194 + > 195 + {({ isInvalid }) => ( 196 + <ComboBoxContent 197 + label={label} 198 + description={description} 199 + errorMessage={errorMessage} 200 + size={size} 201 + variant={variant} 202 + validationState={validationState} 203 + isInvalid={isInvalid} 99 204 placeholder={placeholder} 100 - /> 101 - {suffix != null && ( 102 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 103 - )} 104 - <div {...stylex.props(inputStyles.addon)}> 105 - <IconButton size="sm" variant="secondary" label="Open combobox"> 106 - <ChevronDown size={16} aria-hidden="true" /> 107 - </IconButton> 108 - </div> 109 - </Button> 110 - <Description>{description}</Description> 111 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 112 - <Popover 113 - containerPadding={8} 114 - shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 115 - shouldFlip={shouldFlip} 116 - shouldUpdatePosition={shouldUpdatePosition} 117 - placement={placement} 118 - {...stylex.props( 119 - popoverStyles.wrapper, 120 - popoverStyles.animation, 121 - styles.matchWidth, 122 - )} 123 - > 124 - <ListBox 205 + prefix={prefix} 206 + suffix={suffix} 125 207 items={items} 126 - renderEmptyState={renderEmptyState || EmptyState} 208 + shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 209 + shouldFlip={shouldFlip} 210 + shouldUpdatePosition={shouldUpdatePosition} 211 + placement={placement} 212 + renderEmptyState={renderEmptyState} 127 213 > 128 214 {children} 129 - </ListBox> 130 - </Popover> 215 + </ComboBoxContent> 216 + )} 131 217 </AriaComboBox> 132 218 </SizeContext> 133 219 );
+90 -27
packages/hip-ui/src/components/date-field/index.tsx
··· 11 11 12 12 import { SizeContext } from "../context"; 13 13 import { Description, FieldErrorMessage, Label } from "../label"; 14 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 14 + import { SuffixIcon } from "../suffix-icon"; 15 + import { 16 + InputVariant, 17 + InputValidationState, 18 + Size, 19 + StyleXComponentProps, 20 + } from "../theme/types"; 15 21 import { useInputStyles } from "../theme/useInputStyles"; 16 22 23 + interface DateFieldContentProps { 24 + label?: React.ReactNode; 25 + description?: string; 26 + errorMessage?: string | ((validation: ValidationResult) => string); 27 + size: Size; 28 + variant: InputVariant | undefined; 29 + validationState: InputValidationState | undefined; 30 + isInvalid: boolean; 31 + prefix?: React.ReactNode; 32 + suffix?: React.ReactNode; 33 + } 34 + 35 + function DateFieldContent({ 36 + label, 37 + description, 38 + errorMessage, 39 + size, 40 + variant, 41 + validationState, 42 + isInvalid, 43 + prefix, 44 + suffix, 45 + }: DateFieldContentProps) { 46 + const inputRef = useRef<HTMLInputElement>(null); 47 + const inputStyles = useInputStyles({ 48 + size, 49 + variant, 50 + validationState: isInvalid ? "invalid" : validationState, 51 + }); 52 + 53 + return ( 54 + <> 55 + <Label>{label}</Label> 56 + {/* 57 + This onClick is specifically for mouse users not clicking directly on the input. 58 + A keyboard user would not encounter the same issue. 59 + */} 60 + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 61 + <div 62 + {...stylex.props(inputStyles.wrapper)} 63 + onClick={() => inputRef.current?.focus()} 64 + > 65 + {prefix != null && ( 66 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 67 + )} 68 + <DateInput {...stylex.props(inputStyles.input)} ref={inputRef}> 69 + {(segment) => <DateSegment segment={segment} />} 70 + </DateInput> 71 + <SuffixIcon 72 + suffix={suffix} 73 + style={inputStyles.addon} 74 + validationIconStyle={inputStyles.validationIcon} 75 + validationState={validationState} 76 + /> 77 + </div> 78 + <Description>{description}</Description> 79 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 80 + </> 81 + ); 82 + } 83 + 17 84 export interface DateFieldProps<T extends DateValue> 18 - extends StyleXComponentProps<AriaDateFieldProps<T>> { 85 + extends StyleXComponentProps<Omit<AriaDateFieldProps<T>, "isInvalid">> { 19 86 label?: React.ReactNode; 20 87 description?: string; 21 88 errorMessage?: string | ((validation: ValidationResult) => string); 22 89 size?: Size; 23 90 variant?: InputVariant; 91 + validationState?: InputValidationState; 24 92 prefix?: React.ReactNode; 25 93 suffix?: React.ReactNode; 26 94 } ··· 32 100 style, 33 101 size: sizeProp, 34 102 variant, 103 + validationState, 35 104 prefix, 36 105 suffix, 37 106 ...props 38 107 }: DateFieldProps<T>) { 39 108 const size = sizeProp || use(SizeContext); 40 - const inputRef = useRef<HTMLInputElement>(null); 41 - const inputStyles = useInputStyles({ size, variant }); 109 + const inputStyles = useInputStyles({ size, variant, validationState }); 42 110 43 111 return ( 44 112 <SizeContext value={size}> 45 - <AriaDateField {...props} {...stylex.props(inputStyles.field, style)}> 46 - <Label>{label}</Label> 47 - {/* 48 - This onClick is specifically for mouse users not clicking directly on the input. 49 - A keyboard user would not encounter the same issue. 50 - */} 51 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 52 - <div 53 - {...stylex.props(inputStyles.wrapper)} 54 - onClick={() => inputRef.current?.focus()} 55 - > 56 - {prefix != null && ( 57 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 58 - )} 59 - <DateInput {...stylex.props(inputStyles.input)} ref={inputRef}> 60 - {(segment) => <DateSegment segment={segment} />} 61 - </DateInput> 62 - {suffix != null && ( 63 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 64 - )} 65 - </div> 66 - <Description>{description}</Description> 67 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 113 + <AriaDateField 114 + {...props} 115 + isInvalid={validationState ? validationState === "invalid" : undefined} 116 + {...stylex.props(inputStyles.field, style)} 117 + > 118 + {({ isInvalid }) => ( 119 + <DateFieldContent 120 + label={label} 121 + description={description} 122 + errorMessage={errorMessage} 123 + size={size} 124 + variant={variant} 125 + validationState={validationState} 126 + isInvalid={isInvalid} 127 + prefix={prefix} 128 + suffix={suffix} 129 + /> 130 + )} 68 131 </AriaDateField> 69 132 </SizeContext> 70 133 );
+85 -30
packages/hip-ui/src/components/date-picker/index.tsx
··· 17 17 import { IconButton } from "../icon-button"; 18 18 import { Description, FieldErrorMessage, Label } from "../label"; 19 19 import { spacing } from "../theme/spacing.stylex"; 20 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 20 + import { 21 + InputVariant, 22 + InputValidationState, 23 + Size, 24 + StyleXComponentProps, 25 + } from "../theme/types"; 21 26 import { useInputStyles } from "../theme/useInputStyles"; 22 27 import { usePopoverStyles } from "../theme/usePopoverStyles"; 23 28 24 29 export interface DatePickerProps<T extends DateValue> 25 - extends StyleXComponentProps<AriaDatePickerProps<T>>, 30 + extends StyleXComponentProps<Omit<AriaDatePickerProps<T>, "isInvalid">>, 26 31 Pick<CalendarProps<T>, "weekdayStyle" | "visibleDuration"> { 27 32 label?: React.ReactNode; 28 33 description?: string; 29 34 errorMessage?: string | ((validation: ValidationResult) => string); 30 35 size?: Size; 31 36 variant?: InputVariant; 37 + validationState?: InputValidationState; 32 38 } 33 39 34 40 const styles = stylex.create({ ··· 37 43 }, 38 44 }); 39 45 46 + interface DatePickerContentProps<T extends DateValue> { 47 + label?: React.ReactNode; 48 + description?: string; 49 + errorMessage?: string | ((validation: ValidationResult) => string); 50 + size: Size; 51 + variant: InputVariant | undefined; 52 + validationState: InputValidationState | undefined; 53 + isInvalid: boolean; 54 + weekdayStyle?: CalendarProps<T>["weekdayStyle"]; 55 + visibleDuration?: CalendarProps<T>["visibleDuration"]; 56 + } 57 + 58 + function DatePickerContent<T extends DateValue>({ 59 + label, 60 + description, 61 + errorMessage, 62 + size: _size, 63 + variant, 64 + validationState, 65 + isInvalid: _isInvalid, 66 + weekdayStyle, 67 + visibleDuration, 68 + }: DatePickerContentProps<T>) { 69 + const popoverStyles = usePopoverStyles(); 70 + 71 + return ( 72 + <> 73 + <Label>{label}</Label> 74 + <Group> 75 + <DateField 76 + variant={variant} 77 + validationState={validationState} 78 + suffix={ 79 + <IconButton 80 + size="sm" 81 + aria-label="Open date picker" 82 + variant="tertiary" 83 + > 84 + <CalendarIcon /> 85 + </IconButton> 86 + } 87 + /> 88 + </Group> 89 + <Description>{description}</Description> 90 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 91 + <AriaPopover 92 + {...stylex.props(popoverStyles.wrapper, popoverStyles.animation)} 93 + > 94 + <Dialog {...stylex.props(styles.popoverContent)}> 95 + <Calendar 96 + weekdayStyle={weekdayStyle} 97 + visibleDuration={visibleDuration} 98 + /> 99 + </Dialog> 100 + </AriaPopover> 101 + </> 102 + ); 103 + } 104 + 40 105 export function DatePicker<T extends DateValue>({ 41 106 label, 42 107 description, ··· 46 111 weekdayStyle, 47 112 visibleDuration, 48 113 variant, 114 + validationState, 49 115 ...props 50 116 }: DatePickerProps<T>) { 51 117 const size = sizeProp || use(SizeContext); 52 - const inputStyles = useInputStyles({ size, variant }); 53 - const popoverStyles = usePopoverStyles(); 118 + const inputStyles = useInputStyles({ size, variant, validationState }); 54 119 55 120 return ( 56 121 <SizeContext value={size}> 57 - <AriaDatePicker {...props} {...stylex.props(inputStyles.field, style)}> 58 - <Label>{label}</Label> 59 - <Group> 60 - <DateField 122 + <AriaDatePicker 123 + {...props} 124 + isInvalid={validationState ? validationState === "invalid" : undefined} 125 + {...stylex.props(inputStyles.field, style)} 126 + > 127 + {({ isInvalid }) => ( 128 + <DatePickerContent 129 + label={label} 130 + description={description} 131 + errorMessage={errorMessage} 132 + size={size} 61 133 variant={variant} 62 - suffix={ 63 - <IconButton 64 - size="sm" 65 - aria-label="Open date picker" 66 - variant="tertiary" 67 - > 68 - <CalendarIcon /> 69 - </IconButton> 70 - } 134 + validationState={validationState} 135 + isInvalid={isInvalid} 136 + weekdayStyle={weekdayStyle} 137 + visibleDuration={visibleDuration} 71 138 /> 72 - </Group> 73 - <Description>{description}</Description> 74 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 75 - <AriaPopover 76 - {...stylex.props(popoverStyles.wrapper, popoverStyles.animation)} 77 - > 78 - <Dialog {...stylex.props(styles.popoverContent)}> 79 - <Calendar 80 - weekdayStyle={weekdayStyle} 81 - visibleDuration={visibleDuration} 82 - /> 83 - </Dialog> 84 - </AriaPopover> 139 + )} 85 140 </AriaDatePicker> 86 141 </SizeContext> 87 142 );
+114 -56
packages/hip-ui/src/components/date-range-picker/index.tsx
··· 17 17 import { IconButton } from "../icon-button"; 18 18 import { Description, FieldErrorMessage, Label } from "../label"; 19 19 import { RangeCalendar, RangeCalendarProps } from "../range-calendar"; 20 + import { SuffixIcon } from "../suffix-icon"; 20 21 import { uiColor } from "../theme/semantic-color.stylex"; 21 22 import { spacing } from "../theme/spacing.stylex"; 22 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 23 + import { 24 + InputVariant, 25 + InputValidationState, 26 + Size, 27 + StyleXComponentProps, 28 + } from "../theme/types"; 23 29 import { fontSize } from "../theme/typography.stylex"; 24 30 import { useInputStyles } from "../theme/useInputStyles"; 25 31 import { usePopoverStyles } from "../theme/usePopoverStyles"; 26 32 27 33 export interface DateRangePickerProps<T extends DateValue> 28 - extends StyleXComponentProps<AriaDateRangePickerProps<T>>, 34 + extends StyleXComponentProps<Omit<AriaDateRangePickerProps<T>, "isInvalid">>, 29 35 Pick<RangeCalendarProps<T>, "weekdayStyle" | "visibleDuration"> { 30 36 label?: React.ReactNode; 31 37 description?: string; 32 38 errorMessage?: string | ((validation: ValidationResult) => string); 33 39 size?: Size; 34 40 variant?: InputVariant; 41 + validationState?: InputValidationState; 35 42 } 36 43 37 44 const styles = stylex.create({ 38 45 group: { 46 + gap: spacing["1"], 39 47 alignItems: "center", 40 48 display: "flex", 41 - gap: spacing["1"], 42 49 43 50 fontSize: { 44 - ":is([data-size=sm])": fontSize["xs"], 51 + ":is([data-size=lg])": fontSize["base"], 45 52 ":is([data-size=md])": fontSize["sm"], 46 - ":is([data-size=lg])": fontSize["base"], 53 + ":is([data-size=sm])": fontSize["xs"], 47 54 }, 48 55 }, 49 56 popoverContent: { ··· 51 58 }, 52 59 separator: { 53 60 paddingRight: { 54 - ":is([data-size=sm] *)": spacing["1"], 55 - ":is([data-size=md] *)": spacing["2"], 56 61 ":is([data-size=lg] *)": spacing["1"], 62 + ":is([data-size=md] *)": spacing["2"], 63 + ":is([data-size=sm] *)": spacing["1"], 57 64 }, 58 65 }, 59 66 lastInput: { ··· 66 73 }, 67 74 }); 68 75 76 + interface DateRangePickerContentProps<T extends DateValue> { 77 + label?: React.ReactNode; 78 + description?: string; 79 + errorMessage?: string | ((validation: ValidationResult) => string); 80 + size: Size; 81 + variant: InputVariant | undefined; 82 + validationState: InputValidationState | undefined; 83 + isInvalid: boolean; 84 + weekdayStyle?: RangeCalendarProps<T>["weekdayStyle"]; 85 + visibleDuration?: RangeCalendarProps<T>["visibleDuration"]; 86 + } 87 + 88 + function DateRangePickerContent<T extends DateValue>({ 89 + label, 90 + description, 91 + errorMessage, 92 + size, 93 + variant, 94 + validationState, 95 + isInvalid, 96 + weekdayStyle, 97 + visibleDuration, 98 + }: DateRangePickerContentProps<T>) { 99 + const inputStyles = useInputStyles({ 100 + size, 101 + variant, 102 + validationState: isInvalid ? "invalid" : validationState, 103 + }); 104 + const popoverStyles = usePopoverStyles(); 105 + 106 + return ( 107 + <> 108 + <Label>{label}</Label> 109 + <Group 110 + data-size={size} 111 + {...stylex.props(inputStyles.wrapper, styles.group)} 112 + > 113 + <DateInput slot="start" {...stylex.props(inputStyles.input)}> 114 + {(segment) => ( 115 + <DateSegment segment={segment} {...stylex.props(styles.segment)} /> 116 + )} 117 + </DateInput> 118 + <div aria-hidden="true" {...stylex.props(styles.separator)}> 119 + - 120 + </div> 121 + <DateInput 122 + slot="end" 123 + {...stylex.props(inputStyles.input, styles.lastInput)} 124 + > 125 + {(segment) => ( 126 + <DateSegment segment={segment} {...stylex.props(styles.segment)} /> 127 + )} 128 + </DateInput> 129 + <SuffixIcon 130 + suffix={ 131 + <IconButton 132 + size="sm" 133 + aria-label="Open date picker" 134 + variant="tertiary" 135 + > 136 + <CalendarIcon /> 137 + </IconButton> 138 + } 139 + style={inputStyles.addon} 140 + validationIconStyle={inputStyles.validationIcon} 141 + validationState={validationState} 142 + /> 143 + </Group> 144 + <Description>{description}</Description> 145 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 146 + <AriaPopover 147 + {...stylex.props(popoverStyles.wrapper, popoverStyles.animation)} 148 + > 149 + <Dialog {...stylex.props(styles.popoverContent)}> 150 + <RangeCalendar 151 + weekdayStyle={weekdayStyle} 152 + visibleDuration={visibleDuration} 153 + /> 154 + </Dialog> 155 + </AriaPopover> 156 + </> 157 + ); 158 + } 159 + 69 160 export function DateRangePicker<T extends DateValue>({ 70 161 label, 71 162 description, ··· 75 166 weekdayStyle, 76 167 visibleDuration, 77 168 variant, 169 + validationState, 78 170 ...props 79 171 }: DateRangePickerProps<T>) { 80 172 const size = sizeProp || use(SizeContext); 81 - const inputStyles = useInputStyles({ size, variant }); 82 - const popoverStyles = usePopoverStyles(); 173 + const inputStyles = useInputStyles({ size, variant, validationState }); 83 174 84 175 return ( 85 176 <SizeContext value={size}> 86 177 <AriaDateRangePicker 87 178 {...props} 179 + isInvalid={validationState ? validationState === "invalid" : undefined} 88 180 {...stylex.props(inputStyles.field, style)} 89 181 > 90 - <Label>{label}</Label> 91 - <Group 92 - data-size={size} 93 - {...stylex.props(inputStyles.wrapper, styles.group)} 94 - > 95 - <DateInput slot="start" {...stylex.props(inputStyles.input)}> 96 - {(segment) => ( 97 - <DateSegment 98 - segment={segment} 99 - {...stylex.props(styles.segment)} 100 - /> 101 - )} 102 - </DateInput> 103 - <div aria-hidden="true" {...stylex.props(styles.separator)}> 104 - - 105 - </div> 106 - <DateInput 107 - slot="end" 108 - {...stylex.props(inputStyles.input, styles.lastInput)} 109 - > 110 - {(segment) => ( 111 - <DateSegment 112 - segment={segment} 113 - {...stylex.props(styles.segment)} 114 - /> 115 - )} 116 - </DateInput> 117 - <IconButton 118 - size="sm" 119 - aria-label="Open date picker" 120 - variant="tertiary" 121 - > 122 - <CalendarIcon /> 123 - </IconButton> 124 - </Group> 125 - <Description>{description}</Description> 126 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 127 - <AriaPopover 128 - {...stylex.props(popoverStyles.wrapper, popoverStyles.animation)} 129 - > 130 - <Dialog {...stylex.props(styles.popoverContent)}> 131 - <RangeCalendar 132 - weekdayStyle={weekdayStyle} 133 - visibleDuration={visibleDuration} 134 - /> 135 - </Dialog> 136 - </AriaPopover> 182 + {({ isInvalid }) => ( 183 + <DateRangePickerContent 184 + label={label} 185 + description={description} 186 + errorMessage={errorMessage} 187 + size={size} 188 + variant={variant} 189 + validationState={validationState} 190 + isInvalid={isInvalid} 191 + weekdayStyle={weekdayStyle} 192 + visibleDuration={visibleDuration} 193 + /> 194 + )} 137 195 </AriaDateRangePicker> 138 196 </SizeContext> 139 197 );
+117 -46
packages/hip-ui/src/components/number-field/index.tsx
··· 17 17 18 18 import { SizeContext } from "../context"; 19 19 import { Description, FieldErrorMessage, Label } from "../label"; 20 + import { SuffixIcon } from "../suffix-icon"; 20 21 import { ui, uiColor } from "../theme/semantic-color.stylex"; 21 22 import { spacing } from "../theme/spacing.stylex"; 22 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 23 + import { 24 + InputVariant, 25 + InputValidationState, 26 + Size, 27 + StyleXComponentProps, 28 + } from "../theme/types"; 23 29 import { useInputStyles } from "../theme/useInputStyles"; 24 30 import { usePointerLock } from "./usePointerLock"; 25 31 ··· 81 87 display: "flex", 82 88 }, 83 89 button: { 90 + borderWidth: 0, 84 91 alignItems: "center", 92 + display: "flex", 93 + flexGrow: 1, 94 + justifyContent: "center", 85 95 borderBottomWidth: 0, 86 96 borderLeftStyle: "solid", 87 97 borderLeftWidth: 1, 88 98 borderRightWidth: 0, 89 99 borderTopWidth: 0, 90 - borderWidth: 0, 91 - display: "flex", 92 - flexGrow: 1, 93 - justifyContent: "center", 94 100 minHeight: 0, 95 101 96 102 // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 97 103 ":is(*) svg": { 98 104 flexShrink: 0, 105 + pointerEvents: "none", 99 106 height: spacing["4"], 100 - pointerEvents: "none", 101 107 width: spacing["4"], 102 108 }, 103 109 ··· 108 114 }, 109 115 }); 110 116 117 + interface NumberFieldContentProps { 118 + label?: React.ReactNode; 119 + description?: string; 120 + errorMessage?: string | ((validation: ValidationResult) => string); 121 + size: Size; 122 + variant: InputVariant | undefined; 123 + validationState: InputValidationState | undefined; 124 + isInvalid: boolean; 125 + prefix?: React.ReactNode; 126 + suffix?: React.ReactNode; 127 + placeholder?: string; 128 + hideStepper: boolean; 129 + } 130 + 131 + function NumberFieldContent({ 132 + label, 133 + description, 134 + errorMessage, 135 + size, 136 + variant, 137 + validationState, 138 + isInvalid, 139 + prefix, 140 + suffix, 141 + placeholder, 142 + hideStepper, 143 + }: NumberFieldContentProps) { 144 + const inputRef = useRef<HTMLInputElement>(null); 145 + const inputStyles = useInputStyles({ 146 + size, 147 + variant, 148 + validationState: isInvalid ? "invalid" : validationState, 149 + }); 150 + const buttonStyles = stylex.props( 151 + styles.button, 152 + ui.borderInteractive, 153 + ui.bgAction, 154 + ); 155 + 156 + return ( 157 + <> 158 + <Label>{label}</Label> 159 + {/* 160 + This onClick is specifically for mouse users not clicking directly on the input. 161 + A keyboard user would not encounter the same issue. 162 + */} 163 + <NumberInputWrapper 164 + style={inputStyles.wrapper} 165 + onClick={() => inputRef.current?.focus()} 166 + > 167 + {prefix != null && ( 168 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 169 + )} 170 + <Input 171 + placeholder={placeholder} 172 + ref={inputRef} 173 + {...stylex.props(styles.input, inputStyles.input)} 174 + /> 175 + <SuffixIcon 176 + suffix={suffix} 177 + style={inputStyles.addon} 178 + validationIconStyle={inputStyles.validationIcon} 179 + validationState={validationState} 180 + /> 181 + {!hideStepper && ( 182 + <Group {...stylex.props(styles.buttons)}> 183 + <Button slot="decrement" {...buttonStyles}> 184 + <Minus /> 185 + </Button> 186 + <Button slot="increment" {...buttonStyles}> 187 + <Plus /> 188 + </Button> 189 + </Group> 190 + )} 191 + </NumberInputWrapper> 192 + <Description>{description}</Description> 193 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 194 + </> 195 + ); 196 + } 197 + 111 198 export interface NumberFieldProps 112 - extends StyleXComponentProps<Omit<AriaNumberFieldProps, "children">>, 199 + extends StyleXComponentProps< 200 + Omit<AriaNumberFieldProps, "children" | "isInvalid"> 201 + >, 113 202 Pick<InputProps, "placeholder"> { 114 203 label?: React.ReactNode; 115 204 description?: string; 116 205 errorMessage?: string | ((validation: ValidationResult) => string); 117 206 size?: Size; 118 207 variant?: InputVariant; 208 + validationState?: InputValidationState; 119 209 prefix?: React.ReactNode; 120 210 suffix?: React.ReactNode; 121 211 hideStepper?: boolean; ··· 128 218 style, 129 219 size: sizeProp, 130 220 variant, 221 + validationState, 131 222 prefix, 132 223 suffix, 133 224 placeholder, ··· 135 226 ...props 136 227 }: NumberFieldProps) { 137 228 const size = sizeProp || use(SizeContext); 138 - const inputRef = useRef<HTMLInputElement>(null); 139 - const inputStyles = useInputStyles({ size, variant }); 140 - const buttonStyles = stylex.props( 141 - styles.button, 142 - ui.borderInteractive, 143 - ui.bgAction, 144 - ); 229 + const inputStyles = useInputStyles({ size, variant, validationState }); 145 230 146 231 return ( 147 232 <SizeContext value={size}> 148 - <AriaNumberField {...props} {...stylex.props(inputStyles.field, style)}> 149 - <Label>{label}</Label> 150 - {/* 151 - This onClick is specifically for mouse users not clicking directly on the input. 152 - A keyboard user would not encounter the same issue. 153 - */} 154 - <NumberInputWrapper 155 - style={inputStyles.wrapper} 156 - onClick={() => inputRef.current?.focus()} 157 - > 158 - {prefix != null && ( 159 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 160 - )} 161 - <Input 233 + <AriaNumberField 234 + {...props} 235 + isInvalid={validationState ? validationState === "invalid" : undefined} 236 + {...stylex.props(inputStyles.field, style)} 237 + > 238 + {({ isInvalid }) => ( 239 + <NumberFieldContent 240 + label={label} 241 + description={description} 242 + errorMessage={errorMessage} 243 + size={size} 244 + variant={variant} 245 + validationState={validationState} 246 + isInvalid={isInvalid} 247 + prefix={prefix} 248 + suffix={suffix} 162 249 placeholder={placeholder} 163 - ref={inputRef} 164 - {...stylex.props(styles.input, inputStyles.input)} 250 + hideStepper={hideStepper} 165 251 /> 166 - {suffix != null && ( 167 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 168 - )} 169 - {!hideStepper && ( 170 - <Group {...stylex.props(styles.buttons)}> 171 - <Button slot="decrement" {...buttonStyles}> 172 - <Minus /> 173 - </Button> 174 - <Button slot="increment" {...buttonStyles}> 175 - <Plus /> 176 - </Button> 177 - </Group> 178 - )} 179 - </NumberInputWrapper> 180 - <Description>{description}</Description> 181 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 252 + )} 182 253 </AriaNumberField> 183 254 </SizeContext> 184 255 );
+109 -50
packages/hip-ui/src/components/search-field/index.tsx
··· 12 12 import { SizeContext } from "../context"; 13 13 import { IconButton } from "../icon-button"; 14 14 import { Description, FieldErrorMessage, Label } from "../label"; 15 + import { SuffixIcon } from "../suffix-icon"; 15 16 import { spacing } from "../theme/spacing.stylex"; 16 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 17 + import { 18 + InputVariant, 19 + InputValidationState, 20 + Size, 21 + StyleXComponentProps, 22 + } from "../theme/types"; 17 23 import { useInputStyles } from "../theme/useInputStyles"; 18 24 19 25 const styles = stylex.create({ ··· 22 28 }, 23 29 clearButton: { 24 30 position: "absolute", 31 + transform: "translateY(-50%)", 25 32 right: 0, 26 33 top: "50%", 27 - transform: "translateY(-50%)", 28 34 }, 29 35 clearButtonPadding: { 30 36 paddingRight: spacing["8"], 31 37 }, 32 38 }); 33 39 40 + interface SearchFieldContentProps { 41 + label?: React.ReactNode; 42 + description?: string; 43 + errorMessage?: string | ((validation: ValidationResult) => string); 44 + size: Size; 45 + variant: InputVariant | undefined; 46 + validationState: InputValidationState | undefined; 47 + isInvalid: boolean; 48 + prefix?: React.ReactNode; 49 + suffix?: React.ReactNode; 50 + placeholder?: string; 51 + isEmpty: boolean; 52 + } 53 + 54 + function SearchFieldContent({ 55 + label, 56 + description, 57 + errorMessage, 58 + size, 59 + variant, 60 + validationState, 61 + isInvalid, 62 + prefix, 63 + suffix, 64 + placeholder, 65 + isEmpty, 66 + }: SearchFieldContentProps) { 67 + const inputRef = useRef<HTMLInputElement>(null); 68 + const inputStyles = useInputStyles({ 69 + size, 70 + variant, 71 + validationState: isInvalid ? "invalid" : validationState, 72 + }); 73 + 74 + return ( 75 + <> 76 + <Label>{label}</Label> 77 + {/* 78 + This onClick is specifically for mouse users not clicking directly on the input. 79 + A keyboard user would not encounter the same issue. 80 + */} 81 + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 82 + <div 83 + {...stylex.props(inputStyles.wrapper, styles.wrapper)} 84 + onClick={() => inputRef.current?.focus()} 85 + > 86 + {prefix != null && ( 87 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 88 + )} 89 + <Input 90 + placeholder={placeholder} 91 + ref={inputRef} 92 + {...stylex.props( 93 + inputStyles.input, 94 + !isEmpty && styles.clearButtonPadding, 95 + )} 96 + /> 97 + <SuffixIcon 98 + suffix={suffix} 99 + style={inputStyles.addon} 100 + validationIconStyle={inputStyles.validationIcon} 101 + validationState={validationState} 102 + /> 103 + {!isEmpty && ( 104 + <div {...stylex.props(inputStyles.addon, styles.clearButton)}> 105 + <IconButton label="Clear search" size="sm" variant="secondary"> 106 + <X /> 107 + </IconButton> 108 + </div> 109 + )} 110 + </div> 111 + <Description>{description}</Description> 112 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 113 + </> 114 + ); 115 + } 116 + 34 117 export interface SearchFieldProps 35 - extends StyleXComponentProps<AriaSearchFieldProps>, 118 + extends StyleXComponentProps<Omit<AriaSearchFieldProps, "isInvalid">>, 36 119 Pick<InputProps, "placeholder"> { 37 120 label?: React.ReactNode; 38 121 description?: string; 39 122 errorMessage?: string | ((validation: ValidationResult) => string); 40 123 size?: Size; 41 124 variant?: InputVariant; 125 + validationState?: InputValidationState; 42 126 prefix?: React.ReactNode; 43 127 suffix?: React.ReactNode; 44 128 } ··· 52 136 style, 53 137 size: sizeProp, 54 138 variant, 139 + validationState, 55 140 prefix = defaultPrefix, 56 141 suffix, 57 142 placeholder, 58 143 ...props 59 144 }: SearchFieldProps) { 60 145 const size = sizeProp || use(SizeContext); 61 - const inputRef = useRef<HTMLInputElement>(null); 62 - const inputStyles = useInputStyles({ size, variant }); 146 + const inputStyles = useInputStyles({ size, variant, validationState }); 63 147 64 148 return ( 65 149 <SizeContext value={size}> 66 - <AriaSearchField {...props} {...stylex.props(inputStyles.field, style)}> 67 - {({ isEmpty }) => { 68 - return ( 69 - <> 70 - <Label>{label}</Label> 71 - {/* 72 - This onClick is specifically for mouse users not clicking directly on the input. 73 - A keyboard user would not encounter the same issue. 74 - */} 75 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 76 - <div 77 - {...stylex.props(inputStyles.wrapper, styles.wrapper)} 78 - onClick={() => inputRef.current?.focus()} 79 - > 80 - {prefix != null && ( 81 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 82 - )} 83 - <Input 84 - placeholder={placeholder} 85 - ref={inputRef} 86 - {...stylex.props( 87 - inputStyles.input, 88 - !isEmpty && styles.clearButtonPadding, 89 - )} 90 - /> 91 - {suffix != null && ( 92 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 93 - )} 94 - {!isEmpty && ( 95 - <div {...stylex.props(inputStyles.addon, styles.clearButton)}> 96 - <IconButton 97 - label="Clear search" 98 - size="sm" 99 - variant="secondary" 100 - > 101 - <X /> 102 - </IconButton> 103 - </div> 104 - )} 105 - </div> 106 - <Description>{description}</Description> 107 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 108 - </> 109 - ); 110 - }} 150 + <AriaSearchField 151 + {...props} 152 + isInvalid={validationState ? validationState === "invalid" : undefined} 153 + {...stylex.props(inputStyles.field, style)} 154 + > 155 + {({ isInvalid, isEmpty }) => ( 156 + <SearchFieldContent 157 + label={label} 158 + description={description} 159 + errorMessage={errorMessage} 160 + size={size} 161 + variant={variant} 162 + validationState={validationState} 163 + isInvalid={isInvalid} 164 + prefix={prefix} 165 + suffix={suffix} 166 + placeholder={placeholder} 167 + isEmpty={isEmpty} 168 + /> 169 + )} 111 170 </AriaSearchField> 112 171 </SizeContext> 113 172 );
+140 -51
packages/hip-ui/src/components/select/index.tsx
··· 18 18 import { Description, FieldErrorMessage, Label } from "../label"; 19 19 import { ListBox, ListBoxSeparator } from "../listbox"; 20 20 import { SearchField } from "../search-field"; 21 + import { SuffixIcon } from "../suffix-icon"; 21 22 import { spacing } from "../theme/spacing.stylex"; 22 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 23 + import { 24 + InputVariant, 25 + InputValidationState, 26 + Size, 27 + StyleXComponentProps, 28 + } from "../theme/types"; 23 29 import { useInputStyles } from "../theme/useInputStyles"; 24 30 import { usePopoverStyles } from "../theme/usePopoverStyles"; 25 31 ··· 33 39 }, 34 40 }); 35 41 42 + interface SelectContentProps<T extends object> { 43 + label?: string; 44 + description?: string; 45 + errorMessage?: string | ((validation: ValidationResult) => string); 46 + size: Size; 47 + variant: InputVariant | undefined; 48 + validationState: InputValidationState | undefined; 49 + isInvalid: boolean; 50 + placeholder: string; 51 + prefix?: React.ReactNode; 52 + suffix?: React.ReactNode; 53 + isSearchable: boolean; 54 + items?: Iterable<T>; 55 + children: React.ReactNode | ((item: T) => React.ReactNode); 56 + shouldCloseOnInteractOutside?: ((element: Element) => boolean) | undefined; 57 + shouldFlip?: boolean; 58 + shouldUpdatePosition?: boolean; 59 + placement?: PopoverProps["placement"]; 60 + } 61 + 62 + function SelectContent<T extends object>({ 63 + label, 64 + description, 65 + errorMessage, 66 + size, 67 + variant, 68 + validationState, 69 + isInvalid, 70 + placeholder, 71 + prefix, 72 + suffix, 73 + isSearchable, 74 + items, 75 + children, 76 + shouldCloseOnInteractOutside, 77 + shouldFlip, 78 + shouldUpdatePosition, 79 + placement, 80 + }: SelectContentProps<T>) { 81 + const inputStyles = useInputStyles({ 82 + size, 83 + variant, 84 + validationState: isInvalid ? "invalid" : validationState, 85 + }); 86 + const popoverStyles = usePopoverStyles(); 87 + const { contains } = useFilter({ sensitivity: "base" }); 88 + 89 + return ( 90 + <> 91 + <Label>{label}</Label> 92 + <Button {...stylex.props(inputStyles.wrapper)}> 93 + {prefix != null && ( 94 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 95 + )} 96 + <SelectValue {...stylex.props(inputStyles.input)}> 97 + {({ selectedText, isPlaceholder, defaultChildren }) => { 98 + if (isPlaceholder) return placeholder; 99 + if (selectedText) return selectedText; 100 + 101 + return defaultChildren; 102 + }} 103 + </SelectValue> 104 + <SuffixIcon 105 + suffix={ 106 + <> 107 + {suffix} 108 + <ChevronDown size={16} aria-hidden="true" /> 109 + </> 110 + } 111 + style={inputStyles.addon} 112 + validationIconStyle={inputStyles.validationIcon} 113 + validationState={validationState} 114 + /> 115 + </Button> 116 + <Description>{description}</Description> 117 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 118 + <Popover 119 + containerPadding={8} 120 + shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 121 + shouldFlip={shouldFlip} 122 + shouldUpdatePosition={shouldUpdatePosition} 123 + placement={placement} 124 + {...stylex.props( 125 + popoverStyles.wrapper, 126 + popoverStyles.animation, 127 + styles.matchWidth, 128 + )} 129 + > 130 + {isSearchable ? ( 131 + <Autocomplete filter={contains}> 132 + <div {...stylex.props(styles.searchField)}> 133 + <SearchField placeholder="Search" variant="secondary" /> 134 + </div> 135 + <ListBoxSeparator /> 136 + <ListBox items={items}>{children}</ListBox> 137 + </Autocomplete> 138 + ) : ( 139 + <ListBox items={items}>{children}</ListBox> 140 + )} 141 + </Popover> 142 + </> 143 + ); 144 + } 145 + 36 146 export interface SelectProps<T extends object, M extends "single" | "multiple"> 37 - extends StyleXComponentProps<Omit<AriaSelectProps<T, M>, "children">>, 147 + extends StyleXComponentProps< 148 + Omit<AriaSelectProps<T, M>, "children" | "isInvalid"> 149 + >, 38 150 Pick< 39 151 PopoverProps, 40 152 | "shouldCloseOnInteractOutside" ··· 49 161 children: React.ReactNode | ((item: T) => React.ReactNode); 50 162 size?: Size; 51 163 variant?: InputVariant; 164 + validationState?: InputValidationState; 52 165 placeholder?: string; 53 166 prefix?: React.ReactNode; 54 167 suffix?: React.ReactNode; ··· 67 180 style, 68 181 size: sizeProp, 69 182 variant, 183 + validationState, 70 184 shouldCloseOnInteractOutside, 71 185 shouldFlip, 72 186 shouldUpdatePosition, ··· 78 192 ...props 79 193 }: SelectProps<T, M>) { 80 194 const size = sizeProp || use(SizeContext); 81 - const inputStyles = useInputStyles({ size, variant }); 82 - const popoverStyles = usePopoverStyles(); 83 - const { contains } = useFilter({ sensitivity: "base" }); 195 + const inputStyles = useInputStyles({ size, variant, validationState }); 84 196 85 197 return ( 86 198 <SizeContext value={size}> 87 199 <AriaSelect 88 200 {...props} 201 + isInvalid={validationState ? validationState === "invalid" : undefined} 89 202 {...stylex.props(inputStyles.field, style)} 90 203 placeholder={placeholder} 91 204 > 92 - <Label>{label}</Label> 93 - <Button {...stylex.props(inputStyles.wrapper)}> 94 - {prefix != null && ( 95 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 96 - )} 97 - <SelectValue {...stylex.props(inputStyles.input)}> 98 - {({ selectedText, isPlaceholder, defaultChildren }) => { 99 - if (isPlaceholder) return placeholder; 100 - if (selectedText) return selectedText; 101 - 102 - return defaultChildren; 103 - }} 104 - </SelectValue> 105 - {suffix != null && ( 106 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 107 - )} 108 - <div {...stylex.props(inputStyles.addon)}> 109 - <ChevronDown size={16} aria-hidden="true" /> 110 - </div> 111 - </Button> 112 - <Description>{description}</Description> 113 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 114 - <Popover 115 - containerPadding={8} 116 - shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 117 - shouldFlip={shouldFlip} 118 - shouldUpdatePosition={shouldUpdatePosition} 119 - placement={placement} 120 - {...stylex.props( 121 - popoverStyles.wrapper, 122 - popoverStyles.animation, 123 - styles.matchWidth, 124 - )} 125 - > 126 - {isSearchable ? ( 127 - <Autocomplete filter={contains}> 128 - <div {...stylex.props(styles.searchField)}> 129 - <SearchField placeholder="Search" variant="secondary" /> 130 - </div> 131 - <ListBoxSeparator /> 132 - <ListBox items={items}>{children}</ListBox> 133 - </Autocomplete> 134 - ) : ( 135 - <ListBox items={items}>{children}</ListBox> 136 - )} 137 - </Popover> 205 + {({ isInvalid }) => ( 206 + <SelectContent 207 + label={label} 208 + description={description} 209 + errorMessage={errorMessage} 210 + size={size} 211 + variant={variant} 212 + validationState={validationState} 213 + isInvalid={isInvalid} 214 + placeholder={placeholder} 215 + prefix={prefix} 216 + suffix={suffix} 217 + isSearchable={isSearchable} 218 + items={items} 219 + shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 220 + shouldFlip={shouldFlip} 221 + shouldUpdatePosition={shouldUpdatePosition} 222 + placement={placement} 223 + > 224 + {children} 225 + </SelectContent> 226 + )} 138 227 </AriaSelect> 139 228 </SizeContext> 140 229 );
+1
packages/hip-ui/src/components/select/select-config.ts
··· 11 11 "../theme/shadow.stylex.tsx", 12 12 "../theme/useInputStyles.ts", 13 13 "../theme/usePopoverStyles.ts", 14 + "../suffix-icon/index.tsx", 14 15 ], 15 16 };
+44
packages/hip-ui/src/components/suffix-icon/index.tsx
··· 1 + import * as stylex from "@stylexjs/stylex"; 2 + import { AlertTriangle, Check, CircleX } from "lucide-react"; 3 + import { use } from "react"; 4 + import { FieldErrorContext } from "react-aria-components"; 5 + 6 + import { InputValidationState } from "../theme/types"; 7 + 8 + export interface SuffixIconProps { 9 + suffix: React.ReactNode | undefined; 10 + style?: stylex.StyleXStyles; 11 + validationIconStyle: stylex.StyleXStyles; 12 + validationState: InputValidationState | undefined; 13 + } 14 + 15 + export function SuffixIcon({ 16 + suffix, 17 + validationState, 18 + style, 19 + validationIconStyle, 20 + }: SuffixIconProps) { 21 + const state = use(FieldErrorContext); 22 + const isVisible = state?.isInvalid || validationState || suffix != null; 23 + 24 + if (!isVisible) { 25 + return null; 26 + } 27 + 28 + return ( 29 + <div {...stylex.props(style)}> 30 + {suffix} 31 + {state?.isInvalid || validationState ? ( 32 + <div {...stylex.props(validationIconStyle)}> 33 + {state?.isInvalid || validationState === "invalid" ? ( 34 + <CircleX /> 35 + ) : validationState === "valid" ? ( 36 + <Check /> 37 + ) : ( 38 + <AlertTriangle /> 39 + )} 40 + </div> 41 + ) : null} 42 + </div> 43 + ); 44 + }
+103 -34
packages/hip-ui/src/components/text-field/index.tsx
··· 13 13 import { SizeContext } from "../context"; 14 14 import { IconButton } from "../icon-button"; 15 15 import { Description, FieldErrorMessage, Label } from "../label"; 16 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 16 + import { SuffixIcon } from "../suffix-icon"; 17 + import { 18 + InputValidationState, 19 + InputVariant, 20 + Size, 21 + StyleXComponentProps, 22 + } from "../theme/types"; 17 23 import { useInputStyles } from "../theme/useInputStyles"; 18 24 19 25 function PasswordToggle({ ··· 45 51 ); 46 52 } 47 53 54 + interface TextFieldContentProps { 55 + label?: React.ReactNode; 56 + description?: string; 57 + errorMessage?: string | ((validation: ValidationResult) => string); 58 + size: Size; 59 + variant: InputVariant | undefined; 60 + validationState: InputValidationState | undefined; 61 + isInvalid: boolean; 62 + prefix?: React.ReactNode; 63 + suffix?: React.ReactNode; 64 + placeholder?: string; 65 + type: TextFieldProps["type"]; 66 + setType: (type: TextFieldProps["type"]) => void; 67 + } 68 + 69 + function TextFieldContent({ 70 + label, 71 + description, 72 + errorMessage, 73 + size, 74 + variant, 75 + validationState, 76 + isInvalid, 77 + prefix, 78 + suffix, 79 + placeholder, 80 + type, 81 + setType, 82 + }: TextFieldContentProps) { 83 + const inputRef = useRef<HTMLInputElement>(null); 84 + const isPasswordInput = type === "password"; 85 + const inputStyles = useInputStyles({ 86 + size, 87 + variant, 88 + validationState: isInvalid ? "invalid" : validationState, 89 + }); 90 + 91 + return ( 92 + <> 93 + <Label>{label}</Label> 94 + {/* 95 + This onClick is specifically for mouse users not clicking directly on the input. 96 + A keyboard user would not encounter the same issue. 97 + */} 98 + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 99 + <div 100 + {...stylex.props(inputStyles.wrapper)} 101 + onClick={() => inputRef.current?.focus()} 102 + > 103 + {prefix != null && ( 104 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 105 + )} 106 + <Input 107 + {...stylex.props(inputStyles.input)} 108 + ref={inputRef} 109 + placeholder={placeholder} 110 + /> 111 + {isPasswordInput && ( 112 + <PasswordToggle 113 + type={type} 114 + setType={setType} 115 + style={inputStyles.addon} 116 + /> 117 + )} 118 + <SuffixIcon 119 + suffix={suffix} 120 + style={inputStyles.addon} 121 + validationIconStyle={inputStyles.validationIcon} 122 + validationState={validationState} 123 + /> 124 + </div> 125 + <Description>{description}</Description> 126 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 127 + </> 128 + ); 129 + } 130 + 48 131 export interface TextFieldProps 49 - extends StyleXComponentProps<AriaTextFieldProps>, 132 + extends StyleXComponentProps<Omit<AriaTextFieldProps, "isInvalid">>, 50 133 Pick<InputProps, "placeholder"> { 51 134 label?: React.ReactNode; 52 135 description?: string; 53 136 errorMessage?: string | ((validation: ValidationResult) => string); 54 137 size?: Size; 55 138 variant?: InputVariant; 139 + validationState?: InputValidationState; 56 140 prefix?: React.ReactNode; 57 141 suffix?: React.ReactNode; 58 142 } ··· 64 148 style, 65 149 size: sizeProp, 66 150 variant, 151 + validationState, 67 152 prefix, 68 153 suffix, 69 154 placeholder, 70 155 ...props 71 156 }: TextFieldProps) { 72 157 const size = sizeProp || use(SizeContext); 73 - const inputRef = useRef<HTMLInputElement>(null); 74 158 const [type, setType] = useState<TextFieldProps["type"]>( 75 159 props.type || "text", 76 160 ); 77 - const isPasswordInput = props.type === "password"; 78 - const inputStyles = useInputStyles({ size, variant }); 161 + const inputStyles = useInputStyles({ size, variant, validationState }); 79 162 80 163 return ( 81 164 <SizeContext value={size}> 82 165 <AriaTextField 83 166 {...props} 167 + isInvalid={validationState ? validationState === "invalid" : undefined} 84 168 type={type} 85 169 {...stylex.props(inputStyles.field, style)} 86 170 > 87 - <Label>{label}</Label> 88 - {/* 89 - This onClick is specifically for mouse users not clicking directly on the input. 90 - A keyboard user would not encounter the same issue. 91 - */} 92 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 93 - <div 94 - {...stylex.props(inputStyles.wrapper)} 95 - onClick={() => inputRef.current?.focus()} 96 - > 97 - {prefix != null && ( 98 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 99 - )} 100 - <Input 101 - {...stylex.props(inputStyles.input)} 102 - ref={inputRef} 171 + {({ isInvalid }) => ( 172 + <TextFieldContent 173 + label={label} 174 + description={description} 175 + errorMessage={errorMessage} 176 + size={size} 177 + variant={variant} 178 + validationState={validationState} 179 + isInvalid={isInvalid} 180 + prefix={prefix} 181 + suffix={suffix} 103 182 placeholder={placeholder} 183 + type={type} 184 + setType={setType} 104 185 /> 105 - {suffix != null && ( 106 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 107 - )} 108 - {isPasswordInput && ( 109 - <PasswordToggle 110 - type={type} 111 - setType={setType} 112 - style={inputStyles.addon} 113 - /> 114 - )} 115 - </div> 116 - <Description>{description}</Description> 117 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 186 + )} 118 187 </AriaTextField> 119 188 </SizeContext> 120 189 );
+1
packages/hip-ui/src/components/theme/types.ts
··· 12 12 | "critical" 13 13 | "critical-outline"; 14 14 export type InputVariant = "primary" | "secondary" | "tertiary"; 15 + export type InputValidationState = "valid" | "invalid" | "warning"; 15 16 export type ButtonGroupVariant = "grouped" | "separate"; 16 17 export type TextVariant = "primary" | "secondary" | "critical"; 17 18 export type MeterVariant =
+232 -16
packages/hip-ui/src/components/theme/useInputStyles.ts
··· 2 2 import { use } from "react"; 3 3 4 4 import { SizeContext } from "../context"; 5 - import { InputVariant, Size } from "../theme/types"; 5 + import { InputValidationState, InputVariant, Size } from "../theme/types"; 6 + import { animationDuration } from "./animations-duration.stylex"; 6 7 import { radius } from "./radius.stylex"; 7 - import { criticalColor, ui, uiColor } from "./semantic-color.stylex"; 8 + import { 9 + criticalColor, 10 + successColor, 11 + ui, 12 + uiColor, 13 + warningColor, 14 + } from "./semantic-color.stylex"; 8 15 import { spacing } from "./spacing.stylex"; 9 16 import { lineHeight, fontSize } from "./typography.stylex"; 10 17 ··· 15 22 flexDirection: "column", 16 23 }, 17 24 addon: { 25 + boxSizing: "border-box", 18 26 color: ui.textDim, 19 27 flexShrink: 0, 20 28 height: "100%", 21 - minWidth: spacing["8"], 22 - paddingLeft: { ":first-child": spacing["0.5"] }, 29 + paddingLeft: { ":first-child": spacing["2.5"] }, 23 30 paddingRight: { 24 - ":last-child:has(svg)": spacing["0.5"], 25 - ":last-child": spacing["2"], 31 + ":first-child": spacing["2"], 32 + ":last-child": spacing["2.5"], 26 33 }, 27 34 28 - gap: spacing["0.5"], 35 + gap: spacing["2"], 29 36 alignItems: "center", 30 37 display: "flex", 31 38 justifyContent: "center", ··· 38 45 width: spacing["4"], 39 46 }, 40 47 }, 48 + validationIcon: { 49 + alignItems: "center", 50 + display: "flex", 51 + justifyContent: "center", 52 + }, 53 + invalidIcon: { 54 + color: criticalColor.text1, 55 + }, 56 + validIcon: { 57 + color: successColor.text1, 58 + }, 59 + warningIcon: { 60 + color: warningColor.text1, 61 + }, 41 62 inputWrapper: { 42 63 // eslint-disable-next-line @stylexjs/valid-styles 43 64 cornerShape: "squircle", ··· 59 80 backgroundColor: "transparent", 60 81 boxSizing: "border-box", 61 82 color: { 83 + default: "inherit", 62 84 ":is(::placeholder,[data-placeholder])": uiColor.text1, 63 85 }, 64 86 display: "flex", ··· 74 96 primary: { 75 97 borderColor: { 76 98 default: uiColor.border2, 77 - ":has([data-hovered]):not([data-invalid])": uiColor.border3, 78 - ":has([data-invalid])": criticalColor.border2, 99 + ":has([data-hovered]):not(:has([data-invalid]))": uiColor.border3, 79 100 ":focus": uiColor.solid1, 80 101 }, 81 102 borderStyle: "solid", 82 103 borderWidth: 1, 104 + backgroundColor: { 105 + default: "transparent", 106 + ":hover:not(:has(* button:hover)):not(:disabled)": uiColor.component2, 107 + ":is(:active,[data-pressed=true]):not(:disabled)": uiColor.component3, 108 + ":disabled": "transparent", 109 + }, 110 + boxShadow: { 111 + ":has([data-invalid])": `0 0 0 2px ${criticalColor.component1}`, 112 + }, 113 + transitionDuration: animationDuration.fast, 83 114 transitionProperty: "background-color, border-color", 115 + transitionTimingFunction: "ease-in-out", 116 + }, 117 + primaryInvalid: { 118 + borderColor: { 119 + default: criticalColor.border2, 120 + ":has([data-hovered])": criticalColor.border3, 121 + ":focus": uiColor.solid1, 122 + }, 123 + backgroundColor: { 124 + default: criticalColor.bgSubtle, 125 + ":hover:not(:has(* button:hover)):not(:disabled)": 126 + criticalColor.component2, 127 + ":disabled": "transparent", 128 + }, 129 + boxShadow: `0 0 0 2px ${criticalColor.component1}`, 130 + color: criticalColor.text2, 131 + }, 132 + primaryWarning: { 133 + borderColor: { 134 + default: warningColor.border2, 135 + ":has([data-hovered])": warningColor.border3, 136 + ":focus": uiColor.solid1, 137 + }, 138 + backgroundColor: { 139 + default: warningColor.bgSubtle, 140 + ":hover:not(:has(* button:hover)):not(:disabled)": 141 + warningColor.component2, 142 + ":disabled": "transparent", 143 + }, 144 + boxShadow: `0 0 0 2px ${warningColor.component1}`, 145 + color: warningColor.text2, 146 + }, 147 + primaryValid: { 148 + borderColor: { 149 + default: successColor.border2, 150 + ":has([data-hovered])": successColor.border3, 151 + ":focus": uiColor.solid1, 152 + }, 153 + backgroundColor: { 154 + default: successColor.bgSubtle, 155 + ":hover:not(:has(* button:hover)):not(:disabled)": 156 + successColor.component2, 157 + ":disabled": "transparent", 158 + }, 159 + boxShadow: `0 0 0 2px ${successColor.component1}`, 160 + color: successColor.text2, 84 161 }, 85 162 secondary: { 86 163 borderColor: { 87 164 default: uiColor.component1, 88 - ":has([data-invalid])": criticalColor.border2, 165 + ":hover:not(:has(* button:hover)):not(:disabled)": uiColor.component2, 166 + ":is(:active,[data-pressed=true]):not(:disabled)": uiColor.component3, 167 + ":disabled": uiColor.component1, 89 168 }, 90 169 borderStyle: "solid", 91 170 borderWidth: 1, 171 + backgroundColor: { 172 + default: uiColor.component1, 173 + ":hover:not(:has(* button:hover)):not(:disabled)": uiColor.component2, 174 + ":is(:active,[data-pressed=true]):not(:disabled)": uiColor.component3, 175 + ":disabled": uiColor.component1, 176 + }, 177 + transitionDuration: animationDuration.fast, 92 178 transitionProperty: "background-color, border-color", 179 + transitionTimingFunction: "ease-in-out", 180 + }, 181 + secondaryInvalid: { 182 + borderColor: { 183 + default: criticalColor.component1, 184 + ":hover:not(:has(* button:hover)):not(:disabled)": 185 + criticalColor.component2, 186 + }, 187 + backgroundColor: { 188 + default: criticalColor.component1, 189 + ":hover:not(:has(* button:hover)):not(:disabled)": 190 + criticalColor.component2, 191 + }, 192 + }, 193 + secondaryWarning: { 194 + borderColor: { 195 + default: warningColor.component1, 196 + ":hover:not(:has(* button:hover)):not(:disabled)": 197 + warningColor.component2, 198 + }, 199 + backgroundColor: { 200 + default: warningColor.component1, 201 + ":hover:not(:has(* button:hover)):not(:disabled)": 202 + warningColor.component2, 203 + }, 204 + color: warningColor.text2, 205 + }, 206 + secondaryValid: { 207 + borderColor: { 208 + default: successColor.component1, 209 + ":hover:not(:has(* button:hover)):not(:disabled)": 210 + successColor.component2, 211 + }, 212 + backgroundColor: { 213 + default: successColor.component1, 214 + ":hover:not(:has(* button:hover)):not(:disabled)": 215 + successColor.component2, 216 + }, 217 + color: successColor.text2, 93 218 }, 94 219 tertiary: { 95 220 borderColor: { 96 221 default: "transparent", 97 - ":has([data-invalid])": criticalColor.border2, 222 + ":hover:not(:has(* button:hover)):not(:disabled)": uiColor.component2, 223 + ":is(:active,[data-pressed=true]):not(:disabled)": uiColor.component3, 224 + ":disabled": "transparent", 98 225 }, 99 226 borderStyle: "solid", 100 227 borderWidth: 1, 228 + backgroundColor: { 229 + default: "transparent", 230 + ":hover:not(:has(* button:hover)):not(:disabled)": uiColor.component2, 231 + ":is(:active,[data-pressed=true]):not(:disabled)": uiColor.component3, 232 + ":disabled": "transparent", 233 + }, 234 + transitionDuration: animationDuration.fast, 101 235 transitionProperty: "background-color, border-color", 236 + transitionTimingFunction: "ease-in-out", 102 237 }, 238 + tertiaryInvalid: { 239 + borderColor: { 240 + default: "transparent", 241 + ":hover:not(:has(* button:hover)):not(:disabled)": 242 + criticalColor.component1, 243 + ":is(:active,[data-pressed=true]):not(:disabled)": 244 + criticalColor.component2, 245 + ":disabled": "transparent", 246 + }, 247 + backgroundColor: { 248 + default: "transparent", 249 + ":hover:not(:has(* button:hover)):not(:disabled)": 250 + criticalColor.component1, 251 + ":is(:active,[data-pressed=true]):not(:disabled)": 252 + criticalColor.component2, 253 + ":disabled": "transparent", 254 + }, 255 + color: criticalColor.text2, 256 + }, 257 + tertiaryWarning: { 258 + borderColor: { 259 + default: "transparent", 260 + ":hover:not(:has(* button:hover)):not(:disabled)": 261 + warningColor.component1, 262 + ":is(:active,[data-pressed=true]):not(:disabled)": 263 + warningColor.component2, 264 + ":disabled": "transparent", 265 + }, 266 + backgroundColor: { 267 + default: "transparent", 268 + ":hover:not(:has(* button:hover)):not(:disabled)": 269 + warningColor.component1, 270 + ":is(:active,[data-pressed=true]):not(:disabled)": 271 + warningColor.component2, 272 + ":disabled": "transparent", 273 + }, 274 + color: warningColor.text1, 275 + }, 276 + tertiaryValid: { 277 + borderColor: { 278 + default: "transparent", 279 + ":hover:not(:has(* button:hover)):not(:disabled)": 280 + successColor.component1, 281 + ":is(:active,[data-pressed=true]):not(:disabled)": 282 + successColor.component2, 283 + ":disabled": "transparent", 284 + }, 285 + backgroundColor: { 286 + default: "transparent", 287 + ":hover:not(:has(* button:hover)):not(:disabled)": 288 + successColor.component1, 289 + ":is(:active,[data-pressed=true]):not(:disabled)": 290 + successColor.component2, 291 + ":disabled": "transparent", 292 + }, 293 + color: successColor.text1, 294 + }, 295 + 103 296 inputSize: (size: Size) => ({ 104 297 fontSize: 105 298 size === "sm" ··· 113 306 ? spacing["1"] 114 307 : size === "md" 115 308 ? spacing["2"] 116 - : spacing["1"], 309 + : spacing["3"], 117 310 }, 118 311 paddingRight: 119 312 size === "sm" 120 313 ? spacing["1"] 121 314 : size === "md" 122 315 ? spacing["2"] 123 - : spacing["2"], 316 + : spacing["3"], 124 317 }), 125 318 wrapperSize: (size: Size) => ({ 126 319 height: ··· 135 328 export function useInputStyles({ 136 329 size: sizeProp, 137 330 variant = "primary", 331 + validationState, 138 332 }: { 139 333 size: Size | undefined; 140 334 variant: InputVariant | undefined; 335 + validationState: InputValidationState | undefined; 141 336 }) { 142 337 const size = sizeProp || use(SizeContext); 143 338 ··· 145 340 field: [styles.field], 146 341 wrapper: [ 147 342 styles.inputWrapper, 148 - variant === "primary" && [ui.bgGhost, styles.primary], 149 - variant === "secondary" && [ui.bgUi, styles.secondary], 150 - variant === "tertiary" && [ui.bgGhost, styles.tertiary], 151 343 ui.text, 344 + variant === "primary" && [ 345 + styles.primary, 346 + validationState === "invalid" && [styles.primaryInvalid], 347 + validationState === "warning" && [styles.primaryWarning], 348 + validationState === "valid" && [styles.primaryValid], 349 + ], 350 + variant === "secondary" && [ 351 + styles.secondary, 352 + validationState === "invalid" && [styles.secondaryInvalid], 353 + validationState === "warning" && [styles.secondaryWarning], 354 + validationState === "valid" && [styles.secondaryValid], 355 + ], 356 + variant === "tertiary" && [ 357 + styles.tertiary, 358 + validationState === "invalid" && [styles.tertiaryInvalid], 359 + validationState === "warning" && [styles.tertiaryWarning], 360 + validationState === "valid" && [styles.tertiaryValid], 361 + ], 152 362 styles.wrapperSize(size), 153 363 ], 154 364 input: [styles.input, styles.inputSize(size)], 155 365 addon: styles.addon as unknown as stylex.StyleXStyles, 366 + validationIcon: [ 367 + styles.validationIcon, 368 + validationState === "invalid" && [styles.invalidIcon], 369 + validationState === "valid" && [styles.validIcon], 370 + validationState === "warning" && [styles.warningIcon], 371 + ], 156 372 }; 157 373 }
+90 -27
packages/hip-ui/src/components/time-field/index.tsx
··· 11 11 12 12 import { SizeContext } from "../context"; 13 13 import { Description, FieldErrorMessage, Label } from "../label"; 14 - import { InputVariant, Size, StyleXComponentProps } from "../theme/types"; 14 + import { SuffixIcon } from "../suffix-icon"; 15 + import { 16 + InputVariant, 17 + InputValidationState, 18 + Size, 19 + StyleXComponentProps, 20 + } from "../theme/types"; 15 21 import { useInputStyles } from "../theme/useInputStyles"; 16 22 23 + interface TimeFieldContentProps { 24 + label?: React.ReactNode; 25 + description?: string; 26 + errorMessage?: string | ((validation: ValidationResult) => string); 27 + size: Size; 28 + variant: InputVariant | undefined; 29 + validationState: InputValidationState | undefined; 30 + isInvalid: boolean; 31 + prefix?: React.ReactNode; 32 + suffix?: React.ReactNode; 33 + } 34 + 35 + function TimeFieldContent({ 36 + label, 37 + description, 38 + errorMessage, 39 + size, 40 + variant, 41 + validationState, 42 + isInvalid, 43 + prefix, 44 + suffix, 45 + }: TimeFieldContentProps) { 46 + const inputRef = useRef<HTMLInputElement>(null); 47 + const inputStyles = useInputStyles({ 48 + size, 49 + variant, 50 + validationState: isInvalid ? "invalid" : validationState, 51 + }); 52 + 53 + return ( 54 + <> 55 + <Label>{label}</Label> 56 + {/* 57 + This onClick is specifically for mouse users not clicking directly on the input. 58 + A keyboard user would not encounter the same issue. 59 + */} 60 + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 61 + <div 62 + {...stylex.props(inputStyles.wrapper)} 63 + onClick={() => inputRef.current?.focus()} 64 + > 65 + {prefix != null && ( 66 + <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 67 + )} 68 + <DateInput {...stylex.props(inputStyles.input)} ref={inputRef}> 69 + {(segment) => <DateSegment segment={segment} />} 70 + </DateInput> 71 + <SuffixIcon 72 + suffix={suffix} 73 + style={inputStyles.addon} 74 + validationIconStyle={inputStyles.validationIcon} 75 + validationState={validationState} 76 + /> 77 + </div> 78 + <Description>{description}</Description> 79 + <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 80 + </> 81 + ); 82 + } 83 + 17 84 export interface TimeFieldProps<T extends TimeValue> 18 - extends StyleXComponentProps<AriaTimeFieldProps<T>> { 85 + extends StyleXComponentProps<Omit<AriaTimeFieldProps<T>, "isInvalid">> { 19 86 label?: React.ReactNode; 20 87 description?: string; 21 88 errorMessage?: string | ((validation: ValidationResult) => string); 22 89 size?: Size; 23 90 variant?: InputVariant; 91 + validationState?: InputValidationState; 24 92 prefix?: React.ReactNode; 25 93 suffix?: React.ReactNode; 26 94 } ··· 32 100 style, 33 101 size: sizeProp, 34 102 variant, 103 + validationState, 35 104 prefix, 36 105 suffix, 37 106 ...props 38 107 }: TimeFieldProps<T>) { 39 108 const size = sizeProp || use(SizeContext); 40 - const inputRef = useRef<HTMLInputElement>(null); 41 - const inputStyles = useInputStyles({ size, variant }); 109 + const inputStyles = useInputStyles({ size, variant, validationState }); 42 110 43 111 return ( 44 112 <SizeContext value={size}> 45 - <AriaTimeField {...props} {...stylex.props(inputStyles.field, style)}> 46 - <Label>{label}</Label> 47 - {/* 48 - This onClick is specifically for mouse users not clicking directly on the input. 49 - A keyboard user would not encounter the same issue. 50 - */} 51 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 52 - <div 53 - {...stylex.props(inputStyles.wrapper)} 54 - onClick={() => inputRef.current?.focus()} 55 - > 56 - {prefix != null && ( 57 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 58 - )} 59 - <DateInput {...stylex.props(inputStyles.input)} ref={inputRef}> 60 - {(segment) => <DateSegment segment={segment} />} 61 - </DateInput> 62 - {suffix != null && ( 63 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 64 - )} 65 - </div> 66 - <Description>{description}</Description> 67 - <FieldErrorMessage>{errorMessage}</FieldErrorMessage> 113 + <AriaTimeField 114 + {...props} 115 + isInvalid={validationState ? validationState === "invalid" : undefined} 116 + {...stylex.props(inputStyles.field, style)} 117 + > 118 + {({ isInvalid }) => ( 119 + <TimeFieldContent 120 + label={label} 121 + description={description} 122 + errorMessage={errorMessage} 123 + size={size} 124 + variant={variant} 125 + validationState={validationState} 126 + isInvalid={isInvalid} 127 + prefix={prefix} 128 + suffix={suffix} 129 + /> 130 + )} 68 131 </AriaTimeField> 69 132 </SizeContext> 70 133 );