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.

tree

+800 -340
+18 -8
README.md
··· 6 6 7 7 - [ ] Add Virtualizer 8 8 - [ ] add borderless variant for input fields 9 + - [ ] Field erros 9 10 10 11 ### Components 11 12 ··· 30 31 - [ ] Sidebar 31 32 - [ ] Skeleton 32 33 34 + #### OTher Wrappers 35 + 36 + - [ ] Canvas (tldraw) 37 + - [ ] RichTextEditor (lexical) 38 + - [ ] Window Splitter 39 + 33 40 #### react-aria wrappers 34 41 35 42 - [ ] File Trigger ··· 38 45 - [ ] Switch 39 46 - [ ] Slider 40 47 41 - - [ ] Alert Dialog 42 - - [ ] Breadcrumb 43 - - [ ] Calendar 44 48 - [ ] Color Area 45 49 - [ ] Color Picker 46 50 - [ ] Color Swatch 47 51 - [ ] Color Swatch Picker 48 52 - [ ] Color Wheel 49 - - [ ] Command 50 - - [ ] Data Table 53 + 54 + - [ ] Calendar 51 55 - [ ] Date Picker 56 + - [ ] Range Date Picker 57 + 52 58 - [ ] Dialog 59 + - [ ] Alert Dialog 60 + - [ ] Command 61 + - [ ] Drawer 62 + - [ ] Sheet 63 + 64 + - [ ] Breadcrumb 65 + - [ ] Data Table 53 66 - [ ] Disclosure 54 67 - [ ] Disclosure Group 55 - - [ ] Drawer 56 68 - [ ] Field 57 69 - [ ] Form 58 70 - [ ] Grid List ··· 62 74 - [ ] Menubar 63 75 - [ ] Navigation Menu 64 76 - [ ] Progress 65 - - [ ] Range Date Picker 66 - - [ ] Sheet 67 77 - [ ] Spinner 68 78 - [ ] Table 69 79 - [ ] Tabs
+62 -1
apps/example/src/components/KitchenSink.tsx
··· 14 14 Check, 15 15 CpuIcon, 16 16 Ellipsis, 17 + File, 18 + Folder, 17 19 GlobeIcon, 20 + Image, 18 21 Pin, 19 22 Plus, 20 23 Search, ··· 72 75 import { ColorField } from "./color-field"; 73 76 import { NumberField } from "./number-field"; 74 77 import { ComboBox, ComboBoxItem } from "./combobox"; 78 + import { Tree, TreeItem } from "./tree"; 75 79 76 80 const styles = stylex.create({ 77 81 subCard: { ··· 100 104 borderWidth: 1, 101 105 borderStyle: "solid", 102 106 borderColor: slate[7], 107 + }, 108 + tree: { 109 + height: "300px", 103 110 }, 104 111 }); 105 112 ··· 529 536 <MenuSection> 530 537 <MenuSectionHeader>Menu Section Header</MenuSectionHeader> 531 538 <MenuItem>Menu Item 1</MenuItem> 532 - <MenuItem>Menu Item 2</MenuItem> 539 + <MenuItem isDisabled>Menu Item 2</MenuItem> 533 540 <MenuItem>Menu Item 3</MenuItem> 534 541 </MenuSection> 535 542 <MenuSeparator /> ··· 569 576 ); 570 577 } 571 578 579 + function TreeExample() { 580 + return ( 581 + <> 582 + <Tree 583 + aria-label="Files" 584 + selectionMode="multiple" 585 + selectionBehavior="replace" 586 + defaultExpandedKeys={["documents", "photos", "project"]} 587 + > 588 + <TreeItem id="documents" title="Documents" prefix={<Folder />}> 589 + <TreeItem id="project" title="Project" prefix={<Folder />}> 590 + <TreeItem id="report" title="Weekly Report" prefix={<File />} /> 591 + </TreeItem> 592 + </TreeItem> 593 + <TreeItem id="photos" title="Photos" prefix={<Folder />}> 594 + <TreeItem id="one" title="Image 1" prefix={<Image />} /> 595 + <TreeItem id="two" title="Image 2" isDisabled prefix={<Image />} /> 596 + </TreeItem> 597 + <TreeItem 598 + id="three" 599 + title="Image 3" 600 + prefix={<Image />} 601 + suffix={ 602 + <Menu 603 + placement="right top" 604 + trigger={ 605 + <IconButton size="sm" variant="tertiary" label="More"> 606 + <Ellipsis /> 607 + </IconButton> 608 + } 609 + > 610 + <MenuItem>Menu Item 1</MenuItem> 611 + <MenuItem>Menu Item 2</MenuItem> 612 + <MenuItem>Menu Item 3</MenuItem> 613 + </Menu> 614 + } 615 + /> 616 + </Tree> 617 + </> 618 + ); 619 + } 620 + 572 621 export function KitchenSink() { 622 + return ( 623 + <Flex 624 + direction="column" 625 + gap="10" 626 + style={[gray.bg, gray.text, styles.container]} 627 + > 628 + <TitleCard title="Tree"> 629 + <TreeExample /> 630 + </TitleCard> 631 + <MenuExample /> 632 + </Flex> 633 + ); 573 634 return ( 574 635 <Flex 575 636 direction="column"
+5 -3
apps/example/src/components/checkbox/index.tsx
··· 111 111 <Check size={16} /> 112 112 ) : null} 113 113 </div> 114 - <Flex direction="column" gap="1"> 115 - {children} 116 - </Flex> 114 + {children && ( 115 + <Flex direction="column" gap="1"> 116 + {children} 117 + </Flex> 118 + )} 117 119 </> 118 120 )} 119 121 </AriaCheckbox>
+20 -1
apps/example/src/components/combobox/index.tsx
··· 8 8 } from "react-aria-components"; 9 9 import * as stylex from "@stylexjs/stylex"; 10 10 import type { 11 + ListBoxProps, 11 12 ListBoxSectionProps, 12 13 ValidationResult, 13 14 } from "react-aria-components"; ··· 29 30 import { useInputStyles } from "../theme/useInputStyles"; 30 31 import { usePopoverStyles } from "../theme/usePopoverStyles"; 31 32 import { IconButton } from "../icon-button"; 33 + import { SmallBody } from "../typography"; 34 + import { spacing } from "../theme/spacing.stylex"; 32 35 33 36 const styles = stylex.create({ 34 37 matchWidth: { 35 38 width: "var(--trigger-width)", 36 39 }, 40 + emptyState: { 41 + display: "flex", 42 + justifyContent: "center", 43 + padding: spacing["4"], 44 + }, 37 45 }); 38 46 47 + function EmptyState() { 48 + return ( 49 + <div {...stylex.props(styles.emptyState)}> 50 + <SmallBody variant="secondary">No items found</SmallBody> 51 + </div> 52 + ); 53 + } 54 + 39 55 export interface ComboBoxProps<T extends object> 40 56 extends Omit<AriaComboBoxProps<T>, "children" | "style" | "className">, 41 57 Pick< ··· 44 60 | "shouldFlip" 45 61 | "shouldUpdatePosition" 46 62 | "placement" 47 - > { 63 + >, 64 + Pick<ListBoxProps<T>, "renderEmptyState"> { 48 65 style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 49 66 label?: string; 50 67 description?: string; ··· 72 89 placeholder = "Select an option", 73 90 prefix, 74 91 suffix, 92 + renderEmptyState, 75 93 ...props 76 94 }: ComboBoxProps<T>) { 77 95 const inputStyles = useInputStyles({ size }); ··· 106 124 <ListBox 107 125 items={items} 108 126 {...stylex.props(popoverStyles, styles.matchWidth)} 127 + renderEmptyState={renderEmptyState || EmptyState} 109 128 > 110 129 {children} 111 130 </ListBox>
+15 -98
apps/example/src/components/listbox/index.tsx
··· 11 11 import * as stylex from "@stylexjs/stylex"; 12 12 import { Check } from "lucide-react"; 13 13 import { spacing } from "../theme/spacing.stylex"; 14 - import { plum, slate } from "../theme/colors.stylex"; 15 - import { radius } from "../theme/radius.stylex"; 16 - import { 17 - fontSize, 18 - fontWeight, 19 - lineHeight, 20 - typeramp, 21 - } from "../theme/typography.stylex"; 14 + import { typeramp } from "../theme/typography.stylex"; 22 15 import { Size } from "../types"; 23 16 import { SizeContext } from "../context"; 24 17 import { use, useContext } from "react"; 25 18 import { Separator } from "../separator"; 26 19 import { gray } from "../theme/semantic-color.stylex"; 20 + import { useListBoxItemStyles } from "../theme/useListBoxItemStyles"; 27 21 28 22 const styles = stylex.create({ 29 23 listBox: { 30 24 outline: "none", 31 25 }, 32 - item: { 33 - display: "flex", 34 - userSelect: "none", 35 - 36 - boxSizing: "border-box", 37 - fontWeight: fontWeight["medium"], 38 - outline: { 39 - default: "none", 40 - ":focus": "none", 41 - }, 42 - padding: spacing["1"], 43 - }, 44 - sm: { 45 - minHeight: spacing["9"], 46 - }, 47 - md: { 48 - minHeight: spacing["9"], 49 - }, 50 - lg: { 51 - minHeight: spacing["11"], 52 - }, 53 - itemInner: { 54 - alignItems: "center", 55 - backgroundColor: { 56 - default: "transparent", 57 - [":is(:hover:not([data-disabled]) > *,[data-focused] > *)"]: slate[4], 58 - [":is(:active > *)"]: slate[5], 59 - }, 60 - borderRadius: radius["md"], 61 - boxSizing: "border-box", 62 - color: { 63 - default: slate[12], 64 - [":is([data-disabled] > *)"]: slate[8], 65 - }, 66 - display: "flex", 67 - flexGrow: 1, 68 - gap: spacing["2"], 69 - paddingBottom: spacing["2"], 70 - paddingLeft: spacing["2"], 71 - paddingRight: spacing["2"], 72 - paddingTop: spacing["2"], 73 - transitionDuration: "100ms", 74 - transitionProperty: "background-color", 75 - transitionTimingFunction: "ease-in-out", 76 - }, 77 - smItemInner: { 78 - fontSize: fontSize["xs"], 79 - lineHeight: lineHeight["xs"], 80 - paddingBottom: spacing["1"], 81 - paddingTop: spacing["1"], 82 - }, 83 - check: { 84 - color: plum[9], 85 - }, 86 - section: {}, 87 26 sectionLabel: { 88 27 alignItems: "center", 89 28 boxSizing: "border-box", ··· 106 45 marginBottom: spacing["1.5"], 107 46 marginTop: spacing["1.5"], 108 47 }, 109 - addon: { 110 - alignItems: "center", 111 - display: "flex", 112 - justifyContent: "center", 113 - minWidth: spacing["4"], 114 - 115 - // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 116 - ":is(*) svg": { 117 - color: slate[11], 118 - flexShrink: 0, 119 - height: spacing["4"], 120 - pointerEvents: "none", 121 - width: spacing["4"], 122 - }, 123 - }, 124 - label: { 125 - display: "flex", 126 - flexDirection: "column", 127 - flexGrow: 1, 128 - gap: spacing["1.5"], 129 - }, 130 48 }); 131 49 132 50 export interface ListBoxProps<T extends object> ··· 166 84 suffix, 167 85 ...props 168 86 }: ListBoxItemProps) { 169 - const size = useContext(SizeContext); 87 + const listBoxItemStyles = useListBoxItemStyles(); 170 88 171 89 return ( 172 90 <AriaListBoxItem ··· 175 93 textValue={ 176 94 props.textValue || (typeof children === "string" ? children : undefined) 177 95 } 178 - {...stylex.props(typeramp.label, styles.item, styles[size], style)} 96 + {...stylex.props(listBoxItemStyles.wrapper, style)} 179 97 > 180 98 {({ isSelected }) => ( 181 - <div 182 - {...stylex.props( 183 - styles.itemInner, 184 - size === "sm" && styles.smItemInner 99 + <div {...stylex.props(listBoxItemStyles.inner)}> 100 + {prefix && ( 101 + <div {...stylex.props(listBoxItemStyles.addon)}>{prefix}</div> 185 102 )} 186 - > 187 - {prefix && <div {...stylex.props(styles.addon)}>{prefix}</div>} 188 - <div {...stylex.props(styles.label)}>{children}</div> 189 - {suffix && <div {...stylex.props(styles.addon)}>{suffix}</div>} 190 - {isSelected && <Check size={16} {...stylex.props(styles.check)} />} 103 + <div {...stylex.props(listBoxItemStyles.label)}>{children}</div> 104 + {suffix && ( 105 + <div {...stylex.props(listBoxItemStyles.addon)}>{suffix}</div> 106 + )} 107 + {isSelected && ( 108 + <Check size={16} {...stylex.props(listBoxItemStyles.check)} /> 109 + )} 191 110 </div> 192 111 )} 193 112 </AriaListBoxItem> ··· 204 123 style, 205 124 ...props 206 125 }: ListBoxSectionProps<T>) { 207 - return ( 208 - <AriaListBoxSection {...props} {...stylex.props(styles.section, style)} /> 209 - ); 126 + return <AriaListBoxSection {...props} {...stylex.props(style)} />; 210 127 } 211 128 212 129 export interface ListBoxSeparatorProps
+16 -64
apps/example/src/components/menu/index.tsx
··· 13 13 PopoverProps, 14 14 } from "react-aria-components"; 15 15 import * as stylex from "@stylexjs/stylex"; 16 - import { spacing } from "../theme/spacing.stylex"; 17 - import { radius } from "../theme/radius.stylex"; 18 16 import { Size } from "../types"; 19 17 import { 20 18 ListBoxSectionHeaderProps, ··· 23 21 ListBoxSeparatorProps, 24 22 } from "../listbox"; 25 23 import { SizeContext } from "../context"; 26 - import { fontWeight, typeramp } from "../theme/typography.stylex"; 27 - import { useContext } from "react"; 28 24 import { Check, ChevronRight } from "lucide-react"; 29 - import { plum, slate } from "../theme/colors.stylex"; 30 25 import { usePopoverStyles } from "../theme/usePopoverStyles"; 31 - 32 - const styles = stylex.create({ 33 - section: {}, 34 - item: { 35 - display: "flex", 36 - userSelect: "none", 37 - 38 - boxSizing: "border-box", 39 - fontWeight: fontWeight["medium"], 40 - outline: { 41 - default: "none", 42 - ":focus": "none", 43 - }, 44 - padding: spacing["1"], 45 - }, 46 - sm: { 47 - height: spacing["9"], 48 - }, 49 - md: { 50 - height: spacing["9"], 51 - }, 52 - lg: { 53 - height: spacing["11"], 54 - }, 55 - itemInner: { 56 - alignItems: "center", 57 - backgroundColor: { 58 - default: "transparent", 59 - [":is(:hover > *)"]: slate[4], 60 - [":is(:active > *)"]: slate[5], 61 - }, 62 - borderRadius: radius["md"], 63 - boxSizing: "border-box", 64 - display: "flex", 65 - flexGrow: 1, 66 - gap: spacing["2"], 67 - justifyContent: "space-between", 68 - paddingLeft: spacing["2"], 69 - paddingRight: spacing["2"], 70 - transitionDuration: "100ms", 71 - transitionProperty: "background-color", 72 - transitionTimingFunction: "ease-in-out", 73 - }, 74 - check: { 75 - color: plum[9], 76 - }, 77 - }); 26 + import { useListBoxItemStyles } from "../theme/useListBoxItemStyles"; 78 27 79 28 export interface MenuProps<T extends object> 80 29 extends Omit<MenuTriggerProps, "trigger" | "children">, ··· 182 131 style, 183 132 ...props 184 133 }: MenuSectionProps<T>) { 185 - return ( 186 - <AriaMenuSection {...props} {...stylex.props(styles.section, style)} /> 187 - ); 134 + return <AriaMenuSection {...props} {...stylex.props(style)} />; 188 135 } 189 136 190 137 export interface MenuItemProps ··· 194 141 } 195 142 196 143 export function MenuItem({ style, children, ...props }: MenuItemProps) { 197 - const size = useContext(SizeContext); 144 + const menuItemStyles = useListBoxItemStyles(); 198 145 199 146 return ( 200 - <AriaMenuItem 201 - {...props} 202 - {...stylex.props(typeramp.label, styles.item, styles[size], style)} 203 - > 147 + <AriaMenuItem {...props} {...stylex.props(menuItemStyles.wrapper, style)}> 204 148 {({ isSelected, hasSubmenu }) => ( 205 - <div {...stylex.props(styles.itemInner)}> 206 - {children} 207 - {isSelected && <Check size={16} {...stylex.props(styles.check)} />} 208 - {hasSubmenu && <ChevronRight size={16} />} 149 + <div {...stylex.props(menuItemStyles.inner)}> 150 + <div {...stylex.props(menuItemStyles.label)}>{children}</div> 151 + {isSelected && ( 152 + <div {...stylex.props(menuItemStyles.addon)}> 153 + <Check size={16} {...stylex.props(menuItemStyles.check)} /> 154 + </div> 155 + )} 156 + {hasSubmenu && ( 157 + <div {...stylex.props(menuItemStyles.addon)}> 158 + <ChevronRight size={16} /> 159 + </div> 160 + )} 209 161 </div> 210 162 )} 211 163 </AriaMenuItem>
+102
apps/example/src/components/theme/useListBoxItemStyles.ts
··· 1 + import * as stylex from "@stylexjs/stylex"; 2 + import { spacing } from "../theme/spacing.stylex"; 3 + import { plum, slate } from "../theme/colors.stylex"; 4 + import { radius } from "../theme/radius.stylex"; 5 + import { 6 + fontSize, 7 + fontWeight, 8 + lineHeight, 9 + typeramp, 10 + } from "../theme/typography.stylex"; 11 + import { SizeContext } from "../context"; 12 + import { useContext } from "react"; 13 + 14 + const styles = stylex.create({ 15 + item: { 16 + display: "flex", 17 + userSelect: "none", 18 + 19 + boxSizing: "border-box", 20 + fontWeight: fontWeight["medium"], 21 + outline: { 22 + default: "none", 23 + ":focus": "none", 24 + }, 25 + paddingBottom: spacing["0.5"], 26 + paddingLeft: spacing["1"], 27 + paddingRight: spacing["1"], 28 + paddingTop: spacing["0.5"], 29 + }, 30 + sm: { minHeight: spacing["7"] }, 31 + md: { minHeight: spacing["9"] }, 32 + lg: { minHeight: spacing["12"] }, 33 + itemInner: { 34 + alignItems: "center", 35 + backgroundColor: { 36 + default: "transparent", 37 + [":is([data-react-aria-pressable=true][data-focused] *)"]: slate[4], 38 + [":is([data-react-aria-pressable=true][data-selected=true] *)"]: slate[4], 39 + [":is([data-react-aria-pressable=true]:hover:not([data-disabled]) *)"]: 40 + slate[4], 41 + [":is([data-react-aria-pressable=true]:not([data-disabled]):active *)"]: 42 + slate[5], 43 + }, 44 + borderRadius: radius["md"], 45 + boxSizing: "border-box", 46 + color: { 47 + default: slate[12], 48 + [":is([data-react-aria-pressable=true][data-disabled] *)"]: slate[8], 49 + }, 50 + display: "flex", 51 + flexGrow: 1, 52 + gap: spacing["2"], 53 + paddingBottom: spacing["2"], 54 + paddingLeft: spacing["2"], 55 + paddingRight: spacing["2"], 56 + paddingTop: spacing["2"], 57 + transitionDuration: "100ms", 58 + transitionProperty: "background-color", 59 + transitionTimingFunction: "ease-in-out", 60 + }, 61 + smItemInner: { 62 + fontSize: fontSize["xs"], 63 + lineHeight: lineHeight["xs"], 64 + paddingBottom: spacing["1"], 65 + paddingTop: spacing["1"], 66 + }, 67 + check: { 68 + color: plum[9], 69 + }, 70 + addon: { 71 + alignItems: "center", 72 + display: "flex", 73 + justifyContent: "center", 74 + minWidth: spacing["4"], 75 + 76 + // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 77 + ":is(*) svg": { 78 + flexShrink: 0, 79 + height: spacing["4"], 80 + pointerEvents: "none", 81 + width: spacing["4"], 82 + }, 83 + }, 84 + label: { 85 + display: "flex", 86 + flexDirection: "column", 87 + flexGrow: 1, 88 + gap: spacing["1.5"], 89 + }, 90 + }); 91 + 92 + export function useListBoxItemStyles() { 93 + const size = useContext(SizeContext); 94 + 95 + return { 96 + wrapper: [typeramp.label, styles.item, styles[size]], 97 + inner: [styles.itemInner, size === "sm" && styles.smItemInner], 98 + label: styles.label, 99 + addon: styles.addon, 100 + check: styles.check, 101 + }; 102 + }
+199
apps/example/src/components/tree/index.tsx
··· 1 + import { ChevronRight, GripVertical } from "lucide-react"; 2 + import { 3 + Button, 4 + Tree as AriaTree, 5 + TreeProps as AriaTreeProps, 6 + TreeItemContent as AriaTreeItemContent, 7 + TreeItem as AriaTreeItem, 8 + TreeItemProps as AriaTreeItemProps, 9 + TreeItemContentProps as AriaTreeItemContentProps, 10 + } from "react-aria-components"; 11 + import { Checkbox } from "../checkbox"; 12 + import * as stylex from "@stylexjs/stylex"; 13 + import { Size } from "../types"; 14 + import { SizeContext } from "../context"; 15 + import { useListBoxItemStyles } from "../theme/useListBoxItemStyles"; 16 + import { spacing } from "../theme/spacing.stylex"; 17 + import { gray } from "../theme/semantic-color.stylex"; 18 + import { radius } from "../theme/radius.stylex"; 19 + 20 + const styles = stylex.create({ 21 + wrapper: { 22 + position: "relative", 23 + }, 24 + itemInner: { 25 + gap: spacing["1"], 26 + }, 27 + spacer: { 28 + width: `calc((var(--tree-item-level, 0) - 1) * ${spacing["4"]})`, 29 + }, 30 + content: { 31 + alignItems: "center", 32 + display: "flex", 33 + flexGrow: 1, 34 + gap: spacing["2"], 35 + }, 36 + hidden: { 37 + opacity: 0, 38 + visibility: "hidden", 39 + }, 40 + chevron: { 41 + backgroundColor: "transparent", 42 + borderWidth: 0, 43 + paddingBottom: 0, 44 + paddingLeft: 0, 45 + paddingRight: 0, 46 + paddingTop: 0, 47 + transform: { 48 + default: "rotate(0deg)", 49 + ":is([aria-expanded=true] *)": "rotate(90deg)", 50 + }, 51 + }, 52 + addon: { 53 + marginBottom: `calc(${spacing["2"]} * -1)`, 54 + marginTop: `calc(${spacing["2"]} * -1)`, 55 + }, 56 + dragButtonWrapper: { 57 + opacity: { 58 + default: 0, 59 + ":hover": 1, 60 + ":is([data-react-aria-pressable=true]:hover:not([data-disabled]) *)": 1, 61 + }, 62 + transitionDuration: "100ms", 63 + transitionProperty: "opacity", 64 + transitionTimingFunction: "ease-in-out", 65 + position: "absolute", 66 + top: "50%", 67 + left: 0, 68 + transform: "translate(-100%, -50%)", 69 + }, 70 + dragButton: { 71 + borderRadius: radius["sm"], 72 + display: "flex", 73 + justifyContent: "center", 74 + alignItems: "center", 75 + 76 + height: spacing["8"], 77 + width: spacing["8"], 78 + }, 79 + }); 80 + 81 + interface TreeItemContentProps 82 + extends Omit<AriaTreeItemContentProps, "children"> { 83 + children?: React.ReactNode; 84 + prefix?: React.ReactNode; 85 + suffix?: React.ReactNode; 86 + } 87 + 88 + function TreeItemContent({ children, prefix, suffix }: TreeItemContentProps) { 89 + const listBoxItemStyles = useListBoxItemStyles(); 90 + 91 + return ( 92 + <AriaTreeItemContent> 93 + {({ 94 + hasChildItems, 95 + selectionBehavior, 96 + selectionMode, 97 + allowsDragging, 98 + }) => ( 99 + <div {...stylex.props(listBoxItemStyles.inner, styles.itemInner)}> 100 + {allowsDragging && ( 101 + <div {...stylex.props(styles.dragButtonWrapper)}> 102 + <Button 103 + slot="drag" 104 + {...stylex.props(styles.dragButton, gray.border, gray.bgSubtle)} 105 + > 106 + <GripVertical size={18} /> 107 + </Button> 108 + </div> 109 + )} 110 + {selectionBehavior === "toggle" && selectionMode !== "none" && ( 111 + <Checkbox slot="selection" /> 112 + )} 113 + <div {...stylex.props(styles.spacer)} /> 114 + <Button 115 + slot="chevron" 116 + {...stylex.props( 117 + styles.chevron, 118 + gray.textDim, 119 + listBoxItemStyles.addon, 120 + !hasChildItems && styles.hidden 121 + )} 122 + > 123 + <ChevronRight size={16} /> 124 + </Button> 125 + 126 + <div {...stylex.props(styles.content)}> 127 + {prefix && ( 128 + <div {...stylex.props(listBoxItemStyles.addon, styles.addon)}> 129 + {prefix} 130 + </div> 131 + )} 132 + <div {...stylex.props(listBoxItemStyles.label)}>{children}</div> 133 + {suffix && ( 134 + <div {...stylex.props(listBoxItemStyles.addon, styles.addon)}> 135 + {suffix} 136 + </div> 137 + )} 138 + </div> 139 + </div> 140 + )} 141 + </AriaTreeItemContent> 142 + ); 143 + } 144 + 145 + interface TreeItemProps<T extends object> 146 + extends Omit<AriaTreeItemProps<T>, "style" | "textValue" | "children">, 147 + Pick<TreeItemContentProps, "prefix" | "suffix"> { 148 + style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 149 + title: string; 150 + children?: React.ReactNode; 151 + } 152 + 153 + export function TreeItem<T extends object>({ 154 + style, 155 + title, 156 + prefix, 157 + suffix, 158 + ...props 159 + }: TreeItemProps<T>) { 160 + const listBoxItemStyles = useListBoxItemStyles(); 161 + 162 + return ( 163 + <AriaTreeItem 164 + textValue={title} 165 + {...props} 166 + data-react-aria-pressable 167 + {...stylex.props( 168 + listBoxItemStyles.wrapper, 169 + styles.wrapper, 170 + styles.itemInner, 171 + style 172 + )} 173 + > 174 + <TreeItemContent prefix={prefix} suffix={suffix}> 175 + {title} 176 + </TreeItemContent> 177 + {props.children} 178 + </AriaTreeItem> 179 + ); 180 + } 181 + 182 + export interface TreeProps<T extends object> 183 + extends Omit<AriaTreeProps<T>, "children" | "style"> { 184 + style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 185 + children: React.ReactNode | ((item: T) => React.ReactNode); 186 + size?: Size; 187 + } 188 + 189 + export function Tree<T extends object>({ 190 + style, 191 + size = "md", 192 + ...props 193 + }: TreeProps<T>) { 194 + return ( 195 + <SizeContext.Provider value={size}> 196 + <AriaTree {...props} {...stylex.props(style)} /> 197 + </SizeContext.Provider> 198 + ); 199 + }
+2
packages/hip-ui/src/cli/install.tsx
··· 36 36 import { colorFieldConfig } from "../components/color-field/color-field-config.js"; 37 37 import { numberFieldConfig } from "../components/number-field/number-field-config.js"; 38 38 import { comboboxConfig } from "../components/combobox/combobox-config.js"; 39 + import { treeConfig } from "../components/tree/tree-config.js"; 39 40 40 41 const __dirname = path.dirname(new URL(import.meta.url).pathname); 41 42 ··· 67 68 colorFieldConfig, 68 69 numberFieldConfig, 69 70 comboboxConfig, 71 + treeConfig, 70 72 ]; 71 73 72 74 function StringSetting({
+5 -3
packages/hip-ui/src/components/checkbox/index.tsx
··· 111 111 <Check size={16} /> 112 112 ) : null} 113 113 </div> 114 - <Flex direction="column" gap="1"> 115 - {children} 116 - </Flex> 114 + {children && ( 115 + <Flex direction="column" gap="1"> 116 + {children} 117 + </Flex> 118 + )} 117 119 </> 118 120 )} 119 121 </AriaCheckbox>
+15 -98
packages/hip-ui/src/components/listbox/index.tsx
··· 11 11 import * as stylex from "@stylexjs/stylex"; 12 12 import { Check } from "lucide-react"; 13 13 import { spacing } from "../theme/spacing.stylex"; 14 - import { plum, slate } from "../theme/colors.stylex"; 15 - import { radius } from "../theme/radius.stylex"; 16 - import { 17 - fontSize, 18 - fontWeight, 19 - lineHeight, 20 - typeramp, 21 - } from "../theme/typography.stylex"; 14 + import { typeramp } from "../theme/typography.stylex"; 22 15 import { Size } from "../types"; 23 16 import { SizeContext } from "../context"; 24 17 import { use, useContext } from "react"; 25 18 import { Separator } from "../separator"; 26 19 import { gray } from "../theme/semantic-color.stylex"; 20 + import { useListBoxItemStyles } from "../theme/useListBoxItemStyles"; 27 21 28 22 const styles = stylex.create({ 29 23 listBox: { 30 24 outline: "none", 31 25 }, 32 - item: { 33 - display: "flex", 34 - userSelect: "none", 35 - 36 - boxSizing: "border-box", 37 - fontWeight: fontWeight["medium"], 38 - outline: { 39 - default: "none", 40 - ":focus": "none", 41 - }, 42 - padding: spacing["1"], 43 - }, 44 - sm: { 45 - minHeight: spacing["9"], 46 - }, 47 - md: { 48 - minHeight: spacing["9"], 49 - }, 50 - lg: { 51 - minHeight: spacing["11"], 52 - }, 53 - itemInner: { 54 - alignItems: "center", 55 - backgroundColor: { 56 - default: "transparent", 57 - [":is(:hover:not([data-disabled]) > *,[data-focused] > *)"]: slate[4], 58 - [":is(:active > *)"]: slate[5], 59 - }, 60 - borderRadius: radius["md"], 61 - boxSizing: "border-box", 62 - color: { 63 - default: slate[12], 64 - [":is([data-disabled] > *)"]: slate[8], 65 - }, 66 - display: "flex", 67 - flexGrow: 1, 68 - gap: spacing["2"], 69 - paddingBottom: spacing["2"], 70 - paddingLeft: spacing["2"], 71 - paddingRight: spacing["2"], 72 - paddingTop: spacing["2"], 73 - transitionDuration: "100ms", 74 - transitionProperty: "background-color", 75 - transitionTimingFunction: "ease-in-out", 76 - }, 77 - smItemInner: { 78 - fontSize: fontSize["xs"], 79 - lineHeight: lineHeight["xs"], 80 - paddingBottom: spacing["1"], 81 - paddingTop: spacing["1"], 82 - }, 83 - check: { 84 - color: plum[9], 85 - }, 86 - section: {}, 87 26 sectionLabel: { 88 27 alignItems: "center", 89 28 boxSizing: "border-box", ··· 106 45 marginBottom: spacing["1.5"], 107 46 marginTop: spacing["1.5"], 108 47 }, 109 - addon: { 110 - alignItems: "center", 111 - display: "flex", 112 - justifyContent: "center", 113 - minWidth: spacing["4"], 114 - 115 - // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 116 - ":is(*) svg": { 117 - color: slate[11], 118 - flexShrink: 0, 119 - height: spacing["4"], 120 - pointerEvents: "none", 121 - width: spacing["4"], 122 - }, 123 - }, 124 - label: { 125 - display: "flex", 126 - flexDirection: "column", 127 - flexGrow: 1, 128 - gap: spacing["1.5"], 129 - }, 130 48 }); 131 49 132 50 export interface ListBoxProps<T extends object> ··· 166 84 suffix, 167 85 ...props 168 86 }: ListBoxItemProps) { 169 - const size = useContext(SizeContext); 87 + const listBoxItemStyles = useListBoxItemStyles(); 170 88 171 89 return ( 172 90 <AriaListBoxItem ··· 175 93 textValue={ 176 94 props.textValue || (typeof children === "string" ? children : undefined) 177 95 } 178 - {...stylex.props(typeramp.label, styles.item, styles[size], style)} 96 + {...stylex.props(listBoxItemStyles.wrapper, style)} 179 97 > 180 98 {({ isSelected }) => ( 181 - <div 182 - {...stylex.props( 183 - styles.itemInner, 184 - size === "sm" && styles.smItemInner 99 + <div {...stylex.props(listBoxItemStyles.inner)}> 100 + {prefix && ( 101 + <div {...stylex.props(listBoxItemStyles.addon)}>{prefix}</div> 185 102 )} 186 - > 187 - {prefix && <div {...stylex.props(styles.addon)}>{prefix}</div>} 188 - <div {...stylex.props(styles.label)}>{children}</div> 189 - {suffix && <div {...stylex.props(styles.addon)}>{suffix}</div>} 190 - {isSelected && <Check size={16} {...stylex.props(styles.check)} />} 103 + <div {...stylex.props(listBoxItemStyles.label)}>{children}</div> 104 + {suffix && ( 105 + <div {...stylex.props(listBoxItemStyles.addon)}>{suffix}</div> 106 + )} 107 + {isSelected && ( 108 + <Check size={16} {...stylex.props(listBoxItemStyles.check)} /> 109 + )} 191 110 </div> 192 111 )} 193 112 </AriaListBoxItem> ··· 204 123 style, 205 124 ...props 206 125 }: ListBoxSectionProps<T>) { 207 - return ( 208 - <AriaListBoxSection {...props} {...stylex.props(styles.section, style)} /> 209 - ); 126 + return <AriaListBoxSection {...props} {...stylex.props(style)} />; 210 127 } 211 128 212 129 export interface ListBoxSeparatorProps
+16 -64
packages/hip-ui/src/components/menu/index.tsx
··· 13 13 PopoverProps, 14 14 } from "react-aria-components"; 15 15 import * as stylex from "@stylexjs/stylex"; 16 - import { spacing } from "../theme/spacing.stylex"; 17 - import { radius } from "../theme/radius.stylex"; 18 16 import { Size } from "../types"; 19 17 import { 20 18 ListBoxSectionHeaderProps, ··· 23 21 ListBoxSeparatorProps, 24 22 } from "../listbox"; 25 23 import { SizeContext } from "../context"; 26 - import { fontWeight, typeramp } from "../theme/typography.stylex"; 27 - import { useContext } from "react"; 28 24 import { Check, ChevronRight } from "lucide-react"; 29 - import { plum, slate } from "../theme/colors.stylex"; 30 25 import { usePopoverStyles } from "../theme/usePopoverStyles"; 31 - 32 - const styles = stylex.create({ 33 - section: {}, 34 - item: { 35 - display: "flex", 36 - userSelect: "none", 37 - 38 - boxSizing: "border-box", 39 - fontWeight: fontWeight["medium"], 40 - outline: { 41 - default: "none", 42 - ":focus": "none", 43 - }, 44 - padding: spacing["1"], 45 - }, 46 - sm: { 47 - height: spacing["9"], 48 - }, 49 - md: { 50 - height: spacing["9"], 51 - }, 52 - lg: { 53 - height: spacing["11"], 54 - }, 55 - itemInner: { 56 - alignItems: "center", 57 - backgroundColor: { 58 - default: "transparent", 59 - [":is(:hover > *)"]: slate[4], 60 - [":is(:active > *)"]: slate[5], 61 - }, 62 - borderRadius: radius["md"], 63 - boxSizing: "border-box", 64 - display: "flex", 65 - flexGrow: 1, 66 - gap: spacing["2"], 67 - justifyContent: "space-between", 68 - paddingLeft: spacing["2"], 69 - paddingRight: spacing["2"], 70 - transitionDuration: "100ms", 71 - transitionProperty: "background-color", 72 - transitionTimingFunction: "ease-in-out", 73 - }, 74 - check: { 75 - color: plum[9], 76 - }, 77 - }); 26 + import { useListBoxItemStyles } from "../theme/useListBoxItemStyles"; 78 27 79 28 export interface MenuProps<T extends object> 80 29 extends Omit<MenuTriggerProps, "trigger" | "children">, ··· 182 131 style, 183 132 ...props 184 133 }: MenuSectionProps<T>) { 185 - return ( 186 - <AriaMenuSection {...props} {...stylex.props(styles.section, style)} /> 187 - ); 134 + return <AriaMenuSection {...props} {...stylex.props(style)} />; 188 135 } 189 136 190 137 export interface MenuItemProps ··· 194 141 } 195 142 196 143 export function MenuItem({ style, children, ...props }: MenuItemProps) { 197 - const size = useContext(SizeContext); 144 + const menuItemStyles = useListBoxItemStyles(); 198 145 199 146 return ( 200 - <AriaMenuItem 201 - {...props} 202 - {...stylex.props(typeramp.label, styles.item, styles[size], style)} 203 - > 147 + <AriaMenuItem {...props} {...stylex.props(menuItemStyles.wrapper, style)}> 204 148 {({ isSelected, hasSubmenu }) => ( 205 - <div {...stylex.props(styles.itemInner)}> 206 - {children} 207 - {isSelected && <Check size={16} {...stylex.props(styles.check)} />} 208 - {hasSubmenu && <ChevronRight size={16} />} 149 + <div {...stylex.props(menuItemStyles.inner)}> 150 + <div {...stylex.props(menuItemStyles.label)}>{children}</div> 151 + {isSelected && ( 152 + <div {...stylex.props(menuItemStyles.addon)}> 153 + <Check size={16} {...stylex.props(menuItemStyles.check)} /> 154 + </div> 155 + )} 156 + {hasSubmenu && ( 157 + <div {...stylex.props(menuItemStyles.addon)}> 158 + <ChevronRight size={16} /> 159 + </div> 160 + )} 209 161 </div> 210 162 )} 211 163 </AriaMenuItem>
+5
packages/hip-ui/src/components/menu/menu-config.ts
··· 3 3 export const menuConfig: ComponentConfig = { 4 4 name: "menu", 5 5 filepath: "./index.tsx", 6 + hipDependencies: [ 7 + "../context.ts", 8 + "../theme/usePopoverStyles.ts", 9 + "../theme/useListBoxItemStyles.ts", 10 + ], 6 11 };
+102
packages/hip-ui/src/components/theme/useListBoxItemStyles.ts
··· 1 + import * as stylex from "@stylexjs/stylex"; 2 + import { spacing } from "../theme/spacing.stylex"; 3 + import { plum, slate } from "../theme/colors.stylex"; 4 + import { radius } from "../theme/radius.stylex"; 5 + import { 6 + fontSize, 7 + fontWeight, 8 + lineHeight, 9 + typeramp, 10 + } from "../theme/typography.stylex"; 11 + import { SizeContext } from "../context"; 12 + import { useContext } from "react"; 13 + 14 + const styles = stylex.create({ 15 + item: { 16 + display: "flex", 17 + userSelect: "none", 18 + 19 + boxSizing: "border-box", 20 + fontWeight: fontWeight["medium"], 21 + outline: { 22 + default: "none", 23 + ":focus": "none", 24 + }, 25 + paddingBottom: spacing["0.5"], 26 + paddingLeft: spacing["1"], 27 + paddingRight: spacing["1"], 28 + paddingTop: spacing["0.5"], 29 + }, 30 + sm: { minHeight: spacing["7"] }, 31 + md: { minHeight: spacing["9"] }, 32 + lg: { minHeight: spacing["12"] }, 33 + itemInner: { 34 + alignItems: "center", 35 + backgroundColor: { 36 + default: "transparent", 37 + [":is([data-react-aria-pressable=true][data-focused] *)"]: slate[4], 38 + [":is([data-react-aria-pressable=true][data-selected=true] *)"]: slate[4], 39 + [":is([data-react-aria-pressable=true]:hover:not([data-disabled]) *)"]: 40 + slate[4], 41 + [":is([data-react-aria-pressable=true]:not([data-disabled]):active *)"]: 42 + slate[5], 43 + }, 44 + borderRadius: radius["md"], 45 + boxSizing: "border-box", 46 + color: { 47 + default: slate[12], 48 + [":is([data-react-aria-pressable=true][data-disabled] *)"]: slate[8], 49 + }, 50 + display: "flex", 51 + flexGrow: 1, 52 + gap: spacing["2"], 53 + paddingBottom: spacing["2"], 54 + paddingLeft: spacing["2"], 55 + paddingRight: spacing["2"], 56 + paddingTop: spacing["2"], 57 + transitionDuration: "100ms", 58 + transitionProperty: "background-color", 59 + transitionTimingFunction: "ease-in-out", 60 + }, 61 + smItemInner: { 62 + fontSize: fontSize["xs"], 63 + lineHeight: lineHeight["xs"], 64 + paddingBottom: spacing["1"], 65 + paddingTop: spacing["1"], 66 + }, 67 + check: { 68 + color: plum[9], 69 + }, 70 + addon: { 71 + alignItems: "center", 72 + display: "flex", 73 + justifyContent: "center", 74 + minWidth: spacing["4"], 75 + 76 + // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 77 + ":is(*) svg": { 78 + flexShrink: 0, 79 + height: spacing["4"], 80 + pointerEvents: "none", 81 + width: spacing["4"], 82 + }, 83 + }, 84 + label: { 85 + display: "flex", 86 + flexDirection: "column", 87 + flexGrow: 1, 88 + gap: spacing["1.5"], 89 + }, 90 + }); 91 + 92 + export function useListBoxItemStyles() { 93 + const size = useContext(SizeContext); 94 + 95 + return { 96 + wrapper: [typeramp.label, styles.item, styles[size]], 97 + inner: [styles.itemInner, size === "sm" && styles.smItemInner], 98 + label: styles.label, 99 + addon: styles.addon, 100 + check: styles.check, 101 + }; 102 + }
+199
packages/hip-ui/src/components/tree/index.tsx
··· 1 + import { ChevronRight, GripVertical } from "lucide-react"; 2 + import { 3 + Button, 4 + Tree as AriaTree, 5 + TreeProps as AriaTreeProps, 6 + TreeItemContent as AriaTreeItemContent, 7 + TreeItem as AriaTreeItem, 8 + TreeItemProps as AriaTreeItemProps, 9 + TreeItemContentProps as AriaTreeItemContentProps, 10 + } from "react-aria-components"; 11 + import { Checkbox } from "../checkbox"; 12 + import * as stylex from "@stylexjs/stylex"; 13 + import { Size } from "../types"; 14 + import { SizeContext } from "../context"; 15 + import { useListBoxItemStyles } from "../theme/useListBoxItemStyles"; 16 + import { spacing } from "../theme/spacing.stylex"; 17 + import { gray } from "../theme/semantic-color.stylex"; 18 + import { radius } from "../theme/radius.stylex"; 19 + 20 + const styles = stylex.create({ 21 + wrapper: { 22 + position: "relative", 23 + }, 24 + itemInner: { 25 + gap: spacing["1"], 26 + }, 27 + spacer: { 28 + width: `calc((var(--tree-item-level, 0) - 1) * ${spacing["4"]})`, 29 + }, 30 + content: { 31 + alignItems: "center", 32 + display: "flex", 33 + flexGrow: 1, 34 + gap: spacing["2"], 35 + }, 36 + hidden: { 37 + opacity: 0, 38 + visibility: "hidden", 39 + }, 40 + chevron: { 41 + backgroundColor: "transparent", 42 + borderWidth: 0, 43 + paddingBottom: 0, 44 + paddingLeft: 0, 45 + paddingRight: 0, 46 + paddingTop: 0, 47 + transform: { 48 + default: "rotate(0deg)", 49 + ":is([aria-expanded=true] *)": "rotate(90deg)", 50 + }, 51 + }, 52 + addon: { 53 + marginBottom: `calc(${spacing["2"]} * -1)`, 54 + marginTop: `calc(${spacing["2"]} * -1)`, 55 + }, 56 + dragButtonWrapper: { 57 + opacity: { 58 + default: 0, 59 + ":hover": 1, 60 + ":is([data-react-aria-pressable=true]:hover:not([data-disabled]) *)": 1, 61 + }, 62 + transitionDuration: "100ms", 63 + transitionProperty: "opacity", 64 + position: "absolute", 65 + transitionTimingFunction: "ease-in-out", 66 + left: 0, 67 + top: "50%", 68 + transform: "translate(-100%, -50%)", 69 + }, 70 + dragButton: { 71 + borderRadius: radius["sm"], 72 + display: "flex", 73 + alignItems: "center", 74 + justifyContent: "center", 75 + 76 + height: spacing["8"], 77 + width: spacing["8"], 78 + }, 79 + }); 80 + 81 + interface TreeItemContentProps 82 + extends Omit<AriaTreeItemContentProps, "children"> { 83 + children?: React.ReactNode; 84 + prefix?: React.ReactNode; 85 + suffix?: React.ReactNode; 86 + } 87 + 88 + function TreeItemContent({ children, prefix, suffix }: TreeItemContentProps) { 89 + const listBoxItemStyles = useListBoxItemStyles(); 90 + 91 + return ( 92 + <AriaTreeItemContent> 93 + {({ 94 + hasChildItems, 95 + selectionBehavior, 96 + selectionMode, 97 + allowsDragging, 98 + }) => ( 99 + <div {...stylex.props(listBoxItemStyles.inner, styles.itemInner)}> 100 + {allowsDragging && ( 101 + <div {...stylex.props(styles.dragButtonWrapper)}> 102 + <Button 103 + slot="drag" 104 + {...stylex.props(styles.dragButton, gray.border, gray.bgSubtle)} 105 + > 106 + <GripVertical size={18} /> 107 + </Button> 108 + </div> 109 + )} 110 + {selectionBehavior === "toggle" && selectionMode !== "none" && ( 111 + <Checkbox slot="selection" /> 112 + )} 113 + <div {...stylex.props(styles.spacer)} /> 114 + <Button 115 + slot="chevron" 116 + {...stylex.props( 117 + styles.chevron, 118 + gray.textDim, 119 + listBoxItemStyles.addon, 120 + !hasChildItems && styles.hidden 121 + )} 122 + > 123 + <ChevronRight size={16} /> 124 + </Button> 125 + 126 + <div {...stylex.props(styles.content)}> 127 + {prefix && ( 128 + <div {...stylex.props(listBoxItemStyles.addon, styles.addon)}> 129 + {prefix} 130 + </div> 131 + )} 132 + <div {...stylex.props(listBoxItemStyles.label)}>{children}</div> 133 + {suffix && ( 134 + <div {...stylex.props(listBoxItemStyles.addon, styles.addon)}> 135 + {suffix} 136 + </div> 137 + )} 138 + </div> 139 + </div> 140 + )} 141 + </AriaTreeItemContent> 142 + ); 143 + } 144 + 145 + interface TreeItemProps<T extends object> 146 + extends Omit<AriaTreeItemProps<T>, "style" | "textValue" | "children">, 147 + Pick<TreeItemContentProps, "prefix" | "suffix"> { 148 + style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 149 + title: string; 150 + children?: React.ReactNode; 151 + } 152 + 153 + export function TreeItem<T extends object>({ 154 + style, 155 + title, 156 + prefix, 157 + suffix, 158 + ...props 159 + }: TreeItemProps<T>) { 160 + const listBoxItemStyles = useListBoxItemStyles(); 161 + 162 + return ( 163 + <AriaTreeItem 164 + textValue={title} 165 + {...props} 166 + data-react-aria-pressable 167 + {...stylex.props( 168 + listBoxItemStyles.wrapper, 169 + styles.wrapper, 170 + styles.itemInner, 171 + style 172 + )} 173 + > 174 + <TreeItemContent prefix={prefix} suffix={suffix}> 175 + {title} 176 + </TreeItemContent> 177 + {props.children} 178 + </AriaTreeItem> 179 + ); 180 + } 181 + 182 + export interface TreeProps<T extends object> 183 + extends Omit<AriaTreeProps<T>, "children" | "style"> { 184 + style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 185 + children: React.ReactNode | ((item: T) => React.ReactNode); 186 + size?: Size; 187 + } 188 + 189 + export function Tree<T extends object>({ 190 + style, 191 + size = "md", 192 + ...props 193 + }: TreeProps<T>) { 194 + return ( 195 + <SizeContext.Provider value={size}> 196 + <AriaTree {...props} {...stylex.props(style)} /> 197 + </SizeContext.Provider> 198 + ); 199 + }
+19
packages/hip-ui/src/components/tree/tree-config.ts
··· 1 + import { ComponentConfig } from "../../types"; 2 + 3 + export const treeConfig: ComponentConfig = { 4 + name: "tree", 5 + filepath: "./index.tsx", 6 + hipDependencies: [ 7 + "../theme/spacing.stylex.tsx", 8 + "../theme/colors.stylex.tsx", 9 + "../theme/radius.stylex.tsx", 10 + "../theme/semantic-color.stylex.tsx", 11 + "../theme/typography.stylex.tsx", 12 + "../theme/breakpoints.stylex.tsx", 13 + "../theme/shadow.stylex.tsx", 14 + "../theme/useInputStyles.ts", 15 + ], 16 + dependencies: { 17 + "lucide-react": "^0.545.0", 18 + }, 19 + };