@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,114 @@
|
|
|
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 before —
|
|
6
|
+
* several here are written a class deeper than they look in order to match generated CSS,
|
|
7
|
+
* and a scope that carried weight would break all of them.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* The four things about this control the contract cannot hold.
|
|
12
|
+
*
|
|
13
|
+
* A stacking order, which is an integer with no unit; the ink of a placeholder, which is the
|
|
14
|
+
* same element in another state rather than a part of its own; a sentence shown only while
|
|
15
|
+
* nothing matches, which is the same again; and a keyframed entrance, the element not having
|
|
16
|
+
* been there a moment earlier. Everything with a measure is a token, read through the custom
|
|
17
|
+
* properties the generated stylesheet reads.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
:where([data-dds-context="marketing"]) .dds-select .dds-select__popup {
|
|
21
|
+
/* Over whatever follows the control. An absolutely positioned box already paints above the
|
|
22
|
+
in-flow content of its own stacking context, which is enough until the next thing on the
|
|
23
|
+
page is positioned too — and on a form the next thing is another of these.
|
|
24
|
+
|
|
25
|
+
`layer.popup` is the role this package gives anything that leaves the flow and floats over
|
|
26
|
+
the page, and DropdownMenu's panel already reads it. Two floating surfaces on one page
|
|
27
|
+
whose order depends on which stylesheet the bundler wrote last is not an order anybody
|
|
28
|
+
chose. */
|
|
29
|
+
z-index: var(--layer-popup);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
:where([data-dds-context="marketing"]) .dds-select .dds-select__value[data-placeholder] {
|
|
33
|
+
/* The instruction that stands in for an answer, in the ink an unanswered control deserves —
|
|
34
|
+
`color.fg.tertiary`, which is what TextInput gives its own placeholder, so the two say
|
|
35
|
+
"nothing here yet" the same way on one form.
|
|
36
|
+
|
|
37
|
+
Not a part of its own, because it is never on screen at the same time as the answer it
|
|
38
|
+
replaces: two parts that cannot coexist are one part in two states. */
|
|
39
|
+
color: var(--color-fg-tertiary);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:where([data-dds-context="marketing"]) .dds-select .dds-select__empty {
|
|
43
|
+
/* Absent from the layout while anything matches, rather than absent from the DOM. A list under
|
|
44
|
+
a query is a live thing, and a row arriving on one keystroke and going on the next is a row
|
|
45
|
+
a reader cannot read — where `display: none` is out of the accessibility tree and out of the
|
|
46
|
+
layout, which is the whole of what removing it would have bought. */
|
|
47
|
+
display: none;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
:where([data-dds-context="marketing"]) .dds-select .dds-select__empty[data-shown] {
|
|
51
|
+
display: block;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
:where([data-dds-context="marketing"]) .dds-select .dds-select__message-icon {
|
|
55
|
+
/* The glyph on the line, rather than two and a half pixels above it.
|
|
56
|
+
*
|
|
57
|
+
* The message is `align-items: flex-start`, because a status can wrap and a mark centred
|
|
58
|
+
* against three lines of it sits in the middle of a paragraph. So the icon box is top-aligned
|
|
59
|
+
* against the first line, and its height decides where the glyph lands.
|
|
60
|
+
*
|
|
61
|
+
* That height was the glyph's own. This part is a flex container, so its block size comes from
|
|
62
|
+
* its flex line — sixteen pixels of mark — and a flex container has no strut, which is the
|
|
63
|
+
* thing a line-height would need in order to mean anything here. The `font-size` and
|
|
64
|
+
* `line-height` the contract binds on this part were put there to give the box the line's
|
|
65
|
+
* height and were doing nothing at all: sixteen against a twenty-one-pixel line box centres the
|
|
66
|
+
* mark two and a half pixels above the words.
|
|
67
|
+
*
|
|
68
|
+
* `1lh` is what reads them. It is the element's own line-height — the bound one, 1.5 against a
|
|
69
|
+
* bound 14px — so the box is exactly as tall as the line beside it and cannot drift from it: a
|
|
70
|
+
* change to `font.body.sm` moves both or neither. A pixel figure here would be the same number
|
|
71
|
+
* today and a silent disagreement the first time that role is retuned.
|
|
72
|
+
*
|
|
73
|
+
* Here rather than in the contract because `staticCss` takes keywords, `100%` and `0`, and
|
|
74
|
+
* rightly so — everything with a measure is a token. This is not a measure anyone chose; it is
|
|
75
|
+
* one length written in terms of another the contract already names. */
|
|
76
|
+
min-block-size: 1lh;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/*
|
|
80
|
+
* The surface arriving.
|
|
81
|
+
*
|
|
82
|
+
* An animation rather than a transition, because the element is not there a moment earlier — it
|
|
83
|
+
* is absent when the list is shut, so there is no previous value for a transition to run from.
|
|
84
|
+
* An animation runs on the element appearing, which is exactly the event.
|
|
85
|
+
*
|
|
86
|
+
* Scaling from `motion.scale.enter` with `motion.easing.enter`, which decelerates into place,
|
|
87
|
+
* over `motion.duration.normal` — the roles this package already names for something entering
|
|
88
|
+
* the viewport. Anchored at the top edge, so the list grows downward out of the box rather than
|
|
89
|
+
* outward from its own middle, which is the whole of what the motion says: this came from there.
|
|
90
|
+
*
|
|
91
|
+
* There is no exit. React removes the element when the list shuts, so nothing remains to
|
|
92
|
+
* animate — and keeping it mounted to animate out would cost the two things its absence buys: a
|
|
93
|
+
* shut control covers nothing, and no row is reachable by a reader running past it.
|
|
94
|
+
*/
|
|
95
|
+
@keyframes dds-select-popup-in {
|
|
96
|
+
from {
|
|
97
|
+
opacity: 0;
|
|
98
|
+
scale: var(--motion-scale-enter);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
:where([data-dds-context="marketing"]) .dds-select .dds-select__popup {
|
|
103
|
+
transform-origin: top center;
|
|
104
|
+
animation: dds-select-popup-in var(--motion-duration-normal) var(--motion-easing-enter);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* The reduce block the generated stylesheet writes covers transitions and not this, because it
|
|
108
|
+
is written from the bindings and this is not one. A reader who has asked for less movement has
|
|
109
|
+
asked for this too. */
|
|
110
|
+
@media (prefers-reduced-motion: reduce) {
|
|
111
|
+
:where([data-dds-context="marketing"]) .dds-select .dds-select__popup {
|
|
112
|
+
animation: none;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/* GENERATED from selectchip.contract.json. Do not edit. */
|
|
2
|
+
|
|
3
|
+
:where([data-dds-context="marketing"]) .dds-selectchip {
|
|
4
|
+
transition-property: opacity;
|
|
5
|
+
display: inline-flex;
|
|
6
|
+
position: relative;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
:where([data-dds-context="marketing"]) .dds-selectchip .dds-selectchip__trigger {
|
|
10
|
+
transition-property: background-color, background-image, border-color, color, outline-color, outline-width;
|
|
11
|
+
align-items: center;
|
|
12
|
+
appearance: none;
|
|
13
|
+
border-style: solid;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
display: inline-flex;
|
|
17
|
+
flex: none;
|
|
18
|
+
max-inline-size: 100%;
|
|
19
|
+
outline-style: solid;
|
|
20
|
+
background-color: var(--color-bg-surface-raised);
|
|
21
|
+
border-color: var(--color-border-default);
|
|
22
|
+
border-radius: var(--radius-pill);
|
|
23
|
+
border-width: var(--border-width-default);
|
|
24
|
+
color: var(--color-fg-default);
|
|
25
|
+
gap: var(--space-gap-xs);
|
|
26
|
+
min-inline-size: var(--size-target-min);
|
|
27
|
+
outline-width: var(--border-width-none);
|
|
28
|
+
transition-duration: var(--motion-duration-fast);
|
|
29
|
+
transition-timing-function: var(--motion-easing-standard);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
:where([data-dds-context="marketing"]) .dds-selectchip .dds-selectchip__trigger-icon {
|
|
33
|
+
align-items: center;
|
|
34
|
+
display: flex;
|
|
35
|
+
flex: none;
|
|
36
|
+
justify-content: center;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:where([data-dds-context="marketing"]) .dds-selectchip .dds-selectchip__trigger-label {
|
|
40
|
+
font-variant-numeric: tabular-nums;
|
|
41
|
+
min-inline-size: 0;
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
text-overflow: ellipsis;
|
|
44
|
+
white-space: nowrap;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
:where([data-dds-context="marketing"]) .dds-selectchip .dds-selectchip__chevron {
|
|
48
|
+
flex: none;
|
|
49
|
+
transition-duration: var(--motion-duration-fast);
|
|
50
|
+
transition-timing-function: var(--motion-easing-standard);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:where([data-dds-context="marketing"]) .dds-selectchip .dds-selectchip__listbox {
|
|
54
|
+
border-style: solid;
|
|
55
|
+
box-sizing: border-box;
|
|
56
|
+
inline-size: max-content;
|
|
57
|
+
inset-block-start: 100%;
|
|
58
|
+
inset-inline-end: 0;
|
|
59
|
+
inset-inline-start: 0;
|
|
60
|
+
list-style: none;
|
|
61
|
+
margin: 0;
|
|
62
|
+
min-inline-size: 100%;
|
|
63
|
+
overflow-y: auto;
|
|
64
|
+
position: absolute;
|
|
65
|
+
background-color: var(--color-bg-surface-raised);
|
|
66
|
+
border-color: var(--color-border-subtle);
|
|
67
|
+
border-radius: var(--radius-menu);
|
|
68
|
+
border-width: var(--border-width-default);
|
|
69
|
+
box-shadow: var(--elevation-surface-floating);
|
|
70
|
+
margin-block-start: var(--space-gap-xs);
|
|
71
|
+
max-block-size: var(--size-menu-max);
|
|
72
|
+
padding-block: var(--space-inset-2xs);
|
|
73
|
+
padding-inline: var(--space-inset-2xs);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
:where([data-dds-context="marketing"]) .dds-selectchip[data-alignment="end"] .dds-selectchip__listbox {
|
|
77
|
+
inset-inline-start: auto;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
:where([data-dds-context="marketing"]) .dds-selectchip[data-alignment="start"] .dds-selectchip__listbox {
|
|
81
|
+
inset-inline-end: auto;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
:where([data-dds-context="marketing"]) .dds-selectchip .dds-selectchip__trigger:hover:where(:not(:disabled)) {
|
|
85
|
+
background-image: linear-gradient(var(--color-bg-hover), var(--color-bg-hover));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
:where([data-dds-context="marketing"]) .dds-selectchip .dds-selectchip__trigger:active {
|
|
89
|
+
background-image: linear-gradient(var(--color-bg-active), var(--color-bg-active));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
:where([data-dds-context="marketing"]) .dds-selectchip .dds-selectchip__trigger:focus-visible {
|
|
93
|
+
outline-color: var(--color-border-focus);
|
|
94
|
+
outline-width: var(--border-width-focus);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
:where([data-dds-context="marketing"]) .dds-selectchip .dds-selectchip__trigger[data-chosen="true"] {
|
|
98
|
+
background-color: var(--color-bg-strong);
|
|
99
|
+
border-color: var(--color-bg-strong);
|
|
100
|
+
color: var(--color-fg-on-strong);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
:where([data-dds-context="marketing"]) .dds-selectchip[data-disabled="true"] {
|
|
104
|
+
opacity: var(--opacity-disabled);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
:where([data-dds-context="marketing"]) .dds-selectchip[data-size="md"] .dds-selectchip__chevron {
|
|
108
|
+
block-size: var(--icon-size-sm);
|
|
109
|
+
inline-size: var(--icon-size-sm);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
:where([data-dds-context="marketing"]) .dds-selectchip[data-size="md"] .dds-selectchip__trigger {
|
|
113
|
+
block-size: var(--size-control-md);
|
|
114
|
+
padding-inline: var(--space-inset-md);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
:where([data-dds-context="marketing"]) .dds-selectchip[data-size="md"] .dds-selectchip__trigger-icon {
|
|
118
|
+
block-size: var(--icon-size-sm);
|
|
119
|
+
inline-size: var(--icon-size-sm);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
:where([data-dds-context="marketing"]) .dds-selectchip[data-size="md"] .dds-selectchip__trigger-label {
|
|
123
|
+
font-family: var(--font-label-md-family);
|
|
124
|
+
font-size: var(--font-label-md-size);
|
|
125
|
+
font-weight: var(--font-label-md-weight);
|
|
126
|
+
line-height: var(--font-label-md-line-height);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
:where([data-dds-context="marketing"]) .dds-selectchip[data-size="sm"] .dds-selectchip__chevron {
|
|
130
|
+
block-size: var(--icon-size-xs);
|
|
131
|
+
inline-size: var(--icon-size-xs);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
:where([data-dds-context="marketing"]) .dds-selectchip[data-size="sm"] .dds-selectchip__trigger {
|
|
135
|
+
block-size: var(--size-control-sm);
|
|
136
|
+
padding-inline: var(--space-inset-sm);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
:where([data-dds-context="marketing"]) .dds-selectchip[data-size="sm"] .dds-selectchip__trigger-icon {
|
|
140
|
+
block-size: var(--icon-size-xs);
|
|
141
|
+
inline-size: var(--icon-size-xs);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
:where([data-dds-context="marketing"]) .dds-selectchip[data-size="sm"] .dds-selectchip__trigger-label {
|
|
145
|
+
font-family: var(--font-label-sm-family);
|
|
146
|
+
font-size: var(--font-label-sm-size);
|
|
147
|
+
font-weight: var(--font-label-sm-weight);
|
|
148
|
+
line-height: var(--font-label-sm-line-height);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@media (prefers-reduced-motion: reduce) {
|
|
152
|
+
:where([data-dds-context="marketing"]) .dds-selectchip,
|
|
153
|
+
:where([data-dds-context="marketing"]) .dds-selectchip * { transition: none; }
|
|
154
|
+
}
|
|
155
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import './SelectChip.css';
|
|
2
|
+
import './select-chip-impl.css';
|
|
3
|
+
import { type SelectChipProps } from './SelectChip.types.js';
|
|
4
|
+
export type { SelectChipProps };
|
|
5
|
+
/**
|
|
6
|
+
* A chip that opens a list of answers and keeps the one chosen.
|
|
7
|
+
*
|
|
8
|
+
* It renders its own chip rather than taking one. The chip has to say what is chosen,
|
|
9
|
+
* whether the list is open, and which answer the arrow keys are resting on — three
|
|
10
|
+
* facts that only this component can see, and a consumer holding a chip of their own
|
|
11
|
+
* would have to be handed all three and keep them in step. So the trigger is not a
|
|
12
|
+
* slot, which is where this parts company with this package's DropdownMenu.
|
|
13
|
+
*
|
|
14
|
+
* Focus stays on the chip while the list is open, and the active answer is named from
|
|
15
|
+
* there through `aria-activedescendant`. That is the other thing separating the two:
|
|
16
|
+
* a menu's items are things to do and therefore things to focus, where an answer is
|
|
17
|
+
* not a tab stop, and a list of twenty would otherwise be twenty presses on the way to
|
|
18
|
+
* whatever follows the row.
|
|
19
|
+
*/
|
|
20
|
+
export declare function SelectChip({ size, disabled, alignment, label, value, defaultValue, onChange, open, defaultOpen, onOpenChange, leadingIcon, children, ...rest }: SelectChipProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Children, Fragment, cloneElement, isValidElement, useEffect, useId, useRef, useState, } from 'react';
|
|
4
|
+
import { ChevronDownRegularIcon } from '@deriv-com/quill-icons-web';
|
|
5
|
+
import './SelectChip.css';
|
|
6
|
+
import './select-chip-impl.css';
|
|
7
|
+
import { Icon } from '../icon/Icon.js';
|
|
8
|
+
import { selectChipDefaults, selectChipGlyphStep, selectChipParts, } from './SelectChip.types.js';
|
|
9
|
+
/**
|
|
10
|
+
* The answers, as a list this control can index.
|
|
11
|
+
*
|
|
12
|
+
* Levelled out of `children` rather than assumed to be an array: a set built from
|
|
13
|
+
* data arrives through a `.map()`, and one with a condition in it arrives with a
|
|
14
|
+
* `false` among the rows. `Children.toArray` flattens arrays and drops the falsy
|
|
15
|
+
* entries, which is why it is the way in.
|
|
16
|
+
*
|
|
17
|
+
* It does not flatten fragments, though — a `<>` comes back as one child of type
|
|
18
|
+
* Fragment, and a set written by hand inside one is the ordinary way to write it.
|
|
19
|
+
* Left alone, every answer would disappear into a single unindexable child: the list
|
|
20
|
+
* would render nothing selectable, the ids would land on an element that cannot hold
|
|
21
|
+
* them, and `aria-activedescendant` would point at nothing. So fragments are opened
|
|
22
|
+
* here, recursively, because one may hold another.
|
|
23
|
+
*/
|
|
24
|
+
function optionsOf(children) {
|
|
25
|
+
return Children.toArray(children).flatMap((child) => {
|
|
26
|
+
if (!isValidElement(child))
|
|
27
|
+
return [];
|
|
28
|
+
if (child.type === Fragment) {
|
|
29
|
+
return optionsOf(child.props.children);
|
|
30
|
+
}
|
|
31
|
+
return [child];
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* An option's words, flattened enough to match a letter against, and to show on the chip.
|
|
36
|
+
*
|
|
37
|
+
* Anything that is not a string or a number contributes nothing rather than throwing:
|
|
38
|
+
* a row nobody can type their way to is a smaller failure than a list that cannot render.
|
|
39
|
+
*/
|
|
40
|
+
function words(node) {
|
|
41
|
+
if (typeof node === 'string')
|
|
42
|
+
return node;
|
|
43
|
+
if (typeof node === 'number')
|
|
44
|
+
return String(node);
|
|
45
|
+
if (Array.isArray(node))
|
|
46
|
+
return node.map(words).join('');
|
|
47
|
+
return '';
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* How long a run of keystrokes stays one search rather than starting the next.
|
|
51
|
+
*
|
|
52
|
+
* Long enough that two letters typed on purpose join up, short enough that a letter
|
|
53
|
+
* pressed a beat later starts again.
|
|
54
|
+
*/
|
|
55
|
+
const TYPING_WINDOW = 500;
|
|
56
|
+
/**
|
|
57
|
+
* A chip that opens a list of answers and keeps the one chosen.
|
|
58
|
+
*
|
|
59
|
+
* It renders its own chip rather than taking one. The chip has to say what is chosen,
|
|
60
|
+
* whether the list is open, and which answer the arrow keys are resting on — three
|
|
61
|
+
* facts that only this component can see, and a consumer holding a chip of their own
|
|
62
|
+
* would have to be handed all three and keep them in step. So the trigger is not a
|
|
63
|
+
* slot, which is where this parts company with this package's DropdownMenu.
|
|
64
|
+
*
|
|
65
|
+
* Focus stays on the chip while the list is open, and the active answer is named from
|
|
66
|
+
* there through `aria-activedescendant`. That is the other thing separating the two:
|
|
67
|
+
* a menu's items are things to do and therefore things to focus, where an answer is
|
|
68
|
+
* not a tab stop, and a list of twenty would otherwise be twenty presses on the way to
|
|
69
|
+
* whatever follows the row.
|
|
70
|
+
*/
|
|
71
|
+
export function SelectChip({ size = selectChipDefaults.size, disabled = selectChipDefaults.disabled, alignment = selectChipDefaults.alignment, label, value, defaultValue, onChange, open, defaultOpen, onOpenChange, leadingIcon, children, ...rest }) {
|
|
72
|
+
const options = optionsOf(children);
|
|
73
|
+
const rootId = useId();
|
|
74
|
+
const listId = `${rootId}-list`;
|
|
75
|
+
const rowId = (at) => `${rootId}-option-${at}`;
|
|
76
|
+
const root = useRef(null);
|
|
77
|
+
const typed = useRef({ text: '', at: 0 });
|
|
78
|
+
// Held only for the uncontrolled case. When `value` or `open` is passed the prop is
|
|
79
|
+
// the answer and this is never read, which is what keeps a controlled chip from
|
|
80
|
+
// drifting out of step.
|
|
81
|
+
const [ownValue, setOwnValue] = useState(defaultValue ?? '');
|
|
82
|
+
const [ownOpen, setOwnOpen] = useState(defaultOpen ?? false);
|
|
83
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
84
|
+
const chosen = value ?? ownValue;
|
|
85
|
+
/**
|
|
86
|
+
* Shut whenever the chip cannot be used, whichever prop says otherwise.
|
|
87
|
+
*
|
|
88
|
+
* The trigger carries the native `disabled`, so a reader cannot open it — no click,
|
|
89
|
+
* no key, and no tab stop to reach it from. What that does not cover is a consumer
|
|
90
|
+
* passing `open` or `defaultOpen` alongside it, which asks for a list of answers on
|
|
91
|
+
* a control that cannot take one. The generated type refuses the pair, and this is
|
|
92
|
+
* the runtime half of the same refusal.
|
|
93
|
+
*/
|
|
94
|
+
const expanded = disabled ? false : (open ?? ownOpen);
|
|
95
|
+
const indexOf = (of) => options.findIndex((option) => option.props.value === of);
|
|
96
|
+
const setOpen = (next) => {
|
|
97
|
+
if (open === undefined)
|
|
98
|
+
setOwnOpen(next);
|
|
99
|
+
onOpenChange?.(next);
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* The next answer that can be taken, walking in `by` and wrapping.
|
|
103
|
+
*
|
|
104
|
+
* Refusals are stepped over rather than landed on: an arrow key that stops on an
|
|
105
|
+
* answer nobody may take reads as the control being broken rather than as it being
|
|
106
|
+
* careful.
|
|
107
|
+
*/
|
|
108
|
+
const step = (from, by) => {
|
|
109
|
+
for (let i = 1; i <= options.length; i += 1) {
|
|
110
|
+
const at = (from + by * i + options.length * options.length) % options.length;
|
|
111
|
+
if (options[at]?.props.disabled !== true)
|
|
112
|
+
return at;
|
|
113
|
+
}
|
|
114
|
+
return from;
|
|
115
|
+
};
|
|
116
|
+
const firstOpen = () => step(-1, 1);
|
|
117
|
+
const lastOpen = () => step(options.length, -1);
|
|
118
|
+
const onTheAnswer = () => (chosen === '' ? firstOpen() : indexOf(chosen));
|
|
119
|
+
const openAt = (at) => {
|
|
120
|
+
setActiveIndex(at);
|
|
121
|
+
setOpen(true);
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Taking the answer the arrow keys are resting on.
|
|
125
|
+
*
|
|
126
|
+
* `onChange` is not called when the answer is the one already held — a reader
|
|
127
|
+
* reopening the list and pressing what they chose last time has changed nothing, and
|
|
128
|
+
* a page narrowing its index on that fires a request for a set it is already showing.
|
|
129
|
+
*/
|
|
130
|
+
const take = (at) => {
|
|
131
|
+
const option = options[at];
|
|
132
|
+
if (option === undefined || option.props.disabled === true)
|
|
133
|
+
return;
|
|
134
|
+
const next = option.props.value ?? '';
|
|
135
|
+
if (next !== chosen) {
|
|
136
|
+
if (value === undefined)
|
|
137
|
+
setOwnValue(next);
|
|
138
|
+
onChange?.(next);
|
|
139
|
+
}
|
|
140
|
+
setOpen(false);
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* The first answer whose words begin with what has been typed, searched circularly
|
|
144
|
+
* from `after` — which is what makes a letter pressed twice walk through the answers
|
|
145
|
+
* beginning with it instead of returning to the first one each time.
|
|
146
|
+
*/
|
|
147
|
+
const matching = (query, after) => {
|
|
148
|
+
for (let i = 1; i <= options.length; i += 1) {
|
|
149
|
+
const at = (after + i + options.length * i) % options.length;
|
|
150
|
+
const option = options[at];
|
|
151
|
+
if (option?.props.disabled === true)
|
|
152
|
+
continue;
|
|
153
|
+
if (words(option?.props.children).trim().toLowerCase().startsWith(query))
|
|
154
|
+
return at;
|
|
155
|
+
}
|
|
156
|
+
return -1;
|
|
157
|
+
};
|
|
158
|
+
/** A letter, and what it means given what came just before it. */
|
|
159
|
+
const typeAhead = (key) => {
|
|
160
|
+
const now = Date.now();
|
|
161
|
+
const run = now - typed.current.at > TYPING_WINDOW ? key : typed.current.text + key;
|
|
162
|
+
typed.current = { text: run, at: now };
|
|
163
|
+
const repeated = run.length > 1 && [...run].every((each) => each === run[0]);
|
|
164
|
+
const query = (repeated ? run[0] : run).toLowerCase();
|
|
165
|
+
const found = matching(query, repeated ? activeIndex : Math.max(activeIndex - 1, -1));
|
|
166
|
+
if (found === -1)
|
|
167
|
+
return;
|
|
168
|
+
if (!expanded)
|
|
169
|
+
openAt(found);
|
|
170
|
+
else
|
|
171
|
+
setActiveIndex(found);
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* A key that is a letter somebody typed, rather than a command.
|
|
175
|
+
*
|
|
176
|
+
* Space is excluded, and it has to be: here it does what Enter does, so a space that
|
|
177
|
+
* started a search would be a space that stopped taking the answer.
|
|
178
|
+
*/
|
|
179
|
+
const printable = (event) => event.key.length === 1 && event.key !== ' ' && !event.ctrlKey && !event.metaKey;
|
|
180
|
+
const onKeyDown = (event) => {
|
|
181
|
+
const key = event.key;
|
|
182
|
+
if (!expanded) {
|
|
183
|
+
if (key === 'Enter' || key === ' ' || key === 'ArrowDown') {
|
|
184
|
+
event.preventDefault();
|
|
185
|
+
openAt(onTheAnswer());
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (key === 'ArrowUp') {
|
|
189
|
+
event.preventDefault();
|
|
190
|
+
openAt(chosen === '' ? lastOpen() : indexOf(chosen));
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (printable(event)) {
|
|
194
|
+
// Typing at a shut chip opens it on the match rather than answering outright.
|
|
195
|
+
// A native select replaces the answer, which is how brushing a key while
|
|
196
|
+
// tabbing past one changes a narrowing nobody meant to touch.
|
|
197
|
+
event.preventDefault();
|
|
198
|
+
typeAhead(key);
|
|
199
|
+
}
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (key === 'ArrowDown') {
|
|
203
|
+
event.preventDefault();
|
|
204
|
+
setActiveIndex(step(activeIndex, 1));
|
|
205
|
+
}
|
|
206
|
+
else if (key === 'ArrowUp') {
|
|
207
|
+
event.preventDefault();
|
|
208
|
+
setActiveIndex(step(activeIndex, -1));
|
|
209
|
+
}
|
|
210
|
+
else if (key === 'Home') {
|
|
211
|
+
event.preventDefault();
|
|
212
|
+
setActiveIndex(firstOpen());
|
|
213
|
+
}
|
|
214
|
+
else if (key === 'End') {
|
|
215
|
+
event.preventDefault();
|
|
216
|
+
setActiveIndex(lastOpen());
|
|
217
|
+
}
|
|
218
|
+
else if (key === 'Enter' || key === ' ') {
|
|
219
|
+
event.preventDefault();
|
|
220
|
+
take(activeIndex);
|
|
221
|
+
}
|
|
222
|
+
else if (key === 'Escape') {
|
|
223
|
+
// The answer is left alone. Escape is a reader saying they did not mean to open
|
|
224
|
+
// the list, not that they have changed their mind about what they already answered.
|
|
225
|
+
event.preventDefault();
|
|
226
|
+
setOpen(false);
|
|
227
|
+
}
|
|
228
|
+
else if (printable(event)) {
|
|
229
|
+
event.preventDefault();
|
|
230
|
+
typeAhead(key);
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* Shutting on a press elsewhere, which is the only way out that is not a keystroke.
|
|
235
|
+
*
|
|
236
|
+
* Bound while open and unbound the moment it shuts. `pointerdown` rather than
|
|
237
|
+
* `click`, so the list is gone before whatever was underneath it has moved.
|
|
238
|
+
*/
|
|
239
|
+
useEffect(() => {
|
|
240
|
+
if (!expanded)
|
|
241
|
+
return;
|
|
242
|
+
const onPointerDown = (event) => {
|
|
243
|
+
if (root.current?.contains(event.target) === true)
|
|
244
|
+
return;
|
|
245
|
+
setOpen(false);
|
|
246
|
+
};
|
|
247
|
+
document.addEventListener('pointerdown', onPointerDown);
|
|
248
|
+
return () => document.removeEventListener('pointerdown', onPointerDown);
|
|
249
|
+
});
|
|
250
|
+
const taken = options[indexOf(chosen)];
|
|
251
|
+
// The chip carries the answer once there is one, and the name of the narrowing until
|
|
252
|
+
// then — which is what makes a row of these read as a list of decisions rather than a
|
|
253
|
+
// list of filters.
|
|
254
|
+
const shown = taken === undefined ? label : words(taken.props.children);
|
|
255
|
+
return (_jsxs("div", { className: selectChipParts.root, ...rest, ref: root, "data-size": size, "data-alignment": alignment, "data-disabled": String(disabled), children: [_jsxs("button", { type: "button", className: selectChipParts.trigger,
|
|
256
|
+
// The platform's own, which is the whole of the behaviour: a disabled button
|
|
257
|
+
// takes no click, answers no key, and is not a tab stop — so there is nothing
|
|
258
|
+
// here to gate by hand.
|
|
259
|
+
disabled: disabled, "aria-haspopup": "listbox", "aria-expanded": expanded, "aria-controls": expanded ? listId : undefined, "aria-activedescendant": expanded && activeIndex !== -1 ? rowId(activeIndex) : undefined, "data-chosen": String(taken !== undefined), "data-expanded": String(expanded), onKeyDown: onKeyDown, onClick: () => (expanded ? setOpen(false) : openAt(onTheAnswer())), children: [leadingIcon === undefined ? null : (_jsx("span", { className: selectChipParts['trigger-icon'], children: _jsx(Icon, { size: selectChipGlyphStep[size], children: leadingIcon }) })), _jsx("span", { className: selectChipParts['trigger-label'], children: shown }), _jsx(ChevronDownRegularIcon, { className: selectChipParts.chevron, style: expanded ? { rotate: '180deg' } : undefined, "aria-hidden": "true" })] }), expanded ? (_jsx("ul", { className: selectChipParts.listbox, id: listId, role: "listbox", "aria-label": label, children: options.map((option, at) => cloneElement(option, {
|
|
260
|
+
id: rowId(at),
|
|
261
|
+
size,
|
|
262
|
+
selected: option.props.value === chosen && chosen !== '',
|
|
263
|
+
active: at === activeIndex,
|
|
264
|
+
// `onMouseDown` rather than `onClick`: the document handler above shuts
|
|
265
|
+
// the list on pointerdown, and a click handler here would fire after the
|
|
266
|
+
// row had already gone.
|
|
267
|
+
onMouseDown: (event) => {
|
|
268
|
+
event.preventDefault();
|
|
269
|
+
take(at);
|
|
270
|
+
},
|
|
271
|
+
onMouseEnter: () => setActiveIndex(at),
|
|
272
|
+
})) })) : null] }));
|
|
273
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface SelectChipOwnProps {
|
|
3
|
+
/**
|
|
4
|
+
* `sm` — The default, and the same measure a FilterChip takes at its own default, so a row holding both sits level
|
|
5
|
+
* `md` — A touch-first layout, or a filter row in a hero band where the chips carry more weight
|
|
6
|
+
*/
|
|
7
|
+
size?: 'sm' | 'md';
|
|
8
|
+
/**
|
|
9
|
+
* `start` — The list's leading edge lines up with the chip's. The default, because a reader reads from that edge and the answers begin where the chip's own words began
|
|
10
|
+
* `end` — Its trailing edge lines up instead, for a chip near the end of a row where a list opening the other way would run off the screen
|
|
11
|
+
*/
|
|
12
|
+
alignment?: 'start' | 'end';
|
|
13
|
+
/** Always, and required on that account — it names what is being chosen, and it is what the chip shows until something has been. Short enough to read at a glance in a row of other chips */
|
|
14
|
+
label: string;
|
|
15
|
+
/** The page owns the answer — it arrives from a URL, is shared with something else on screen, or has to survive the chip unmounting. Passed, this is the answer, and onChange is the only way it moves */
|
|
16
|
+
value?: string;
|
|
17
|
+
/** An answer the chip arrives carrying, which the reader is then free to change. The uncontrolled half of the pair, and what almost every use wants */
|
|
18
|
+
defaultValue?: string;
|
|
19
|
+
/** Always, and it is required for that reason. It hands back the value of the answer taken, each time one is taken. It is also the only way the answer reaches the page: this renders a div, a button and a list, so there is no form field carrying the choice and no name to submit it under — and a narrowing the page never learns about narrows nothing. The chip goes on showing it either way, which is what makes the omission quiet */
|
|
20
|
+
onChange: (value: string) => void;
|
|
21
|
+
/** The list is showing when the chip arrives, and the chip owns it from there */
|
|
22
|
+
defaultOpen?: boolean;
|
|
23
|
+
/** Something outside the chip has to know the list opened or shut — closing another one beside it, or reporting the interaction */
|
|
24
|
+
onOpenChange?: (open: boolean) => void;
|
|
25
|
+
/** A glyph makes the kind of narrowing faster to recognise than its name alone. It sits before the words and never replaces them. Pass the glyph itself rather than one already wrapped in an Icon: the chip wraps it at icon.size.xs at sm and icon.size.sm at md, the same step its chevron takes */
|
|
26
|
+
leadingIcon?: ReactNode;
|
|
27
|
+
/** Allowed: Option */
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
}
|
|
30
|
+
export type SelectChipProps = SelectChipOwnProps & ({
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
open?: false;
|
|
33
|
+
} | {
|
|
34
|
+
disabled?: false;
|
|
35
|
+
open?: boolean;
|
|
36
|
+
});
|
|
37
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
38
|
+
export declare const selectChipParts: {
|
|
39
|
+
readonly root: "dds-selectchip";
|
|
40
|
+
readonly trigger: "dds-selectchip__trigger";
|
|
41
|
+
readonly 'trigger-icon': "dds-selectchip__trigger-icon";
|
|
42
|
+
readonly 'trigger-label': "dds-selectchip__trigger-label";
|
|
43
|
+
readonly chevron: "dds-selectchip__chevron";
|
|
44
|
+
readonly listbox: "dds-selectchip__listbox";
|
|
45
|
+
};
|
|
46
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
47
|
+
export declare const selectChipDefaults: {
|
|
48
|
+
readonly disabled: false;
|
|
49
|
+
readonly size: "sm";
|
|
50
|
+
readonly alignment: "start";
|
|
51
|
+
};
|
|
52
|
+
/** The step this component draws a glyph slot at. Generated — do not retype. */
|
|
53
|
+
export declare const selectChipGlyphStep: {
|
|
54
|
+
readonly sm: "xs";
|
|
55
|
+
readonly md: "sm";
|
|
56
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// GENERATED from select-chip.contract.json. Do not edit.
|
|
2
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
3
|
+
export const selectChipParts = {
|
|
4
|
+
root: 'dds-selectchip',
|
|
5
|
+
trigger: 'dds-selectchip__trigger',
|
|
6
|
+
'trigger-icon': 'dds-selectchip__trigger-icon',
|
|
7
|
+
'trigger-label': 'dds-selectchip__trigger-label',
|
|
8
|
+
chevron: 'dds-selectchip__chevron',
|
|
9
|
+
listbox: 'dds-selectchip__listbox',
|
|
10
|
+
};
|
|
11
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
12
|
+
export const selectChipDefaults = { disabled: false, size: 'sm', alignment: 'start' };
|
|
13
|
+
/** The step this component draws a glyph slot at. Generated — do not retype. */
|
|
14
|
+
export const selectChipGlyphStep = { sm: 'xs', md: 'sm' };
|
|
@@ -0,0 +1,38 @@
|
|
|
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 — both here are written a class deeper than they look in order to match
|
|
7
|
+
* generated CSS, and a scope that carried weight would break them.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* Implementation CSS the contract cannot express.
|
|
12
|
+
*
|
|
13
|
+
* A token binding carries one state, and these are two at once. `chosen` is a state rather than
|
|
14
|
+
* an axis because whether an answer has been taken is derived from the value rather than passed
|
|
15
|
+
* in — so it cannot be a `when`, and a binding cannot say "chosen, and hovered" in one breath.
|
|
16
|
+
*
|
|
17
|
+
* Nothing here is a value. Every measure comes from the same tokens the bindings use, which is
|
|
18
|
+
* what keeps these two rules honest: they are the cascade the contract could not reach, not a
|
|
19
|
+
* second opinion about what the chip should look like.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/* The chosen chip's own hover, which would otherwise fall back to the unchosen one and wash the
|
|
23
|
+
fill in the wrong direction — a black alpha over a ground that is already near-black shows
|
|
24
|
+
nothing at all. This is the case color.bg.hover-inverse exists for. */
|
|
25
|
+
:where([data-dds-context="marketing"]) .dds-selectchip .dds-selectchip__trigger[data-chosen="true"]:hover {
|
|
26
|
+
background-image: linear-gradient(
|
|
27
|
+
var(--color-bg-hover-inverse),
|
|
28
|
+
var(--color-bg-hover-inverse)
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* An open chip borrows the heavier edge, but only while nothing is chosen. Said of both, it would
|
|
33
|
+
be a second rule as specific as the one it argues with, and the cascade would settle it by
|
|
34
|
+
source order — so the exclusion is written rather than left to whichever sorted last. A chosen
|
|
35
|
+
chip already carries a painted edge, so there is nothing for opening to add. */
|
|
36
|
+
:where([data-dds-context="marketing"]) .dds-selectchip .dds-selectchip__trigger[data-expanded="true"]:not([data-chosen="true"]) {
|
|
37
|
+
border-color: var(--color-border-strong);
|
|
38
|
+
}
|