@chassis-ui/react 0.0.0-20260831090525
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +65 -0
- package/dist/index.d.ts +5909 -0
- package/dist/index.js +2 -0
- package/dist/style.css +1 -0
- package/package.json +114 -0
- package/src/components/accordion/Accordion.tsx +190 -0
- package/src/components/accordion/AccordionBody.tsx +46 -0
- package/src/components/accordion/AccordionHeader.tsx +21 -0
- package/src/components/accordion/AccordionItem.tsx +59 -0
- package/src/components/accordion/context.ts +8 -0
- package/src/components/accordion/index.ts +8 -0
- package/src/components/autocomplete/Autocomplete.tsx +464 -0
- package/src/components/autocomplete/AutocompleteGroup.tsx +20 -0
- package/src/components/autocomplete/AutocompleteItem.tsx +18 -0
- package/src/components/autocomplete/index.ts +6 -0
- package/src/components/avatar/Avatar.tsx +134 -0
- package/src/components/avatar/AvatarImage.tsx +19 -0
- package/src/components/avatar/AvatarStack.tsx +98 -0
- package/src/components/avatar/index.ts +6 -0
- package/src/components/badge/Badge.tsx +94 -0
- package/src/components/badge/index.ts +2 -0
- package/src/components/breadcrumb/Breadcrumb.tsx +59 -0
- package/src/components/breadcrumb/BreadcrumbItem.tsx +38 -0
- package/src/components/breadcrumb/index.ts +4 -0
- package/src/components/button/Button.tsx +229 -0
- package/src/components/button/index.ts +2 -0
- package/src/components/button-group/ButtonGroup.tsx +55 -0
- package/src/components/button-group/ButtonToolbar.tsx +47 -0
- package/src/components/button-group/index.ts +4 -0
- package/src/components/calendar/Calendar.scss +57 -0
- package/src/components/calendar/Calendar.tsx +324 -0
- package/src/components/calendar/CalendarMonthBlock.tsx +57 -0
- package/src/components/calendar/CalendarMonthGrid.tsx +92 -0
- package/src/components/calendar/CalendarMonthYearPicker.tsx +162 -0
- package/src/components/calendar/CalendarNavButton.tsx +24 -0
- package/src/components/calendar/CalendarWeekGrid.tsx +58 -0
- package/src/components/calendar/CalendarYearGrid.tsx +126 -0
- package/src/components/calendar/RangeCalendar.scss +95 -0
- package/src/components/calendar/RangeCalendar.tsx +361 -0
- package/src/components/calendar/index.ts +5 -0
- package/src/components/card/Card.tsx +173 -0
- package/src/components/card/CardBody.tsx +75 -0
- package/src/components/card/CardFooter.tsx +47 -0
- package/src/components/card/CardGroup.tsx +51 -0
- package/src/components/card/CardHeader.tsx +47 -0
- package/src/components/card/CardImage.tsx +70 -0
- package/src/components/card/CardImageOverlay.tsx +47 -0
- package/src/components/card/CardLink.tsx +40 -0
- package/src/components/card/CardSubtitle.tsx +47 -0
- package/src/components/card/CardText.tsx +47 -0
- package/src/components/card/CardTitle.tsx +47 -0
- package/src/components/card/index.ts +22 -0
- package/src/components/carousel/Carousel.tsx +742 -0
- package/src/components/carousel/CarouselControlButton.tsx +74 -0
- package/src/components/carousel/CarouselControlNext.tsx +22 -0
- package/src/components/carousel/CarouselControlPrev.tsx +22 -0
- package/src/components/carousel/CarouselIndicators.tsx +44 -0
- package/src/components/carousel/CarouselInner.tsx +56 -0
- package/src/components/carousel/CarouselItem.tsx +51 -0
- package/src/components/carousel/CarouselOverlay.tsx +51 -0
- package/src/components/carousel/CarouselPlayPause.tsx +61 -0
- package/src/components/carousel/carouselEngine.ts +170 -0
- package/src/components/carousel/context.ts +29 -0
- package/src/components/carousel/index.ts +21 -0
- package/src/components/checkbox/Checkbox.tsx +236 -0
- package/src/components/checkbox/CheckboxGroup.tsx +145 -0
- package/src/components/checkbox/context.ts +14 -0
- package/src/components/checkbox/index.ts +4 -0
- package/src/components/chip/Chip.tsx +183 -0
- package/src/components/chip/index.ts +2 -0
- package/src/components/chip-input/ChipInput.tsx +363 -0
- package/src/components/chip-input/ChipList.tsx +95 -0
- package/src/components/chip-input/index.ts +2 -0
- package/src/components/close-button/CloseButton.tsx +205 -0
- package/src/components/close-button/index.ts +2 -0
- package/src/components/collapse/Collapse.tsx +128 -0
- package/src/components/collapse/index.ts +2 -0
- package/src/components/color-input/ColorInput.tsx +106 -0
- package/src/components/color-input/index.ts +2 -0
- package/src/components/combobox/Combobox.tsx +320 -0
- package/src/components/combobox/ComboboxGroup.tsx +27 -0
- package/src/components/combobox/ComboboxItem.tsx +44 -0
- package/src/components/combobox/ComboboxListBox.tsx +98 -0
- package/src/components/combobox/index.ts +6 -0
- package/src/components/datepicker/CalendarToggleButton.tsx +58 -0
- package/src/components/datepicker/ClearButton.tsx +35 -0
- package/src/components/datepicker/DateField.tsx +54 -0
- package/src/components/datepicker/DatePicker.scss +51 -0
- package/src/components/datepicker/DatePicker.tsx +574 -0
- package/src/components/datepicker/DateRangePicker.scss +11 -0
- package/src/components/datepicker/DateRangePicker.tsx +343 -0
- package/src/components/datepicker/index.ts +4 -0
- package/src/components/datepicker/renderDatePickerShell.tsx +104 -0
- package/src/components/drawer/Drawer.tsx +211 -0
- package/src/components/drawer/DrawerBody.tsx +47 -0
- package/src/components/drawer/DrawerFooter.tsx +51 -0
- package/src/components/drawer/DrawerHeader.tsx +60 -0
- package/src/components/drawer/DrawerTitle.tsx +49 -0
- package/src/components/drawer/index.ts +10 -0
- package/src/components/file-input/FileInput.tsx +100 -0
- package/src/components/file-input/index.ts +2 -0
- package/src/components/flex/Flex.tsx +134 -0
- package/src/components/flex/index.ts +2 -0
- package/src/components/floating-input/FloatingInput.tsx +94 -0
- package/src/components/floating-input/index.ts +2 -0
- package/src/components/form/Form.tsx +26 -0
- package/src/components/form/FormFeedback.tsx +64 -0
- package/src/components/form/FormHelp.tsx +46 -0
- package/src/components/form/FormLabel.tsx +26 -0
- package/src/components/form/index.ts +8 -0
- package/src/components/form/renderFormCheck.tsx +86 -0
- package/src/components/form-field/FormField.tsx +84 -0
- package/src/components/form-field/index.ts +2 -0
- package/src/components/form-field/renderFormField.tsx +74 -0
- package/src/components/grid/Col.tsx +69 -0
- package/src/components/grid/Container.tsx +59 -0
- package/src/components/grid/Grid.tsx +86 -0
- package/src/components/grid/GridItem.tsx +123 -0
- package/src/components/grid/Row.tsx +71 -0
- package/src/components/grid/gap.ts +8 -0
- package/src/components/grid/index.ts +10 -0
- package/src/components/icon/Icon.tsx +74 -0
- package/src/components/icon/index.ts +2 -0
- package/src/components/input-adorn/InputAdorn.tsx +55 -0
- package/src/components/input-adorn/index.ts +2 -0
- package/src/components/input-group/InputGroup.tsx +50 -0
- package/src/components/input-group/InputGroupAddon.tsx +50 -0
- package/src/components/input-group/index.ts +4 -0
- package/src/components/link/Link.tsx +148 -0
- package/src/components/link/index.ts +2 -0
- package/src/components/list/List.tsx +193 -0
- package/src/components/list/ListItem.tsx +91 -0
- package/src/components/list/index.ts +4 -0
- package/src/components/menu/Menu.tsx +398 -0
- package/src/components/menu/MenuDivider.tsx +19 -0
- package/src/components/menu/MenuHeader.tsx +55 -0
- package/src/components/menu/MenuItem.tsx +85 -0
- package/src/components/menu/MenuItemDef.ts +83 -0
- package/src/components/menu/MenuList.tsx +142 -0
- package/src/components/menu/MenuSubmenu.tsx +284 -0
- package/src/components/menu/MenuSubmenuBack.tsx +39 -0
- package/src/components/menu/MenuText.tsx +47 -0
- package/src/components/menu/MenuToggle.tsx +148 -0
- package/src/components/menu/index.ts +19 -0
- package/src/components/menu/menuNavigation.ts +106 -0
- package/src/components/menu/submenuGroup.ts +43 -0
- package/src/components/modal/Modal.tsx +162 -0
- package/src/components/modal/ModalBody.tsx +47 -0
- package/src/components/modal/ModalFooter.tsx +51 -0
- package/src/components/modal/ModalHeader.tsx +60 -0
- package/src/components/modal/ModalTitle.tsx +49 -0
- package/src/components/modal/index.ts +10 -0
- package/src/components/nav/Nav.tsx +97 -0
- package/src/components/nav/NavItem.tsx +42 -0
- package/src/components/nav/NavLink.tsx +48 -0
- package/src/components/nav/NavTitle.tsx +22 -0
- package/src/components/nav/index.ts +7 -0
- package/src/components/navbar/Navbar.tsx +112 -0
- package/src/components/navbar/NavbarBrand.tsx +55 -0
- package/src/components/navbar/NavbarNav.tsx +47 -0
- package/src/components/navbar/NavbarText.tsx +47 -0
- package/src/components/navbar/NavbarToggler.tsx +34 -0
- package/src/components/navbar/index.ts +10 -0
- package/src/components/notification/Notification.scss +15 -0
- package/src/components/notification/Notification.tsx +187 -0
- package/src/components/notification/NotificationIcon.tsx +21 -0
- package/src/components/notification/NotificationStack.tsx +66 -0
- package/src/components/notification/NotificationText.tsx +47 -0
- package/src/components/notification/NotificationTitle.tsx +47 -0
- package/src/components/notification/context.ts +14 -0
- package/src/components/notification/index.ts +17 -0
- package/src/components/notification/notificationQueue.ts +48 -0
- package/src/components/otp-input/OtpBox.tsx +68 -0
- package/src/components/otp-input/OtpInput.tsx +341 -0
- package/src/components/otp-input/index.ts +2 -0
- package/src/components/pagination/Pagination.tsx +199 -0
- package/src/components/pagination/PaginationItem.tsx +133 -0
- package/src/components/pagination/index.ts +4 -0
- package/src/components/password-strength/PasswordStrength.tsx +155 -0
- package/src/components/password-strength/index.ts +2 -0
- package/src/components/password-strength/strengthScore.ts +79 -0
- package/src/components/placeholder/Placeholder.tsx +178 -0
- package/src/components/placeholder/index.ts +2 -0
- package/src/components/popover/Popover.tsx +243 -0
- package/src/components/popover/index.ts +2 -0
- package/src/components/progress/Progress.tsx +154 -0
- package/src/components/progress/ProgressBar.tsx +88 -0
- package/src/components/progress/index.ts +4 -0
- package/src/components/radio/Radio.tsx +88 -0
- package/src/components/radio/RadioGroup.tsx +142 -0
- package/src/components/radio/context.ts +14 -0
- package/src/components/radio/index.ts +4 -0
- package/src/components/range-input/RangeInput.tsx +109 -0
- package/src/components/range-input/index.ts +2 -0
- package/src/components/select/Select.tsx +277 -0
- package/src/components/select/index.ts +2 -0
- package/src/components/skeleton/Skeleton.tsx +89 -0
- package/src/components/skeleton/SkeletonLoader.tsx +91 -0
- package/src/components/skeleton/index.ts +4 -0
- package/src/components/spinner/Spinner.tsx +77 -0
- package/src/components/spinner/index.ts +2 -0
- package/src/components/stack/Stack.tsx +81 -0
- package/src/components/stack/index.ts +2 -0
- package/src/components/stepper/Stepper.tsx +172 -0
- package/src/components/stepper/StepperItem.tsx +66 -0
- package/src/components/stepper/index.ts +4 -0
- package/src/components/switch/Switch.tsx +246 -0
- package/src/components/switch/index.ts +2 -0
- package/src/components/table/Table.css +39 -0
- package/src/components/table/Table.tsx +390 -0
- package/src/components/table/TableBody.tsx +25 -0
- package/src/components/table/TableCell.tsx +27 -0
- package/src/components/table/TableColumn.tsx +31 -0
- package/src/components/table/TableHeader.tsx +26 -0
- package/src/components/table/TableRow.tsx +24 -0
- package/src/components/table/index.ts +12 -0
- package/src/components/tabs/Tab.tsx +36 -0
- package/src/components/tabs/TabList.tsx +76 -0
- package/src/components/tabs/TabPanel.tsx +68 -0
- package/src/components/tabs/Tabs.tsx +136 -0
- package/src/components/tabs/context.ts +24 -0
- package/src/components/tabs/index.ts +8 -0
- package/src/components/text-input/TextInput.tsx +188 -0
- package/src/components/text-input/index.ts +2 -0
- package/src/components/textarea/Textarea.tsx +145 -0
- package/src/components/textarea/index.ts +2 -0
- package/src/components/toast/Toast.tsx +219 -0
- package/src/components/toast/ToastBody.tsx +64 -0
- package/src/components/toast/ToastFooter.tsx +47 -0
- package/src/components/toast/ToastHeader.tsx +104 -0
- package/src/components/toast/ToastIcon.tsx +21 -0
- package/src/components/toast/Toaster.tsx +87 -0
- package/src/components/toast/context.ts +14 -0
- package/src/components/toast/index.ts +18 -0
- package/src/components/toast/toastQueue.ts +56 -0
- package/src/components/tooltip/Tooltip.tsx +155 -0
- package/src/components/tooltip/index.ts +2 -0
- package/src/global.d.ts +2 -0
- package/src/hooks/index.ts +57 -0
- package/src/hooks/useAutoDismiss.ts +88 -0
- package/src/hooks/useButtonSemantics.ts +33 -0
- package/src/hooks/useControllableState.ts +24 -0
- package/src/hooks/useDialogElement.ts +216 -0
- package/src/hooks/useDisabledAnchorGuard.ts +22 -0
- package/src/hooks/useDismissibleTransition.ts +126 -0
- package/src/hooks/useDrawer.ts +9 -0
- package/src/hooks/useFloatingOverlay.ts +115 -0
- package/src/hooks/useForkedRef.ts +50 -0
- package/src/hooks/useFormField.ts +89 -0
- package/src/hooks/useIsomorphicLayoutEffect.ts +9 -0
- package/src/hooks/useModal.ts +9 -0
- package/src/hooks/useNotification.ts +10 -0
- package/src/hooks/useOverlayPlacement.ts +93 -0
- package/src/hooks/usePagination.ts +85 -0
- package/src/hooks/useToast.ts +9 -0
- package/src/hooks/useToastRegionQueue.ts +27 -0
- package/src/index.ts +276 -0
- package/src/types.ts +133 -0
- package/src/utils/breakpoints.ts +43 -0
- package/src/utils/comboboxCollection.tsx +152 -0
- package/src/utils/dateRangePresets.ts +6 -0
- package/src/utils/dialogTransition.ts +39 -0
- package/src/utils/focusRedirect.ts +29 -0
- package/src/utils/isWholeUnitDisabled.ts +17 -0
- package/src/utils/mergeIsDateUnavailable.ts +15 -0
- package/src/utils/overlayPlacement.ts +93 -0
- package/src/utils/pointerInteraction.ts +21 -0
- package/src/utils/polymorphic.ts +36 -0
- package/src/utils/renderMenuItemContent.tsx +62 -0
- package/src/utils/setVisibleRangeStart.ts +64 -0
- package/src/utils/spacingClassName.ts +14 -0
- package/src/utils/suppressFocusRingGlobally.ts +69 -0
- package/src/utils/validationClassName.ts +8 -0
- package/src/utils/virtualFocusStyle.ts +16 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
// Side-effect only: installs the single document-level pointerdown listener that works around the
|
|
4
|
+
// browser's `:focus-visible` first-click heuristic misfire — see the module's own comment. Needs to
|
|
5
|
+
// run once wherever this package is used, not per-component, so it's imported here rather than
|
|
6
|
+
// from any individual component.
|
|
7
|
+
import './utils/suppressFocusRingGlobally'
|
|
8
|
+
|
|
9
|
+
import { Accordion, AccordionBody, AccordionHeader, AccordionItem } from './components/accordion'
|
|
10
|
+
import { Autocomplete, AutocompleteGroup, AutocompleteItem } from './components/autocomplete'
|
|
11
|
+
import { Avatar, AvatarImage, AvatarStack } from './components/avatar'
|
|
12
|
+
import {
|
|
13
|
+
Notification,
|
|
14
|
+
NotificationTitle,
|
|
15
|
+
NotificationIcon,
|
|
16
|
+
NotificationText,
|
|
17
|
+
NotificationStack,
|
|
18
|
+
addNotification,
|
|
19
|
+
closeNotification,
|
|
20
|
+
notificationQueue
|
|
21
|
+
} from './components/notification'
|
|
22
|
+
import { Badge } from './components/badge'
|
|
23
|
+
import { Breadcrumb, BreadcrumbItem } from './components/breadcrumb'
|
|
24
|
+
import { Button } from './components/button'
|
|
25
|
+
import { ButtonGroup, ButtonToolbar } from './components/button-group'
|
|
26
|
+
import { Calendar, RangeCalendar } from './components/calendar'
|
|
27
|
+
import {
|
|
28
|
+
Card,
|
|
29
|
+
CardBody,
|
|
30
|
+
CardFooter,
|
|
31
|
+
CardGroup,
|
|
32
|
+
CardHeader,
|
|
33
|
+
CardImage,
|
|
34
|
+
CardImageOverlay,
|
|
35
|
+
CardLink,
|
|
36
|
+
CardSubtitle,
|
|
37
|
+
CardText,
|
|
38
|
+
CardTitle
|
|
39
|
+
} from './components/card'
|
|
40
|
+
import {
|
|
41
|
+
Carousel,
|
|
42
|
+
CarouselControlNext,
|
|
43
|
+
CarouselControlPrev,
|
|
44
|
+
CarouselIndicators,
|
|
45
|
+
CarouselInner,
|
|
46
|
+
CarouselItem,
|
|
47
|
+
CarouselOverlay,
|
|
48
|
+
CarouselPlayPause
|
|
49
|
+
} from './components/carousel'
|
|
50
|
+
import { Collapse } from './components/collapse'
|
|
51
|
+
import { ChipInput } from './components/chip-input'
|
|
52
|
+
import { CloseButton } from './components/close-button'
|
|
53
|
+
import { ColorInput } from './components/color-input'
|
|
54
|
+
import { FileInput } from './components/file-input'
|
|
55
|
+
import { Combobox, ComboboxGroup, ComboboxItem } from './components/combobox'
|
|
56
|
+
import { DatePicker, DateRangePicker } from './components/datepicker'
|
|
57
|
+
import { OtpInput } from './components/otp-input'
|
|
58
|
+
import { PasswordStrength } from './components/password-strength'
|
|
59
|
+
import { I18nProvider } from 'react-aria'
|
|
60
|
+
import {
|
|
61
|
+
Menu,
|
|
62
|
+
MenuDivider,
|
|
63
|
+
MenuHeader,
|
|
64
|
+
MenuItem,
|
|
65
|
+
MenuList,
|
|
66
|
+
MenuText,
|
|
67
|
+
MenuToggle,
|
|
68
|
+
MenuSubmenu,
|
|
69
|
+
MenuSubmenuBack
|
|
70
|
+
} from './components/menu'
|
|
71
|
+
import { Col, Container, Grid, GridItem, Row } from './components/grid'
|
|
72
|
+
import { Checkbox, CheckboxGroup } from './components/checkbox'
|
|
73
|
+
import { Form, FormFeedback, FormHelp, FormLabel } from './components/form'
|
|
74
|
+
import { FloatingInput } from './components/floating-input'
|
|
75
|
+
import { FormField } from './components/form-field'
|
|
76
|
+
import { InputGroup, InputGroupAddon } from './components/input-group'
|
|
77
|
+
import { InputAdorn } from './components/input-adorn'
|
|
78
|
+
import { Radio, RadioGroup } from './components/radio'
|
|
79
|
+
import { RangeInput } from './components/range-input'
|
|
80
|
+
import { Select } from './components/select'
|
|
81
|
+
import { Switch } from './components/switch'
|
|
82
|
+
import { TextInput } from './components/text-input'
|
|
83
|
+
import { Textarea } from './components/textarea'
|
|
84
|
+
import { Icon } from './components/icon'
|
|
85
|
+
import { Placeholder } from './components/placeholder'
|
|
86
|
+
import { Link } from './components/link'
|
|
87
|
+
import { List, ListItem } from './components/list'
|
|
88
|
+
import { Modal, ModalBody, ModalFooter, ModalHeader, ModalTitle } from './components/modal'
|
|
89
|
+
import { Nav, NavItem, NavLink, NavTitle } from './components/nav'
|
|
90
|
+
import { Navbar, NavbarBrand, NavbarNav, NavbarText, NavbarToggler } from './components/navbar'
|
|
91
|
+
import { Pagination, PaginationItem } from './components/pagination'
|
|
92
|
+
import { Popover } from './components/popover'
|
|
93
|
+
import { Progress, ProgressBar } from './components/progress'
|
|
94
|
+
import { Drawer, DrawerBody, DrawerFooter, DrawerHeader, DrawerTitle } from './components/drawer'
|
|
95
|
+
import { Skeleton, SkeletonLoader } from './components/skeleton'
|
|
96
|
+
import { Spinner } from './components/spinner'
|
|
97
|
+
import { Stepper, StepperItem } from './components/stepper'
|
|
98
|
+
import { Table, TableBody, TableCell, TableColumn, TableHeader, TableRow } from './components/table'
|
|
99
|
+
import { Tabs, Tab, TabList, TabPanel } from './components/tabs'
|
|
100
|
+
import {
|
|
101
|
+
Toast,
|
|
102
|
+
ToastBody,
|
|
103
|
+
ToastFooter,
|
|
104
|
+
ToastHeader,
|
|
105
|
+
ToastIcon,
|
|
106
|
+
Toaster,
|
|
107
|
+
addToast,
|
|
108
|
+
closeToast,
|
|
109
|
+
toastQueue
|
|
110
|
+
} from './components/toast'
|
|
111
|
+
import { Tooltip } from './components/tooltip'
|
|
112
|
+
import { useDrawer, useModal, useNotification, usePagination, useToast } from './hooks'
|
|
113
|
+
import { Chip } from './components/chip'
|
|
114
|
+
import { Flex } from './components/flex'
|
|
115
|
+
import { Stack } from './components/stack'
|
|
116
|
+
|
|
117
|
+
export {
|
|
118
|
+
Chip,
|
|
119
|
+
Flex,
|
|
120
|
+
Stack,
|
|
121
|
+
Accordion,
|
|
122
|
+
AccordionBody,
|
|
123
|
+
AccordionHeader,
|
|
124
|
+
AccordionItem,
|
|
125
|
+
Autocomplete,
|
|
126
|
+
AutocompleteGroup,
|
|
127
|
+
AutocompleteItem,
|
|
128
|
+
Avatar,
|
|
129
|
+
AvatarImage,
|
|
130
|
+
AvatarStack,
|
|
131
|
+
Notification,
|
|
132
|
+
NotificationTitle,
|
|
133
|
+
NotificationIcon,
|
|
134
|
+
NotificationText,
|
|
135
|
+
NotificationStack,
|
|
136
|
+
addNotification,
|
|
137
|
+
closeNotification,
|
|
138
|
+
notificationQueue,
|
|
139
|
+
useNotification,
|
|
140
|
+
Badge,
|
|
141
|
+
Breadcrumb,
|
|
142
|
+
BreadcrumbItem,
|
|
143
|
+
Button,
|
|
144
|
+
ButtonGroup,
|
|
145
|
+
ButtonToolbar,
|
|
146
|
+
Calendar,
|
|
147
|
+
RangeCalendar,
|
|
148
|
+
Card,
|
|
149
|
+
CardBody,
|
|
150
|
+
CardFooter,
|
|
151
|
+
CardGroup,
|
|
152
|
+
CardHeader,
|
|
153
|
+
CardImage,
|
|
154
|
+
CardImageOverlay,
|
|
155
|
+
CardLink,
|
|
156
|
+
CardSubtitle,
|
|
157
|
+
CardText,
|
|
158
|
+
CardTitle,
|
|
159
|
+
Carousel,
|
|
160
|
+
CarouselControlNext,
|
|
161
|
+
CarouselControlPrev,
|
|
162
|
+
CarouselIndicators,
|
|
163
|
+
CarouselInner,
|
|
164
|
+
CarouselItem,
|
|
165
|
+
CarouselOverlay,
|
|
166
|
+
CarouselPlayPause,
|
|
167
|
+
ChipInput,
|
|
168
|
+
CloseButton,
|
|
169
|
+
Collapse,
|
|
170
|
+
ColorInput,
|
|
171
|
+
Combobox,
|
|
172
|
+
ComboboxGroup,
|
|
173
|
+
ComboboxItem,
|
|
174
|
+
DatePicker,
|
|
175
|
+
DateRangePicker,
|
|
176
|
+
FileInput,
|
|
177
|
+
// Re-exported (not a component from this package): react-aria is a bundled dependency, not a
|
|
178
|
+
// peer, so its module — including the `I18nProvider` context `DatePicker` reads locale from via
|
|
179
|
+
// `useLocale()` — is inlined into this package's own build output, distinct from any react-aria
|
|
180
|
+
// copy a consumer might separately install. A consumer's own `<I18nProvider>` would set a
|
|
181
|
+
// *different* context instance and silently have no effect on `DatePicker`; this re-export is
|
|
182
|
+
// the one that actually reaches it.
|
|
183
|
+
I18nProvider,
|
|
184
|
+
OtpInput,
|
|
185
|
+
PasswordStrength,
|
|
186
|
+
Menu,
|
|
187
|
+
MenuDivider,
|
|
188
|
+
MenuHeader,
|
|
189
|
+
MenuItem,
|
|
190
|
+
MenuList,
|
|
191
|
+
MenuText,
|
|
192
|
+
MenuToggle,
|
|
193
|
+
MenuSubmenu,
|
|
194
|
+
MenuSubmenuBack,
|
|
195
|
+
Col,
|
|
196
|
+
Container,
|
|
197
|
+
Grid,
|
|
198
|
+
GridItem,
|
|
199
|
+
Row,
|
|
200
|
+
Checkbox,
|
|
201
|
+
CheckboxGroup,
|
|
202
|
+
FloatingInput,
|
|
203
|
+
Form,
|
|
204
|
+
FormField,
|
|
205
|
+
FormFeedback,
|
|
206
|
+
FormHelp,
|
|
207
|
+
FormLabel,
|
|
208
|
+
Icon,
|
|
209
|
+
Placeholder,
|
|
210
|
+
InputGroup,
|
|
211
|
+
InputGroupAddon,
|
|
212
|
+
InputAdorn,
|
|
213
|
+
Link,
|
|
214
|
+
List,
|
|
215
|
+
ListItem,
|
|
216
|
+
Modal,
|
|
217
|
+
ModalBody,
|
|
218
|
+
ModalFooter,
|
|
219
|
+
ModalHeader,
|
|
220
|
+
ModalTitle,
|
|
221
|
+
useModal,
|
|
222
|
+
Nav,
|
|
223
|
+
NavItem,
|
|
224
|
+
NavLink,
|
|
225
|
+
NavTitle,
|
|
226
|
+
Navbar,
|
|
227
|
+
NavbarBrand,
|
|
228
|
+
NavbarNav,
|
|
229
|
+
NavbarText,
|
|
230
|
+
NavbarToggler,
|
|
231
|
+
Pagination,
|
|
232
|
+
PaginationItem,
|
|
233
|
+
usePagination,
|
|
234
|
+
Popover,
|
|
235
|
+
Progress,
|
|
236
|
+
ProgressBar,
|
|
237
|
+
Radio,
|
|
238
|
+
RadioGroup,
|
|
239
|
+
RangeInput,
|
|
240
|
+
Drawer,
|
|
241
|
+
DrawerBody,
|
|
242
|
+
DrawerFooter,
|
|
243
|
+
DrawerHeader,
|
|
244
|
+
DrawerTitle,
|
|
245
|
+
useDrawer,
|
|
246
|
+
Select,
|
|
247
|
+
Skeleton,
|
|
248
|
+
SkeletonLoader,
|
|
249
|
+
Spinner,
|
|
250
|
+
Stepper,
|
|
251
|
+
StepperItem,
|
|
252
|
+
Switch,
|
|
253
|
+
Table,
|
|
254
|
+
TableBody,
|
|
255
|
+
TableCell,
|
|
256
|
+
TableColumn,
|
|
257
|
+
TableHeader,
|
|
258
|
+
TableRow,
|
|
259
|
+
Tabs,
|
|
260
|
+
Tab,
|
|
261
|
+
TabList,
|
|
262
|
+
TabPanel,
|
|
263
|
+
TextInput,
|
|
264
|
+
Textarea,
|
|
265
|
+
Toast,
|
|
266
|
+
ToastBody,
|
|
267
|
+
ToastFooter,
|
|
268
|
+
ToastHeader,
|
|
269
|
+
ToastIcon,
|
|
270
|
+
Toaster,
|
|
271
|
+
addToast,
|
|
272
|
+
closeToast,
|
|
273
|
+
toastQueue,
|
|
274
|
+
useToast,
|
|
275
|
+
Tooltip
|
|
276
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Breakpoints
|
|
3
|
+
*/
|
|
4
|
+
export type Breakpoint = 'small' | 'medium' | 'large' | 'xlarge' | '2xlarge'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Context colors
|
|
8
|
+
*/
|
|
9
|
+
export type ContextColor =
|
|
10
|
+
| 'default'
|
|
11
|
+
| 'alternate'
|
|
12
|
+
| 'primary'
|
|
13
|
+
| 'secondary'
|
|
14
|
+
| 'neutral'
|
|
15
|
+
| 'success'
|
|
16
|
+
| 'danger'
|
|
17
|
+
| 'warning'
|
|
18
|
+
| 'info'
|
|
19
|
+
| 'black'
|
|
20
|
+
| 'white'
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Context styles
|
|
24
|
+
*/
|
|
25
|
+
export type ContextStyle = 'basic' | 'solid' | 'outline' | 'smooth'
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Component sizes
|
|
29
|
+
*/
|
|
30
|
+
export type Sizing = 'small' | 'medium' | 'large'
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Extended sizes
|
|
34
|
+
*/
|
|
35
|
+
export type ExtendedSizing = '2xsmall' | 'xsmall' | Sizing | 'xlarge' | '2xlarge'
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Spacing values. `SPACING` is the runtime source of truth — `Spacing` is derived from it so the
|
|
39
|
+
* two can't drift apart; anything needing the values at runtime (e.g. validating a string against
|
|
40
|
+
* the scale) should import `SPACING`, not hand-copy the list.
|
|
41
|
+
*/
|
|
42
|
+
export const SPACING = [
|
|
43
|
+
'zero',
|
|
44
|
+
'4xsmall',
|
|
45
|
+
'3xsmall',
|
|
46
|
+
'2xsmall',
|
|
47
|
+
'xsmall',
|
|
48
|
+
'small',
|
|
49
|
+
'medium',
|
|
50
|
+
'large',
|
|
51
|
+
'xlarge',
|
|
52
|
+
'2xlarge',
|
|
53
|
+
'3xlarge',
|
|
54
|
+
'4xlarge',
|
|
55
|
+
'5xlarge',
|
|
56
|
+
'6xlarge'
|
|
57
|
+
] as const
|
|
58
|
+
|
|
59
|
+
export type Spacing = (typeof SPACING)[number]
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Font families
|
|
63
|
+
*/
|
|
64
|
+
export type FontFamily = 'text' | 'display' | 'code' | 'html'
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Font weights
|
|
68
|
+
*/
|
|
69
|
+
export type FontWeight = 'elegant' | 'normal' | 'strong' | 'mass'
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Font sizes
|
|
73
|
+
*/
|
|
74
|
+
export type FontSize =
|
|
75
|
+
| '2xsmall'
|
|
76
|
+
| 'xsmall'
|
|
77
|
+
| 'small'
|
|
78
|
+
| 'medium'
|
|
79
|
+
| 'large'
|
|
80
|
+
| 'xlarge'
|
|
81
|
+
| '2xlarge'
|
|
82
|
+
| '3xlarge'
|
|
83
|
+
| '4xlarge'
|
|
84
|
+
| '5xlarge'
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Component placements
|
|
88
|
+
*/
|
|
89
|
+
export type Placements =
|
|
90
|
+
| 'auto'
|
|
91
|
+
| 'auto-start'
|
|
92
|
+
| 'auto-end'
|
|
93
|
+
| 'top-end'
|
|
94
|
+
| 'top'
|
|
95
|
+
| 'top-start'
|
|
96
|
+
| 'bottom-end'
|
|
97
|
+
| 'bottom'
|
|
98
|
+
| 'bottom-start'
|
|
99
|
+
| 'right-start'
|
|
100
|
+
| 'right'
|
|
101
|
+
| 'right-end'
|
|
102
|
+
| 'left-start'
|
|
103
|
+
| 'left'
|
|
104
|
+
| 'left-end'
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Component shapes
|
|
108
|
+
*/
|
|
109
|
+
export type Shapes =
|
|
110
|
+
| 'rounded'
|
|
111
|
+
| 'rounded-top'
|
|
112
|
+
| 'rounded-end'
|
|
113
|
+
| 'rounded-bottom'
|
|
114
|
+
| 'rounded-start'
|
|
115
|
+
| 'rounded-circle'
|
|
116
|
+
| 'rounded-pill'
|
|
117
|
+
| 'rounded-0'
|
|
118
|
+
| 'rounded-1'
|
|
119
|
+
| 'rounded-2'
|
|
120
|
+
| 'rounded-3'
|
|
121
|
+
|
|
122
|
+
export type TextColor =
|
|
123
|
+
| ContextColor
|
|
124
|
+
| 'main'
|
|
125
|
+
| 'subtle'
|
|
126
|
+
| 'slight'
|
|
127
|
+
| 'solid'
|
|
128
|
+
| 'inverse'
|
|
129
|
+
| 'highlight'
|
|
130
|
+
| 'active'
|
|
131
|
+
| 'contrast'
|
|
132
|
+
|
|
133
|
+
export type Triggers = 'hover' | 'focus' | 'click'
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Breakpoint } from '../types'
|
|
2
|
+
|
|
3
|
+
// Mobile-first ascending order. Every responsive layout prop (`Flex`/`Stack`/`Row`/`Col`/
|
|
4
|
+
// `Skeleton`'s `responsive`) keys its overrides by these literal chassis-css breakpoint names.
|
|
5
|
+
export const BREAKPOINTS: Breakpoint[] = ['small', 'medium', 'large', 'xlarge', '2xlarge']
|
|
6
|
+
|
|
7
|
+
// A column/width span: a track count, `'auto'` for a natural-width track, or `true` for the bare
|
|
8
|
+
// (no explicit width) case. Shared by `Col` and `Skeleton`, both of which map it to the same
|
|
9
|
+
// `col-{n}` / `col` chassis-css classes.
|
|
10
|
+
export type Span = 'auto' | number | string | boolean
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Builds the class list for a component's base layout plus per-breakpoint overrides supplied via
|
|
14
|
+
* a `responsive` prop — the pattern shared by `Flex`, `Stack`, and (from Phase 2) `Row`/`Col`.
|
|
15
|
+
*
|
|
16
|
+
* `toClassNames` maps one breakpoint's layout value to class name fragments for a given prefix
|
|
17
|
+
* (`''` for the base/unprefixed case, `` `${breakpoint}:` `` otherwise). Falsy entries in its
|
|
18
|
+
* return value are fine — `classnames` drops them at the call site — so fields the layout object
|
|
19
|
+
* doesn't set can just map to `undefined`/`false`.
|
|
20
|
+
*/
|
|
21
|
+
export function buildResponsiveClassNames<TLayout>(
|
|
22
|
+
toClassNames: (layout: TLayout, prefix: string) => Array<string | false | null | undefined>,
|
|
23
|
+
base: TLayout,
|
|
24
|
+
responsive?: Partial<Record<Breakpoint, TLayout>>
|
|
25
|
+
): Array<string | false | null | undefined> {
|
|
26
|
+
const responsiveClassNames = responsive
|
|
27
|
+
? BREAKPOINTS.filter((bp) => responsive[bp]).flatMap((bp) =>
|
|
28
|
+
toClassNames(responsive[bp] as TLayout, `${bp}:`)
|
|
29
|
+
)
|
|
30
|
+
: []
|
|
31
|
+
|
|
32
|
+
return [...toClassNames(base, ''), ...responsiveClassNames]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type FlexDirection = 'row' | 'column'
|
|
36
|
+
|
|
37
|
+
// A `buildResponsiveClassNames` `toClassNames` fn for the `flex-row`/`flex-column` direction
|
|
38
|
+
// toggle shared by `Card` and `CardBody`, both of which map a `direction` prop to the same
|
|
39
|
+
// chassis-css class.
|
|
40
|
+
export const flexDirectionClassNames = (
|
|
41
|
+
direction: FlexDirection | undefined,
|
|
42
|
+
prefix: string
|
|
43
|
+
): Array<string | false | undefined> => [direction && `${prefix}flex-${direction}`]
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React, { ComponentType, ReactElement, ReactNode } from 'react'
|
|
2
|
+
import { Item, Key, Section } from 'react-stately'
|
|
3
|
+
|
|
4
|
+
import { ComboboxGroupProps } from '../components/combobox/ComboboxGroup'
|
|
5
|
+
import { ComboboxItem, ComboboxItemProps } from '../components/combobox/ComboboxItem'
|
|
6
|
+
import { MenuItemsDef } from '../components/menu/MenuItemDef'
|
|
7
|
+
import { renderMenuItemContent } from './renderMenuItemContent'
|
|
8
|
+
|
|
9
|
+
// Shared between Combobox.tsx/ComboboxListBox.tsx (which build/render this collection) and
|
|
10
|
+
// Autocomplete.tsx (which reuses the same entry shape — see the comment on
|
|
11
|
+
// `buildEntriesFromChildren` below). Lives in `utils/` rather than `components/combobox/` because
|
|
12
|
+
// it crosses that folder boundary; kept in its own file to also avoid a circular import between
|
|
13
|
+
// Combobox.tsx and ComboboxListBox.tsx.
|
|
14
|
+
|
|
15
|
+
export type ComboboxItemElement = ReactElement<ComboboxItemProps>
|
|
16
|
+
|
|
17
|
+
export interface ComboboxGroupEntry {
|
|
18
|
+
entryType: 'group'
|
|
19
|
+
key: Key
|
|
20
|
+
label: ReactNode
|
|
21
|
+
items: ComboboxItemElement[]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type ComboboxEntry = ComboboxItemElement | ComboboxGroupEntry
|
|
25
|
+
|
|
26
|
+
// `useComboBoxState`/`useComboBox`'s own `SelectionMode` ('single' | 'multiple') isn't
|
|
27
|
+
// re-exported from react-stately's public entry point (only `ComboBoxState` etc. are) — this is
|
|
28
|
+
// a structurally-identical stand-in so `ComboboxListBox` can stay generic over it without a
|
|
29
|
+
// fragile deep import.
|
|
30
|
+
export type ComboboxSelectionMode = 'single' | 'multiple'
|
|
31
|
+
|
|
32
|
+
export const isComboboxGroupEntry = (entry: ComboboxEntry): entry is ComboboxGroupEntry =>
|
|
33
|
+
(entry as ComboboxGroupEntry).entryType === 'group'
|
|
34
|
+
|
|
35
|
+
// `Autocomplete`'s own `AutocompleteItem`/`AutocompleteGroup` are structurally identical to
|
|
36
|
+
// `ComboboxItem`/`ComboboxGroup` (see AutocompleteItem.tsx/AutocompleteGroup.tsx — kept as
|
|
37
|
+
// separate named types only so `Autocomplete`'s public API doesn't leak `Combobox`'s own prop
|
|
38
|
+
// type), but they're different *runtime* component identities, which is what
|
|
39
|
+
// `buildEntriesFromChildren` below needs to check consumer-authored `children` against. Passing
|
|
40
|
+
// the pair in lets one implementation serve both families instead of two near-duplicate copies.
|
|
41
|
+
export interface ComboboxCollectionComponents {
|
|
42
|
+
Group: ComponentType<ComboboxGroupProps>
|
|
43
|
+
Item: ComponentType<ComboboxItemProps>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Splits `children` into a flat, ordered list of entries — bare `Item` elements and
|
|
47
|
+
// `Group`-wrapped clusters of them — mirroring how `useComboBoxState`'s dynamic collection needs
|
|
48
|
+
// top-level nodes: some rendered as a plain `<Item>`, some as a `<Section>` wrapping several
|
|
49
|
+
// `<Item>`s (see `comboboxCollectionChildren` below).
|
|
50
|
+
export const buildEntriesFromChildren = (
|
|
51
|
+
children: ReactNode,
|
|
52
|
+
{ Group, Item: ItemComponent }: ComboboxCollectionComponents
|
|
53
|
+
): ComboboxEntry[] => {
|
|
54
|
+
const entries: ComboboxEntry[] = []
|
|
55
|
+
React.Children.forEach(children, (child, index) => {
|
|
56
|
+
if (!React.isValidElement(child)) return
|
|
57
|
+
if (child.type === Group) {
|
|
58
|
+
const groupProps = child.props as ComboboxGroupProps
|
|
59
|
+
const items: ComboboxItemElement[] = []
|
|
60
|
+
React.Children.forEach(groupProps.children, (groupChild) => {
|
|
61
|
+
if (React.isValidElement(groupChild) && groupChild.type === ItemComponent) {
|
|
62
|
+
items.push(groupChild as ComboboxItemElement)
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
entries.push({ entryType: 'group', key: `group-${index}`, label: groupProps.label, items })
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
if (child.type === ItemComponent) {
|
|
69
|
+
entries.push(child as ComboboxItemElement)
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
return entries
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Same shape as `buildEntriesFromChildren`, from a flat `MenuItemsDef` instead. A `'header'`
|
|
76
|
+
// entry opens a new group that all following items join until the next header (or the end of
|
|
77
|
+
// the array) — matching how chassis-css itself renders grouped items (flat siblings, no
|
|
78
|
+
// wrapping element per group). `'divider'` entries aren't meaningful for a listbox/option
|
|
79
|
+
// collection and are skipped.
|
|
80
|
+
//
|
|
81
|
+
// Always builds a bare `ComboboxItem` internally regardless of which family (`Combobox` or
|
|
82
|
+
// `Autocomplete`) called it: unlike `buildEntriesFromChildren`, nothing downstream re-checks
|
|
83
|
+
// these elements' runtime type (they're read only via `.props.*`, never matched against a
|
|
84
|
+
// component reference again), so there's no need to thread `ComboboxCollectionComponents`
|
|
85
|
+
// through here too. `def.href`/`def.onClick` are intentionally not read — see the doc comments on
|
|
86
|
+
// `MenuItemDef` itself for why: they're `Menu`-only fields on this shared type.
|
|
87
|
+
export const buildEntriesFromItemsDef = (defs: MenuItemsDef): ComboboxEntry[] => {
|
|
88
|
+
const entries: ComboboxEntry[] = []
|
|
89
|
+
let currentGroup: ComboboxGroupEntry | null = null
|
|
90
|
+
|
|
91
|
+
defs.forEach((def) => {
|
|
92
|
+
if (def.type === 'divider') return
|
|
93
|
+
if (def.type === 'header') {
|
|
94
|
+
currentGroup = { entryType: 'group', key: def.id, label: def.label, items: [] }
|
|
95
|
+
entries.push(currentGroup)
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
const item = (
|
|
99
|
+
<ComboboxItem
|
|
100
|
+
key={def.id}
|
|
101
|
+
id={def.id}
|
|
102
|
+
disabled={def.disabled}
|
|
103
|
+
icon={def.icon}
|
|
104
|
+
description={def.description}
|
|
105
|
+
textValue={def.textValue}
|
|
106
|
+
>
|
|
107
|
+
{def.label}
|
|
108
|
+
</ComboboxItem>
|
|
109
|
+
)
|
|
110
|
+
if (currentGroup) currentGroup.items.push(item)
|
|
111
|
+
else entries.push(item)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
return entries
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const getDisabledKeys = (entries: ComboboxEntry[]): Key[] =>
|
|
118
|
+
entries.reduce<Key[]>((keys, entry) => {
|
|
119
|
+
const items = isComboboxGroupEntry(entry) ? entry.items : [entry]
|
|
120
|
+
return keys.concat(items.filter((item) => item.props.disabled).map((item) => item.props.id))
|
|
121
|
+
}, [])
|
|
122
|
+
|
|
123
|
+
// Builds the react-stately `Item` node `useComboBoxState`'s collection actually renders from one
|
|
124
|
+
// entry's props — identical for `Combobox` and `Autocomplete` regardless of which authoring
|
|
125
|
+
// component (`ComboboxItem`/`AutocompleteItem`) produced it, since both share the same prop shape.
|
|
126
|
+
export const renderComboboxCollectionItem = (item: ComboboxItemElement) => (
|
|
127
|
+
<Item
|
|
128
|
+
key={item.props.id}
|
|
129
|
+
textValue={
|
|
130
|
+
item.props.textValue ??
|
|
131
|
+
(typeof item.props.children === 'string' ? item.props.children : undefined)
|
|
132
|
+
}
|
|
133
|
+
>
|
|
134
|
+
{renderMenuItemContent({
|
|
135
|
+
icon: item.props.icon,
|
|
136
|
+
label: item.props.children,
|
|
137
|
+
description: item.props.description
|
|
138
|
+
})}
|
|
139
|
+
</Item>
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
// `useComboBoxState`'s own `children` render prop, given one `ComboboxEntry` — a plain `Item` for
|
|
143
|
+
// a bare entry, a `Section` wrapping its items for a group. Identical for `Combobox` and
|
|
144
|
+
// `Autocomplete`'s state setup.
|
|
145
|
+
export const comboboxCollectionChildren = (entry: ComboboxEntry) =>
|
|
146
|
+
isComboboxGroupEntry(entry) ? (
|
|
147
|
+
<Section key={entry.key} title={entry.label} items={entry.items}>
|
|
148
|
+
{renderComboboxCollectionItem}
|
|
149
|
+
</Section>
|
|
150
|
+
) : (
|
|
151
|
+
renderComboboxCollectionItem(entry)
|
|
152
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Shared transition timing for native <dialog>-based components (Modal, Drawer). Body-scroll
|
|
2
|
+
// locking is handled by react-aria's usePreventScroll directly in each component.
|
|
3
|
+
|
|
4
|
+
export const getTransitionDuration = (element: HTMLElement) => {
|
|
5
|
+
const { transitionDuration, transitionDelay } = window.getComputedStyle(element)
|
|
6
|
+
const duration = Number.parseFloat(transitionDuration) || 0
|
|
7
|
+
const delay = Number.parseFloat(transitionDelay) || 0
|
|
8
|
+
if (!duration && !delay) return 0
|
|
9
|
+
return (duration + delay) * 1000
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const executeAfterTransition = (
|
|
13
|
+
element: HTMLElement,
|
|
14
|
+
callback: () => void,
|
|
15
|
+
animated: boolean
|
|
16
|
+
) => {
|
|
17
|
+
if (!animated) {
|
|
18
|
+
callback()
|
|
19
|
+
return () => undefined
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let called = false
|
|
23
|
+
const done = () => {
|
|
24
|
+
if (called) return
|
|
25
|
+
called = true
|
|
26
|
+
element.removeEventListener('transitionend', handleEnd)
|
|
27
|
+
clearTimeout(timer)
|
|
28
|
+
callback()
|
|
29
|
+
}
|
|
30
|
+
const handleEnd = (event: Event) => {
|
|
31
|
+
if (event.target === element) done()
|
|
32
|
+
}
|
|
33
|
+
element.addEventListener('transitionend', handleEnd)
|
|
34
|
+
const timer = setTimeout(done, getTransitionDuration(element) + 50)
|
|
35
|
+
return () => {
|
|
36
|
+
element.removeEventListener('transitionend', handleEnd)
|
|
37
|
+
clearTimeout(timer)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Safari shows a `:focus-visible` ring on an element focused via script even when the
|
|
2
|
+
// interaction that triggered the script was a real pointer click — unlike Chromium/Firefox,
|
|
3
|
+
// which correctly suppress it in that case. Force the ring off for a pointer-triggered redirect,
|
|
4
|
+
// then let normal focus-visible behavior resume the next time this element is genuinely
|
|
5
|
+
// (re)focused, e.g. via Tab.
|
|
6
|
+
export function focusRedirect(
|
|
7
|
+
el: HTMLElement | null,
|
|
8
|
+
viaPointer: boolean,
|
|
9
|
+
focusOptions?: FocusOptions
|
|
10
|
+
): void {
|
|
11
|
+
if (!el) return
|
|
12
|
+
if (!viaPointer) {
|
|
13
|
+
el.focus(focusOptions)
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
const prevOutline = el.style.outline
|
|
17
|
+
const prevBoxShadow = el.style.boxShadow
|
|
18
|
+
el.style.outline = 'none'
|
|
19
|
+
el.style.boxShadow = 'none'
|
|
20
|
+
el.focus(focusOptions)
|
|
21
|
+
el.addEventListener(
|
|
22
|
+
'blur',
|
|
23
|
+
() => {
|
|
24
|
+
el.style.outline = prevOutline
|
|
25
|
+
el.style.boxShadow = prevBoxShadow
|
|
26
|
+
},
|
|
27
|
+
{ once: true }
|
|
28
|
+
)
|
|
29
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CalendarState, RangeCalendarState } from 'react-stately'
|
|
2
|
+
import { CalendarDate, toCalendarDate } from '@internationalized/date'
|
|
3
|
+
|
|
4
|
+
// Shared by `CalendarMonthGrid` and `CalendarYearGrid` — a month/year button is disabled when
|
|
5
|
+
// every day it covers falls outside `minValue`/`maxValue`, not just when its first day does (e.g.
|
|
6
|
+
// a `maxValue` of March 15th still leaves March itself partly selectable, so March's button stays
|
|
7
|
+
// enabled; April's doesn't). `unitEnd` is the last day of the button's own month/year.
|
|
8
|
+
export const isWholeUnitDisabled = (
|
|
9
|
+
state: CalendarState<'single' | 'multiple'> | RangeCalendarState,
|
|
10
|
+
unitStart: CalendarDate,
|
|
11
|
+
unitEnd: CalendarDate
|
|
12
|
+
): boolean => {
|
|
13
|
+
if (state.isDisabled) return true
|
|
14
|
+
if (state.maxValue && unitStart.compare(toCalendarDate(state.maxValue)) > 0) return true
|
|
15
|
+
if (state.minValue && unitEnd.compare(toCalendarDate(state.minValue)) < 0) return true
|
|
16
|
+
return false
|
|
17
|
+
}
|