@deriv-com/dds-marketing 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.llm/components/accordion.md +193 -0
- package/.llm/components/accordionitem.md +236 -0
- package/.llm/components/aspectratio.md +212 -0
- package/.llm/components/badge.md +231 -0
- package/.llm/components/bottomsheet.md +404 -0
- package/.llm/components/breadcrumb.md +197 -0
- package/.llm/components/breadcrumbitem.md +178 -0
- package/.llm/components/button.md +271 -0
- package/.llm/components/buttonicon.md +313 -0
- package/.llm/components/card.md +313 -0
- package/.llm/components/cardbody.md +409 -0
- package/.llm/components/cardbutton.md +259 -0
- package/.llm/components/checkbox.md +285 -0
- package/.llm/components/divider.md +230 -0
- package/.llm/components/dropdownmenu.md +453 -0
- package/.llm/components/filterchip.md +314 -0
- package/.llm/components/footer.md +408 -0
- package/.llm/components/footergroup.md +241 -0
- package/.llm/components/grid.md +659 -0
- package/.llm/components/icon.md +194 -0
- package/.llm/components/link.md +354 -0
- package/.llm/components/menuitem.md +218 -0
- package/.llm/components/navbar.md +458 -0
- package/.llm/components/navbaritem.md +238 -0
- package/.llm/components/navbarmenu.md +319 -0
- package/.llm/components/navbarmenugroup.md +184 -0
- package/.llm/components/navbarpanel.md +255 -0
- package/.llm/components/navbarswitcher.md +343 -0
- package/.llm/components/navbarswitcheroption.md +156 -0
- package/.llm/components/option.md +268 -0
- package/.llm/components/pagination.md +361 -0
- package/.llm/components/removablechip.md +247 -0
- package/.llm/components/row.md +381 -0
- package/.llm/components/scroller.md +470 -0
- package/.llm/components/searchinput.md +279 -0
- package/.llm/components/segmentedcontrol.md +358 -0
- package/.llm/components/segmentedcontrolitem.md +272 -0
- package/.llm/components/select.md +509 -0
- package/.llm/components/selectchip.md +334 -0
- package/.llm/components/spinner.md +222 -0
- package/.llm/components/stack.md +334 -0
- package/.llm/components/statusdot.md +205 -0
- package/.llm/components/subdomainnavbar.md +327 -0
- package/.llm/components/tab.md +291 -0
- package/.llm/components/table.md +660 -0
- package/.llm/components/tablebody.md +258 -0
- package/.llm/components/tablecell.md +248 -0
- package/.llm/components/tablehead.md +248 -0
- package/.llm/components/tableheadercell.md +298 -0
- package/.llm/components/tablerow.md +285 -0
- package/.llm/components/tablist.md +210 -0
- package/.llm/components/textarea.md +362 -0
- package/.llm/components/textinput.md +467 -0
- package/.llm/components/tooltip.md +267 -0
- package/.llm/components/typography.md +245 -0
- package/.llm/digest/accordion.md +43 -0
- package/.llm/digest/accordionitem.md +47 -0
- package/.llm/digest/aspectratio.md +47 -0
- package/.llm/digest/badge.md +45 -0
- package/.llm/digest/bottomsheet.md +69 -0
- package/.llm/digest/breadcrumb.md +38 -0
- package/.llm/digest/breadcrumbitem.md +43 -0
- package/.llm/digest/button.md +48 -0
- package/.llm/digest/buttonicon.md +61 -0
- package/.llm/digest/card.md +50 -0
- package/.llm/digest/cardbody.md +68 -0
- package/.llm/digest/cardbutton.md +49 -0
- package/.llm/digest/checkbox.md +63 -0
- package/.llm/digest/divider.md +52 -0
- package/.llm/digest/dropdownmenu.md +67 -0
- package/.llm/digest/filterchip.md +68 -0
- package/.llm/digest/footer.md +57 -0
- package/.llm/digest/footergroup.md +42 -0
- package/.llm/digest/grid.md +62 -0
- package/.llm/digest/icon.md +45 -0
- package/.llm/digest/link.md +59 -0
- package/.llm/digest/menuitem.md +46 -0
- package/.llm/digest/navbar.md +60 -0
- package/.llm/digest/navbaritem.md +54 -0
- package/.llm/digest/navbarmenu.md +54 -0
- package/.llm/digest/navbarmenugroup.md +40 -0
- package/.llm/digest/navbarpanel.md +53 -0
- package/.llm/digest/navbarswitcher.md +51 -0
- package/.llm/digest/navbarswitcheroption.md +37 -0
- package/.llm/digest/option.md +54 -0
- package/.llm/digest/pagination.md +71 -0
- package/.llm/digest/removablechip.md +51 -0
- package/.llm/digest/row.md +60 -0
- package/.llm/digest/scroller.md +59 -0
- package/.llm/digest/searchinput.md +56 -0
- package/.llm/digest/segmentedcontrol.md +59 -0
- package/.llm/digest/segmentedcontrolitem.md +59 -0
- package/.llm/digest/select.md +92 -0
- package/.llm/digest/selectchip.md +68 -0
- package/.llm/digest/spinner.md +52 -0
- package/.llm/digest/stack.md +56 -0
- package/.llm/digest/statusdot.md +46 -0
- package/.llm/digest/subdomainnavbar.md +54 -0
- package/.llm/digest/tab.md +60 -0
- package/.llm/digest/table.md +71 -0
- package/.llm/digest/tablebody.md +49 -0
- package/.llm/digest/tablecell.md +55 -0
- package/.llm/digest/tablehead.md +50 -0
- package/.llm/digest/tableheadercell.md +65 -0
- package/.llm/digest/tablerow.md +56 -0
- package/.llm/digest/tablist.md +46 -0
- package/.llm/digest/textarea.md +78 -0
- package/.llm/digest/textinput.md +95 -0
- package/.llm/digest/tooltip.md +58 -0
- package/.llm/digest/typography.md +59 -0
- package/.llm/index.md +86 -0
- package/.llm/rules.md +122 -0
- package/.llm/tokens.md +341 -0
- package/AGENTS.md +164 -0
- package/LICENSE +21 -0
- package/README.md +63 -15
- package/dist/components/core/accordion/Accordion.css +10 -0
- package/dist/components/core/accordion/Accordion.d.ts +20 -0
- package/dist/components/core/accordion/Accordion.js +69 -0
- package/dist/components/core/accordion/Accordion.types.d.ts +20 -0
- package/dist/components/core/accordion/Accordion.types.js +7 -0
- package/dist/components/core/accordion-item/AccordionItem.css +98 -0
- package/dist/components/core/accordion-item/AccordionItem.d.ts +44 -0
- package/dist/components/core/accordion-item/AccordionItem.js +63 -0
- package/dist/components/core/accordion-item/AccordionItem.types.d.ts +32 -0
- package/dist/components/core/accordion-item/AccordionItem.types.js +13 -0
- package/dist/components/core/accordion-item/accordion-item-impl.css +107 -0
- package/dist/components/core/badge/Badge.css +37 -0
- package/dist/components/core/badge/Badge.d.ts +37 -0
- package/dist/components/core/badge/Badge.js +40 -0
- package/dist/components/core/badge/Badge.types.d.ts +24 -0
- package/dist/components/core/badge/Badge.types.js +8 -0
- package/dist/components/core/badge/badge-impl.css +32 -0
- package/dist/components/core/bottom-sheet/BottomSheet.css +178 -0
- package/dist/components/core/bottom-sheet/BottomSheet.d.ts +22 -0
- package/dist/components/core/bottom-sheet/BottomSheet.js +359 -0
- package/dist/components/core/bottom-sheet/BottomSheet.types.d.ts +67 -0
- package/dist/components/core/bottom-sheet/BottomSheet.types.js +18 -0
- package/dist/components/core/bottom-sheet/bottom-sheet-impl.css +57 -0
- package/dist/components/core/breadcrumb/Breadcrumb.css +19 -0
- package/dist/components/core/breadcrumb/Breadcrumb.d.ts +16 -0
- package/dist/components/core/breadcrumb/Breadcrumb.js +22 -0
- package/dist/components/core/breadcrumb/Breadcrumb.types.d.ts +18 -0
- package/dist/components/core/breadcrumb/Breadcrumb.types.js +9 -0
- package/dist/components/core/breadcrumb-item/BreadcrumbItem.css +34 -0
- package/dist/components/core/breadcrumb-item/BreadcrumbItem.d.ts +12 -0
- package/dist/components/core/breadcrumb-item/BreadcrumbItem.js +15 -0
- package/dist/components/core/breadcrumb-item/BreadcrumbItem.types.d.ts +22 -0
- package/dist/components/core/breadcrumb-item/BreadcrumbItem.types.js +9 -0
- package/dist/components/core/button/Button.css +141 -0
- package/dist/components/core/button/Button.d.ts +25 -0
- package/dist/components/core/button/Button.js +28 -0
- package/dist/components/core/button/Button.types.d.ts +40 -0
- package/dist/components/core/button/Button.types.js +9 -0
- package/dist/components/core/button/button-impl.css +46 -0
- package/dist/components/core/button-icon/ButtonIcon.css +135 -0
- package/dist/components/core/button-icon/ButtonIcon.d.ts +34 -0
- package/dist/components/core/button-icon/ButtonIcon.js +117 -0
- package/dist/components/core/button-icon/ButtonIcon.types.d.ts +41 -0
- package/dist/components/core/button-icon/ButtonIcon.types.js +8 -0
- package/dist/components/core/card/Card.css +65 -0
- package/dist/components/core/card/Card.d.ts +24 -0
- package/dist/components/core/card/Card.js +26 -0
- package/dist/components/core/card/Card.types.d.ts +33 -0
- package/dist/components/core/card/Card.types.js +7 -0
- package/dist/components/core/card-body/CardBody.css +139 -0
- package/dist/components/core/card-body/CardBody.d.ts +62 -0
- package/dist/components/core/card-body/CardBody.js +97 -0
- package/dist/components/core/card-body/CardBody.types.d.ts +61 -0
- package/dist/components/core/card-body/CardBody.types.js +15 -0
- package/dist/components/core/card-body/card-body-impl.css +87 -0
- package/dist/components/core/card-button/CardButton.css +73 -0
- package/dist/components/core/card-button/CardButton.d.ts +27 -0
- package/dist/components/core/card-button/CardButton.js +37 -0
- package/dist/components/core/card-button/CardButton.types.d.ts +24 -0
- package/dist/components/core/card-button/CardButton.types.js +7 -0
- package/dist/components/core/card-button/card-button-impl.css +39 -0
- package/dist/components/core/checkbox/Checkbox.css +149 -0
- package/dist/components/core/checkbox/Checkbox.d.ts +21 -0
- package/dist/components/core/checkbox/Checkbox.js +97 -0
- package/dist/components/core/checkbox/Checkbox.types.d.ts +46 -0
- package/dist/components/core/checkbox/Checkbox.types.js +15 -0
- package/dist/components/core/checkbox/checkbox-impl.css +90 -0
- package/dist/components/core/divider/Divider.css +41 -0
- package/dist/components/core/divider/Divider.d.ts +46 -0
- package/dist/components/core/divider/Divider.js +51 -0
- package/dist/components/core/divider/Divider.types.d.ts +25 -0
- package/dist/components/core/divider/Divider.types.js +9 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.css +146 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.d.ts +22 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.js +309 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.types.d.ts +62 -0
- package/dist/components/core/dropdown-menu/DropdownMenu.types.js +12 -0
- package/dist/components/core/dropdown-menu/dropdown-menu-impl.css +70 -0
- package/dist/components/core/filter-chip/FilterChip.css +149 -0
- package/dist/components/core/filter-chip/FilterChip.d.ts +23 -0
- package/dist/components/core/filter-chip/FilterChip.js +37 -0
- package/dist/components/core/filter-chip/FilterChip.types.d.ts +53 -0
- package/dist/components/core/filter-chip/FilterChip.types.js +12 -0
- package/dist/components/core/footer/Footer.css +104 -0
- package/dist/components/core/footer/Footer.d.ts +43 -0
- package/dist/components/core/footer/Footer.js +53 -0
- package/dist/components/core/footer/Footer.types.d.ts +47 -0
- package/dist/components/core/footer/Footer.types.js +18 -0
- package/dist/components/core/footer/footer-impl.css +218 -0
- package/dist/components/core/footer-group/FooterGroup.css +90 -0
- package/dist/components/core/footer-group/FooterGroup.d.ts +32 -0
- package/dist/components/core/footer-group/FooterGroup.js +64 -0
- package/dist/components/core/footer-group/FooterGroup.types.d.ts +25 -0
- package/dist/components/core/footer-group/FooterGroup.types.js +12 -0
- package/dist/components/core/footer-group/footer-group-impl.css +78 -0
- package/dist/components/core/icon/Icon.css +40 -0
- package/dist/components/core/icon/Icon.d.ts +23 -0
- package/dist/components/core/icon/Icon.js +79 -0
- package/dist/components/core/icon/Icon.types.d.ts +24 -0
- package/dist/components/core/icon/Icon.types.js +7 -0
- package/dist/components/core/link/Link.css +89 -0
- package/dist/components/core/link/Link.d.ts +37 -0
- package/dist/components/core/link/Link.js +141 -0
- package/dist/components/core/link/Link.types.d.ts +41 -0
- package/dist/components/core/link/Link.types.js +9 -0
- package/dist/components/core/link/link-impl.css +168 -0
- package/dist/components/core/menu-item/MenuItem.css +70 -0
- package/dist/components/core/menu-item/MenuItem.d.ts +11 -0
- package/dist/components/core/menu-item/MenuItem.js +26 -0
- package/dist/components/core/menu-item/MenuItem.types.d.ts +28 -0
- package/dist/components/core/menu-item/MenuItem.types.js +9 -0
- package/dist/components/core/navbar/Navbar.css +135 -0
- package/dist/components/core/navbar/Navbar.d.ts +36 -0
- package/dist/components/core/navbar/Navbar.js +371 -0
- package/dist/components/core/navbar/Navbar.types.d.ts +49 -0
- package/dist/components/core/navbar/Navbar.types.js +17 -0
- package/dist/components/core/navbar/navbar-impl.css +590 -0
- package/dist/components/core/navbar-item/NavbarItem.css +75 -0
- package/dist/components/core/navbar-item/NavbarItem.d.ts +22 -0
- package/dist/components/core/navbar-item/NavbarItem.js +40 -0
- package/dist/components/core/navbar-item/NavbarItem.types.d.ts +34 -0
- package/dist/components/core/navbar-item/NavbarItem.types.js +10 -0
- package/dist/components/core/navbar-menu/NavbarMenu.css +128 -0
- package/dist/components/core/navbar-menu/NavbarMenu.d.ts +5 -0
- package/dist/components/core/navbar-menu/NavbarMenu.js +186 -0
- package/dist/components/core/navbar-menu/NavbarMenu.types.d.ts +45 -0
- package/dist/components/core/navbar-menu/NavbarMenu.types.js +12 -0
- package/dist/components/core/navbar-menu/navbar-menu-impl.css +186 -0
- package/dist/components/core/navbar-menu-group/NavbarMenuGroup.css +26 -0
- package/dist/components/core/navbar-menu-group/NavbarMenuGroup.d.ts +17 -0
- package/dist/components/core/navbar-menu-group/NavbarMenuGroup.js +22 -0
- package/dist/components/core/navbar-menu-group/NavbarMenuGroup.types.d.ts +14 -0
- package/dist/components/core/navbar-menu-group/NavbarMenuGroup.types.js +7 -0
- package/dist/components/core/navbar-panel/NavbarPanel.css +87 -0
- package/dist/components/core/navbar-panel/NavbarPanel.d.ts +34 -0
- package/dist/components/core/navbar-panel/NavbarPanel.js +46 -0
- package/dist/components/core/navbar-panel/NavbarPanel.types.d.ts +29 -0
- package/dist/components/core/navbar-panel/NavbarPanel.types.js +12 -0
- package/dist/components/core/navbar-panel/navbar-panel-impl.css +104 -0
- package/dist/components/core/navbar-panel/use-navbar-panel.d.ts +26 -0
- package/dist/components/core/navbar-panel/use-navbar-panel.js +135 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.css +117 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.d.ts +20 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.js +90 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.types.d.ts +46 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.types.js +13 -0
- package/dist/components/core/navbar-switcher/navbar-switcher-impl.css +179 -0
- package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.css +39 -0
- package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.d.ts +16 -0
- package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.js +19 -0
- package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.types.d.ts +18 -0
- package/dist/components/core/navbar-switcher-option/NavbarSwitcherOption.types.js +7 -0
- package/dist/components/core/option/Option.css +133 -0
- package/dist/components/core/option/Option.d.ts +25 -0
- package/dist/components/core/option/Option.js +31 -0
- package/dist/components/core/option/Option.types.d.ts +44 -0
- package/dist/components/core/option/Option.types.js +14 -0
- package/dist/components/core/pagination/Pagination.css +237 -0
- package/dist/components/core/pagination/Pagination.d.ts +30 -0
- package/dist/components/core/pagination/Pagination.js +406 -0
- package/dist/components/core/pagination/Pagination.types.d.ts +59 -0
- package/dist/components/core/pagination/Pagination.types.js +14 -0
- package/dist/components/core/pagination/pagination-impl.css +17 -0
- package/dist/components/core/removable-chip/RemovableChip.css +125 -0
- package/dist/components/core/removable-chip/RemovableChip.d.ts +25 -0
- package/dist/components/core/removable-chip/RemovableChip.js +36 -0
- package/dist/components/core/removable-chip/RemovableChip.types.d.ts +38 -0
- package/dist/components/core/removable-chip/RemovableChip.types.js +13 -0
- package/dist/components/core/search-input/SearchInput.css +205 -0
- package/dist/components/core/search-input/SearchInput.d.ts +5 -0
- package/dist/components/core/search-input/SearchInput.js +81 -0
- package/dist/components/core/search-input/SearchInput.types.d.ts +43 -0
- package/dist/components/core/search-input/SearchInput.types.js +13 -0
- package/dist/components/core/search-input/search-input-impl.css +20 -0
- package/dist/components/core/segmented-control/SegmentedControl.css +57 -0
- package/dist/components/core/segmented-control/SegmentedControl.d.ts +37 -0
- package/dist/components/core/segmented-control/SegmentedControl.js +269 -0
- package/dist/components/core/segmented-control/SegmentedControl.types.d.ts +38 -0
- package/dist/components/core/segmented-control/SegmentedControl.types.js +8 -0
- package/dist/components/core/segmented-control/segmented-control-impl.css +57 -0
- package/dist/components/core/segmented-control-item/SegmentedControlItem.css +151 -0
- package/dist/components/core/segmented-control-item/SegmentedControlItem.d.ts +50 -0
- package/dist/components/core/segmented-control-item/SegmentedControlItem.js +101 -0
- package/dist/components/core/segmented-control-item/SegmentedControlItem.types.d.ts +37 -0
- package/dist/components/core/segmented-control-item/SegmentedControlItem.types.js +10 -0
- package/dist/components/core/segmented-control-item/segmented-control-item-impl.css +69 -0
- package/dist/components/core/select/Select.css +400 -0
- package/dist/components/core/select/Select.d.ts +29 -0
- package/dist/components/core/select/Select.js +524 -0
- package/dist/components/core/select/Select.types.d.ts +96 -0
- package/dist/components/core/select/Select.types.js +26 -0
- package/dist/components/core/select/select-impl.css +114 -0
- package/dist/components/core/select-chip/SelectChip.css +155 -0
- package/dist/components/core/select-chip/SelectChip.d.ts +20 -0
- package/dist/components/core/select-chip/SelectChip.js +273 -0
- package/dist/components/core/select-chip/SelectChip.types.d.ts +56 -0
- package/dist/components/core/select-chip/SelectChip.types.js +14 -0
- package/dist/components/core/select-chip/select-chip-impl.css +38 -0
- package/dist/components/core/spinner/Spinner.css +76 -0
- package/dist/components/core/spinner/Spinner.d.ts +5 -0
- package/dist/components/core/spinner/Spinner.js +29 -0
- package/dist/components/core/spinner/Spinner.types.d.ts +37 -0
- package/dist/components/core/spinner/Spinner.types.js +10 -0
- package/dist/components/core/spinner/spinner-impl.css +27 -0
- package/dist/components/core/status-dot/StatusDot.css +43 -0
- package/dist/components/core/status-dot/StatusDot.d.ts +35 -0
- package/dist/components/core/status-dot/StatusDot.js +46 -0
- package/dist/components/core/status-dot/StatusDot.types.d.ts +29 -0
- package/dist/components/core/status-dot/StatusDot.types.js +7 -0
- package/dist/components/core/status-dot/status-dot-impl.css +42 -0
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.css +89 -0
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.d.ts +21 -0
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.js +127 -0
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.types.d.ts +43 -0
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.types.js +13 -0
- package/dist/components/core/subdomain-navbar/subdomain-navbar-impl.css +147 -0
- package/dist/components/core/tab/Tab.css +113 -0
- package/dist/components/core/tab/Tab.d.ts +36 -0
- package/dist/components/core/tab/Tab.js +53 -0
- package/dist/components/core/tab/Tab.types.d.ts +42 -0
- package/dist/components/core/tab/Tab.types.js +13 -0
- package/dist/components/core/tab/tab-impl.css +49 -0
- package/dist/components/core/tab-list/TabList.css +40 -0
- package/dist/components/core/tab-list/TabList.d.ts +26 -0
- package/dist/components/core/tab-list/TabList.js +124 -0
- package/dist/components/core/tab-list/TabList.types.d.ts +20 -0
- package/dist/components/core/tab-list/TabList.types.js +7 -0
- package/dist/components/core/tab-list/tab-list-impl.css +56 -0
- package/dist/components/core/table/Table.css +40 -0
- package/dist/components/core/table/Table.d.ts +19 -0
- package/dist/components/core/table/Table.js +55 -0
- package/dist/components/core/table/Table.types.d.ts +59 -0
- package/dist/components/core/table/Table.types.js +9 -0
- package/dist/components/core/table/table-impl.css +75 -0
- package/dist/components/core/table/use-table-sort.d.ts +43 -0
- package/dist/components/core/table/use-table-sort.js +51 -0
- package/dist/components/core/table-body/TableBody.css +6 -0
- package/dist/components/core/table-body/TableBody.d.ts +12 -0
- package/dist/components/core/table-body/TableBody.js +26 -0
- package/dist/components/core/table-body/TableBody.types.d.ts +36 -0
- package/dist/components/core/table-body/TableBody.types.js +7 -0
- package/dist/components/core/table-cell/TableCell.css +76 -0
- package/dist/components/core/table-cell/TableCell.d.ts +21 -0
- package/dist/components/core/table-cell/TableCell.js +31 -0
- package/dist/components/core/table-cell/TableCell.types.d.ts +43 -0
- package/dist/components/core/table-cell/TableCell.types.js +7 -0
- package/dist/components/core/table-head/TableHead.css +6 -0
- package/dist/components/core/table-head/TableHead.d.ts +22 -0
- package/dist/components/core/table-head/TableHead.js +52 -0
- package/dist/components/core/table-head/TableHead.types.d.ts +39 -0
- package/dist/components/core/table-head/TableHead.types.js +7 -0
- package/dist/components/core/table-head/table-head-impl.css +51 -0
- package/dist/components/core/table-header-cell/TableHeaderCell.css +126 -0
- package/dist/components/core/table-header-cell/TableHeaderCell.d.ts +21 -0
- package/dist/components/core/table-header-cell/TableHeaderCell.js +34 -0
- package/dist/components/core/table-header-cell/TableHeaderCell.types.d.ts +56 -0
- package/dist/components/core/table-header-cell/TableHeaderCell.types.js +9 -0
- package/dist/components/core/table-header-cell/table-header-cell-impl.css +74 -0
- package/dist/components/core/table-row/TableRow.css +18 -0
- package/dist/components/core/table-row/TableRow.d.ts +17 -0
- package/dist/components/core/table-row/TableRow.js +32 -0
- package/dist/components/core/table-row/TableRow.types.d.ts +45 -0
- package/dist/components/core/table-row/TableRow.types.js +7 -0
- package/dist/components/core/table-row/table-row-impl.css +31 -0
- package/dist/components/core/text-area/TextArea.css +325 -0
- package/dist/components/core/text-area/TextArea.d.ts +13 -0
- package/dist/components/core/text-area/TextArea.js +133 -0
- package/dist/components/core/text-area/TextArea.types.d.ts +67 -0
- package/dist/components/core/text-area/TextArea.types.js +19 -0
- package/dist/components/core/text-area/text-area-impl.css +36 -0
- package/dist/components/core/text-input/TextInput.css +400 -0
- package/dist/components/core/text-input/TextInput.d.ts +5 -0
- package/dist/components/core/text-input/TextInput.js +130 -0
- package/dist/components/core/text-input/TextInput.types.d.ts +96 -0
- package/dist/components/core/text-input/TextInput.types.js +24 -0
- package/dist/components/core/text-input/text-input-impl.css +36 -0
- package/dist/components/core/tooltip/Tooltip.css +101 -0
- package/dist/components/core/tooltip/Tooltip.d.ts +51 -0
- package/dist/components/core/tooltip/Tooltip.js +87 -0
- package/dist/components/core/tooltip/Tooltip.types.d.ts +38 -0
- package/dist/components/core/tooltip/Tooltip.types.js +9 -0
- package/dist/components/core/tooltip/TooltipAnchor.d.ts +52 -0
- package/dist/components/core/tooltip/TooltipAnchor.js +69 -0
- package/dist/components/core/tooltip/tooltip-anchor.css +145 -0
- package/dist/components/core/tooltip/tooltip-impl.css +54 -0
- package/dist/components/core/tooltip/use-tooltip.d.ts +111 -0
- package/dist/components/core/tooltip/use-tooltip.js +189 -0
- package/dist/components/core/typography/Typography.css +96 -0
- package/dist/components/core/typography/Typography.d.ts +297 -0
- package/dist/components/core/typography/Typography.js +28 -0
- package/dist/components/core/typography/Typography.types.d.ts +40 -0
- package/dist/components/core/typography/Typography.types.js +7 -0
- package/dist/components/css-time.d.ts +20 -0
- package/dist/components/css-time.js +30 -0
- package/dist/components/given.d.ts +7 -0
- package/dist/components/given.js +9 -0
- package/dist/components/hover-open.d.ts +34 -0
- package/dist/components/hover-open.js +90 -0
- package/dist/components/index.d.ts +114 -1
- package/dist/components/index.js +115 -2
- package/dist/components/layout/aspect-ratio/AspectRatio.css +29 -0
- package/dist/components/layout/aspect-ratio/AspectRatio.d.ts +24 -0
- package/dist/components/layout/aspect-ratio/AspectRatio.js +26 -0
- package/dist/components/layout/aspect-ratio/AspectRatio.types.d.ts +22 -0
- package/dist/components/layout/aspect-ratio/AspectRatio.types.js +7 -0
- package/dist/components/layout/aspect-ratio/aspect-ratio-impl.css +44 -0
- package/dist/components/layout/grid/Grid.css +76 -0
- package/dist/components/layout/grid/Grid.d.ts +31 -0
- package/dist/components/layout/grid/Grid.js +33 -0
- package/dist/components/layout/grid/Grid.types.d.ts +48 -0
- package/dist/components/layout/grid/Grid.types.js +7 -0
- package/dist/components/layout/grid/grid-impl.css +62 -0
- package/dist/components/layout/row/Row.css +85 -0
- package/dist/components/layout/row/Row.d.ts +32 -0
- package/dist/components/layout/row/Row.js +34 -0
- package/dist/components/layout/row/Row.types.d.ts +45 -0
- package/dist/components/layout/row/Row.types.js +7 -0
- package/dist/components/layout/scroller/Scroller.css +59 -0
- package/dist/components/layout/scroller/Scroller.d.ts +34 -0
- package/dist/components/layout/scroller/Scroller.js +36 -0
- package/dist/components/layout/scroller/Scroller.types.d.ts +38 -0
- package/dist/components/layout/scroller/Scroller.types.js +7 -0
- package/dist/components/layout/scroller/scroller-impl.css +45 -0
- package/dist/components/layout/stack/Stack.css +73 -0
- package/dist/components/layout/stack/Stack.d.ts +28 -0
- package/dist/components/layout/stack/Stack.js +30 -0
- package/dist/components/layout/stack/Stack.types.d.ts +41 -0
- package/dist/components/layout/stack/Stack.types.js +7 -0
- package/dist/components/visually-hidden.d.ts +22 -0
- package/dist/components/visually-hidden.js +31 -0
- package/dist/fonts/LICENSE-inter.txt +93 -0
- package/dist/fonts/LICENSE-red-hat-mono.txt +93 -0
- package/dist/fonts/fonts.css +111 -0
- package/dist/fonts/inter-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-cyrillic-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-greek-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-greek-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-vietnamese-wght-normal.woff2 +0 -0
- package/dist/fonts/red-hat-mono-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/red-hat-mono-latin-wght-normal.woff2 +0 -0
- package/dist/marketing.css +289 -241
- package/package.json +18 -4
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Children, cloneElement, isValidElement, useCallback, useEffect, useLayoutEffect, useRef, useState, } from 'react';
|
|
4
|
+
import './TabList.css';
|
|
5
|
+
import './tab-list-impl.css';
|
|
6
|
+
import { tabParts } from '../tab/Tab.types.js';
|
|
7
|
+
import { tabListParts } from './TabList.types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Both handlers, the tab's own first.
|
|
10
|
+
*
|
|
11
|
+
* `cloneElement` replaces rather than merges, so a tab already reporting its own
|
|
12
|
+
* presses would silently stop — and that is the handler a page is most likely to
|
|
13
|
+
* have written, since it is how they learn which tab was pressed.
|
|
14
|
+
*/
|
|
15
|
+
function chain(theirs, ours) {
|
|
16
|
+
if (theirs === undefined)
|
|
17
|
+
return ours;
|
|
18
|
+
return (value) => {
|
|
19
|
+
theirs(value);
|
|
20
|
+
ours(value);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A strip of comparable versions of one thing, and the two things that belong to
|
|
25
|
+
* the set rather than to any tab: which is current, and where the bar sits.
|
|
26
|
+
*
|
|
27
|
+
* Controlled, and only controlled. The strip holds no selection state because the
|
|
28
|
+
* choice is not its to hold — the page renders whichever slice matches, so the
|
|
29
|
+
* page is where the answer lives. A private copy would be a second source of
|
|
30
|
+
* truth for the same question, and the two would disagree the first time the page
|
|
31
|
+
* set it from anywhere else. Product's keeps an uncontrolled mode because an app
|
|
32
|
+
* tab strip often has nothing else holding the view; here there always is.
|
|
33
|
+
*
|
|
34
|
+
* A `value` naming no tab selects none of them. Falling back to the first would
|
|
35
|
+
* tell the reader they are looking at a version they did not ask for, while the
|
|
36
|
+
* page beneath showed something else.
|
|
37
|
+
*
|
|
38
|
+
* `role="group"` with a name. Not `role="tablist"` — that names a widget whose
|
|
39
|
+
* tabs own panels through `aria-controls`, and the panels here belong to the
|
|
40
|
+
* page, so it is a promise this component cannot keep. Not `role="navigation"`
|
|
41
|
+
* either: a landmark says the items go places, and these change what is showing
|
|
42
|
+
* on the page the reader is already on.
|
|
43
|
+
*/
|
|
44
|
+
export function TabList({ label, value, onChange, children, ...rest }) {
|
|
45
|
+
const listRef = useRef(null);
|
|
46
|
+
const [bar, setBar] = useState(null);
|
|
47
|
+
const tabs = Children.toArray(children).filter((isValidElement));
|
|
48
|
+
/*
|
|
49
|
+
Seeded from whichever tab arrived selected, and from the first tab when none
|
|
50
|
+
did. A strip always has a current one: it is showing a slice of the page
|
|
51
|
+
either way, so a strip marking nothing would be a page whose content had no
|
|
52
|
+
heading over it.
|
|
53
|
+
|
|
54
|
+
This is not the rule about a value naming no tab. That one is about a page
|
|
55
|
+
asking for something that is not here, which is a mistake worth showing
|
|
56
|
+
rather than papering over. This is about nobody having asked at all.
|
|
57
|
+
*/
|
|
58
|
+
const [picked, setPicked] = useState(() => tabs.find((tab) => tab.props.selected === true)?.props.value ?? tabs[0]?.props.value ?? null);
|
|
59
|
+
const controlled = value !== undefined;
|
|
60
|
+
const current = controlled ? value : picked;
|
|
61
|
+
const active = tabs.findIndex((tab) => tab.props.value !== undefined && tab.props.value === current);
|
|
62
|
+
const measure = useCallback(() => {
|
|
63
|
+
const list = listRef.current;
|
|
64
|
+
if (list === null)
|
|
65
|
+
return;
|
|
66
|
+
if (active === -1) {
|
|
67
|
+
setBar(null);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
/*
|
|
71
|
+
Queried rather than indexed into `children`: the bar is a child of this
|
|
72
|
+
element too, so the nth child and the nth tab stopped being the same thing
|
|
73
|
+
the moment it arrived.
|
|
74
|
+
|
|
75
|
+
The content box rather than the tab, so the mark is as wide as the words
|
|
76
|
+
instead of running out under the pill's padding. Read off Tab's own
|
|
77
|
+
generated constant rather than typed out here — the class belongs to
|
|
78
|
+
another component, and a literal would make this measurement depend on a
|
|
79
|
+
name nothing checks: rename the part and the bar stops working with every
|
|
80
|
+
gate still green.
|
|
81
|
+
*/
|
|
82
|
+
const items = list.querySelectorAll(`:scope > .${tabParts.root}`);
|
|
83
|
+
const content = items[active]?.querySelector(`.${tabParts.content}`);
|
|
84
|
+
if (content === null || content === undefined) {
|
|
85
|
+
setBar(null);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// offsetLeft is measured from the nearest positioned ancestor, which the
|
|
89
|
+
// contract makes the list — so this is content-relative and travels with the
|
|
90
|
+
// scroll rather than needing it subtracted.
|
|
91
|
+
setBar({ along: content.offsetLeft, length: content.offsetWidth });
|
|
92
|
+
}, [active]);
|
|
93
|
+
// Layout rather than a plain effect: between the two the bar would be painted
|
|
94
|
+
// at its previous place, which is a frame of the mark under the wrong tab.
|
|
95
|
+
useLayoutEffect(measure, [measure, tabs.length]);
|
|
96
|
+
/*
|
|
97
|
+
The strip changing shape moves the tab underneath the bar.
|
|
98
|
+
|
|
99
|
+
Absent where there is no ResizeObserver rather than fatal — the bar stays
|
|
100
|
+
where the last measurement put it, which is correct until something resizes.
|
|
101
|
+
jsdom is the environment that asks: the generated behaviour test runs there.
|
|
102
|
+
*/
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
const list = listRef.current;
|
|
105
|
+
if (list === null)
|
|
106
|
+
return;
|
|
107
|
+
if (typeof ResizeObserver === 'undefined')
|
|
108
|
+
return;
|
|
109
|
+
const observer = new ResizeObserver(() => measure());
|
|
110
|
+
observer.observe(list);
|
|
111
|
+
return () => observer.disconnect();
|
|
112
|
+
}, [measure]);
|
|
113
|
+
return (_jsx("div", { ...rest, className: tabListParts.root, role: "group", "aria-label": label, children: _jsxs("div", { className: tabListParts.list, ref: listRef, children: [tabs.map((tab, index) => cloneElement(tab, {
|
|
114
|
+
selected: index === active,
|
|
115
|
+
onSelect: chain(tab.props.onSelect, (pressed) => {
|
|
116
|
+
// The strip records the choice only when nobody else is holding it.
|
|
117
|
+
// A controlled strip that also moved its own copy would have two
|
|
118
|
+
// answers to one question and show the stale one for a frame.
|
|
119
|
+
if (!controlled)
|
|
120
|
+
setPicked(pressed);
|
|
121
|
+
onChange?.(pressed);
|
|
122
|
+
}),
|
|
123
|
+
})), _jsx("span", { className: tabListParts.indicator, hidden: bar === null, style: bar === null ? undefined : { inlineSize: `${bar.length}px`, translate: `${bar.along}px` } })] }) }));
|
|
124
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface TabListOwnProps {
|
|
3
|
+
/** Always — a group with no name is a group a screen reader announces as nothing, and the reader is told there is a set without being told what it is a set of. Name what the tabs switch between rather than the act of switching: 'Billing period', not 'Choose a billing period' */
|
|
4
|
+
label: string;
|
|
5
|
+
/** The page is holding which tab is current, because the choice also drives what is rendered beneath the strip — the ordinary case here. Passing it makes the strip controlled: it shows what it is told and reports presses through onChange.
|
|
6
|
+
|
|
7
|
+
Leave it off and the strip holds its own answer, seeded from whichever tab arrived selected and from the first tab when none did. That is for a strip whose slices are all on the page already and only need showing one at a time, and it is what Accordion does with its rows. */
|
|
8
|
+
value?: string;
|
|
9
|
+
/** Whenever value is — together they are how a page holds the choice. It is called with the pressed tab's value after that tab's own onSelect, so a tab that reports its own presses keeps doing so inside a set */
|
|
10
|
+
onChange?: (value: string) => void;
|
|
11
|
+
/** Allowed: Tab */
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export type TabListProps = TabListOwnProps & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'label' | 'value' | 'onChange'>;
|
|
15
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
16
|
+
export declare const tabListParts: {
|
|
17
|
+
readonly root: "dds-tablist";
|
|
18
|
+
readonly list: "dds-tablist__list";
|
|
19
|
+
readonly indicator: "dds-tablist__indicator";
|
|
20
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Scoped to this package, like the generated sheet beside it.
|
|
3
|
+
*
|
|
4
|
+
* `:where([data-dds-context="marketing"])` confines these rules without contributing
|
|
5
|
+
* specificity, so every override below still ties or beats exactly what it did
|
|
6
|
+
* before — several here are written a class deeper than they look in order to
|
|
7
|
+
* match generated CSS, and a scope that carried weight would break all of them.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/* Implementation CSS that the contract's staticCss cannot express. */
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* The strip overlaps its own rail by the rail's own thickness.
|
|
14
|
+
*
|
|
15
|
+
* The rail is the root's `border-block-end` and the bar is the last thing inside the list,
|
|
16
|
+
* so by default they stack: a 1px line with a 4px bar sitting on top of it and a visible
|
|
17
|
+
* seam between the two. Pulling the list down by exactly the rail's width closes it — the
|
|
18
|
+
* border moves up under the list's last row, and a child paints over its parent's border,
|
|
19
|
+
* so the bar covers the line rather than butting against it. Where no tab is current the
|
|
20
|
+
* rail shows through unbroken, which is the point.
|
|
21
|
+
*
|
|
22
|
+
* On the list rather than on the bar, and that matters: the list is `overflow-x: auto`,
|
|
23
|
+
* which makes its block axis `auto` too, so a bar hanging 1px past the bottom would be
|
|
24
|
+
* clipped there or earn a vertical scrollbar. Moving the whole row keeps every box inside
|
|
25
|
+
* its own scroll container.
|
|
26
|
+
*
|
|
27
|
+
* Not a token and not expressible as one: this is the negation of another value rather than
|
|
28
|
+
* a value of its own, and it reads that value rather than repeating it — retune
|
|
29
|
+
* border.width.default and the overlap follows without anything here being touched. No
|
|
30
|
+
* contract can hold a negative dimension, which is why it is here at all.
|
|
31
|
+
*/
|
|
32
|
+
:where([data-dds-context="marketing"]) .dds-tablist .dds-tablist__list {
|
|
33
|
+
margin-block-end: calc(var(--border-width-default) * -1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/*
|
|
37
|
+
* What the bar's travel is made of.
|
|
38
|
+
*
|
|
39
|
+
* `transition-property` is a list of property names, which no token can be — so it is here,
|
|
40
|
+
* while how long the travel takes and on what curve are decisions and live in the contract
|
|
41
|
+
* as motion.duration.normal and motion.easing.standard. The reduced-motion guard the
|
|
42
|
+
* generator writes covers `.dds-tablist *`, so this is switched off with everything else.
|
|
43
|
+
*
|
|
44
|
+
* `translate` and `inline-size` rather than `left` and `width`: those are the properties the
|
|
45
|
+
* bar is actually set with, and translate is the one a browser can animate without laying
|
|
46
|
+
* the row out again on every frame.
|
|
47
|
+
*
|
|
48
|
+
* Two classes deep. The emitter writes a `transition-property` of its own only for
|
|
49
|
+
* properties that vary by a state or a boolean axis, and nothing on this part varies by
|
|
50
|
+
* either today — so a bare class would win. That is luck rather than correctness: give this
|
|
51
|
+
* component any boolean axis reaching the bar and the generated rule appears at two classes,
|
|
52
|
+
* outranks a bare one, and the bar stops travelling with every gate still green.
|
|
53
|
+
*/
|
|
54
|
+
:where([data-dds-context="marketing"]) .dds-tablist .dds-tablist__indicator {
|
|
55
|
+
transition-property: translate, inline-size;
|
|
56
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* GENERATED from table.contract.json. Do not edit. */
|
|
2
|
+
|
|
3
|
+
:where([data-dds-context="marketing"]) .dds-table {
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
outline-style: solid;
|
|
6
|
+
overflow-x: auto;
|
|
7
|
+
overflow-y: visible;
|
|
8
|
+
outline-width: var(--border-width-none);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
:where([data-dds-context="marketing"]) .dds-table .dds-table__grid {
|
|
12
|
+
border-collapse: separate;
|
|
13
|
+
border-spacing: 0;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
inline-size: 100%;
|
|
16
|
+
color: var(--color-fg-default);
|
|
17
|
+
font-family: var(--font-body-md-family);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
:where([data-dds-context="marketing"]) .dds-table[data-layout="auto"] .dds-table__grid {
|
|
21
|
+
table-layout: auto;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:where([data-dds-context="marketing"]) .dds-table[data-layout="fixed"] .dds-table__grid {
|
|
25
|
+
table-layout: fixed;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
:where([data-dds-context="marketing"]) .dds-table .dds-table__caption {
|
|
29
|
+
font-family: var(--font-subtitle-family);
|
|
30
|
+
font-size: var(--font-subtitle-size);
|
|
31
|
+
font-weight: var(--font-subtitle-weight);
|
|
32
|
+
line-height: var(--font-subtitle-line-height);
|
|
33
|
+
padding-block-end: var(--space-gap-md);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
:where([data-dds-context="marketing"]) .dds-table:focus-visible {
|
|
37
|
+
outline-color: var(--color-border-focus);
|
|
38
|
+
outline-width: var(--border-width-focus);
|
|
39
|
+
}
|
|
40
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import './Table.css';
|
|
2
|
+
import './table-impl.css';
|
|
3
|
+
import { type TableProps } from './Table.types.js';
|
|
4
|
+
export type { TableProps };
|
|
5
|
+
export { useTableSort, type TableSort, type TableSortDirection } from './use-table-sort.js';
|
|
6
|
+
/**
|
|
7
|
+
* Structured data in rows and columns, where every row has the same shape.
|
|
8
|
+
*
|
|
9
|
+
* It owns what the whole table shares and none of what any cell holds. `size` and `dividers` are
|
|
10
|
+
* declared here and drawn nowhere here — a table's air is its cells' padding and its rules are its
|
|
11
|
+
* rows' edges — so both are handed to the sections, which hand them on. The same cascade `List`
|
|
12
|
+
* makes to its items, one level deeper because a table has sections.
|
|
13
|
+
*
|
|
14
|
+
* It remembers nothing. Which column is sorted, which rows are picked and which columns are shown
|
|
15
|
+
* all outlive a render, so they arrive as hooks beside this component and what the table renders is
|
|
16
|
+
* whatever they answer. Composed without any of them it is a static grid, which is what a
|
|
17
|
+
* documentation page and a preview both need.
|
|
18
|
+
*/
|
|
19
|
+
export declare function Table({ layout, pinFirstColumn, size, dividers, hoverable, overflow, headerCase, caption, children, ...rest }: TableProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Children, cloneElement, isValidElement, useId } from 'react';
|
|
4
|
+
import './Table.css';
|
|
5
|
+
import './table-impl.css';
|
|
6
|
+
import { given } from '../../given.js';
|
|
7
|
+
import { tableDefaults, tableParts } from './Table.types.js';
|
|
8
|
+
// The one table hook this package ships. Product has two more beside it — row selection and
|
|
9
|
+
// column management — and neither comes over: they are how an application operates a table, and
|
|
10
|
+
// a marketing table is read rather than operated.
|
|
11
|
+
export { useTableSort } from './use-table-sort.js';
|
|
12
|
+
/**
|
|
13
|
+
* Structured data in rows and columns, where every row has the same shape.
|
|
14
|
+
*
|
|
15
|
+
* It owns what the whole table shares and none of what any cell holds. `size` and `dividers` are
|
|
16
|
+
* declared here and drawn nowhere here — a table's air is its cells' padding and its rules are its
|
|
17
|
+
* rows' edges — so both are handed to the sections, which hand them on. The same cascade `List`
|
|
18
|
+
* makes to its items, one level deeper because a table has sections.
|
|
19
|
+
*
|
|
20
|
+
* It remembers nothing. Which column is sorted, which rows are picked and which columns are shown
|
|
21
|
+
* all outlive a render, so they arrive as hooks beside this component and what the table renders is
|
|
22
|
+
* whatever they answer. Composed without any of them it is a static grid, which is what a
|
|
23
|
+
* documentation page and a preview both need.
|
|
24
|
+
*/
|
|
25
|
+
export function Table({ layout = tableDefaults.layout, pinFirstColumn = tableDefaults.pinFirstColumn, size = tableDefaults.size, dividers = tableDefaults.dividers, hoverable = tableDefaults.hoverable, overflow = tableDefaults.overflow, headerCase = tableDefaults.headerCase, caption, children, ...rest }) {
|
|
26
|
+
const named = given(caption);
|
|
27
|
+
const captionId = `${useId()}-caption`;
|
|
28
|
+
return (
|
|
29
|
+
/*
|
|
30
|
+
The scroll container, and the reason this renders two elements. A table cannot scroll
|
|
31
|
+
itself — `display: table` establishes no scroll container — so the box that does has to
|
|
32
|
+
be around it. It matters most where the screen is narrowest: the surface a table sits on
|
|
33
|
+
clips, Card holding `overflow: hidden` to keep its corner, so a table wider than its card
|
|
34
|
+
was cut off at the edge with nothing to say so and no way to reach the rest.
|
|
35
|
+
|
|
36
|
+
The spread lands here rather than on the table, because this is the element the consumer
|
|
37
|
+
is handed — the same place `className` and a ref would go.
|
|
38
|
+
*/
|
|
39
|
+
_jsx("div", { ...rest, className: tableParts.root, "data-layout": layout, "data-pin-first-column": String(pinFirstColumn),
|
|
40
|
+
/*
|
|
41
|
+
A scroll region a pointer can move and a keyboard cannot is unreachable for anybody not
|
|
42
|
+
using a mouse, and on the screens this exists for that is most of the columns. The tab
|
|
43
|
+
stop is the cost of the scroller and not optional.
|
|
44
|
+
*/
|
|
45
|
+
tabIndex: 0, role: "group", "aria-labelledby": named ? captionId : undefined, children: _jsxs("table", { className: tableParts.grid, children: [named ? (_jsx("caption", { id: captionId, className: tableParts.caption, children: caption })) : null, Children.toArray(children)
|
|
46
|
+
.filter(isValidElement)
|
|
47
|
+
.map((section, at) => cloneElement(section, {
|
|
48
|
+
key: section.key ?? at,
|
|
49
|
+
size,
|
|
50
|
+
dividers,
|
|
51
|
+
headerCase,
|
|
52
|
+
hoverable,
|
|
53
|
+
overflow,
|
|
54
|
+
}))] }) }));
|
|
55
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface TableOwnProps {
|
|
3
|
+
/**
|
|
4
|
+
* `auto` — The default. Columns take their widths from what is in them, which is right when the content is known and varied — a name column wants more room than a status one and can say so itself
|
|
5
|
+
* `fixed` — Columns take an equal share of the width whatever they hold, and the table stops re-flowing as data changes. Reach for it when rows arrive over time: with auto widths every new page of results shifts every column and the reader loses the shape they had learnt.
|
|
6
|
+
|
|
7
|
+
Equal shares is the whole of what it does here. `table-layout: fixed` exists to make declared column widths authoritative, and this component declares none — there is no per-column width to set — so three columns are a third each however unlike they are.
|
|
8
|
+
*/
|
|
9
|
+
layout?: 'auto' | 'fixed';
|
|
10
|
+
/** The first column is what identifies the row — a market, a product, a plan — and the columns after it are the values being compared. Pinned, the name stays while the numbers scroll, so a reader who has scrolled three columns out still knows which row they are reading. It is worth asking for exactly when the table is wider than the screen it is read on, which on a marketing page is most tables on a phone */
|
|
11
|
+
pinFirstColumn?: boolean;
|
|
12
|
+
/** Where nothing else names the table. A table is announced as a grid of so many rows and columns, so a reader landing inside an unnamed one has to read a cell to find out what they are in — "Open positions", "October statements". It renders a real `<caption>`, which browsers centre above the grid in bold, so it is a visible heading rather than a hidden label.
|
|
13
|
+
|
|
14
|
+
Most pages already have that heading, sitting above the table and styled by the page rather than by this component. Point at it with aria-labelledby and leave this out: two headings, one of them the browser's own idea of what a caption looks like, is worse than the one the page had. */
|
|
15
|
+
caption?: string;
|
|
16
|
+
/**
|
|
17
|
+
* `rows` — The default. A line between rows and none between columns, which is what stops the eye slipping from one row's start to another's end — the mistake a wide table invites and the one a reader never notices making
|
|
18
|
+
* `grid` — Lines both ways, for a table read as a matrix rather than as a list of records: a rate card, a comparison where the reader traces a column as often as a row. It is more lines than most tables need, so it should be asked for
|
|
19
|
+
* `none` — No lines at all. Right for two or three rows, where the rules are more structure than data, and for a table whose columns are already separated by their alignment
|
|
20
|
+
*/
|
|
21
|
+
dividers?: 'rows' | 'grid' | 'none';
|
|
22
|
+
/**
|
|
23
|
+
* `upper` — The house setting: column names in capitals, at the role that suits them. A header is read once where the data under it is read many times, and capitals are what stop it competing
|
|
24
|
+
* `title` — Names drawn as they were written, at twelve pixels. Right where the names are long, are proper nouns whose own capitals would be flattened, or are in a script with no case at all
|
|
25
|
+
*/
|
|
26
|
+
headerCase?: 'upper' | 'title';
|
|
27
|
+
/** On by default. A wash follows the pointer and says which row a press would land on, which a wide table needs and a narrow one is not harmed by: the further a row runs, the easier it is to be reading one and about to click another. Only on devices that have a pointer, which the row's own stylesheet gates */
|
|
28
|
+
hoverable?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* `wrap` — The default. Text too long for its column wraps and the row grows taller, so nothing is hidden — right whenever the value is the point and a reader has to read all of it
|
|
31
|
+
* `truncate` — Rows must stay one line high — a dense table a reader scans down, where a row that grew would break the rhythm they are scanning by. The value is clipped with an ellipsis and the whole of it is still reachable, so this trades seeing for scanning rather than losing anything
|
|
32
|
+
*/
|
|
33
|
+
overflow?: 'wrap' | 'truncate';
|
|
34
|
+
/**
|
|
35
|
+
* `sm` — Compact. Dense data a reader scans rather than reads — a ledger, a positions table, anything where fitting more rows on screen is worth more than air around each one
|
|
36
|
+
* `md` — Balanced, and the default: rows a reader moves through at reading pace, with enough room that the eye does not slip between them
|
|
37
|
+
* `lg` — Spacious. Few rows, each carrying something substantial — a plan comparison, a summary of three accounts. Reach for it when the table is the page rather than a part of it
|
|
38
|
+
*/
|
|
39
|
+
size?: 'sm' | 'md' | 'lg';
|
|
40
|
+
/** Allowed: TableHead, TableBody */
|
|
41
|
+
children: ReactNode;
|
|
42
|
+
}
|
|
43
|
+
export type TableProps = TableOwnProps & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'layout' | 'pinFirstColumn' | 'caption' | 'dividers' | 'headerCase' | 'hoverable' | 'overflow' | 'size'>;
|
|
44
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
45
|
+
export declare const tableParts: {
|
|
46
|
+
readonly root: "dds-table";
|
|
47
|
+
readonly grid: "dds-table__grid";
|
|
48
|
+
readonly caption: "dds-table__caption";
|
|
49
|
+
};
|
|
50
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
51
|
+
export declare const tableDefaults: {
|
|
52
|
+
readonly layout: "auto";
|
|
53
|
+
readonly pinFirstColumn: false;
|
|
54
|
+
readonly dividers: "rows";
|
|
55
|
+
readonly headerCase: "upper";
|
|
56
|
+
readonly hoverable: true;
|
|
57
|
+
readonly overflow: "wrap";
|
|
58
|
+
readonly size: "md";
|
|
59
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// GENERATED from table.contract.json. Do not edit.
|
|
2
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
3
|
+
export const tableParts = {
|
|
4
|
+
root: 'dds-table',
|
|
5
|
+
grid: 'dds-table__grid',
|
|
6
|
+
caption: 'dds-table__caption',
|
|
7
|
+
};
|
|
8
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
9
|
+
export const tableDefaults = { layout: 'auto', pinFirstColumn: false, dividers: 'rows', headerCase: 'upper', hoverable: true, overflow: 'wrap', size: 'md' };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Scoped to this package, like the generated sheet beside it.
|
|
3
|
+
*
|
|
4
|
+
* `:where([data-dds-context="marketing"])` confines these rules without contributing
|
|
5
|
+
* specificity, so every override below still ties or beats exactly what it did
|
|
6
|
+
* before — several here are written a class deeper than they look in order to
|
|
7
|
+
* match generated CSS, and a scope that carried weight would break all of them.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* The vertical rules, which the contract cannot bind.
|
|
12
|
+
*
|
|
13
|
+
* `border-inline-start-width` is not a property this system knows — `border-block-start-width` is,
|
|
14
|
+
* which is how a cell draws the line above it — so the horizontal rules are bindings and these are
|
|
15
|
+
* not. The measure is still the token: what is written here is which edge, not how thick.
|
|
16
|
+
*
|
|
17
|
+
* Scoped to `grid`, because that is the only value that asks for them. `rows` is a line between
|
|
18
|
+
* records and none between columns, which is what a table read as a list of records wants; `grid`
|
|
19
|
+
* is for one read as a matrix, where a reader traces a column as often as a row.
|
|
20
|
+
*/
|
|
21
|
+
:where([data-dds-context="marketing"]) .dds-table [data-dividers='grid'] {
|
|
22
|
+
border-inline-start-width: var(--border-width-hairline);
|
|
23
|
+
border-inline-end-width: 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/*
|
|
27
|
+
* Except the first cell in each row, which would otherwise draw a line down the table's own edge —
|
|
28
|
+
* inside a rounded corner, where it reads as a crack rather than as a rule.
|
|
29
|
+
*/
|
|
30
|
+
:where([data-dds-context="marketing"]) .dds-table .dds-tablerow > [data-dividers='grid']:first-child {
|
|
31
|
+
border-inline-start-width: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* The pinned first column.
|
|
36
|
+
*
|
|
37
|
+
* Nothing sticks until there is something to scroll, so this costs nothing on a table that fits —
|
|
38
|
+
* `position: sticky` is inert without an overflowing scroll container, and the one this table
|
|
39
|
+
* renders is the container it sticks inside.
|
|
40
|
+
*
|
|
41
|
+
* It has to be opaque, and that is the whole difficulty. A table paints nothing: the surface
|
|
42
|
+
* belongs to whatever put it there, which is the right arrangement everywhere except here, where a
|
|
43
|
+
* cell that stays put while the rest slides under it shows the sliding through itself. So the
|
|
44
|
+
* pinned cell paints the ground its card holds — the one colour it can name that a page will have
|
|
45
|
+
* put behind it.
|
|
46
|
+
*
|
|
47
|
+
* The row's own states cannot simply be inherited through it, because both are alpha: selected is
|
|
48
|
+
* eight percent black and hover is five, and a translucent cell over scrolled content is the same
|
|
49
|
+
* failure with a tint on it. So each is restated here over the opaque floor, the selected one as a
|
|
50
|
+
* colour and the hover one as an image layered above it. That is the arrangement FilterChip makes
|
|
51
|
+
* for exactly the same reason, and the second time this package has needed it.
|
|
52
|
+
*
|
|
53
|
+
* The stacking order is an integer with no unit and no token to name it — this package has one
|
|
54
|
+
* layer role and it is for popups, which this is not. One is enough: the pinned cell has to paint
|
|
55
|
+
* over its own row's later siblings and nothing else in the document.
|
|
56
|
+
*/
|
|
57
|
+
:where([data-dds-context="marketing"]) .dds-table[data-pin-first-column='true'] .dds-tablerow > :first-child {
|
|
58
|
+
position: sticky;
|
|
59
|
+
inset-inline-start: 0;
|
|
60
|
+
z-index: 1;
|
|
61
|
+
background-color: var(--color-bg-surface-raised);
|
|
62
|
+
border-inline-end-width: var(--border-width-hairline);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* The chosen row keeps its ground where it is pinned, restated because an alpha cannot be inherited
|
|
66
|
+
onto a cell that has scrolled content behind it. */
|
|
67
|
+
:where([data-dds-context="marketing"]) .dds-table[data-pin-first-column='true'] .dds-tablerow[data-selected='true'] > :first-child {
|
|
68
|
+
background-color: var(--color-bg-selected);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* And the pointer's wash, as an image over the floor rather than instead of it — the layering
|
|
72
|
+
FilterChip uses, for the same reason: the token tints what it lands on rather than replacing it. */
|
|
73
|
+
:where([data-dds-context="marketing"]) .dds-table[data-pin-first-column='true'] .dds-tablerow[data-hoverable='true']:hover > :first-child {
|
|
74
|
+
background-image: linear-gradient(var(--color-bg-hover), var(--color-bg-hover));
|
|
75
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** Which way a column is ordered, in the words `aria-sort` uses. */
|
|
2
|
+
export type TableSortDirection = 'none' | 'ascending' | 'descending';
|
|
3
|
+
export interface TableSort {
|
|
4
|
+
/** The column the table is ordered by, or undefined while it is ordered by none. */
|
|
5
|
+
column: string | undefined;
|
|
6
|
+
/** Which way that column runs. `none` for every other column. */
|
|
7
|
+
direction: TableSortDirection;
|
|
8
|
+
/** What a header cell needs to draw itself: spread it onto the TableHeaderCell. */
|
|
9
|
+
columnProps: (column: string) => {
|
|
10
|
+
sortable: true;
|
|
11
|
+
sortDirection: TableSortDirection;
|
|
12
|
+
onSort: () => void;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Which column a table is ordered by, and which way.
|
|
17
|
+
*
|
|
18
|
+
* The table does not keep this and cannot: the order outlives a render, and a table holding it
|
|
19
|
+
* would be a second copy of something the page already has — the rows themselves are sorted by
|
|
20
|
+
* whatever fetched them, and the two disagree the first time either changes.
|
|
21
|
+
*
|
|
22
|
+
* So this owns the answer and the page owns the rows. It reports which column and which direction,
|
|
23
|
+
* and sorting the data is the caller's: a table built at request time passes the pair to whatever
|
|
24
|
+
* fetched the rows, and one sorted in the browser sorts an array with it. Neither is this hook's
|
|
25
|
+
* business, which is why it returns no rows.
|
|
26
|
+
*
|
|
27
|
+
* It is the only one of product's three table hooks this package ships. Row selection and column
|
|
28
|
+
* management are how an application operates a table; a marketing table is read rather than
|
|
29
|
+
* operated, and a page that needs a reader to pick rows out of a set is an application view.
|
|
30
|
+
*
|
|
31
|
+
* The cycle is ascending, descending, none. Three states rather than two because a table ordered
|
|
32
|
+
* by nothing is a real state — it is the order the data arrived in, which for a feed is the only
|
|
33
|
+
* meaningful one, and a two-state toggle makes it unreachable once a reader has pressed anything.
|
|
34
|
+
*
|
|
35
|
+
* ```tsx
|
|
36
|
+
* const sort = useTableSort()
|
|
37
|
+
* <TableHeaderCell {...sort.columnProps('balance')} align="end">Balance</TableHeaderCell>
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function useTableSort(initial?: {
|
|
41
|
+
column: string;
|
|
42
|
+
direction: TableSortDirection;
|
|
43
|
+
}): TableSort;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useCallback, useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Which column a table is ordered by, and which way.
|
|
5
|
+
*
|
|
6
|
+
* The table does not keep this and cannot: the order outlives a render, and a table holding it
|
|
7
|
+
* would be a second copy of something the page already has — the rows themselves are sorted by
|
|
8
|
+
* whatever fetched them, and the two disagree the first time either changes.
|
|
9
|
+
*
|
|
10
|
+
* So this owns the answer and the page owns the rows. It reports which column and which direction,
|
|
11
|
+
* and sorting the data is the caller's: a table built at request time passes the pair to whatever
|
|
12
|
+
* fetched the rows, and one sorted in the browser sorts an array with it. Neither is this hook's
|
|
13
|
+
* business, which is why it returns no rows.
|
|
14
|
+
*
|
|
15
|
+
* It is the only one of product's three table hooks this package ships. Row selection and column
|
|
16
|
+
* management are how an application operates a table; a marketing table is read rather than
|
|
17
|
+
* operated, and a page that needs a reader to pick rows out of a set is an application view.
|
|
18
|
+
*
|
|
19
|
+
* The cycle is ascending, descending, none. Three states rather than two because a table ordered
|
|
20
|
+
* by nothing is a real state — it is the order the data arrived in, which for a feed is the only
|
|
21
|
+
* meaningful one, and a two-state toggle makes it unreachable once a reader has pressed anything.
|
|
22
|
+
*
|
|
23
|
+
* ```tsx
|
|
24
|
+
* const sort = useTableSort()
|
|
25
|
+
* <TableHeaderCell {...sort.columnProps('balance')} align="end">Balance</TableHeaderCell>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function useTableSort(initial) {
|
|
29
|
+
const [column, setColumn] = useState(initial?.column);
|
|
30
|
+
const [direction, setDirection] = useState(initial?.direction ?? 'none');
|
|
31
|
+
const columnProps = useCallback((name) => ({
|
|
32
|
+
sortable: true,
|
|
33
|
+
// Every other column reads `none`: a direction is a fact about the sorted column, and a
|
|
34
|
+
// header claiming one while another column is sorted tells the reader the data runs two ways.
|
|
35
|
+
sortDirection: column === name ? direction : 'none',
|
|
36
|
+
onSort: () => {
|
|
37
|
+
if (column !== name) {
|
|
38
|
+
setColumn(name);
|
|
39
|
+
setDirection('ascending');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// Ascending, descending, then back to no order at all — which releases the column rather
|
|
43
|
+
// than leaving the table stuck between two states it can never leave.
|
|
44
|
+
const next = direction === 'ascending' ? 'descending' : direction === 'descending' ? 'none' : 'ascending';
|
|
45
|
+
setDirection(next);
|
|
46
|
+
if (next === 'none')
|
|
47
|
+
setColumn(undefined);
|
|
48
|
+
},
|
|
49
|
+
}), [column, direction]);
|
|
50
|
+
return { column, direction, columnProps };
|
|
51
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import './TableBody.css';
|
|
2
|
+
import { type TableBodyProps } from './TableBody.types.js';
|
|
3
|
+
export type { TableBodyProps };
|
|
4
|
+
/**
|
|
5
|
+
* The rows of data, under the header.
|
|
6
|
+
*
|
|
7
|
+
* It is where the table's rules reach the rows: a line belongs between two data rows and nowhere
|
|
8
|
+
* else, so the section holding only data is the one that hands them out. It paints the surface the
|
|
9
|
+
* data sits on, which is the other half of the header's band — the names are tinted and the values
|
|
10
|
+
* are not, so the two read as different kinds of row without a second rule between them.
|
|
11
|
+
*/
|
|
12
|
+
export declare function TableBody({ size, dividers, hoverable, overflow, children, ...rest }: TableBodyProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Children, cloneElement, isValidElement } from 'react';
|
|
4
|
+
import './TableBody.css';
|
|
5
|
+
import { tableBodyDefaults, tableBodyParts } from './TableBody.types.js';
|
|
6
|
+
/**
|
|
7
|
+
* The rows of data, under the header.
|
|
8
|
+
*
|
|
9
|
+
* It is where the table's rules reach the rows: a line belongs between two data rows and nowhere
|
|
10
|
+
* else, so the section holding only data is the one that hands them out. It paints the surface the
|
|
11
|
+
* data sits on, which is the other half of the header's band — the names are tinted and the values
|
|
12
|
+
* are not, so the two read as different kinds of row without a second rule between them.
|
|
13
|
+
*/
|
|
14
|
+
export function TableBody({ size = tableBodyDefaults.size, dividers = tableBodyDefaults.dividers, hoverable = tableBodyDefaults.hoverable, overflow = tableBodyDefaults.overflow, children, ...rest }) {
|
|
15
|
+
return (_jsx("tbody", { ...rest, className: tableBodyParts.root, children: Children.toArray(children)
|
|
16
|
+
.filter(isValidElement)
|
|
17
|
+
.map((row, at) => cloneElement(row, {
|
|
18
|
+
key: row.key ?? at,
|
|
19
|
+
size,
|
|
20
|
+
// The first row's rule is the line under the header, so every row draws one and the
|
|
21
|
+
// table still ends clean — the edge is on the block-start side.
|
|
22
|
+
dividers,
|
|
23
|
+
hoverable,
|
|
24
|
+
overflow,
|
|
25
|
+
})) }));
|
|
26
|
+
}
|